From owner-dev-commits-src-all@freebsd.org Fri Jan 29 01:19:50 2021 Return-Path: Delivered-To: dev-commits-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 78AA44F416C for ; Fri, 29 Jan 2021 01:19:50 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4DRfdb1bDzz3HJ2; Fri, 29 Jan 2021 01:19:46 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id D91311A008; Fri, 29 Jan 2021 01:19:45 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 10T1JjUU058899; Fri, 29 Jan 2021 01:19:45 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 10T1Jju6058898; Fri, 29 Jan 2021 01:19:45 GMT (envelope-from git) Date: Fri, 29 Jan 2021 01:19:45 GMT Message-Id: <202101290119.10T1Jju6058898@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org From: Ed Maste Subject: git: 6bddcd7682b1 - releng/12.2 - Ensure that dirent's d_off field is initialized MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: emaste X-Git-Repository: src X-Git-Refname: refs/heads/releng/12.2 X-Git-Reftype: branch X-Git-Commit: 6bddcd7682b1ac90f01134c7ffa3f9ed023b1338 Auto-Submitted: auto-generated X-BeenThere: dev-commits-src-all@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Commit messages for all branches of the src repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 29 Jan 2021 01:19:50 -0000 The branch releng/12.2 has been updated by emaste: URL: https://cgit.FreeBSD.org/src/commit/?id=6bddcd7682b1ac90f01134c7ffa3f9ed023b1338 commit 6bddcd7682b1ac90f01134c7ffa3f9ed023b1338 Author: Mark Johnston AuthorDate: 2021-01-03 16:32:30 +0000 Commit: Ed Maste CommitDate: 2021-01-29 01:14:58 +0000 Ensure that dirent's d_off field is initialized We have the d_off field in struct dirent for providing the seek offset of the next directory entry. Several filesystems were not initializing the field, which ends up being copied out to userland. Reported by: Syed Faraz Abrar Reviewed by: kib (cherry picked from commit 90f580b954090e669da234f6c8e8d0379ff9d8bc) (cherry picked from commit acaac0eefa1f2675dfc49faa077e3fb10949d540) Approved by: so Security: CVE-2020-25578 --- sys/fs/autofs/autofs_vnops.c | 1 + sys/fs/smbfs/smbfs_io.c | 2 ++ sys/fs/tmpfs/tmpfs_subr.c | 50 ++++++++++++++++++++++++++++---------------- sys/kern/uipc_mqueue.c | 1 + 4 files changed, 36 insertions(+), 18 deletions(-) diff --git a/sys/fs/autofs/autofs_vnops.c b/sys/fs/autofs/autofs_vnops.c index 09d77b9fccf8..ac5886f96054 100644 --- a/sys/fs/autofs/autofs_vnops.c +++ b/sys/fs/autofs/autofs_vnops.c @@ -369,6 +369,7 @@ autofs_readdir_one(struct uio *uio, const char *name, int fileno, return (EINVAL); dirent.d_fileno = fileno; + dirent.d_off = uio->uio_offset + reclen; dirent.d_reclen = reclen; dirent.d_type = DT_DIR; dirent.d_namlen = namlen; diff --git a/sys/fs/smbfs/smbfs_io.c b/sys/fs/smbfs/smbfs_io.c index 790538d7ce8b..78a11309edc3 100644 --- a/sys/fs/smbfs/smbfs_io.c +++ b/sys/fs/smbfs/smbfs_io.c @@ -103,6 +103,7 @@ smbfs_readvdir(struct vnode *vp, struct uio *uio, struct ucred *cred) (np->n_parent ? np->n_parentino : 2); if (de.d_fileno == 0) de.d_fileno = 0x7ffffffd + offset; + de.d_off = offset + 1; de.d_namlen = offset + 1; de.d_name[0] = '.'; de.d_name[1] = '.'; @@ -153,6 +154,7 @@ smbfs_readvdir(struct vnode *vp, struct uio *uio, struct ucred *cred) bzero((caddr_t)&de, DE_SIZE); de.d_reclen = DE_SIZE; de.d_fileno = ctx->f_attr.fa_ino; + de.d_off = offset + 1; 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); diff --git a/sys/fs/tmpfs/tmpfs_subr.c b/sys/fs/tmpfs/tmpfs_subr.c index f03537640e32..2e035ed8d7f1 100644 --- a/sys/fs/tmpfs/tmpfs_subr.c +++ b/sys/fs/tmpfs/tmpfs_subr.c @@ -1188,6 +1188,7 @@ tmpfs_dir_getdotdent(struct tmpfs_mount *tm, struct tmpfs_node *node, MPASS(uio->uio_offset == TMPFS_DIRCOOKIE_DOT); dent.d_fileno = node->tn_id; + dent.d_off = TMPFS_DIRCOOKIE_DOTDOT; dent.d_type = DT_DIR; dent.d_namlen = 1; dent.d_name[0] = '.'; @@ -1213,7 +1214,7 @@ tmpfs_dir_getdotdent(struct tmpfs_mount *tm, struct tmpfs_node *node, */ static int tmpfs_dir_getdotdotdent(struct tmpfs_mount *tm, struct tmpfs_node *node, - struct uio *uio) + struct uio *uio, off_t next) { struct tmpfs_node *parent; struct dirent dent; @@ -1234,6 +1235,7 @@ tmpfs_dir_getdotdotdent(struct tmpfs_mount *tm, struct tmpfs_node *node, dent.d_fileno = parent->tn_id; TMPFS_NODE_UNLOCK(parent); + dent.d_off = next; dent.d_type = DT_DIR; dent.d_namlen = 2; dent.d_name[0] = '.'; @@ -1263,7 +1265,7 @@ tmpfs_dir_getdents(struct tmpfs_mount *tm, struct tmpfs_node *node, struct uio *uio, int maxcookies, u_long *cookies, int *ncookies) { struct tmpfs_dir_cursor dc; - struct tmpfs_dirent *de; + struct tmpfs_dirent *de, *nde; off_t off; int error; @@ -1284,18 +1286,19 @@ tmpfs_dir_getdents(struct tmpfs_mount *tm, struct tmpfs_node *node, error = tmpfs_dir_getdotdent(tm, node, uio); if (error != 0) return (error); - uio->uio_offset = TMPFS_DIRCOOKIE_DOTDOT; + uio->uio_offset = off = TMPFS_DIRCOOKIE_DOTDOT; if (cookies != NULL) - cookies[(*ncookies)++] = off = uio->uio_offset; + cookies[(*ncookies)++] = off; /* FALLTHROUGH */ case TMPFS_DIRCOOKIE_DOTDOT: - error = tmpfs_dir_getdotdotdent(tm, node, uio); + de = tmpfs_dir_first(node, &dc); + off = tmpfs_dirent_cookie(de); + error = tmpfs_dir_getdotdotdent(tm, node, uio, off); if (error != 0) return (error); - de = tmpfs_dir_first(node, &dc); - uio->uio_offset = tmpfs_dirent_cookie(de); + uio->uio_offset = off; if (cookies != NULL) - cookies[(*ncookies)++] = off = uio->uio_offset; + cookies[(*ncookies)++] = off; /* EOF. */ if (de == NULL) return (0); @@ -1310,13 +1313,17 @@ tmpfs_dir_getdents(struct tmpfs_mount *tm, struct tmpfs_node *node, off = tmpfs_dirent_cookie(de); } - /* Read as much entries as possible; i.e., until we reach the end of - * the directory or we exhaust uio space. */ + /* + * Read as much entries as possible; i.e., until we reach the end of the + * directory or we exhaust uio space. + */ do { struct dirent d; - /* Create a dirent structure representing the current - * tmpfs_node and fill it. */ + /* + * Create a dirent structure representing the current tmpfs_node + * and fill it. + */ if (de->td_node == NULL) { d.d_fileno = 1; d.d_type = DT_WHT; @@ -1360,20 +1367,27 @@ tmpfs_dir_getdents(struct tmpfs_mount *tm, struct tmpfs_node *node, MPASS(de->td_namelen < sizeof(d.d_name)); (void)memcpy(d.d_name, de->ud.td_name, de->td_namelen); 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. */ + /* + * Stop reading if the directory entry we are treating is bigger + * than the amount of data that can be returned. + */ if (d.d_reclen > uio->uio_resid) { error = EJUSTRETURN; break; } - /* Copy the new dirent structure into the output buffer and - * advance pointers. */ + nde = tmpfs_dir_next(node, &dc); + d.d_off = tmpfs_dirent_cookie(nde); + dirent_terminate(&d); + + /* + * Copy the new dirent structure into the output buffer and + * advance pointers. + */ error = uiomove(&d, d.d_reclen, uio); if (error == 0) { - de = tmpfs_dir_next(node, &dc); + de = nde; if (cookies != NULL) { off = tmpfs_dirent_cookie(de); MPASS(*ncookies < maxcookies); diff --git a/sys/kern/uipc_mqueue.c b/sys/kern/uipc_mqueue.c index 67c828cae222..84f51fafb636 100644 --- a/sys/kern/uipc_mqueue.c +++ b/sys/kern/uipc_mqueue.c @@ -1426,6 +1426,7 @@ mqfs_readdir(struct vop_readdir_args *ap) if (!pn->mn_fileno) mqfs_fileno_alloc(mi, pn); entry.d_fileno = pn->mn_fileno; + entry.d_off = offset + entry.d_reclen; for (i = 0; i < MQFS_NAMELEN - 1 && pn->mn_name[i] != '\0'; ++i) entry.d_name[i] = pn->mn_name[i]; entry.d_namlen = i;