DragonFlyBSD Kernel Audit
DF-2562 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/vfs/hammer2/hammer2_vnops.c b/sys/vfs/hammer2/hammer2_vnops.c
--- a/sys/vfs/hammer2/hammer2_vnops.c
+++ b/sys/vfs/hammer2/hammer2_vnops.c
@@ -700,14 +700,24 @@
 		hammer2_cluster_bref(&xop->head.cluster, &bref);
 
 		if (bref.type == HAMMER2_BREF_TYPE_INODE) {
+			uint16_t name_len;
+
 			ripdata = &hammer2_xop_gdata(&xop->head)->ipdata;
 			dtype = hammer2_get_dtype(ripdata->meta.type);
 			saveoff = bref.key & HAMMER2_DIRHASH_USERMSK;
+			name_len = ripdata->meta.name_len;
+			if (name_len > HAMMER2_INODE_MAXNAME) {
+				kprintf("hammer2_readdir: ignoring inode "
+					"with corrupt name_len %u\n",
+					name_len);
+				hammer2_xop_pdata(&xop->head);
+				goto next_entry;
+			}
 			r = vop_write_dirent(&error, uio,
 					     ripdata->meta.inum &
 					      HAMMER2_DIRHASH_USERMSK,
 					     dtype,
-					     ripdata->meta.name_len,
+					     name_len,
 					     ripdata->filename);
 			hammer2_xop_pdata(&xop->head);
 			if (r)
@@ -721,6 +731,12 @@
 			dtype = hammer2_get_dtype(bref.embed.dirent.type);
 			saveoff = bref.key & HAMMER2_DIRHASH_USERMSK;
 			namlen = bref.embed.dirent.namlen;
+			if (namlen > HAMMER2_INODE_MAXNAME) {
+				kprintf("hammer2_readdir: ignoring dirent "
+					"with corrupt namlen %u\n",
+					namlen);
+				goto next_entry;
+			}
 			if (namlen <= sizeof(bref.check.buf)) {
 				dname = bref.check.buf;
 			} else {
@@ -740,6 +756,9 @@
 			/* XXX chain error */
 			kprintf("bad chain type readdir %d\n", bref.type);
 		}
+	next_entry:
+		/* label for skipping corrupt entries */
+		;
 	}
 	hammer2_xop_retire(&xop->head, HAMMER2_XOPMASK_VOP);
 	if (error == ENOENT) {