svn commit: r340856 - in head/sys: cddl/contrib/opensolaris/uts/common/fs/zfs fs/autofs fs/cd9660 fs/devfs fs/ext2fs fs/fdescfs fs/fuse fs/msdosfs fs/nandfs fs/pseudofs fs/smbfs fs/tmpfs fs/udf ker...

Mark Johnston markj at FreeBSD.org
Fri Nov 23 22:25:04 UTC 2018


Author: markj
Date: Fri Nov 23 22:24:59 2018
New Revision: 340856
URL: https://svnweb.freebsd.org/changeset/base/340856

Log:
  Ensure that directory entry padding bytes are zeroed.
  
  Directory entries must be padded to maintain alignment; in many
  filesystems the padding was not initialized, resulting in stack
  memory being copied out to userspace.  With the ino64 work there
  are also some explicit pad fields in struct dirent.  Add a subroutine
  to clear these bytes and use it in the in-tree filesystems.  The
  NFS client is omitted for now as it was fixed separately in r340787.
  
  Reported by:	Thomas Barabosch, Fraunhofer FKIE
  Reviewed by:	kib
  MFC after:	3 days
  Sponsored by:	The FreeBSD Foundation

Modified:
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
  head/sys/fs/autofs/autofs_vnops.c
  head/sys/fs/cd9660/cd9660_vnops.c
  head/sys/fs/devfs/devfs_devs.c
  head/sys/fs/ext2fs/ext2_lookup.c
  head/sys/fs/fdescfs/fdesc_vnops.c
  head/sys/fs/fuse/fuse_internal.c
  head/sys/fs/msdosfs/msdosfs_vnops.c
  head/sys/fs/nandfs/nandfs_vnops.c
  head/sys/fs/pseudofs/pseudofs_vnops.c
  head/sys/fs/smbfs/smbfs_io.c
  head/sys/fs/tmpfs/tmpfs_subr.c
  head/sys/fs/tmpfs/tmpfs_vfsops.c
  head/sys/fs/tmpfs/tmpfs_vnops.c
  head/sys/fs/udf/udf_vnops.c
  head/sys/kern/uipc_mqueue.c
  head/sys/kern/vfs_export.c
  head/sys/sys/dirent.h
  head/sys/ufs/ufs/ufs_vnops.c

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c	Fri Nov 23 21:08:11 2018	(r340855)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c	Fri Nov 23 22:24:59 2018	(r340856)
@@ -262,9 +262,9 @@ sfs_readdir_common(uint64_t parent_id, uint64_t id, st
 		entry.d_fileno = id;
 		entry.d_type = DT_DIR;
 		entry.d_name[0] = '.';
-		entry.d_name[1] = '\0';
 		entry.d_namlen = 1;
 		entry.d_reclen = sizeof(entry);
+		dirent_terminate(&entry);
 		error = vfs_read_dirent(ap, &entry, uio->uio_offset);
 		if (error != 0)
 			return (SET_ERROR(error));
@@ -277,9 +277,9 @@ sfs_readdir_common(uint64_t parent_id, uint64_t id, st
 		entry.d_type = DT_DIR;
 		entry.d_name[0] = '.';
 		entry.d_name[1] = '.';
-		entry.d_name[2] = '\0';
 		entry.d_namlen = 2;
 		entry.d_reclen = sizeof(entry);
+		dirent_terminate(&entry);
 		error = vfs_read_dirent(ap, &entry, uio->uio_offset);
 		if (error != 0)
 			return (SET_ERROR(error));
@@ -694,6 +694,7 @@ zfsctl_root_readdir(ap)
 	strcpy(entry.d_name, node->snapdir->sn_name);
 	entry.d_namlen = strlen(entry.d_name);
 	entry.d_reclen = sizeof(entry);
+	dirent_terminate(&entry);
 	error = vfs_read_dirent(ap, &entry, uio->uio_offset);
 	if (error != 0) {
 		if (error == ENAMETOOLONG)
@@ -1099,6 +1100,7 @@ zfsctl_snapdir_readdir(ap)
 		entry.d_reclen = sizeof(entry);
 		/* NOTE: d_off is the offset for the *next* entry. */
 		entry.d_off = cookie + dots_offset;
+		dirent_terminate(&entry);
 		error = vfs_read_dirent(ap, &entry, uio->uio_offset);
 		if (error != 0) {
 			if (error == ENAMETOOLONG)

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c	Fri Nov 23 21:08:11 2018	(r340855)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c	Fri Nov 23 22:24:59 2018	(r340856)
@@ -2547,6 +2547,7 @@ zfs_readdir(vnode_t *vp, uio_t *uio, cred_t *cr, int *
 			next = &odp->d_off;
 			(void) strlcpy(odp->d_name, zap.za_name, odp->d_namlen + 1);
 			odp->d_type = type;
+			dirent_terminate(odp);
 			odp = (dirent64_t *)((intptr_t)odp + reclen);
 		}
 		outcount += reclen;

Modified: head/sys/fs/autofs/autofs_vnops.c
==============================================================================
--- head/sys/fs/autofs/autofs_vnops.c	Fri Nov 23 21:08:11 2018	(r340855)
+++ head/sys/fs/autofs/autofs_vnops.c	Fri Nov 23 22:24:59 2018	(r340856)
@@ -34,6 +34,7 @@
 __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
+#include <sys/systm.h>
 #include <sys/kernel.h>
 #include <sys/condvar.h>
 #include <sys/dirent.h>
@@ -44,7 +45,6 @@ __FBSDID("$FreeBSD$");
 #include <sys/namei.h>
 #include <sys/signalvar.h>
 #include <sys/stat.h>
-#include <sys/systm.h>
 #include <sys/taskqueue.h>
 #include <sys/tree.h>
 #include <sys/vnode.h>
@@ -354,14 +354,11 @@ autofs_readdir_one(struct uio *uio, const char *name, 
     size_t *reclenp)
 {
 	struct dirent dirent;
-	size_t namlen, padded_namlen, reclen;
+	size_t namlen, reclen;
 	int error;
 
 	namlen = strlen(name);
-	padded_namlen = roundup2(namlen + 1, __alignof(struct dirent));
-	KASSERT(padded_namlen <= MAXNAMLEN, ("%zd > MAXNAMLEN", padded_namlen));
-	reclen = offsetof(struct dirent, d_name) + padded_namlen;
-
+	reclen = _GENERIC_DIRLEN(namlen);
 	if (reclenp != NULL)
 		*reclenp = reclen;
 
@@ -376,7 +373,7 @@ autofs_readdir_one(struct uio *uio, const char *name, 
 	dirent.d_type = DT_DIR;
 	dirent.d_namlen = namlen;
 	memcpy(dirent.d_name, name, namlen);
-	memset(dirent.d_name + namlen, 0, padded_namlen - namlen);
+	dirent_terminate(&dirent);
 	error = uiomove(&dirent, reclen, uio);
 
 	return (error);

Modified: head/sys/fs/cd9660/cd9660_vnops.c
==============================================================================
--- head/sys/fs/cd9660/cd9660_vnops.c	Fri Nov 23 21:08:11 2018	(r340855)
+++ head/sys/fs/cd9660/cd9660_vnops.c	Fri Nov 23 22:24:59 2018	(r340856)
@@ -380,8 +380,8 @@ iso_uiodir(idp,dp,off)
 {
 	int error;
 
-	dp->d_name[dp->d_namlen] = 0;
 	dp->d_reclen = GENERIC_DIRSIZ(dp);
+	dirent_terminate(dp);
 
 	if (idp->uio->uio_resid < dp->d_reclen) {
 		idp->eofflag = 0;

Modified: head/sys/fs/devfs/devfs_devs.c
==============================================================================
--- head/sys/fs/devfs/devfs_devs.c	Fri Nov 23 21:08:11 2018	(r340855)
+++ head/sys/fs/devfs/devfs_devs.c	Fri Nov 23 22:24:59 2018	(r340856)
@@ -226,7 +226,7 @@ devfs_newdirent(char *name, int namelen)
 	de->de_dirent->d_namlen = namelen;
 	de->de_dirent->d_reclen = GENERIC_DIRSIZ(&d);
 	bcopy(name, de->de_dirent->d_name, namelen);
-	de->de_dirent->d_name[namelen] = '\0';
+	dirent_terminate(de->de_dirent);
 	vfs_timestamp(&de->de_ctime);
 	de->de_mtime = de->de_atime = de->de_ctime;
 	de->de_links = 1;

Modified: head/sys/fs/ext2fs/ext2_lookup.c
==============================================================================
--- head/sys/fs/ext2fs/ext2_lookup.c	Fri Nov 23 21:08:11 2018	(r340855)
+++ head/sys/fs/ext2fs/ext2_lookup.c	Fri Nov 23 22:24:59 2018	(r340856)
@@ -223,9 +223,9 @@ ext2_readdir(struct vop_readdir_args *ap)
 			dstdp.d_fileno = dp->e2d_ino;
 			dstdp.d_reclen = GENERIC_DIRSIZ(&dstdp);
 			bcopy(dp->e2d_name, dstdp.d_name, dstdp.d_namlen);
-			dstdp.d_name[dstdp.d_namlen] = '\0';
 			/* NOTE: d_off is the offset of the *next* entry. */
 			dstdp.d_off = offset + dp->e2d_reclen;
+			dirent_terminate(&dstdp);
 			if (dstdp.d_reclen > uio->uio_resid) {
 				if (uio->uio_resid == startresid)
 					error = EINVAL;

Modified: head/sys/fs/fdescfs/fdesc_vnops.c
==============================================================================
--- head/sys/fs/fdescfs/fdesc_vnops.c	Fri Nov 23 21:08:11 2018	(r340855)
+++ head/sys/fs/fdescfs/fdesc_vnops.c	Fri Nov 23 22:24:59 2018	(r340856)
@@ -561,8 +561,8 @@ fdesc_readdir(struct vop_readdir_args *ap)
 			dp->d_namlen = i + 1;
 			dp->d_reclen = UIO_MX;
 			bcopy("..", dp->d_name, dp->d_namlen);
-			dp->d_name[i + 1] = '\0';
 			dp->d_type = DT_DIR;
+			dirent_terminate(dp);
 			break;
 		default:
 			if (fdp->fd_ofiles[fcnt].fde_file == NULL)
@@ -572,6 +572,7 @@ fdesc_readdir(struct vop_readdir_args *ap)
 			dp->d_type = (fmp->flags & FMNT_LINRDLNKF) == 0 ?
 			    DT_CHR : DT_LNK;
 			dp->d_fileno = i + FD_DESC;
+			dirent_terminate(dp);
 			break;
 		}
 		/* NOTE: d_off is the offset of the *next* entry. */

Modified: head/sys/fs/fuse/fuse_internal.c
==============================================================================
--- head/sys/fs/fuse/fuse_internal.c	Fri Nov 23 21:08:11 2018	(r340855)
+++ head/sys/fs/fuse/fuse_internal.c	Fri Nov 23 22:24:59 2018	(r340856)
@@ -357,7 +357,7 @@ fuse_internal_readdir_processdata(struct uio *uio,
 		memcpy((char *)cookediov->base + sizeof(struct dirent) - 
 		       MAXNAMLEN - 1,
 		       (char *)buf + FUSE_NAME_OFFSET, fudge->namelen);
-		((char *)cookediov->base)[bytesavail - 1] = '\0';
+		dirent_terminate(de);
 
 		err = uiomove(cookediov->base, cookediov->len, uio);
 		if (err) {

Modified: head/sys/fs/msdosfs/msdosfs_vnops.c
==============================================================================
--- head/sys/fs/msdosfs/msdosfs_vnops.c	Fri Nov 23 21:08:11 2018	(r340855)
+++ head/sys/fs/msdosfs/msdosfs_vnops.c	Fri Nov 23 22:24:59 2018	(r340856)
@@ -1550,16 +1550,18 @@ msdosfs_readdir(struct vop_readdir_args *ap)
 				switch (n) {
 				case 0:
 					dirbuf.d_namlen = 1;
-					strcpy(dirbuf.d_name, ".");
+					dirbuf.d_name[0] = '.';
 					break;
 				case 1:
 					dirbuf.d_namlen = 2;
-					strcpy(dirbuf.d_name, "..");
+					dirbuf.d_name[0] = '.';
+					dirbuf.d_name[1] = '.';
 					break;
 				}
 				dirbuf.d_reclen = GENERIC_DIRSIZ(&dirbuf);
 				/* NOTE: d_off is the offset of the *next* entry. */
 				dirbuf.d_off = offset + sizeof(struct direntry);
+				dirent_terminate(&dirbuf);
 				if (uio->uio_resid < dirbuf.d_reclen)
 					goto out;
 				error = uiomove(&dirbuf, dirbuf.d_reclen, uio);

Modified: head/sys/fs/nandfs/nandfs_vnops.c
==============================================================================
--- head/sys/fs/nandfs/nandfs_vnops.c	Fri Nov 23 21:08:11 2018	(r340855)
+++ head/sys/fs/nandfs/nandfs_vnops.c	Fri Nov 23 22:24:59 2018	(r340856)
@@ -1226,7 +1226,6 @@ nandfs_readdir(struct vop_readdir_args *ap)
 			ndirent = (struct nandfs_dir_entry *)pos;
 
 			name_len = ndirent->name_len;
-			memset(&dirent, 0, sizeof(struct dirent));
 			dirent.d_fileno = ndirent->inode;
 			if (dirent.d_fileno) {
 				dirent.d_type = ndirent->file_type;
@@ -1235,6 +1234,7 @@ nandfs_readdir(struct vop_readdir_args *ap)
 				dirent.d_reclen = GENERIC_DIRSIZ(&dirent);
 				/* NOTE: d_off is the offset of the *next* entry. */
 				dirent.d_off = diroffset + ndirent->rec_len;
+				dirent_terminate(&dirent);
 				DPRINTF(READDIR, ("copying `%*.*s`\n", name_len,
 				    name_len, dirent.d_name));
 			}
@@ -1243,12 +1243,12 @@ nandfs_readdir(struct vop_readdir_args *ap)
 			 * If there isn't enough space in the uio to return a
 			 * whole dirent, break off read
 			 */
-			if (uio->uio_resid < GENERIC_DIRSIZ(&dirent))
+			if (uio->uio_resid < dirent.d_reclen)
 				break;
 
 			/* Transfer */
 			if (dirent.d_fileno)
-				uiomove(&dirent, GENERIC_DIRSIZ(&dirent), uio);
+				uiomove(&dirent, dirent.d_reclen, uio);
 
 			/* Advance */
 			diroffset += ndirent->rec_len;

Modified: head/sys/fs/pseudofs/pseudofs_vnops.c
==============================================================================
--- head/sys/fs/pseudofs/pseudofs_vnops.c	Fri Nov 23 21:08:11 2018	(r340855)
+++ head/sys/fs/pseudofs/pseudofs_vnops.c	Fri Nov 23 22:24:59 2018	(r340856)
@@ -828,7 +828,6 @@ pfs_readdir(struct vop_readdir_args *va)
 		/* PFS_DELEN was picked to fit PFS_NAMLEN */
 		for (i = 0; i < PFS_NAMELEN - 1 && pn->pn_name[i] != '\0'; ++i)
 			pfsent->entry.d_name[i] = pn->pn_name[i];
-		pfsent->entry.d_name[i] = 0;
 		pfsent->entry.d_namlen = i;
 		/* NOTE: d_off is the offset of the *next* entry. */
 		pfsent->entry.d_off = offset + PFS_DELEN;
@@ -855,6 +854,7 @@ pfs_readdir(struct vop_readdir_args *va)
 			panic("%s has unexpected node type: %d", pn->pn_name, pn->pn_type);
 		}
 		PFS_TRACE(("%s", pfsent->entry.d_name));
+		dirent_terminate(&pfsent->entry);
 		STAILQ_INSERT_TAIL(&lst, pfsent, link);
 		offset += PFS_DELEN;
 		resid -= PFS_DELEN;

Modified: head/sys/fs/smbfs/smbfs_io.c
==============================================================================
--- head/sys/fs/smbfs/smbfs_io.c	Fri Nov 23 21:08:11 2018	(r340855)
+++ head/sys/fs/smbfs/smbfs_io.c	Fri Nov 23 22:24:59 2018	(r340856)
@@ -106,8 +106,8 @@ smbfs_readvdir(struct vnode *vp, struct uio *uio, stru
 		de.d_namlen = offset + 1;
 		de.d_name[0] = '.';
 		de.d_name[1] = '.';
-		de.d_name[offset + 1] = '\0';
 		de.d_type = DT_DIR;
+		dirent_terminate(&de);
 		error = uiomove(&de, DE_SIZE, uio);
 		if (error)
 			goto out;
@@ -156,7 +156,7 @@ smbfs_readvdir(struct vnode *vp, struct uio *uio, stru
 		de.d_type = (ctx->f_attr.fa_attr & SMB_FA_DIR) ? DT_DIR : DT_REG;
 		de.d_namlen = ctx->f_nmlen;
 		bcopy(ctx->f_name, de.d_name, de.d_namlen);
-		de.d_name[de.d_namlen] = '\0';
+		dirent_terminate(&de);
 		if (smbfs_fastlookup) {
 			error = smbfs_nget(vp->v_mount, vp, ctx->f_name,
 			    ctx->f_nmlen, &ctx->f_attr, &newvp);

Modified: head/sys/fs/tmpfs/tmpfs_subr.c
==============================================================================
--- head/sys/fs/tmpfs/tmpfs_subr.c	Fri Nov 23 21:08:11 2018	(r340855)
+++ head/sys/fs/tmpfs/tmpfs_subr.c	Fri Nov 23 22:24:59 2018	(r340856)
@@ -39,6 +39,7 @@
 __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
+#include <sys/systm.h>
 #include <sys/dirent.h>
 #include <sys/fnv_hash.h>
 #include <sys/lock.h>
@@ -50,7 +51,6 @@ __FBSDID("$FreeBSD$");
 #include <sys/random.h>
 #include <sys/rwlock.h>
 #include <sys/stat.h>
-#include <sys/systm.h>
 #include <sys/sysctl.h>
 #include <sys/vnode.h>
 #include <sys/vmmeter.h>
@@ -1120,8 +1120,8 @@ tmpfs_dir_getdotdent(struct tmpfs_node *node, struct u
 	dent.d_type = DT_DIR;
 	dent.d_namlen = 1;
 	dent.d_name[0] = '.';
-	dent.d_name[1] = '\0';
 	dent.d_reclen = GENERIC_DIRSIZ(&dent);
+	dirent_terminate(&dent);
 
 	if (dent.d_reclen > uio->uio_resid)
 		error = EJUSTRETURN;
@@ -1164,8 +1164,8 @@ tmpfs_dir_getdotdotdent(struct tmpfs_node *node, struc
 	dent.d_namlen = 2;
 	dent.d_name[0] = '.';
 	dent.d_name[1] = '.';
-	dent.d_name[2] = '\0';
 	dent.d_reclen = GENERIC_DIRSIZ(&dent);
+	dirent_terminate(&dent);
 
 	if (dent.d_reclen > uio->uio_resid)
 		error = EJUSTRETURN;
@@ -1285,8 +1285,8 @@ tmpfs_dir_getdents(struct tmpfs_node *node, struct uio
 		d.d_namlen = de->td_namelen;
 		MPASS(de->td_namelen < sizeof(d.d_name));
 		(void)memcpy(d.d_name, de->ud.td_name, de->td_namelen);
-		d.d_name[de->td_namelen] = '\0';
 		d.d_reclen = GENERIC_DIRSIZ(&d);
+		dirent_terminate(&d);
 
 		/* Stop reading if the directory entry we are treating is
 		 * bigger than the amount of data that can be returned. */

Modified: head/sys/fs/tmpfs/tmpfs_vfsops.c
==============================================================================
--- head/sys/fs/tmpfs/tmpfs_vfsops.c	Fri Nov 23 21:08:11 2018	(r340855)
+++ head/sys/fs/tmpfs/tmpfs_vfsops.c	Fri Nov 23 22:24:59 2018	(r340856)
@@ -46,6 +46,7 @@
 __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
+#include <sys/systm.h>
 #include <sys/dirent.h>
 #include <sys/limits.h>
 #include <sys/lock.h>
@@ -56,7 +57,6 @@ __FBSDID("$FreeBSD$");
 #include <sys/kernel.h>
 #include <sys/rwlock.h>
 #include <sys/stat.h>
-#include <sys/systm.h>
 #include <sys/sysctl.h>
 #include <sys/vnode.h>
 

Modified: head/sys/fs/tmpfs/tmpfs_vnops.c
==============================================================================
--- head/sys/fs/tmpfs/tmpfs_vnops.c	Fri Nov 23 21:08:11 2018	(r340855)
+++ head/sys/fs/tmpfs/tmpfs_vnops.c	Fri Nov 23 22:24:59 2018	(r340856)
@@ -39,6 +39,7 @@
 __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
+#include <sys/systm.h>
 #include <sys/dirent.h>
 #include <sys/fcntl.h>
 #include <sys/limits.h>
@@ -51,7 +52,6 @@ __FBSDID("$FreeBSD$");
 #include <sys/rwlock.h>
 #include <sys/sched.h>
 #include <sys/stat.h>
-#include <sys/systm.h>
 #include <sys/sysctl.h>
 #include <sys/unistd.h>
 #include <sys/vnode.h>

Modified: head/sys/fs/udf/udf_vnops.c
==============================================================================
--- head/sys/fs/udf/udf_vnops.c	Fri Nov 23 21:08:11 2018	(r340855)
+++ head/sys/fs/udf/udf_vnops.c	Fri Nov 23 22:24:59 2018	(r340856)
@@ -843,10 +843,10 @@ udf_readdir(struct vop_readdir_args *a)
 			dir.d_fileno = node->hash_id;
 			dir.d_type = DT_DIR;
 			dir.d_name[0] = '.';
-			dir.d_name[1] = '\0';
 			dir.d_namlen = 1;
 			dir.d_reclen = GENERIC_DIRSIZ(&dir);
 			dir.d_off = 1;
+			dirent_terminate(&dir);
 			uiodir.dirent = &dir;
 			error = udf_uiodir(&uiodir, dir.d_reclen, uio, 1);
 			if (error)
@@ -856,10 +856,10 @@ udf_readdir(struct vop_readdir_args *a)
 			dir.d_type = DT_DIR;
 			dir.d_name[0] = '.';
 			dir.d_name[1] = '.';
-			dir.d_name[2] = '\0';
 			dir.d_namlen = 2;
 			dir.d_reclen = GENERIC_DIRSIZ(&dir);
 			dir.d_off = 2;
+			dirent_terminate(&dir);
 			uiodir.dirent = &dir;
 			error = udf_uiodir(&uiodir, dir.d_reclen, uio, 2);
 		} else {
@@ -870,6 +870,7 @@ udf_readdir(struct vop_readdir_args *a)
 			    DT_DIR : DT_UNKNOWN;
 			dir.d_reclen = GENERIC_DIRSIZ(&dir);
 			dir.d_off = ds->this_off;
+			dirent_terminate(&dir);
 			uiodir.dirent = &dir;
 			error = udf_uiodir(&uiodir, dir.d_reclen, uio,
 			    ds->this_off);

Modified: head/sys/kern/uipc_mqueue.c
==============================================================================
--- head/sys/kern/uipc_mqueue.c	Fri Nov 23 21:08:11 2018	(r340855)
+++ head/sys/kern/uipc_mqueue.c	Fri Nov 23 22:24:59 2018	(r340856)
@@ -1428,7 +1428,6 @@ mqfs_readdir(struct vop_readdir_args *ap)
 		entry.d_fileno = pn->mn_fileno;
 		for (i = 0; i < MQFS_NAMELEN - 1 && pn->mn_name[i] != '\0'; ++i)
 			entry.d_name[i] = pn->mn_name[i];
-		entry.d_name[i] = 0;
 		entry.d_namlen = i;
 		switch (pn->mn_type) {
 		case mqfstype_root:
@@ -1447,6 +1446,7 @@ mqfs_readdir(struct vop_readdir_args *ap)
 			panic("%s has unexpected node type: %d", pn->mn_name,
 				pn->mn_type);
 		}
+		dirent_terminate(&entry);
 		if (entry.d_reclen > uio->uio_resid)
                         break;
 		if (offset >= uio->uio_offset) {

Modified: head/sys/kern/vfs_export.c
==============================================================================
--- head/sys/kern/vfs_export.c	Fri Nov 23 21:08:11 2018	(r340855)
+++ head/sys/kern/vfs_export.c	Fri Nov 23 22:24:59 2018	(r340856)
@@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$");
 #include "opt_inet6.h"
 
 #include <sys/param.h>
+#include <sys/systm.h>
 #include <sys/dirent.h>
 #include <sys/jail.h>
 #include <sys/kernel.h>
@@ -55,7 +56,6 @@ __FBSDID("$FreeBSD$");
 #include <sys/refcount.h>
 #include <sys/signalvar.h>
 #include <sys/socket.h>
-#include <sys/systm.h>
 #include <sys/vnode.h>
 
 #include <netinet/in.h>

Modified: head/sys/sys/dirent.h
==============================================================================
--- head/sys/sys/dirent.h	Fri Nov 23 21:08:11 2018	(r340855)
+++ head/sys/sys/dirent.h	Fri Nov 23 22:24:59 2018	(r340856)
@@ -126,6 +126,19 @@ struct freebsd11_dirent {
 
 #ifdef _KERNEL
 #define	GENERIC_DIRSIZ(dp)	_GENERIC_DIRSIZ(dp)
+
+/*
+ * Ensure that padding bytes are zeroed and that the name is NUL-terminated.
+ */
+static inline void
+dirent_terminate(struct dirent *dp)
+{
+
+	dp->d_pad0 = 0;
+	dp->d_pad1 = 0;
+	memset(dp->d_name + dp->d_namlen, 0,
+	    dp->d_reclen - (__offsetof(struct dirent, d_name) + dp->d_namlen));
+}
 #endif
 
 #endif /* !_SYS_DIRENT_H_ */

Modified: head/sys/ufs/ufs/ufs_vnops.c
==============================================================================
--- head/sys/ufs/ufs/ufs_vnops.c	Fri Nov 23 21:08:11 2018	(r340855)
+++ head/sys/ufs/ufs/ufs_vnops.c	Fri Nov 23 22:24:59 2018	(r340856)
@@ -2217,9 +2217,9 @@ ufs_readdir(ap)
 			dstdp.d_fileno = dp->d_ino;
 			dstdp.d_reclen = GENERIC_DIRSIZ(&dstdp);
 			bcopy(dp->d_name, dstdp.d_name, dstdp.d_namlen);
-			dstdp.d_name[dstdp.d_namlen] = '\0';
 			/* NOTE: d_off is the offset of the *next* entry. */
 			dstdp.d_off = offset + dp->d_reclen;
+			dirent_terminate(&dstdp);
 			if (dstdp.d_reclen > uio->uio_resid) {
 				if (uio->uio_resid == startresid)
 					error = EINVAL;


More information about the svn-src-all mailing list