summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikolaus Rath <Nikolaus@rath.org>2016-11-22 15:56:55 -0800
committerNikolaus Rath <Nikolaus@rath.org>2016-11-22 15:56:55 -0800
commit05de3c98c07e636e007e7ecf6516508426d02c83 (patch)
tree7a477ea529fcfd76f5a59a25a58f811914ef012b
parente16fdc06d7473f00499b6b03fb7bd06259a22135 (diff)
downloadfuse-05de3c98c07e636e007e7ecf6516508426d02c83.tar.gz
Add support for FUSE_HANDLE_KILLPRIV
Fixes #116.
-rw-r--r--ChangeLog.rst7
-rw-r--r--include/fuse.h12
-rw-r--r--include/fuse_common.h9
-rw-r--r--include/fuse_lowlevel.h10
-rw-r--r--lib/fuse_lowlevel.c3
5 files changed, 40 insertions, 1 deletions
diff --git a/ChangeLog.rst b/ChangeLog.rst
index 9c1a5dd..999f431 100644
--- a/ChangeLog.rst
+++ b/ChangeLog.rst
@@ -22,8 +22,13 @@ UNRELEASED CHANGES
particular capability can still be disabled by unsetting the
corresponding bit of `fuse_conn_info.wants` in the init() handler.
-* Added FUSE_CAP_PARALLEL_DIROPS and FUSE_CAP_POSIX_ACL feature flags.
+* Added FUSE_CAP_PARALLEL_DIROPS and FUSE_CAP_POSIX_ACL,
+ FUSE_HANDLE_KILLPRIV feature flags.
+* FUSE filesystems are now responsible for unsetting the setuid/setgid
+ flags when a file is written, truncated, or its owner
+ changed. Previously, this was handled by the kernel but subject to
+ race conditions.
FUSE 3.0.0-rc2 (2016-11-06)
===========================
diff --git a/include/fuse.h b/include/fuse.h
index 60015ca..56539f1 100644
--- a/include/fuse.h
+++ b/include/fuse.h
@@ -351,6 +351,9 @@ struct fuse_operations {
*
* `fi` will always be NULL if the file is not currenly open, but
* may also be NULL if the file is open.
+ *
+ * Unless FUSE_CAP_HANDLE_KILLPRIV is disabled, this method is
+ * expected to reset the setuid and setgid bits.
*/
int (*chown) (const char *, uid_t, gid_t, struct fuse_file_info *fi);
@@ -358,6 +361,9 @@ struct fuse_operations {
*
* `fi` will always be NULL if the file is not currenly open, but
* may also be NULL if the file is open.
+ *
+ * Unless FUSE_CAP_HANDLE_KILLPRIV is disabled, this method is
+ * expected to reset the setuid and setgid bits.
*/
int (*truncate) (const char *, off_t, struct fuse_file_info *fi);
@@ -395,6 +401,9 @@ struct fuse_operations {
* Write should return exactly the number of bytes requested
* except on error. An exception to this is when the 'direct_io'
* mount option is specified (see read operation).
+ *
+ * Unless FUSE_CAP_HANDLE_KILLPRIV is disabled, this method is
+ * expected to reset the setuid and setgid bits.
*/
int (*write) (const char *, const char *, size_t, off_t,
struct fuse_file_info *);
@@ -635,6 +644,9 @@ struct fuse_operations {
* Similar to the write() method, but data is supplied in a
* generic buffer. Use fuse_buf_copy() to transfer data to
* the destination.
+ *
+ * Unless FUSE_CAP_HANDLE_KILLPRIV is disabled, this method is
+ * expected to reset the setuid and setgid bits.
*/
int (*write_buf) (const char *, struct fuse_bufvec *buf, off_t off,
struct fuse_file_info *);
diff --git a/include/fuse_common.h b/include/fuse_common.h
index f336129..04b378f 100644
--- a/include/fuse_common.h
+++ b/include/fuse_common.h
@@ -268,6 +268,15 @@ struct fuse_file_info {
#define FUSE_CAP_POSIX_ACL (1 << 19)
/**
+ * Indicates that the filesystem is responsible for unsetting
+ * setuid and setgid bits when a file is written, truncated, or
+ * its owner is changed.
+ *
+ * This feature is enabled by default when supported by the kernel.
+ */
+#define FUSE_CAP_HANDLE_KILLPRIV (1 << 20)
+
+/**
* Ioctl flags
*
* FUSE_IOCTL_COMPAT: 32bit compat ioctl on 64bit machine
diff --git a/include/fuse_lowlevel.h b/include/fuse_lowlevel.h
index dbf1a27..2cebb30 100644
--- a/include/fuse_lowlevel.h
+++ b/include/fuse_lowlevel.h
@@ -276,6 +276,10 @@ struct fuse_lowlevel_ops {
* bitmask contain valid values. Other members contain undefined
* values.
*
+ * Unless FUSE_CAP_HANDLE_KILLPRIV is disabled, this method is
+ * expected to reset the setuid and setgid bits if the file
+ * size or owner is being changed.
+ *
* If the setattr was invoked from the ftruncate() system call
* under Linux kernel versions 2.6.15 or later, the fi->fh will
* contain the value set by the open method or will be undefined
@@ -509,6 +513,9 @@ struct fuse_lowlevel_ops {
* of the write system call will reflect the return value of this
* operation.
*
+ * Unless FUSE_CAP_HANDLE_KILLPRIV is disabled, this method is
+ * expected to reset the setuid and setgid bits.
+ *
* fi->fh will contain the value set by the open method, or will
* be undefined if the open method didn't set any value.
*
@@ -1013,6 +1020,9 @@ struct fuse_lowlevel_ops {
* bufv->off is correctly updated (reflecting the number of
* bytes read from bufv->buf[0]).
*
+ * Unless FUSE_CAP_HANDLE_KILLPRIV is disabled, this method is
+ * expected to reset the setuid and setgid bits.
+ *
* Valid replies:
* fuse_reply_write
* fuse_reply_err
diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c
index 3941c7f..9386f1a 100644
--- a/lib/fuse_lowlevel.c
+++ b/lib/fuse_lowlevel.c
@@ -1879,6 +1879,8 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
se->conn.capable |= FUSE_CAP_PARALLEL_DIROPS;
if (arg->flags & FUSE_POSIX_ACL)
se->conn.capable |= FUSE_CAP_POSIX_ACL;
+ if (arg->flags & FUSE_HANDLE_KILLPRIV)
+ se->conn.capable |= FUSE_CAP_HANDLE_KILLPRIV;
} else {
se->conn.max_readahead = 0;
}
@@ -1907,6 +1909,7 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
LL_SET_DEFAULT(1, FUSE_CAP_ASYNC_READ);
LL_SET_DEFAULT(1, FUSE_CAP_PARALLEL_DIROPS);
LL_SET_DEFAULT(1, FUSE_CAP_AUTO_INVAL_DATA);
+ LL_SET_DEFAULT(1, FUSE_CAP_HANDLE_KILLPRIV);
LL_SET_DEFAULT(1, FUSE_CAP_ASYNC_DIO);
LL_SET_DEFAULT(1, FUSE_CAP_IOCTL_DIR);
LL_SET_DEFAULT(1, FUSE_CAP_ATOMIC_O_TRUNC);