--- include/fuse_common.h | 5 ++++- include/fuse_kernel.h | 2 ++ lib/fuse_lowlevel.c | 12 ++++++++---- 3 files changed, 14 insertions(+), 5 deletions(-) --- a/include/fuse_common.h +++ b/include/fuse_common.h @@ -64,8 +64,11 @@ struct fuse_file_info { May only be set in ->release(). */ unsigned int flock_release : 1; + /* Kill suid and sgid bits on write */ + unsigned int write_kill_priv : 1; + /** Padding. Do not use*/ - unsigned int padding : 27; + unsigned int padding : 26; /** File handle. May be filled in by filesystem in open(). Available in all other file operations */ --- a/include/fuse_kernel.h +++ b/include/fuse_kernel.h @@ -304,9 +304,11 @@ struct fuse_file_lock { * * 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 */ #define FUSE_WRITE_CACHE (1 << 0) #define FUSE_WRITE_LOCKOWNER (1 << 1) +#define FUSE_WRITE_KILL_PRIV (1 << 2) /** * Read flags --- a/lib/fuse_lowlevel.c +++ b/lib/fuse_lowlevel.c @@ -1315,12 +1315,14 @@ static void do_write(fuse_req_t req, fus memset(&fi, 0, sizeof(fi)); fi.fh = arg->fh; - fi.writepage = (arg->write_flags & 1) != 0; + fi.writepage = (arg->write_flags & FUSE_WRITE_CACHE) != 0; + fi.write_kill_priv = (arg->write_flags & FUSE_WRITE_KILL_PRIV) != 0; if (req->se->conn.proto_minor < 9) { param = ((char *) arg) + FUSE_COMPAT_WRITE_IN_SIZE; } else { - fi.lock_owner = arg->lock_owner; + if (arg->write_flags & FUSE_WRITE_LOCKOWNER) + fi.lock_owner = arg->lock_owner; fi.flags = arg->flags; param = PARAM(arg); } @@ -1345,7 +1347,8 @@ static void do_write_buf(fuse_req_t req, memset(&fi, 0, sizeof(fi)); fi.fh = arg->fh; - fi.writepage = arg->write_flags & 1; + fi.writepage = (arg->write_flags & FUSE_WRITE_CACHE) != 0; + fi.write_kill_priv = (arg->write_flags & FUSE_WRITE_KILL_PRIV) != 0; if (se->conn.proto_minor < 9) { bufv.buf[0].mem = ((char *) arg) + FUSE_COMPAT_WRITE_IN_SIZE; @@ -1353,7 +1356,8 @@ static void do_write_buf(fuse_req_t req, FUSE_COMPAT_WRITE_IN_SIZE; assert(!(bufv.buf[0].flags & FUSE_BUF_IS_FD)); } else { - fi.lock_owner = arg->lock_owner; + if (arg->write_flags & FUSE_WRITE_LOCKOWNER) + fi.lock_owner = arg->lock_owner; fi.flags = arg->flags; if (!(bufv.buf[0].flags & FUSE_BUF_IS_FD)) bufv.buf[0].mem = PARAM(arg);