DragonFlyBSD Kernel Audit
DF-0009 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -1842,7 +1842,19 @@
 		vfsp = vfsconf_find_by_typenum(name[2]);
 		if (vfsp == NULL)
 			return (EOPNOTSUPP);
-		return (SYSCTL_OUT(req, vfsp, sizeof *vfsp));
+		/*
+		 * DF-0009: do not disclose kernel pointers (vfc_vfsops,
+		 * vfc_next) to unprivileged readers.  Preserve the struct
+		 * size/ABI; clear the pointer fields before copyout.
+		 */
+		{
+			struct vfsconf vfc_redacted;
+			vfc_redacted = *vfsp;
+			vfc_redacted.vfc_vfsops = NULL;
+			vfc_redacted.vfc_next.stqe_next = NULL;
+			return (SYSCTL_OUT(req, &vfc_redacted,
+			    sizeof(vfc_redacted)));
+		}
 	}
 	return (EOPNOTSUPP);
 }
@@ -1860,7 +1872,11 @@
 	struct sysctl_req *req = (struct sysctl_req*) data;
 
 	bzero(&ovfs, sizeof(ovfs));
-	ovfs.vfc_vfsops = vfsp->vfc_vfsops;	/* XXX used as flag */
+	/*
+	 * DF-0009: vfc_vfsops is a raw kernel pointer in struct ovfsconf too;
+	 * expose only a non-NULL "is-configured" flag rather than the address.
+	 */
+	ovfs.vfc_vfsops = (vfsp->vfc_vfsops != NULL) ? (void *)1 : NULL;
 	strcpy(ovfs.vfc_name, vfsp->vfc_name);
 	ovfs.vfc_index = vfsp->vfc_typenum;
 	ovfs.vfc_refcount = vfsp->vfc_refcount;