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