From: claudio Date: Thu, 12 Sep 2024 09:04:51 +0000 (+0000) Subject: Ensure that file names passed back by readdir do not include a '/' X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=46f7109a9e03df89b66ada65cf07c4da6ddb41a1;p=openbsd Ensure that file names passed back by readdir do not include a '/' character. The '/' char is the path separator and is not allowed in any filename. NFS specific report by Apple Security Engineering and Architecture (SEAR). Input from guenther@ and millert@ OK beck@ miod@ --- diff --git a/sys/isofs/cd9660/cd9660_vnops.c b/sys/isofs/cd9660/cd9660_vnops.c index 3ac15e3a21e..553060e2378 100644 --- a/sys/isofs/cd9660/cd9660_vnops.c +++ b/sys/isofs/cd9660/cd9660_vnops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cd9660_vnops.c,v 1.95 2023/09/08 20:00:28 mvs Exp $ */ +/* $OpenBSD: cd9660_vnops.c,v 1.96 2024/09/12 09:04:51 claudio Exp $ */ /* $NetBSD: cd9660_vnops.c,v 1.42 1997/10/16 23:56:57 christos Exp $ */ /*- @@ -317,6 +317,11 @@ iso_uiodir(struct isoreaddir *idp, struct dirent *dp, off_t off) 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); diff --git a/sys/isofs/udf/udf_vnops.c b/sys/isofs/udf/udf_vnops.c index c7ffaf58ef7..21440614f09 100644 --- a/sys/isofs/udf/udf_vnops.c +++ b/sys/isofs/udf/udf_vnops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: udf_vnops.c,v 1.72 2024/05/13 11:17:40 semarie Exp $ */ +/* $OpenBSD: udf_vnops.c,v 1.73 2024/09/12 09:04:51 claudio Exp $ */ /* * Copyright (c) 2001, 2002 Scott Long @@ -565,6 +565,12 @@ udf_uiodir(struct udf_uiodir *uiodir, struct uio *uio, long off) 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)); } diff --git a/sys/nfs/nfs_vnops.c b/sys/nfs/nfs_vnops.c index 1e307f33169..8dbf9f0f67f 100644 --- a/sys/nfs/nfs_vnops.c +++ b/sys/nfs/nfs_vnops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nfs_vnops.c,v 1.202 2024/09/11 12:22:34 claudio Exp $ */ +/* $OpenBSD: nfs_vnops.c,v 1.203 2024/09/12 09:04:51 claudio Exp $ */ /* $NetBSD: nfs_vnops.c,v 1.62.4.1 1996/07/08 20:26:52 jtc Exp $ */ /* @@ -2263,6 +2263,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; diff --git a/sys/ntfs/ntfs_vnops.c b/sys/ntfs/ntfs_vnops.c index ad9da143aa6..a523c602b32 100644 --- a/sys/ntfs/ntfs_vnops.c +++ b/sys/ntfs/ntfs_vnops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ntfs_vnops.c,v 1.49 2024/05/13 11:17:40 semarie Exp $ */ +/* $OpenBSD: ntfs_vnops.c,v 1.50 2024/09/12 09:04:51 claudio Exp $ */ /* $NetBSD: ntfs_vnops.c,v 1.6 2003/04/10 21:57:26 jdolecek Exp $ */ /* @@ -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); diff --git a/sys/tmpfs/tmpfs_subr.c b/sys/tmpfs/tmpfs_subr.c index 04d3e900fe6..70ea9baa9dc 100644 --- a/sys/tmpfs/tmpfs_subr.c +++ b/sys/tmpfs/tmpfs_subr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tmpfs_subr.c,v 1.26 2022/11/15 17:16:44 mvs Exp $ */ +/* $OpenBSD: tmpfs_subr.c,v 1.27 2024/09/12 09:04:51 claudio Exp $ */ /* $NetBSD: tmpfs_subr.c,v 1.79 2012/03/13 18:40:50 elad Exp $ */ /* @@ -820,6 +820,11 @@ tmpfs_dir_getdents(tmpfs_node_t *node, struct uio *uio) 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; diff --git a/sys/ufs/ext2fs/ext2fs_lookup.c b/sys/ufs/ext2fs/ext2fs_lookup.c index 36e182465c5..435f8c7c662 100644 --- a/sys/ufs/ext2fs/ext2fs_lookup.c +++ b/sys/ufs/ext2fs/ext2fs_lookup.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ext2fs_lookup.c,v 1.46 2022/01/11 03:13:59 jsg Exp $ */ +/* $OpenBSD: ext2fs_lookup.c,v 1.47 2024/09/12 09:04:51 claudio Exp $ */ /* $NetBSD: ext2fs_lookup.c,v 1.16 2000/08/03 20:29:26 thorpej Exp $ */ /* @@ -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; diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c index 098814a995a..289f745f55c 100644 --- a/sys/ufs/ufs/ufs_vnops.c +++ b/sys/ufs/ufs/ufs_vnops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ufs_vnops.c,v 1.162 2024/05/13 11:17:41 semarie Exp $ */ +/* $OpenBSD: ufs_vnops.c,v 1.163 2024/09/12 09:04:51 claudio Exp $ */ /* $NetBSD: ufs_vnops.c,v 1.18 1996/05/11 18:28:04 mycroft Exp $ */ /* @@ -1395,6 +1395,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); }