untrusted comment: verify with openbsd-75-base.pub
RWRGj1pRpprAfpd9ovli7/bzDrZB0aIvCbHHcGfRAta9tmqBVIlIq88UiniWW/iAgUVMIJ0evCjmAtWdktuDfkJFyP3lI4HyZQ0=
OpenBSD 7.5 errata 009, 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-75-base.pub -x 009_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:06:06 -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:06:07 -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:06:07 -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:06:07 -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:06:06 -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:06:07 -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:06:07 -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:06:07 -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.160 ufs_vnops.c
--- sys/ufs/ufs/ufs_vnops.c 3 Feb 2024 18:51:59 -0000 1.160
+++ sys/ufs/ufs/ufs_vnops.c 14 Sep 2024 22:06:07 -0000
@@ -1410,6 +1410,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);
}