From nobody Wed Jul 1 08:44:08 2026 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4gqtpw3BvTz6jqrN for ; Wed, 01 Jul 2026 08:44:08 +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 "YR1" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4gqtpw1ndpz3SyX for ; Wed, 01 Jul 2026 08:44:08 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1782895448; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=qBIBzMRHPT/b3TRd1+5V5z7stJhKhjEOCGK0H+61u2M=; b=rcJZk+nRRbkX0kq3JkJ+qNZCWFoWSH66y5+/x7Y3hdeEw2DbytwWyMGeb4pyYDChh3195x /y9IZJpbK3TrzKEkZGu36gA8EDmBipzlP29MnsrGiigRobsI8wC1kI+hWO7lJd+4kuzsyb pUZenDNguhE186JqP/ynnT+M38cI+6d9m4wdkNS3PbZr7ZFrGNVtUOCDh4SngKoWtKiLet 7wC7NClqo6Reu/DuWHK9Ees+ue/4exuEWnFUsOHKNbEXNSLKsgGBQ9rf3soAnvv1rJRPlG I8g5pFJNmomiPPO3aNLT8QgU96LBHkzzZ8sk7CwchfRg5vgYuIkx8he6KaK8eg== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1782895448; a=rsa-sha256; cv=none; b=Tl+GS9YCdClPdwNjWAnrLyE+5RNvYGJhPNTAlcGEZZTxl977OIuyGqxP1uHtw24uqN7HHA yT9eIm1qiRl9DdeJ9MMORzcih6wLIALrIpDiIuq/0TLWH8nU/HwxKhayUhdAXdFkvof3T3 TtGbmNwtLSFCwBTJ/k2sbrAurPmF3s+i4nJuDSD5NlZvb93OudRfAHJW3JpQWqOgM2TW6V Hct2LczI6a2wXOqPPtbUbdYIiMlzZhcmYKqVOFpEM14h8GzYY2xgTfdRhirXGaIrlR+DQj 3HFOY42AczH5JpbF7kgtJ8RV58VuXOLnWvaFHa03IfPHWchofaYHPw+y5+yfAA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1782895448; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=qBIBzMRHPT/b3TRd1+5V5z7stJhKhjEOCGK0H+61u2M=; b=BCdIam5b0MUyKyT8/FyRCFRuXITCnP9iNXPJcXlyp0fdxzXHd1F+nu//65MThiJzsHnu4N dR0DVYKRoQCNdbL9L+3PpWCT/GR3nB+2ZsLpkRF+z8Hmo3/l2sHkNrvt9J9KbZ2XK4a94/ SH3ExeVyz8PEAmk5QyZz4CB9UMtUlTx+GpQ4jJKn4+3PXHt2QBq79LAPHERUibm4hj9m5U shWsVKdlkZ6SbUodrzxynjc7cZbMmc8ycQTTuvtwGA+xGVGtge1MbWrvBKyO362cP9hHeM 6+/E6MBXRpCQqQXsTQUSMQ0YAwJb11g0hnirCAlwFVJoJ+E2hFMQGCnAYbKXIQ== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4gqtpw0jjSz1Lxj for ; Wed, 01 Jul 2026 08:44:08 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 36b75 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Wed, 01 Jul 2026 08:44:08 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Cc: YAO, Xin From: Pouria Mousavizadeh Tehrani Subject: git: 2fc95fe26e72 - main - linuxulator: Add linux_extattr_get_vp() for atomic getxattr List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: pouria X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 2fc95fe26e725439209217f53dd76437a52be76b Auto-Submitted: auto-generated Date: Wed, 01 Jul 2026 08:44:08 +0000 Message-Id: <6a44d358.36b75.5aa46ec4@gitrepo.freebsd.org> The branch main has been updated by pouria: URL: https://cgit.FreeBSD.org/src/commit/?id=2fc95fe26e725439209217f53dd76437a52be76b commit 2fc95fe26e725439209217f53dd76437a52be76b Author: YAO, Xin AuthorDate: 2026-06-29 01:55:25 +0000 Commit: Pouria Mousavizadeh Tehrani CommitDate: 2026-07-01 08:38:32 +0000 linuxulator: Add linux_extattr_get_vp() for atomic getxattr Move the atomic size-probe-and-read logic into a new linux_extattr_get_vp() function in linux_xattr.c instead of modifying the generic extattr_get_vp() in vfs_extattr.c. This keeps Linux-specific getxattr semantics (ERANGE on too-small buffer, EOPNOTSUPP to ENOATTR mapping) self-contained within the linuxulator. The function probes the attribute size and reads the data under a single vnode lock, preventing a TOCTOU race between the size probe and data read. Signed-off-by: YAO, Xin Reviewed by: kib Pull Request: https://github.com/freebsd/freebsd-src/pull/2263 --- sys/compat/linux/linux_xattr.c | 105 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 94 insertions(+), 11 deletions(-) diff --git a/sys/compat/linux/linux_xattr.c b/sys/compat/linux/linux_xattr.c index 70e4c3a1d3db..296b70ff409a 100644 --- a/sys/compat/linux/linux_xattr.c +++ b/sys/compat/linux/linux_xattr.c @@ -33,6 +33,9 @@ #include #include #include +#include + +#include #ifdef COMPAT_LINUX32 #include @@ -334,11 +337,83 @@ linux_fremovexattr(struct thread *td, struct linux_fremovexattr_args *args) return (removexattr(td, &eargs)); } +/*- + * Linux-specific atomic extended attribute get on a vnode. + * + * Probes the attribute size and reads the data under a single vnode lock, + * preventing a TOCTOU race and returning ERANGE when the buffer is too + * small (matching Linux getxattr(2) semantics). + */ +static int +linux_extattr_get_vp(struct vnode *vp, int attrnamespace, const char *attrname, + void *data, size_t nbytes, struct thread *td) +{ + struct uio auio; + struct iovec aiov; + size_t size; + int error; + + if (nbytes > IOSIZE_MAX) + return (EINVAL); + + vn_lock(vp, LK_SHARED | LK_RETRY); + +#ifdef MAC + error = mac_vnode_check_getextattr(td->td_ucred, vp, attrnamespace, + attrname); + if (error != 0) + goto done; +#endif + + /* + * Probe the attribute size first under the vnode lock; + */ + error = VOP_GETEXTATTR(vp, attrnamespace, attrname, NULL, + &size, td->td_ucred, td); + if (error != 0) + goto done; + + /* + * The caller only wants the size, so we are done after this. + */ + if (data == NULL || nbytes == 0) { + td->td_retval[0] = size; + goto done; + } + /* + * If the buffer is too small, return ERANGE + * so the caller can retry (Linux getxattr semantics). + */ + if (size > nbytes) { + error = ERANGE; + goto done; + } + /* Buffer is large enough; read the value. */ + aiov.iov_base = data; + aiov.iov_len = nbytes; + auio.uio_iov = &aiov; + auio.uio_iovcnt = 1; + auio.uio_offset = 0; + auio.uio_resid = nbytes; + auio.uio_rw = UIO_READ; + auio.uio_segflg = UIO_USERSPACE; + auio.uio_td = td; + error = VOP_GETEXTATTR(vp, attrnamespace, attrname, &auio, NULL, + td->td_ucred, td); + if (error == 0) + td->td_retval[0] = nbytes - auio.uio_resid; +done: + VOP_UNLOCK(vp); + return (error); +} + static int getxattr(struct thread *td, struct getxattr_args *args) { char attrname[LINUX_XATTR_NAME_MAX + 1]; struct file *fp = NULL; + struct nameidata nd; + struct vnode *vp; cap_rights_t rights; int attrnamespace, error; @@ -347,22 +422,30 @@ getxattr(struct thread *td, struct getxattr_args *args) cap_rights_init_one(&rights, CAP_EXTATTR_GET), &fp); if (error != 0) return (error); + vp = fp->f_vnode; + } else { + NDINIT_ATRIGHTS(&nd, LOOKUP, args->follow, UIO_USERSPACE, + args->path, AT_FDCWD, + cap_rights_init_one(&rights, CAP_EXTATTR_GET)); + error = namei(&nd); + if (error != 0) + return (error); + NDFREE_PNBUF(&nd); + vp = nd.ni_vp; } error = xattr_to_extattr(args->name, &attrnamespace, attrname); - if (error != 0) - goto out_err; - if (args->path != NULL) - error = kern_extattr_get_path(td, args->path, attrnamespace, - attrname, args->value, args->size, args->follow, UIO_USERSPACE); - else - error = kern_extattr_get_fp(td, fp, attrnamespace, - attrname, args->value, args->size); + if (error == 0) { + error = linux_extattr_get_vp(vp, attrnamespace, attrname, + args->value, args->size, td); + } -out_err: - if (fp != NULL) + if (fp != NULL) { fdrop(fp, td); - return (error == EPERM ? ENOATTR : error); + } else { + vrele(nd.ni_vp); + } + return (error == EPERM || error == EOPNOTSUPP ? ENOATTR : error); } int