untrusted comment: verify with openbsd-74-base.pub RWRoyQmAD08ajahR912Ly8Gpc8REyRBZWcYwvXU9BKci7FXaGX5r85kpnRU2mZ3oLBH4cL8gCryHycgA5tW2x560lGma+Cv44AI= OpenBSD 7.4 errata 022, September 17, 2024: In readdir name validation exclude any '/' to avoid unexpected directory traversal on untrusted file systems. Apply by doing: signify -Vep /etc/signify/openbsd-74-base.pub -x 022_readdir.patch.sig \ -m - | (cd /usr/src && patch -p0) And then rebuild and install a new kernel: KK=`sysctl -n kern.osversion | cut -d# -f1` cd /usr/src/sys/arch/`machine`/compile/$KK make obj make config make make install Index: sys/isofs/cd9660/cd9660_vnops.c =================================================================== RCS file: /cvs/src/sys/isofs/cd9660/cd9660_vnops.c,v diff -u -p -r1.95 cd9660_vnops.c --- sys/isofs/cd9660/cd9660_vnops.c 8 Sep 2023 20:00:28 -0000 1.95 +++ sys/isofs/cd9660/cd9660_vnops.c 14 Sep 2024 22:07:34 -0000 @@ -317,6 +317,11 @@ iso_uiodir(struct isoreaddir *idp, struc dp->d_name[dp->d_namlen] = 0; dp->d_reclen = DIRENT_SIZE(dp); + if (memchr(dp->d_name, '/', dp->d_namlen) != NULL) { + /* illegal file name */ + return (EINVAL); + } + if (idp->uio->uio_resid < dp->d_reclen) { idp->eofflag = 0; return (-1); Index: sys/isofs/udf/udf_vnops.c =================================================================== RCS file: /cvs/src/sys/isofs/udf/udf_vnops.c,v diff -u -p -r1.70 udf_vnops.c --- sys/isofs/udf/udf_vnops.c 13 Apr 2023 02:19:05 -0000 1.70 +++ sys/isofs/udf/udf_vnops.c 14 Sep 2024 22:07:35 -0000 @@ -548,6 +548,12 @@ udf_uiodir(struct udf_uiodir *uiodir, st uiodir->dirent->d_off = off; uiodir->dirent->d_reclen = de_size; + if (memchr(uiodir->dirent->d_name, '/', + uiodir->dirent->d_namlen) != NULL) { + /* illegal file name */ + return (EINVAL); + } + return (uiomove(uiodir->dirent, de_size, uio)); } Index: sys/miscfs/fuse/fuse_vnops.c =================================================================== RCS file: /cvs/src/sys/miscfs/fuse/fuse_vnops.c,v diff -u -p -r1.67 fuse_vnops.c --- sys/miscfs/fuse/fuse_vnops.c 8 Sep 2023 20:00:28 -0000 1.67 +++ sys/miscfs/fuse/fuse_vnops.c 14 Sep 2024 22:07:35 -0000 @@ -762,6 +762,8 @@ fusefs_readdir(void *v) struct fusefs_node *ip; struct fusefs_mnt *fmp; struct fusebuf *fbuf; + struct dirent *dp; + char *edp; struct vnode *vp; struct proc *p; struct uio *uio; @@ -812,6 +814,35 @@ fusefs_readdir(void *v) /* ack end of readdir */ if (fbuf->fb_len == 0) { eofflag = 1; + fb_delete(fbuf); + break; + } + + /* validate the returned dirents */ + dp = (struct dirent *)fbuf->fb_dat; + edp = fbuf->fb_dat + fbuf->fb_len; + while ((char *)dp < edp) { + if ((char *)dp + offsetof(struct dirent, d_name) >= edp + || dp->d_reclen <= offsetof(struct dirent, d_name) + || (char *)dp + dp->d_reclen > edp) { + error = EINVAL; + break; + } + if (dp->d_namlen + offsetof(struct dirent, d_name) >= + dp->d_reclen) { + error = EINVAL; + break; + } + memset(dp->d_name + dp->d_namlen, 0, dp->d_reclen - + dp->d_namlen - offsetof(struct dirent, d_name)); + + if (memchr(dp->d_name, '/', dp->d_namlen) != NULL) { + error = EINVAL; + break; + } + dp = (struct dirent *)((char *)dp + dp->d_reclen); + } + if (error) { fb_delete(fbuf); break; } Index: sys/msdosfs/msdosfs_conv.c =================================================================== RCS file: /cvs/src/sys/msdosfs/msdosfs_conv.c,v diff -u -p -r1.20 msdosfs_conv.c --- sys/msdosfs/msdosfs_conv.c 4 Sep 2019 14:40:22 -0000 1.20 +++ sys/msdosfs/msdosfs_conv.c 14 Sep 2024 22:07:35 -0000 @@ -274,7 +274,7 @@ dos2unix[256] = { 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, /* 10-17 */ 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, /* 18-1f */ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 20-27 */ - 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 28-2f */ + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x3f, /* 28-2f */ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 30-37 */ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 38-3f */ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 40-47 */ @@ -310,7 +310,7 @@ u2l[256] = { 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 10-17 */ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 18-1f */ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 20-27 */ - 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 28-2f */ + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x3f, /* 28-2f */ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 30-37 */ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 38-3f */ 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 40-47 */ Index: sys/nfs/nfs_vnops.c =================================================================== RCS file: /cvs/src/sys/nfs/nfs_vnops.c,v diff -u -p -r1.193 nfs_vnops.c --- sys/nfs/nfs_vnops.c 26 Apr 2023 10:00:37 -0000 1.193 +++ sys/nfs/nfs_vnops.c 14 Sep 2024 22:07:34 -0000 @@ -2116,6 +2116,11 @@ nfs_readdir(void *v) dp->d_reclen -= NFS_DIRENT_OVERHEAD; dp->d_off = fxdr_hyper(&ndp->cookie[0]); + if (memchr(dp->d_name, '/', dp->d_namlen) != NULL) { + error = EBADRPC; + break; + } + if (uio->uio_resid < dp->d_reclen) { eof = 0; done = 1; Index: sys/ntfs/ntfs_vnops.c =================================================================== RCS file: /cvs/src/sys/ntfs/ntfs_vnops.c,v diff -u -p -r1.47 ntfs_vnops.c --- sys/ntfs/ntfs_vnops.c 15 Oct 2021 06:30:06 -0000 1.47 +++ sys/ntfs/ntfs_vnops.c 14 Sep 2024 22:07:35 -0000 @@ -489,6 +489,10 @@ ntfs_readdir(void *v) "flag: %u, ", num, cde.d_name, iep->ie_fnametype, iep->ie_flag); cde.d_namlen = fname - (char *) cde.d_name; + if (memchr(cde.d_name, '/', cde.d_namlen) != NULL) { + error = EINVAL; + goto out; + } cde.d_fileno = iep->ie_number; cde.d_type = (iep->ie_fflag & NTFS_FFLAG_DIR) ? DT_DIR : DT_REG; cde.d_reclen = sizeof(struct dirent); Index: sys/tmpfs/tmpfs_subr.c =================================================================== RCS file: /cvs/src/sys/tmpfs/tmpfs_subr.c,v diff -u -p -r1.26 tmpfs_subr.c --- sys/tmpfs/tmpfs_subr.c 15 Nov 2022 17:16:44 -0000 1.26 +++ sys/tmpfs/tmpfs_subr.c 14 Sep 2024 22:07:36 -0000 @@ -820,6 +820,11 @@ tmpfs_dir_getdents(tmpfs_node_t *node, s dent.d_name[de->td_namelen] = '\0'; dent.d_reclen = DIRENT_SIZE(&dent); + if (memchr(dent.d_name, '/', dent.d_namlen) != NULL) { + error = EINVAL; + break; + } + next_de = TAILQ_NEXT(de, td_entries); if (next_de == NULL) dent.d_off = TMPFS_DIRSEQ_EOF; Index: sys/ufs/ext2fs/ext2fs_lookup.c =================================================================== RCS file: /cvs/src/sys/ufs/ext2fs/ext2fs_lookup.c,v diff -u -p -r1.46 ext2fs_lookup.c --- sys/ufs/ext2fs/ext2fs_lookup.c 11 Jan 2022 03:13:59 -0000 1.46 +++ sys/ufs/ext2fs/ext2fs_lookup.c 14 Sep 2024 22:07:36 -0000 @@ -173,7 +173,11 @@ ext2fs_readdir(void *v) break; } ext2fs_dirconv2ffs(dp, &dstd); - if(dstd.d_reclen > uio->uio_resid) { + if (memchr(dstd.d_name, '/', dstd.d_namlen) != NULL) { + error = EINVAL; + break; + } + if (dstd.d_reclen > uio->uio_resid) { break; } dstd.d_off = off + e2d_reclen; Index: sys/ufs/ufs/ufs_vnops.c =================================================================== RCS file: /cvs/src/sys/ufs/ufs/ufs_vnops.c,v diff -u -p -r1.158 ufs_vnops.c --- sys/ufs/ufs/ufs_vnops.c 8 Sep 2023 20:00:28 -0000 1.158 +++ sys/ufs/ufs/ufs_vnops.c 14 Sep 2024 22:07:36 -0000 @@ -1482,6 +1482,11 @@ ufs_readdir(void *v) memset(u.dn.d_name + u.dn.d_namlen, 0, u.dn.d_reclen - u.dn.d_namlen - offsetof(struct dirent, d_name)); + if (memchr(u.dn.d_name, '/', u.dn.d_namlen) != NULL) { + error = EINVAL; + break; + } + error = uiomove(&u.dn, u.dn.d_reclen, uio); dp = (struct direct *)((char *)dp + dp->d_reclen); }