Fixes #116.
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)
===========================
*
* `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);
*
* `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);
* 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 *);
* 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 *);
*/
#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
*
* 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
* 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.
*
* 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
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;
}
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);