aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBernd Schubert <bschubert@ddn.com>2024-03-28 15:18:14 +0100
committerBernd Schubert <bernd.schubert@fastmail.fm>2024-03-29 13:04:45 +0100
commit3e283a1bcbc4ec78fb45c4a8b3f683b8e3082c53 (patch)
treecf00051abd35fc7edba7d8014e9d41952acf37fb
parent67d4db405059f83d3c2f4ee577a712c424b481db (diff)
downloadlibfuse-3e283a1bcbc4ec78fb45c4a8b3f683b8e3082c53.tar.gz
Add support for FUSE_CAP_HANDLE_KILLPRIV_V2
This just adds in the basic handler, but does not use it yet in examples.
-rw-r--r--example/printcap.c8
-rw-r--r--include/fuse_common.h17
-rw-r--r--lib/fuse_lowlevel.c4
3 files changed, 29 insertions, 0 deletions
diff --git a/example/printcap.c b/example/printcap.c
index 30e2057..bbbc1b8 100644
--- a/example/printcap.c
+++ b/example/printcap.c
@@ -81,6 +81,14 @@ static void pc_init(void *userdata,
printf("\tFUSE_CAP_EXPLICIT_INVAL_DATA\n");
if(conn->capable & FUSE_CAP_EXPIRE_ONLY)
printf("\tFUSE_CAP_EXPIRE_ONLY\n");
+ if(conn->capable & FUSE_CAP_SETXATTR_EXT)
+ printf("\tFUSE_CAP_SETXATTR_EXT\n");
+ if(conn->capable & FUSE_CAP_HANDLE_KILLPRIV)
+ printf("\tFUSE_CAP_HANDLE_KILLPRIV\n");
+ if(conn->capable & FUSE_CAP_HANDLE_KILLPRIV_V2)
+ printf("\tFUSE_CAP_HANDLE_KILLPRIV_V2\n");
+ if(conn->capable & FUSE_CAP_DIRECT_IO_ALLOW_MMAP)
+ printf("\tFUSE_CAP_DIRECT_IO_ALLOW_MMAP\n");
fuse_session_exit(se);
}
diff --git a/include/fuse_common.h b/include/fuse_common.h
index 52b691a..f052b67 100644
--- a/include/fuse_common.h
+++ b/include/fuse_common.h
@@ -368,6 +368,23 @@ struct fuse_loop_config_v1 {
#define FUSE_CAP_HANDLE_KILLPRIV (1 << 20)
/**
+ * Indicates that the filesystem is responsible for unsetting
+ * setuid and setgid bit and additionally cap (stored as xattr) when a
+ * file is written, truncated, or its owner is changed.
+ * 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).
+ * KILLPRIV_V2 requires handling of
+ * - FUSE_OPEN_KILL_SUIDGID (set in struct fuse_create_in::open_flags)
+ * - FATTR_KILL_SUIDGID (set in struct fuse_setattr_in::valid)
+ * - FUSE_WRITE_KILL_SUIDGID (set in struct fuse_write_in::write_flags)
+ *
+ * This feature is disabled by default.
+ */
+#define FUSE_CAP_HANDLE_KILLPRIV_V2 (1 << 21)
+
+/**
* Indicates that the kernel supports caching symlinks in its page cache.
*
* When this feature is enabled, symlink targets are saved in the page cache.
diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c
index 26e5699..d9844b0 100644
--- a/lib/fuse_lowlevel.c
+++ b/lib/fuse_lowlevel.c
@@ -2001,6 +2001,8 @@ void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
se->conn.capable |= FUSE_CAP_POSIX_ACL;
if (inargflags & FUSE_HANDLE_KILLPRIV)
se->conn.capable |= FUSE_CAP_HANDLE_KILLPRIV;
+ if (inargflags & FUSE_HANDLE_KILLPRIV_V2)
+ se->conn.capable |= FUSE_CAP_HANDLE_KILLPRIV_V2;
if (inargflags & FUSE_CACHE_SYMLINKS)
se->conn.capable |= FUSE_CAP_CACHE_SYMLINKS;
if (inargflags & FUSE_NO_OPENDIR_SUPPORT)
@@ -2145,6 +2147,8 @@ void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
outargflags |= FUSE_POSIX_ACL;
if (se->conn.want & FUSE_CAP_HANDLE_KILLPRIV)
outargflags |= FUSE_HANDLE_KILLPRIV;
+ if (se->conn.want & FUSE_CAP_HANDLE_KILLPRIV_V2)
+ outargflags |= FUSE_HANDLE_KILLPRIV_V2;
if (se->conn.want & FUSE_CAP_CACHE_SYMLINKS)
outargflags |= FUSE_CACHE_SYMLINKS;
if (se->conn.want & FUSE_CAP_EXPLICIT_INVAL_DATA)