DragonFlyBSD Kernel Audit
DF-0866 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/vfs/isofs/cd9660/cd9660_vnops.c b/sys/vfs/isofs/cd9660/cd9660_vnops.c
--- a/sys/vfs/isofs/cd9660/cd9660_vnops.c
+++ b/sys/vfs/isofs/cd9660/cd9660_vnops.c
@@ -338,11 +338,27 @@
 int
 iso_uiodir(struct isoreaddir *idp, struct dirent *dp, off_t off)
 {
-	int error;
+	int error, recsz, padlen;
 
 	dp->d_name[dp->d_namlen] = 0;
+	/*
+	 * Zero the reserved fields and the trailing d_name padding
+	 * (between d_name[d_namlen+1] and the next 8-byte boundary)
+	 * so we do not leak kernel heap bytes from the kmalloc() in
+	 * cd9660_readdir() (which has no M_ZERO) nor residue from a
+	 * prior entry, since idp->current/saveent/assocent are reused
+	 * across directory entries within one readdir() call.
+	 * vop_write_dirent() achieves the same effect by allocating a
+	 * fresh M_ZERO dirent per entry.
+	 */
+	dp->d_unused1 = 0;
+	dp->d_unused2 = 0;
+	recsz = _DIRENT_DIRSIZ(dp);
+	padlen = recsz - (__offsetof(struct dirent, d_name) + dp->d_namlen + 1);
+	if (padlen > 0)
+		bzero(&dp->d_name[dp->d_namlen + 1], padlen);
 
-	if (idp->uio->uio_resid < _DIRENT_DIRSIZ(dp)) {
+	if (idp->uio->uio_resid < recsz) {
 		idp->eofflag = 0;
 		return (-1);
 	}
@@ -357,7 +373,7 @@
 		--idp->ncookies;
 	}
 
-	if ((error = uiomove((caddr_t) dp,_DIRENT_DIRSIZ(dp),idp->uio)) != 0)
+	if ((error = uiomove((caddr_t) dp, recsz, idp->uio)) != 0)
 		return (error);
 	idp->uio_off = off;
 	return (0);
@@ -444,7 +460,7 @@
 	if (error)
 		return (error);
 
-	idp = kmalloc(sizeof(*idp), M_TEMP, M_WAITOK);
+	idp = kmalloc(sizeof(*idp), M_TEMP, M_WAITOK | M_ZERO);
 	idp->saveent.de.d_namlen = idp->assocent.de.d_namlen = 0;
 	/*
 	 * XXX