From nobody Thu Nov 06 00:38:39 2025 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 4d23G767rvz6FB5m; Thu, 06 Nov 2025 00:38:39 +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 "R12" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4d23G74Hvtz3dKS; Thu, 06 Nov 2025 00:38:39 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1762389519; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=j76NDAXS63ptblTrD9t9/GMT4P/rIVPfcm+aqhstBrk=; b=gUGzKMO/NAHyRE7ReHzrprQ5grtJdLafFb67M/6LRj1BOodIm3BVuDZM0r+DqL6OU73p8p GkUEUNI11NnVdq5FsDBl481ETpd3rsSOL0eEx8Zqzh06/Xx5jUXg+qkyRs0ezH3hEMKcrw 8PwUjeIEoYZLdijUXpmuY6lnKcjrCArAPKYNwi+lM+OOWSOicUw6aXgnMlc77NiN0F5NUs nDNBE1f+c0G9iUmOqBqpJwsCOXdIjcVRkTsrzLQOKpy9O2s8nCpv4Vp+xlPV0iyabZaIqP yy6m2rpnu7np7arNkxs+vadvrN9NHyVI+IRz0Eckey2um0+KZUi0dHpgKiDCqQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1762389519; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=j76NDAXS63ptblTrD9t9/GMT4P/rIVPfcm+aqhstBrk=; b=mLG6e+ajbZh1Do3pdtGl/kVta/rOUvYScskNhQg0QS2jxuEphQXucOrS9ef1IaI6d8KOAg WBzGar8pNe70hWSvIjmXVZPoh+w1B0bRQv03Ne3O3arM0S60eP72CiFNlJy2G+yUKjT3a5 6FVcjuErWhJNu7ryY0ammqsuLTWj8xtXsimT1BWHmplTST+H6Bh41y01VGY+TzOyi37Fz0 zoGzcsMq9C0lPn5glcbMHJr93Ilpqf00Hzq/px4/WgCT+MBBZkVmd+Q3zDLFOnMLg6oj4d vTOUuDES1a7eY6NXs+ZrGM+LeJQfNLuHrd+yc035DbSZ4DrZUEw9/eY+qWxWiA== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1762389519; a=rsa-sha256; cv=none; b=xUEGCHKA6AJ+oVjs6H0SUC9FdSeUIukxQYjrOl7LPVJY4zbR7E7pdcgzz9kZgeGTrJUZG1 iuuKMxgGYwR1pv/CEAgVjut635bOCL5GP/6Xd9DrmgeOJNCAAqZVtl7M8vSGIHyilrnerV hri0hgl7k17a2xK/c/t/ssz+VJ9Vj28MM8KmaAZAAUFkSvfhSB0/vJJlFU3Z7Ofy68Gxof oKqUl8venGXxAawPB0ggR9UnOYp9gDR45RqklSxG83YDGBP4IWESU03BtjFIbDvn+zkuZd 4ujgEukVmG4uEW6wEn3utQ+3fRT0LEwv0BOUPHSvilpBh6gVloHEJAXUANnhnQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none 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 4d23G73lQ5z166V; Thu, 06 Nov 2025 00:38:39 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 5A60cdkm052254; Thu, 6 Nov 2025 00:38:39 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 5A60cde9052251; Thu, 6 Nov 2025 00:38:39 GMT (envelope-from git) Date: Thu, 6 Nov 2025 00:38:39 GMT Message-Id: <202511060038.5A60cde9052251@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Alan Somers Subject: git: a23bd71deaad - stable/15 - fusefs: respect the server's FUSE_SETXATTR_EXT flag 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 MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: asomers X-Git-Repository: src X-Git-Refname: refs/heads/stable/15 X-Git-Reftype: branch X-Git-Commit: a23bd71deaad478cbe41ae756b96ea7a32537311 Auto-Submitted: auto-generated The branch stable/15 has been updated by asomers: URL: https://cgit.FreeBSD.org/src/commit/?id=a23bd71deaad478cbe41ae756b96ea7a32537311 commit a23bd71deaad478cbe41ae756b96ea7a32537311 Author: Alan Somers AuthorDate: 2025-10-26 18:06:51 +0000 Commit: Alan Somers CommitDate: 2025-11-06 00:25:27 +0000 fusefs: respect the server's FUSE_SETXATTR_EXT flag FUSE protocol 7.33 extended the FUSE_SETXATTR request format. But the extension is optional. The server must opt-in by setting the FUSE_SETXATTR_IN flag during FUSE_INIT. We were wrongly using the extended format for any server using protocol 7.33 or later. PR: 290547 Co-authored-by: CismonX Fixes: d5e3cf41e89 ("fusefs: Upgrade FUSE protocol to version 7.33") MFC after: 3 days (cherry picked from commit e8449c0e0fcb8a3eb5872cbee5c3dde4b05a5f50) --- sys/fs/fuse/fuse_internal.c | 5 +++- sys/fs/fuse/fuse_ipc.h | 1 + sys/fs/fuse/fuse_vnops.c | 4 +-- tests/sys/fs/fusefs/xattr.cc | 67 ++++++++++++++++++++++++++++++++++---------- 4 files changed, 59 insertions(+), 18 deletions(-) diff --git a/sys/fs/fuse/fuse_internal.c b/sys/fs/fuse/fuse_internal.c index 61fe2ed032f6..eba0a8a79ff3 100644 --- a/sys/fs/fuse/fuse_internal.c +++ b/sys/fs/fuse/fuse_internal.c @@ -1063,6 +1063,8 @@ fuse_internal_init_callback(struct fuse_ticket *tick, struct uio *uio) if (!fuse_libabi_geq(data, 7, 28)) fsess_set_notimpl(data->mp, FUSE_COPY_FILE_RANGE); + if (fuse_libabi_geq(data, 7, 33) && (fiio->flags & FUSE_SETXATTR_EXT)) + data->dataflags |= FSESS_SETXATTR_EXT; out: if (err) { fdata_set_dead(data); @@ -1115,7 +1117,8 @@ fuse_internal_send_init(struct fuse_data *data, struct thread *td) */ fiii->flags = FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES | FUSE_WRITEBACK_CACHE - | FUSE_NO_OPEN_SUPPORT | FUSE_NO_OPENDIR_SUPPORT; + | FUSE_NO_OPEN_SUPPORT | FUSE_NO_OPENDIR_SUPPORT + | FUSE_SETXATTR_EXT; fuse_insert_callback(fdi.tick, fuse_internal_init_callback); fuse_insert_message(fdi.tick, false); diff --git a/sys/fs/fuse/fuse_ipc.h b/sys/fs/fuse/fuse_ipc.h index 3bfc859dbac9..d9d79f38c269 100644 --- a/sys/fs/fuse/fuse_ipc.h +++ b/sys/fs/fuse/fuse_ipc.h @@ -243,6 +243,7 @@ struct fuse_data { #define FSESS_MNTOPTS_MASK ( \ FSESS_DAEMON_CAN_SPY | FSESS_PUSH_SYMLINKS_IN | \ FSESS_DEFAULT_PERMISSIONS | FSESS_INTR) +#define FSESS_SETXATTR_EXT 0x8000000 /* extended fuse_setxattr_in */ extern int fuse_data_cache_mode; diff --git a/sys/fs/fuse/fuse_vnops.c b/sys/fs/fuse/fuse_vnops.c index be600b57f0a3..00ad11108ee0 100644 --- a/sys/fs/fuse/fuse_vnops.c +++ b/sys/fs/fuse/fuse_vnops.c @@ -2777,7 +2777,7 @@ fuse_vnop_setextattr(struct vop_setextattr_args *ap) strlen(ap->a_name) + 1; /* older FUSE servers use a smaller fuse_setxattr_in struct*/ - if (fuse_libabi_geq(fuse_get_mpdata(mp), 7, 33)) + if (fuse_get_mpdata(mp)->dataflags & FSESS_SETXATTR_EXT) struct_size = sizeof(*set_xattr_in); fdisp_init(&fdi, len + struct_size + uio->uio_resid); @@ -2786,7 +2786,7 @@ fuse_vnop_setextattr(struct vop_setextattr_args *ap) set_xattr_in = fdi.indata; set_xattr_in->size = uio->uio_resid; - if (fuse_libabi_geq(fuse_get_mpdata(mp), 7, 33)) { + if (fuse_get_mpdata(mp)->dataflags & FSESS_SETXATTR_EXT) { set_xattr_in->setxattr_flags = 0; set_xattr_in->padding = 0; } diff --git a/tests/sys/fs/fusefs/xattr.cc b/tests/sys/fs/fusefs/xattr.cc index 0ab203c96254..afeacd4a249e 100644 --- a/tests/sys/fs/fusefs/xattr.cc +++ b/tests/sys/fs/fusefs/xattr.cc @@ -100,7 +100,11 @@ void expect_removexattr(uint64_t ino, const char *attr, int error) ).WillOnce(Invoke(ReturnErrno(error))); } -void expect_setxattr(uint64_t ino, const char *attr, const char *value, +/* + * Expect a FUSE_SETXATTR request in the format used by protocol 7.33 and + * later, with the FUSE_SETXATTR_EXT bit set. + */ +void expect_setxattr_ext(uint64_t ino, const char *attr, const char *value, ProcessMockerT r) { EXPECT_CALL(*m_mock, process( @@ -119,16 +123,10 @@ void expect_setxattr(uint64_t ino, const char *attr, const char *value, ).WillOnce(Invoke(r)); } -}; - -class Xattr_7_32:public FuseTest { -public: -virtual void SetUp() -{ - m_kernel_minor_version = 32; - FuseTest::SetUp(); -} - +/* + * Expect a FUSE_SETXATTR request in the format used by protocol 7.32 and + * earlier. + */ void expect_setxattr_7_32(uint64_t ino, const char *attr, const char *value, ProcessMockerT r) { @@ -148,6 +146,15 @@ void expect_setxattr_7_32(uint64_t ino, const char *attr, const char *value, } }; +class Xattr_7_32: public Xattr { +public: +virtual void SetUp() +{ + m_kernel_minor_version = 32; + Xattr::SetUp(); +} +}; + class Getxattr: public Xattr {}; class Listxattr: public Xattr {}; @@ -182,6 +189,13 @@ void TearDown() { class Removexattr: public Xattr {}; class Setxattr: public Xattr {}; +class SetxattrExt: public Setxattr { +public: +virtual void SetUp() { + m_init_flags |= FUSE_SETXATTR_EXT; + Setxattr::SetUp(); +} +}; class Setxattr_7_32:public Xattr_7_32 {}; class RofsXattr: public Xattr { public: @@ -773,7 +787,7 @@ TEST_F(Setxattr, enosys) ssize_t r; expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 2); - expect_setxattr(ino, "user.foo", value, ReturnErrno(ENOSYS)); + expect_setxattr_7_32(ino, "user.foo", value, ReturnErrno(ENOSYS)); r = extattr_set_file(FULLPATH, ns, "foo", (const void*)value, value_len); @@ -800,7 +814,7 @@ TEST_F(Setxattr, enotsup) ssize_t r; expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 1); - expect_setxattr(ino, "user.foo", value, ReturnErrno(ENOTSUP)); + expect_setxattr_7_32(ino, "user.foo", value, ReturnErrno(ENOTSUP)); r = extattr_set_file(FULLPATH, ns, "foo", (const void*)value, value_len); @@ -820,7 +834,7 @@ TEST_F(Setxattr, user) ssize_t r; expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 1); - expect_setxattr(ino, "user.foo", value, ReturnErrno(0)); + expect_setxattr_7_32(ino, "user.foo", value, ReturnErrno(0)); r = extattr_set_file(FULLPATH, ns, "foo", (const void*)value, value_len); @@ -839,7 +853,7 @@ TEST_F(Setxattr, system) ssize_t r; expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 1); - expect_setxattr(ino, "system.foo", value, ReturnErrno(0)); + expect_setxattr_7_32(ino, "system.foo", value, ReturnErrno(0)); r = extattr_set_file(FULLPATH, ns, "foo", (const void*)value, value_len); @@ -847,6 +861,10 @@ TEST_F(Setxattr, system) } +/* + * For servers using protocol 7.32 and older, the kernel should use the older + * FUSE_SETXATTR format. + */ TEST_F(Setxattr_7_32, ok) { uint64_t ino = 42; @@ -863,6 +881,25 @@ TEST_F(Setxattr_7_32, ok) ASSERT_EQ(value_len, r) << strerror(errno); } +/* + * Successfully set a user attribute using the extended format + */ +TEST_F(SetxattrExt, user) +{ + uint64_t ino = 42; + const char value[] = "whatever"; + ssize_t value_len = strlen(value) + 1; + int ns = EXTATTR_NAMESPACE_USER; + ssize_t r; + + expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 1); + expect_setxattr_ext(ino, "user.foo", value, ReturnErrno(0)); + + r = extattr_set_file(FULLPATH, ns, "foo", (const void*)value, + value_len); + ASSERT_EQ(value_len, r) << strerror(errno); +} + TEST_F(RofsXattr, deleteextattr_erofs) { uint64_t ino = 42;