Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F109801240
D48818.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
D48818.diff
View Options
diff --git a/sys/fs/fuse/fuse_kernel.h b/sys/fs/fuse/fuse_kernel.h
--- a/sys/fs/fuse/fuse_kernel.h
+++ b/sys/fs/fuse/fuse_kernel.h
@@ -176,6 +176,12 @@
*
* 7.32
* - add flags to fuse_attr, add FUSE_ATTR_SUBMOUNT, add FUSE_SUBMOUNTS
+ *
+ * 7.33
+ * - add FUSE_HANDLE_KILLPRIV_V2, FUSE_WRITE_KILL_SUIDGID, FATTR_KILL_SUIDGID
+ * - add FUSE_OPEN_KILL_SUIDGID
+ * - extend fuse_setxattr_in, add FUSE_SETXATTR_EXT
+ * - add FUSE_SETXATTR_ACL_KILL_SGID
*/
#ifndef _FUSE_FUSE_KERNEL_H
@@ -211,7 +217,7 @@
#define FUSE_KERNEL_VERSION 7
/** Minor version number of this interface */
-#define FUSE_KERNEL_MINOR_VERSION 32
+#define FUSE_KERNEL_MINOR_VERSION 33
/** The node ID of the root inode */
#define FUSE_ROOT_ID 1
@@ -272,6 +278,7 @@
#define FATTR_MTIME_NOW (1 << 8)
#define FATTR_LOCKOWNER (1 << 9)
#define FATTR_CTIME (1 << 10)
+#define FATTR_KILL_SUIDGID (1 << 11)
/**
* Flags returned by the OPEN request
@@ -321,6 +328,12 @@
* foffset and moffset fields in struct
* fuse_setupmapping_out and fuse_removemapping_one.
* FUSE_SUBMOUNTS: kernel supports auto-mounting directory submounts
+ * FUSE_HANDLE_KILLPRIV_V2: fs kills suid/sgid/cap on write/chown/trunc.
+ * Upon write/truncate suid/sgid is only killed if caller
+ * does not have CAP_FSETID. Additionally upon
+ * write/truncate sgid is killed only if file has group
+ * execute permission. (Same as Linux VFS behavior).
+ * FUSE_SETXATTR_EXT: Server supports extended struct fuse_setxattr_in
*/
#define FUSE_ASYNC_READ (1 << 0)
#define FUSE_POSIX_LOCKS (1 << 1)
@@ -350,6 +363,8 @@
#define FUSE_EXPLICIT_INVAL_DATA (1 << 25)
#define FUSE_MAP_ALIGNMENT (1 << 26)
#define FUSE_SUBMOUNTS (1 << 27)
+#define FUSE_HANDLE_KILLPRIV_V2 (1 << 28)
+#define FUSE_SETXATTR_EXT (1 << 29)
#ifdef linux
/**
@@ -381,11 +396,14 @@
*
* FUSE_WRITE_CACHE: delayed write from page cache, file handle is guessed
* FUSE_WRITE_LOCKOWNER: lock_owner field is valid
- * FUSE_WRITE_KILL_PRIV: kill suid and sgid bits
+ * FUSE_WRITE_KILL_SUIDGID: kill suid and sgid bits
*/
#define FUSE_WRITE_CACHE (1 << 0)
#define FUSE_WRITE_LOCKOWNER (1 << 1)
-#define FUSE_WRITE_KILL_PRIV (1 << 2)
+#define FUSE_WRITE_KILL_SUIDGID (1 << 2)
+
+/* Obsolete alias; this flag implies killing suid/sgid only. */
+#define FUSE_WRITE_KILL_PRIV FUSE_WRITE_KILL_SUIDGID
/**
* Read flags
@@ -435,11 +453,22 @@
/**
* fuse_attr flags
- *
* FUSE_ATTR_SUBMOUNT: Object is a submount root
*/
#define FUSE_ATTR_SUBMOUNT (1 << 0)
+/**
+ * Open flags
+ * FUSE_OPEN_KILL_SUIDGID: Kill suid and sgid if executable
+ */
+#define FUSE_OPEN_KILL_SUIDGID (1 << 0)
+
+/**
+ * setxattr flags
+ * FUSE_SETXATTR_ACL_KILL_SGID: Clear SGID when system.posix_acl_access is set
+ */
+#define FUSE_SETXATTR_ACL_KILL_SGID (1 << 0)
+
enum fuse_opcode {
FUSE_LOOKUP = 1,
FUSE_FORGET = 2, /* no reply */
@@ -494,7 +523,7 @@
CUSE_INIT = 4096,
/* Reserved opcodes: helpful to detect structure endian-ness */
CUSE_INIT_BSWAP_RESERVED = 1048576, /* CUSE_INIT << 8 */
- FUSE_INIT_BSWAP_RESERVED = 436207616, /* FUSE_INIT << 24 */
+ FUSE_INIT_BSWAP_RESERVED = 436207616, /* FUSE_INIT << 24 */
#endif /* linux */
};
@@ -602,14 +631,14 @@
struct fuse_open_in {
uint32_t flags;
- uint32_t unused;
+ uint32_t open_flags; /* FUSE_OPEN_... */
};
struct fuse_create_in {
uint32_t flags;
uint32_t mode;
uint32_t umask;
- uint32_t padding;
+ uint32_t open_flags; /* FUSE_OPEN_... */
};
struct fuse_open_out {
@@ -671,9 +700,13 @@
uint32_t padding;
};
+#define FUSE_COMPAT_SETXATTR_IN_SIZE 8
+
struct fuse_setxattr_in {
uint32_t size;
uint32_t flags;
+ uint32_t setxattr_flags;
+ uint32_t padding;
};
struct fuse_listxattr_in {
@@ -928,7 +961,6 @@
uint64_t flags;
};
-
#define FUSE_SETUPMAPPING_FLAG_WRITE (1ull << 0)
#define FUSE_SETUPMAPPING_FLAG_READ (1ull << 1)
struct fuse_setupmapping_in {
@@ -957,6 +989,6 @@
};
#define FUSE_REMOVEMAPPING_MAX_ENTRY \
- (PAGE_SIZE / sizeof(struct fuse_removemapping_one))
+ (PAGE_SIZE / sizeof(struct fuse_removemapping_one))
#endif /* _FUSE_FUSE_KERNEL_H */
diff --git a/sys/fs/fuse/fuse_vnops.c b/sys/fs/fuse/fuse_vnops.c
--- a/sys/fs/fuse/fuse_vnops.c
+++ b/sys/fs/fuse/fuse_vnops.c
@@ -2704,6 +2704,7 @@
struct mount *mp = vnode_mount(vp);
struct thread *td = ap->a_td;
struct ucred *cred = ap->a_cred;
+ size_t struct_size = FUSE_COMPAT_SETXATTR_IN_SIZE;
char *prefix;
size_t len;
char *attr_str;
@@ -2744,17 +2745,26 @@
len = strlen(prefix) + sizeof(extattr_namespace_separator) +
strlen(ap->a_name) + 1;
- fdisp_init(&fdi, len + sizeof(*set_xattr_in) + uio->uio_resid);
+ /* we want to be binary compatible */
+ if (fuse_libabi_geq(fuse_get_mpdata(mp), 7, 33))
+ struct_size = sizeof(*set_xattr_in);
+
+ fdisp_init(&fdi, len + struct_size + uio->uio_resid);
fdisp_make_vp(&fdi, FUSE_SETXATTR, vp, td, cred);
set_xattr_in = fdi.indata;
set_xattr_in->size = uio->uio_resid;
- attr_str = (char *)fdi.indata + sizeof(*set_xattr_in);
+ if (fuse_libabi_geq(fuse_get_mpdata(mp), 7, 33)) {
+ set_xattr_in->setxattr_flags = 0;
+ set_xattr_in->padding = 0;
+ }
+
+ attr_str = (char *)fdi.indata + struct_size;
snprintf(attr_str, len, "%s%c%s", prefix, extattr_namespace_separator,
ap->a_name);
- err = uiomove((char *)fdi.indata + sizeof(*set_xattr_in) + len,
+ err = uiomove((char *)fdi.indata + struct_size + len,
uio->uio_resid, uio);
if (err != 0) {
goto out;
diff --git a/tests/sys/fs/fusefs/xattr.cc b/tests/sys/fs/fusefs/xattr.cc
--- a/tests/sys/fs/fusefs/xattr.cc
+++ b/tests/sys/fs/fusefs/xattr.cc
@@ -110,6 +110,8 @@
const char *v = a + strlen(a) + 1;
return (in.header.opcode == FUSE_SETXATTR &&
in.header.nodeid == ino &&
+ in.body.setxattr.size == (strlen(value) + 1) &&
+ in.body.setxattr.flags == 0 &&
0 == strcmp(attr, a) &&
0 == strcmp(value, v));
}, Eq(true)),
@@ -119,6 +121,33 @@
};
+class Xattr_7_32: public FuseTest {
+public:
+ virtual void SetUp() {
+ m_kernel_minor_version = 32;
+ FuseTest::SetUp();
+ }
+
+void expect_setxattr_7_32(uint64_t ino, const char *attr, const char *value,
+ ProcessMockerT r)
+{
+ EXPECT_CALL(*m_mock, process(
+ ResultOf([=](auto in) {
+ const char *a = (const char*)in.body.bytes +
+ FUSE_COMPAT_SETXATTR_IN_SIZE;
+ const char *v = a + strlen(a) + 1;
+ return (in.header.opcode == FUSE_SETXATTR &&
+ in.header.nodeid == ino &&
+ in.body.setxattr.size == (strlen(value) + 1) &&
+ in.body.setxattr.flags == 0 &&
+ 0 == strcmp(attr, a) &&
+ 0 == strcmp(value, v));
+ }, Eq(true)),
+ _)
+ ).WillOnce(Invoke(r));
+}
+};
+
class Getxattr: public Xattr {};
class Listxattr: public Xattr {};
@@ -153,6 +182,7 @@
class Removexattr: public Xattr {};
class Setxattr: public Xattr {};
+class Setxattr_7_32: public Xattr_7_32 {};
class RofsXattr: public Xattr {
public:
virtual void SetUp() {
@@ -728,6 +758,7 @@
<< strerror(errno);
}
+
/*
* If the filesystem returns ENOSYS, then it will be treated as a permanent
* failure and all future VOP_SETEXTATTR calls will fail with EOPNOTSUPP
@@ -815,6 +846,23 @@
ASSERT_EQ(value_len, r) << strerror(errno);
}
+
+TEST_F(Setxattr_7_32, ok)
+{
+ 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_7_32(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;
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Feb 10, 5:29 PM (7 h, 21 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16553260
Default Alt Text
D48818.diff (7 KB)
Attached To
Mode
D48818: fusefs: Upgrade FUSE protocol to version 7.33.
Attached
Detach File
Event Timeline
Log In to Comment