From nobody Wed Jul 1 08:44:07 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 4gqtq11H5xz6jr04 for ; Wed, 01 Jul 2026 08:44:13 +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 4gqtq046rLz3TWb for ; Wed, 01 Jul 2026 08:44:12 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1782895452; 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=01CL+LmAuZMIFsdt8nlgMnYRMEtsH9JwZuFUvhH1Fus=; b=CUyOFA5SruqIDTlRtWWb8GT9gOJUWQnbPfbDokCXJz4t3Vzq/oaDjlUN2hdBll+45c+zrl 9K/lJgd4FQJA1rNUgUJyRfXx3qeBTbyQwcXGmvqmPzMJNT+dQ2pJmEuzoqa0Kt3qlxZ7g7 dFiGT81mLRlChzHjCNzTLPde6GAo9wNyCSZgOcoNh0ZkqhxKhw+LFrHRNQI2TmcJ0K0WxC 5S7IQ4Uh9wg3HO4Kzv25L4iIvqZwkxqtuCbruQNYxOYUMh3spzUfAzAacw4y/1jcO8neuL biBP8ipFqsXHblxNzOFLZDfdZnLOHyME+nGBJLGDe8GSuT7v720Mrqm5OKagfQ== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1782895452; a=rsa-sha256; cv=none; b=TVD9fx9gh/IRA+jMS/pRc7UV2Mgj+AVU1q/43csped10RnYxstWIRDNA5klBXPucul94+t I1rRS618+pBd4md2xeNwg18KVneCtjbk0EGE0EHJpOWG3r2OVRxuKjsBN4r9xtisDCr7jg T4i+aMMZMF+0PCagkX+sVTNpLmIYJaKIiGcKQTFY48NymrWMIXqIChrlJPBHCtcFq8gdss 2VY5fmk/aOe9g3yfothdXiqVw2icJlcsRbs1DqV/x6lesIYRph58Wr0QEtCaLdZyEiUtRB mOiAeip4KxVDuo33P4zOY75mSS9ffPtPFvSYuc4LBLjk2LBeYkqynGKbz3haPA== 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=1782895452; 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=01CL+LmAuZMIFsdt8nlgMnYRMEtsH9JwZuFUvhH1Fus=; b=MHcRpdxWgyWvOzqmXUR0wIS7vU+LGiIzFGBemwhByoGrOzjHaHvRfs2iRknjsoJHi6HFFF C08gyzhyHciOqnTWrBXXL8OFMalCLaP7vUrAvl0RjU+gzbjpRoVOTv58iqQ+Y2Nyj6N0sZ xkTNKlqVPsUydBWbt72HmjnAEis9Dol5Bs9AaoXKAcbZplpbq3Vsl7yFQrHMhoH1xHjjwc IlthIOGZxxIVXKtd8nO3m94rQXG9+pFE6mTB086F5WeJ4LKdGG66F10bobCardM5ICWLh5 6FYzdPMoeK2w3W08rJkFkXtMsoCwqypYKKMeHTb/yze+uZRuCVGEILekAChv3w== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4gqtq01tSsz1MDT for ; Wed, 01 Jul 2026 08:44:12 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 392d0 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Wed, 01 Jul 2026 08:44:07 +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: 2c905456312b - main - linuxulator: Fix O_PATH file descriptors errno for f*xattr(2) 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: 2c905456312b2e5986afe3402a9c87d49eb9cf86 Auto-Submitted: auto-generated Date: Wed, 01 Jul 2026 08:44:07 +0000 Message-Id: <6a44d357.392d0.4b7213ca@gitrepo.freebsd.org> The branch main has been updated by pouria: URL: https://cgit.FreeBSD.org/src/commit/?id=2c905456312b2e5986afe3402a9c87d49eb9cf86 commit 2c905456312b2e5986afe3402a9c87d49eb9cf86 Author: YAO, Xin AuthorDate: 2026-05-07 06:39:16 +0000 Commit: Pouria Mousavizadeh Tehrani CommitDate: 2026-07-01 08:38:05 +0000 linuxulator: Fix O_PATH file descriptors errno for f*xattr(2) LTP open13 expects these operations to fail with EBADF, matching Linux behavior, but FreeBSD currently returns EOPNOTSUPP for fgetxattr() on an O_PATH fd Look up Linux fd-based xattr descriptors with getvnode() and route the operations through shared kern_extattr_*_fp() helpers so the O_PATH check and the extattr operation use the same referenced file. Apply the same EBADF handling to fsetxattr(), fremovexattr(), and flistxattr() so the xattr paths stay consistent. Signed-off-by: YAO, Xin PR: 295537 Reviewed by: kib Pull Request: https://github.com/freebsd/freebsd-src/pull/2263 --- sys/compat/linux/linux_xattr.c | 81 ++++++++++++++++++++++++++++++++++++------ sys/kern/vfs_extattr.c | 47 ++++++++++++++++++++---- sys/sys/syscallsubr.h | 10 ++++++ 3 files changed, 121 insertions(+), 17 deletions(-) diff --git a/sys/compat/linux/linux_xattr.c b/sys/compat/linux/linux_xattr.c index 2eec33f8ef93..70e4c3a1d3db 100644 --- a/sys/compat/linux/linux_xattr.c +++ b/sys/compat/linux/linux_xattr.c @@ -26,8 +26,10 @@ */ #include +#include #include #include +#include #include #include #include @@ -132,12 +134,21 @@ listxattr(struct thread *td, struct listxattr_args *args) { char attrname[LINUX_XATTR_NAME_MAX + 1]; char *data, *prefix, *key; + cap_rights_t rights; + struct file *fp = NULL; struct uio auio; struct iovec aiov; unsigned char keylen; size_t sz, cnt, rs, prefixlen, pairlen; int attrnamespace, error; + if (args->path == NULL) { + error = getvnode(td, args->fd, + cap_rights_init_one(&rights, CAP_EXTATTR_LIST), &fp); + if (error != 0) + return (error); + } + if (args->size != 0) sz = min(LINUX_XATTR_LIST_MAX, args->size); else @@ -162,7 +173,7 @@ listxattr(struct thread *td, struct listxattr_args *args) error = kern_extattr_list_path(td, args->path, attrnamespace, &auio, args->follow, UIO_USERSPACE); else - error = kern_extattr_list_fd(td, args->fd, + error = kern_extattr_list_fp(td, fp, attrnamespace, &auio); rs = sz - auio.uio_resid; if (error == EPERM) @@ -204,6 +215,8 @@ listxattr(struct thread *td, struct listxattr_args *args) if (error == 0) td->td_retval[0] = cnt; free(data, M_LINUX); + if (fp != NULL) + fdrop(fp, td); return (error_to_xattrerror(attrnamespace, error)); } @@ -253,18 +266,33 @@ static int removexattr(struct thread *td, struct removexattr_args *args) { char attrname[LINUX_XATTR_NAME_MAX + 1]; + struct file *fp = NULL; + cap_rights_t rights; int attrnamespace, error; + if (args->path == NULL) { + error = getvnode(td, args->fd, + cap_rights_init_one(&rights, CAP_EXTATTR_DELETE), &fp); + if (error != 0) + return (error); + } + error = xattr_to_extattr(args->name, &attrnamespace, attrname); if (error != 0) - return (error); + goto out_err; if (args->path != NULL) error = kern_extattr_delete_path(td, args->path, attrnamespace, attrname, args->follow, UIO_USERSPACE); else - error = kern_extattr_delete_fd(td, args->fd, attrnamespace, + error = kern_extattr_delete_fp(td, fp, attrnamespace, attrname); + if (fp != NULL) + fdrop(fp, td); return (error_to_xattrerror(attrnamespace, error)); +out_err: + if (fp != NULL) + fdrop(fp, td); + return (error); } int @@ -310,17 +338,30 @@ static int getxattr(struct thread *td, struct getxattr_args *args) { char attrname[LINUX_XATTR_NAME_MAX + 1]; + struct file *fp = NULL; + cap_rights_t rights; int attrnamespace, error; + if (args->path == NULL) { + error = getvnode(td, args->fd, + cap_rights_init_one(&rights, CAP_EXTATTR_GET), &fp); + if (error != 0) + return (error); + } + error = xattr_to_extattr(args->name, &attrnamespace, attrname); if (error != 0) - return (error); + 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_fd(td, args->fd, attrnamespace, + error = kern_extattr_get_fp(td, fp, attrnamespace, attrname, args->value, args->size); + +out_err: + if (fp != NULL) + fdrop(fp, td); return (error == EPERM ? ENOATTR : error); } @@ -373,14 +414,28 @@ static int setxattr(struct thread *td, struct setxattr_args *args) { char attrname[LINUX_XATTR_NAME_MAX + 1]; + struct file *fp = NULL; + cap_rights_t rights; int attrnamespace, error; + if (args->path == NULL) { + if ((args->flags & LINUX_XATTR_FLAGS) != 0) + cap_rights_init(&rights, CAP_EXTATTR_GET, CAP_EXTATTR_SET); + else + cap_rights_init_one(&rights, CAP_EXTATTR_SET); + error = getvnode(td, args->fd, &rights, &fp); + if (error != 0) + return (error); + } + if ((args->flags & ~(LINUX_XATTR_FLAGS)) != 0 || - args->flags == (LINUX_XATTR_FLAGS)) - return (EINVAL); + args->flags == (LINUX_XATTR_FLAGS)) { + error = EINVAL; + goto out_err; + } error = xattr_to_extattr(args->name, &attrnamespace, attrname); if (error != 0) - return (error); + goto out_err; if ((args->flags & (LINUX_XATTR_FLAGS)) != 0 ) { if (args->path != NULL) @@ -388,7 +443,7 @@ setxattr(struct thread *td, struct setxattr_args *args) attrnamespace, attrname, NULL, args->size, args->follow, UIO_USERSPACE); else - error = kern_extattr_get_fd(td, args->fd, + error = kern_extattr_get_fp(td, fp, attrnamespace, attrname, NULL, args->size); if ((args->flags & LINUX_XATTR_CREATE) != 0) { if (error == 0) @@ -404,11 +459,17 @@ setxattr(struct thread *td, struct setxattr_args *args) attrname, args->value, args->size, args->follow, UIO_USERSPACE); else - error = kern_extattr_set_fd(td, args->fd, attrnamespace, + error = kern_extattr_set_fp(td, fp, attrnamespace, attrname, args->value, args->size); out: + if (fp != NULL) + fdrop(fp, td); td->td_retval[0] = 0; return (error_to_xattrerror(attrnamespace, error)); +out_err: + if (fp != NULL) + fdrop(fp, td); + return (error); } int diff --git a/sys/kern/vfs_extattr.c b/sys/kern/vfs_extattr.c index 1fe7494f3998..01bfe343a1e4 100644 --- a/sys/kern/vfs_extattr.c +++ b/sys/kern/vfs_extattr.c @@ -240,6 +240,15 @@ sys_extattr_set_fd(struct thread *td, struct extattr_set_fd_args *uap) attrname, uap->data, uap->nbytes)); } +int +kern_extattr_set_fp(struct thread *td, struct file *fp, int attrnamespace, + const char *attrname, void *data, size_t nbytes) +{ + + return (extattr_set_vp(fp->f_vnode, attrnamespace, attrname, data, + nbytes, td)); +} + int kern_extattr_set_fd(struct thread *td, int fd, int attrnamespace, const char *attrname, void *data, size_t nbytes) @@ -257,8 +266,8 @@ kern_extattr_set_fd(struct thread *td, int fd, int attrnamespace, if (error) return (error); - error = extattr_set_vp(fp->f_vnode, attrnamespace, - attrname, data, nbytes, td); + error = kern_extattr_set_fp(td, fp, attrnamespace, attrname, data, + nbytes); fdrop(fp, td); return (error); @@ -428,6 +437,15 @@ sys_extattr_get_fd(struct thread *td, struct extattr_get_fd_args *uap) attrname, uap->data, uap->nbytes)); } +int +kern_extattr_get_fp(struct thread *td, struct file *fp, int attrnamespace, + const char *attrname, void *data, size_t nbytes) +{ + + return (extattr_get_vp(fp->f_vnode, attrnamespace, attrname, data, + nbytes, td)); +} + int kern_extattr_get_fd(struct thread *td, int fd, int attrnamespace, const char *attrname, void *data, size_t nbytes) @@ -445,8 +463,8 @@ kern_extattr_get_fd(struct thread *td, int fd, int attrnamespace, if (error) return (error); - error = extattr_get_vp(fp->f_vnode, attrnamespace, - attrname, data, nbytes, td); + error = kern_extattr_get_fp(td, fp, attrnamespace, attrname, data, + nbytes); fdrop(fp, td); return (error); @@ -584,6 +602,14 @@ sys_extattr_delete_fd(struct thread *td, struct extattr_delete_fd_args *uap) attrname)); } +int +kern_extattr_delete_fp(struct thread *td, struct file *fp, int attrnamespace, + const char *attrname) +{ + + return (extattr_delete_vp(fp->f_vnode, attrnamespace, attrname, td)); +} + int kern_extattr_delete_fd(struct thread *td, int fd, int attrnamespace, const char *attrname) @@ -601,8 +627,7 @@ kern_extattr_delete_fd(struct thread *td, int fd, int attrnamespace, if (error) return (error); - error = extattr_delete_vp(fp->f_vnode, attrnamespace, - attrname, td); + error = kern_extattr_delete_fp(td, fp, attrnamespace, attrname); fdrop(fp, td); return (error); } @@ -753,6 +778,14 @@ sys_extattr_list_fd(struct thread *td, struct extattr_list_fd_args *uap) auiop)); } +int +kern_extattr_list_fp(struct thread *td, struct file *fp, int attrnamespace, + struct uio *auiop) +{ + + return (extattr_list_vp(fp->f_vnode, attrnamespace, auiop, td)); +} + int kern_extattr_list_fd(struct thread *td, int fd, int attrnamespace, struct uio *auiop) @@ -768,7 +801,7 @@ kern_extattr_list_fd(struct thread *td, int fd, int attrnamespace, if (error) return (error); - error = extattr_list_vp(fp->f_vnode, attrnamespace, auiop, td); + error = kern_extattr_list_fp(td, fp, attrnamespace, auiop); fdrop(fp, td); return (error); diff --git a/sys/sys/syscallsubr.h b/sys/sys/syscallsubr.h index 0eb471cc9dde..c6bfe89dcf35 100644 --- a/sys/sys/syscallsubr.h +++ b/sys/sys/syscallsubr.h @@ -139,21 +139,31 @@ int kern_execve(struct thread *td, struct image_args *args, void kern_exit(struct thread *, int, int); int kern_extattr_delete_fd(struct thread *td, int fd, int attrnamespace, const char *attrname); +int kern_extattr_delete_fp(struct thread *td, struct file *fp, + int attrnamespace, const char *attrname); int kern_extattr_delete_path(struct thread *td, const char *path, int attrnamespace, const char *attrname, int follow, enum uio_seg pathseg); int kern_extattr_get_fd(struct thread *td, int fd, int attrnamespace, const char *attrname, void *data, size_t nbytes); +int kern_extattr_get_fp(struct thread *td, struct file *fp, + int attrnamespace, const char *attrname, void *data, + size_t nbytes); int kern_extattr_get_path(struct thread *td, const char *path, int attrnamespace, const char *attrname, void *data, size_t nbytes, int follow, enum uio_seg pathseg); int kern_extattr_list_fd(struct thread *td, int fd, int attrnamespace, struct uio *auiop); +int kern_extattr_list_fp(struct thread *td, struct file *fp, + int attrnamespace, struct uio *auiop); int kern_extattr_list_path(struct thread *td, const char *path, int attrnamespace, struct uio *auiop, int follow, enum uio_seg pathseg); int kern_extattr_set_fd(struct thread *td, int fd, int attrnamespace, const char *attrname, void *data, size_t nbytes); +int kern_extattr_set_fp(struct thread *td, struct file *fp, + int attrnamespace, const char *attrname, void *data, + size_t nbytes); int kern_extattr_set_path(struct thread *td, const char *path, int attrnamespace, const char *attrname, void *data, size_t nbytes, int follow, enum uio_seg pathseg);