DragonFlyBSD Kernel Audit
DF-0898 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/vfs/devfs/devfs_rules.c b/sys/vfs/devfs/devfs_rules.c
index 0000000..1111111 100644
--- a/sys/vfs/devfs/devfs_rules.c
+++ b/sys/vfs/devfs/devfs_rules.c
@@ -111,6 +111,17 @@
 	}
 
 	if (templ->rule_cmd & DEVFS_RULE_LINK) {
+		/*
+		 * devfs_rule_create_link() unconditionally dereferences
+		 * rule->name (to detect a trailing '*' wildcard), so a LINK
+		 * rule must also carry DEVFS_RULE_NAME -- otherwise rule->name
+		 * stays NULL and rule->namlen stays 0, and the later apply
+		 * faults at address 0xffffffffffffffff (NULL + (u_char)0 - 1).
+		 */
+		if (!(templ->rule_type & DEVFS_RULE_NAME))
+			goto error_out;
+			/* NOTREACHED */
+
 		if (templ->linkname == NULL)
 			goto error_out;
 			/* NOTREACHED */
@@ -240,7 +251,15 @@
 	char *path = NULL;
 	char *name, name_buf[PATH_MAX], buf[PATH_MAX];
 
-	if (rule->name[rule->namlen-1] == '*') {
+	/*
+	 * Defense in depth: devfs_rule_alloc() now rejects LINK rules
+	 * that lack NAME, but be defensive against any pre-existing rule
+	 * or future code path that could leave rule->name == NULL.
+	 * Without a name there is no wildcard suffix to strip, so just
+	 * create the alias verbatim from linkname.
+	 */
+	if ((rule->name != NULL) && (rule->namlen > 0) &&
+	    (rule->name[rule->namlen-1] == '*')) {
 		devfs_resolve_name_path(rule->name, name_buf, &path, &name);
 		len = strlen(name);
 		--len;