qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v5 0/5] virtiofsd: Add support to enable/disable posix acls
@ 2021-03-25 15:38 Vivek Goyal
  2021-03-25 15:38 ` [PATCH v5 1/5] virtiofsd: Add umask to seccom allow list Vivek Goyal
                   ` (5 more replies)
  0 siblings, 6 replies; 10+ messages in thread
From: Vivek Goyal @ 2021-03-25 15:38 UTC (permalink / raw)
  To: qemu-devel, virtio-fs; +Cc: lhenriques, dgilbert, vgoyal, miklos

Hi,

This is V5 of the patches.

Changes since V4:

- Added support to clear SGID while setting posix access acl. fuse
  client sends this information in a flag in SETXATTR message. This
  also requires opting in for using SETXATTR V2.

These patches have dependency on fuse kernel patches. So kernel patches
need to be get merged first.

https://lore.kernel.org/linux-fsdevel/20210325151823.572089-1-vgoyal@redhat.com/

Posting patches anyway, so that patches can get reviewed and tested.

Thanks
Vivek
 
Vivek Goyal (5):
  virtiofsd: Add umask to seccom allow list
  virtiofsd: Add capability to change/restore umask
  virtiofsd: Add an option to enable/disable posix acls
  virtiofsd: Add support for setxattr_v2
  virtiofsd: Switch creds, drop FSETID for system.posix_acl_access xattr

 docs/tools/virtiofsd.rst              |   3 +
 include/standard-headers/linux/fuse.h |  19 ++-
 tools/virtiofsd/fuse_common.h         |   6 +
 tools/virtiofsd/fuse_lowlevel.c       |  42 ++++++-
 tools/virtiofsd/fuse_lowlevel.h       |   3 +-
 tools/virtiofsd/helper.c              |   1 +
 tools/virtiofsd/passthrough_ll.c      | 166 ++++++++++++++++++++++++--
 tools/virtiofsd/passthrough_seccomp.c |   1 +
 8 files changed, 230 insertions(+), 11 deletions(-)

-- 
2.25.4



^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH v5 1/5] virtiofsd: Add umask to seccom allow list
  2021-03-25 15:38 [PATCH v5 0/5] virtiofsd: Add support to enable/disable posix acls Vivek Goyal
@ 2021-03-25 15:38 ` Vivek Goyal
  2021-03-25 15:38 ` [PATCH v5 2/5] virtiofsd: Add capability to change/restore umask Vivek Goyal
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 10+ messages in thread
From: Vivek Goyal @ 2021-03-25 15:38 UTC (permalink / raw)
  To: qemu-devel, virtio-fs
  Cc: lhenriques, Stefan Hajnoczi, dgilbert, vgoyal, miklos

Patches in this series  are going to make use of "umask" syscall.
So allow it.

Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 tools/virtiofsd/passthrough_seccomp.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tools/virtiofsd/passthrough_seccomp.c b/tools/virtiofsd/passthrough_seccomp.c
index 62441cfcdb..f49ed94b5e 100644
--- a/tools/virtiofsd/passthrough_seccomp.c
+++ b/tools/virtiofsd/passthrough_seccomp.c
@@ -114,6 +114,7 @@ static const int syscall_allowlist[] = {
     SCMP_SYS(utimensat),
     SCMP_SYS(write),
     SCMP_SYS(writev),
+    SCMP_SYS(umask),
 };
 
 /* Syscalls used when --syslog is enabled */
-- 
2.25.4



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v5 2/5] virtiofsd: Add capability to change/restore umask
  2021-03-25 15:38 [PATCH v5 0/5] virtiofsd: Add support to enable/disable posix acls Vivek Goyal
  2021-03-25 15:38 ` [PATCH v5 1/5] virtiofsd: Add umask to seccom allow list Vivek Goyal
@ 2021-03-25 15:38 ` Vivek Goyal
  2021-03-25 15:38 ` [PATCH v5 3/5] virtiofsd: Add an option to enable/disable posix acls Vivek Goyal
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 10+ messages in thread
From: Vivek Goyal @ 2021-03-25 15:38 UTC (permalink / raw)
  To: qemu-devel, virtio-fs
  Cc: lhenriques, Stefan Hajnoczi, dgilbert, vgoyal, miklos

When parent directory has default acl and a file is created in that
directory, then umask is ignored and final file permissions are
determined using default acl instead. (man 2 umask).

Currently, fuse applies the umask and sends modified mode in create
request accordingly. fuse server can set FUSE_DONT_MASK and tell
fuse client to not apply umask and fuse server will take care of
it as needed.

With posix acls enabled, requirement will be that we want umask
to determine final file mode if parent directory does not have
default acl.

So if posix acls are enabled, opt in for FUSE_DONT_MASK. virtiofsd
will set umask of the thread doing file creation. And host kernel
should use that umask if parent directory does not have default
acls, otherwise umask does not take affect.

Miklos mentioned that we already call unshare(CLONE_FS) for
every thread. That means umask has now become property of per
thread and it should be ok to manipulate it in file creation path.

This patch only adds capability to change umask and restore it. It
does not enable it yet. Next patch will add capability to enable it
based on if user enabled posix_acl or not.

This should fix fstest generic/099.

Reported-by: Luis Henriques <lhenriques@suse.de>
Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 tools/virtiofsd/passthrough_ll.c | 22 ++++++++++++++++------
 1 file changed, 16 insertions(+), 6 deletions(-)

diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c
index b144320e48..e6ae3d38d7 100644
--- a/tools/virtiofsd/passthrough_ll.c
+++ b/tools/virtiofsd/passthrough_ll.c
@@ -122,6 +122,7 @@ struct lo_inode {
 struct lo_cred {
     uid_t euid;
     gid_t egid;
+    mode_t umask;
 };
 
 enum {
@@ -172,6 +173,8 @@ struct lo_data {
     /* An O_PATH file descriptor to /proc/self/fd/ */
     int proc_self_fd;
     int user_killpriv_v2, killpriv_v2;
+    /* If set, virtiofsd is responsible for setting umask during creation */
+    bool change_umask;
 };
 
 static const struct fuse_opt lo_opts[] = {
@@ -1134,7 +1137,8 @@ static void lo_lookup(fuse_req_t req, fuse_ino_t parent, const char *name)
  * ownership of caller.
  * TODO: What about selinux context?
  */
-static int lo_change_cred(fuse_req_t req, struct lo_cred *old)
+static int lo_change_cred(fuse_req_t req, struct lo_cred *old,
+                          bool change_umask)
 {
     int res;
 
@@ -1154,11 +1158,14 @@ static int lo_change_cred(fuse_req_t req, struct lo_cred *old)
         return errno_save;
     }
 
+    if (change_umask) {
+        old->umask = umask(req->ctx.umask);
+    }
     return 0;
 }
 
 /* Regain Privileges */
-static void lo_restore_cred(struct lo_cred *old)
+static void lo_restore_cred(struct lo_cred *old, bool restore_umask)
 {
     int res;
 
@@ -1173,6 +1180,9 @@ static void lo_restore_cred(struct lo_cred *old)
         fuse_log(FUSE_LOG_ERR, "setegid(%u): %m\n", old->egid);
         exit(1);
     }
+
+    if (restore_umask)
+        umask(old->umask);
 }
 
 static void lo_mknod_symlink(fuse_req_t req, fuse_ino_t parent,
@@ -1202,7 +1212,7 @@ static void lo_mknod_symlink(fuse_req_t req, fuse_ino_t parent,
         return;
     }
 
-    saverr = lo_change_cred(req, &old);
+    saverr = lo_change_cred(req, &old, lo->change_umask && !S_ISLNK(mode));
     if (saverr) {
         goto out;
     }
@@ -1211,7 +1221,7 @@ static void lo_mknod_symlink(fuse_req_t req, fuse_ino_t parent,
 
     saverr = errno;
 
-    lo_restore_cred(&old);
+    lo_restore_cred(&old, lo->change_umask && !S_ISLNK(mode));
 
     if (res == -1) {
         goto out;
@@ -1918,7 +1928,7 @@ static void lo_create(fuse_req_t req, fuse_ino_t parent, const char *name,
         return;
     }
 
-    err = lo_change_cred(req, &old);
+    err = lo_change_cred(req, &old, lo->change_umask);
     if (err) {
         goto out;
     }
@@ -1929,7 +1939,7 @@ static void lo_create(fuse_req_t req, fuse_ino_t parent, const char *name,
     fd = openat(parent_inode->fd, name, fi->flags | O_CREAT | O_EXCL, mode);
     err = fd == -1 ? errno : 0;
 
-    lo_restore_cred(&old);
+    lo_restore_cred(&old, lo->change_umask);
 
     /* Ignore the error if file exists and O_EXCL was not given */
     if (err && (err != EEXIST || (fi->flags & O_EXCL))) {
-- 
2.25.4



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v5 3/5] virtiofsd: Add an option to enable/disable posix acls
  2021-03-25 15:38 [PATCH v5 0/5] virtiofsd: Add support to enable/disable posix acls Vivek Goyal
  2021-03-25 15:38 ` [PATCH v5 1/5] virtiofsd: Add umask to seccom allow list Vivek Goyal
  2021-03-25 15:38 ` [PATCH v5 2/5] virtiofsd: Add capability to change/restore umask Vivek Goyal
@ 2021-03-25 15:38 ` Vivek Goyal
  2021-03-25 15:38 ` [PATCH v5 4/5] virtiofsd: Add support for setxattr_v2 Vivek Goyal
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 10+ messages in thread
From: Vivek Goyal @ 2021-03-25 15:38 UTC (permalink / raw)
  To: qemu-devel, virtio-fs; +Cc: lhenriques, dgilbert, vgoyal, miklos

fuse has an option FUSE_POSIX_ACL which needs to be opted in by fuse
server to enable posix acls. As of now we are not opting in for this,
so posix acls are disabled on virtiofs by default.

Add virtiofsd option "-o posix_acl/no_posix_acl" to let users enable/disable
posix acl support. By default it is disabled as of now due to performance
concerns with cache=none.

Currently even if file server has not opted in for FUSE_POSIX_ACL, user can
still query acl and set acl, and system.posix_acl_access and
system.posix_acl_default xattrs show up listxattr response.

Miklos said this is confusing. So he said lets block and filter
system.posix_acl_access and system.posix_acl_default xattrs in
getxattr/setxattr/listxattr if user has explicitly disabled
posix acls using -o no_posix_acl.

As of now continuing to keeping the existing behavior if user did not
specify any option to disable acl support due to concerns about backward
compatibility.

Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
---
 docs/tools/virtiofsd.rst         |   3 +
 tools/virtiofsd/helper.c         |   1 +
 tools/virtiofsd/passthrough_ll.c | 103 ++++++++++++++++++++++++++++++-
 3 files changed, 106 insertions(+), 1 deletion(-)

diff --git a/docs/tools/virtiofsd.rst b/docs/tools/virtiofsd.rst
index 00554c75bd..a41f934999 100644
--- a/docs/tools/virtiofsd.rst
+++ b/docs/tools/virtiofsd.rst
@@ -101,6 +101,9 @@ Options
     Enable/disable extended attributes (xattr) on files and directories.  The
     default is ``no_xattr``.
 
+  * posix_acl|no_posix_acl -
+    Enable/disable posix acl support.  Posix ACLs are disabled by default`.
+
 .. option:: --socket-path=PATH
 
   Listen on vhost-user UNIX domain socket at PATH.
diff --git a/tools/virtiofsd/helper.c b/tools/virtiofsd/helper.c
index 28243b51b2..800a1a6801 100644
--- a/tools/virtiofsd/helper.c
+++ b/tools/virtiofsd/helper.c
@@ -183,6 +183,7 @@ void fuse_cmdline_help(void)
            "                               to virtiofsd from guest applications.\n"
            "                               default: no_allow_direct_io\n"
            "    -o announce_submounts      Announce sub-mount points to the guest\n"
+           "    -o posix_acl/no_posix_acl  Enable/Disable posix_acl. (default: disabled)\n"
            );
 }
 
diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c
index e6ae3d38d7..f5fcdeba15 100644
--- a/tools/virtiofsd/passthrough_ll.c
+++ b/tools/virtiofsd/passthrough_ll.c
@@ -175,6 +175,7 @@ struct lo_data {
     int user_killpriv_v2, killpriv_v2;
     /* If set, virtiofsd is responsible for setting umask during creation */
     bool change_umask;
+    int user_posix_acl;
 };
 
 static const struct fuse_opt lo_opts[] = {
@@ -207,6 +208,8 @@ static const struct fuse_opt lo_opts[] = {
     { "announce_submounts", offsetof(struct lo_data, announce_submounts), 1 },
     { "killpriv_v2", offsetof(struct lo_data, user_killpriv_v2), 1 },
     { "no_killpriv_v2", offsetof(struct lo_data, user_killpriv_v2), 0 },
+    { "posix_acl", offsetof(struct lo_data, user_posix_acl), 1 },
+    { "no_posix_acl", offsetof(struct lo_data, user_posix_acl), 0 },
     FUSE_OPT_END
 };
 static bool use_syslog = false;
@@ -705,6 +708,21 @@ static void lo_init(void *userdata, struct fuse_conn_info *conn)
         conn->want &= ~FUSE_CAP_HANDLE_KILLPRIV_V2;
         lo->killpriv_v2 = 0;
     }
+
+    if (lo->user_posix_acl == 1) {
+        /*
+         * User explicitly asked for this option. Enable it unconditionally.
+         * If connection does not have this capability, it should fail
+         * in fuse_lowlevel.c
+         */
+        fuse_log(FUSE_LOG_DEBUG, "lo_init: enabling posix acl\n");
+        conn->want |= FUSE_CAP_POSIX_ACL | FUSE_CAP_DONT_MASK;
+        lo->change_umask = true;
+    } else {
+        /* User either did not specify anything or wants it disabled */
+        fuse_log(FUSE_LOG_DEBUG, "lo_init: disabling posix_acl\n");
+        conn->want &= ~FUSE_CAP_POSIX_ACL;
+    }
 }
 
 static void lo_getattr(fuse_req_t req, fuse_ino_t ino,
@@ -2732,6 +2750,63 @@ static int xattr_map_server(const struct lo_data *lo, const char *server_name,
     return -ENODATA;
 }
 
+static bool block_xattr(struct lo_data *lo, const char *name)
+{
+    /*
+     * If user explicitly enabled posix_acl or did not provide any option,
+     * do not block acl. Otherwise block system.posix_acl_access and
+     * system.posix_acl_default xattrs.
+     */
+    if (lo->user_posix_acl) {
+        return false;
+    }
+    if (!strcmp(name, "system.posix_acl_access") ||
+        !strcmp(name, "system.posix_acl_default"))
+            return true;
+
+    return false;
+}
+
+/*
+ * Returns number of bytes in xattr_list after filtering on success. This
+ * could be zero as well if nothing is left after filtering.
+ *
+ * Returns negative error code on failure.
+ * xattr_list is modified in place.
+ */
+static int remove_blocked_xattrs(struct lo_data *lo, char *xattr_list,
+                                 unsigned in_size)
+{
+    size_t out_index, in_index;
+
+    /*
+     * As of now we only filter out acl xattrs. If acls are enabled or
+     * they have not been explicitly disabled, there is nothing to
+     * filter.
+     */
+    if (lo->user_posix_acl) {
+        return in_size;
+    }
+
+    out_index = 0;
+    in_index = 0;
+    while (in_index < in_size) {
+        char *in_ptr = xattr_list + in_index;
+
+        /* Length of current attribute name */
+        size_t in_len = strlen(xattr_list + in_index) + 1;
+
+        if (!block_xattr(lo, in_ptr)) {
+            if (in_index != out_index) {
+                memmove(xattr_list + out_index, xattr_list + in_index, in_len);
+            }
+            out_index += in_len;
+        }
+        in_index += in_len;
+     }
+    return out_index;
+}
+
 static void lo_getxattr(fuse_req_t req, fuse_ino_t ino, const char *in_name,
                         size_t size)
 {
@@ -2745,6 +2820,11 @@ static void lo_getxattr(fuse_req_t req, fuse_ino_t ino, const char *in_name,
     int saverr;
     int fd = -1;
 
+    if (block_xattr(lo, in_name)) {
+        fuse_reply_err(req, EOPNOTSUPP);
+        return;
+    }
+
     mapped_name = NULL;
     name = in_name;
     if (lo->xattrmap) {
@@ -2886,7 +2966,6 @@ static void lo_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size)
         if (ret == 0) {
             goto out;
         }
-
         if (lo->xattr_map_list) {
             /*
              * Map the names back, some attributes might be dropped,
@@ -2933,6 +3012,12 @@ static void lo_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size)
                 goto out;
             }
         }
+
+        ret = remove_blocked_xattrs(lo, value, ret);
+        if (ret <= 0) {
+            saverr = -ret;
+            goto out;
+        }
         fuse_reply_buf(req, value, ret);
     } else {
         /*
@@ -2971,6 +3056,11 @@ static void lo_setxattr(fuse_req_t req, fuse_ino_t ino, const char *in_name,
     int saverr;
     int fd = -1;
 
+    if (block_xattr(lo, in_name)) {
+        fuse_reply_err(req, EOPNOTSUPP);
+        return;
+    }
+
     mapped_name = NULL;
     name = in_name;
     if (lo->xattrmap) {
@@ -3037,6 +3127,11 @@ static void lo_removexattr(fuse_req_t req, fuse_ino_t ino, const char *in_name)
     int saverr;
     int fd = -1;
 
+    if (block_xattr(lo, in_name)) {
+        fuse_reply_err(req, EOPNOTSUPP);
+        return;
+    }
+
     mapped_name = NULL;
     name = in_name;
     if (lo->xattrmap) {
@@ -3730,6 +3825,7 @@ int main(int argc, char *argv[])
         .allow_direct_io = 0,
         .proc_self_fd = -1,
         .user_killpriv_v2 = -1,
+        .user_posix_acl = -1,
     };
     struct lo_map_elem *root_elem;
     struct lo_map_elem *reserve_elem;
@@ -3857,6 +3953,11 @@ int main(int argc, char *argv[])
         exit(1);
     }
 
+    if (lo.user_posix_acl == 1 && !lo.xattr) {
+        fuse_log(FUSE_LOG_ERR, "Can't enable posix ACLs. xattrs are disabled.\n");
+        exit(1);
+    }
+
     lo.use_statx = true;
 
     se = fuse_session_new(&args, &lo_oper, sizeof(lo_oper), &lo);
-- 
2.25.4



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v5 4/5] virtiofsd: Add support for setxattr_v2
  2021-03-25 15:38 [PATCH v5 0/5] virtiofsd: Add support to enable/disable posix acls Vivek Goyal
                   ` (2 preceding siblings ...)
  2021-03-25 15:38 ` [PATCH v5 3/5] virtiofsd: Add an option to enable/disable posix acls Vivek Goyal
@ 2021-03-25 15:38 ` Vivek Goyal
  2021-03-25 15:38 ` [PATCH v5 5/5] virtiofsd: Switch creds, drop FSETID for system.posix_acl_access xattr Vivek Goyal
  2021-03-25 16:03 ` [PATCH v5 0/5] virtiofsd: Add support to enable/disable posix acls no-reply
  5 siblings, 0 replies; 10+ messages in thread
From: Vivek Goyal @ 2021-03-25 15:38 UTC (permalink / raw)
  To: qemu-devel, virtio-fs; +Cc: lhenriques, dgilbert, vgoyal, miklos

Add the bits to enable support for setxattr_v2 if fuse offers it.

Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
---
 include/standard-headers/linux/fuse.h | 12 +++++++-
 tools/virtiofsd/fuse_common.h         |  6 ++++
 tools/virtiofsd/fuse_lowlevel.c       | 42 ++++++++++++++++++++++++++-
 tools/virtiofsd/fuse_lowlevel.h       |  3 +-
 tools/virtiofsd/passthrough_ll.c      |  3 +-
 5 files changed, 62 insertions(+), 4 deletions(-)

diff --git a/include/standard-headers/linux/fuse.h b/include/standard-headers/linux/fuse.h
index 950d7edb7e..cc87ff27d0 100644
--- a/include/standard-headers/linux/fuse.h
+++ b/include/standard-headers/linux/fuse.h
@@ -179,6 +179,7 @@
  *  7.33
  *  - add FUSE_HANDLE_KILLPRIV_V2, FUSE_WRITE_KILL_SUIDGID, FATTR_KILL_SUIDGID
  *  - add FUSE_OPEN_KILL_SUIDGID
+ *  - add FUSE_SETXATTR_V2
  */
 
 #ifndef _LINUX_FUSE_H
@@ -210,7 +211,7 @@
 #define FUSE_KERNEL_VERSION 7
 
 /** Minor version number of this interface */
-#define FUSE_KERNEL_MINOR_VERSION 33
+#define FUSE_KERNEL_MINOR_VERSION 34
 
 /** The node ID of the root inode */
 #define FUSE_ROOT_ID 1
@@ -326,6 +327,7 @@ struct fuse_file_lock {
  *			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_V2:	Does file server support V2 of struct fuse_setxattr_in
  */
 #define FUSE_ASYNC_READ		(1 << 0)
 #define FUSE_POSIX_LOCKS	(1 << 1)
@@ -356,6 +358,7 @@ struct fuse_file_lock {
 #define FUSE_MAP_ALIGNMENT	(1 << 26)
 #define FUSE_SUBMOUNTS		(1 << 27)
 #define FUSE_HANDLE_KILLPRIV_V2	(1 << 28)
+#define FUSE_SETXATTR_V2	(1 << 29)
 
 /**
  * CUSE INIT request/reply flags
@@ -682,6 +685,13 @@ struct fuse_setxattr_in {
 	uint32_t	flags;
 };
 
+struct fuse_setxattr_in_v2 {
+	uint32_t	size;
+	uint32_t	flags;
+	uint32_t	setxattr_flags;
+	uint32_t	padding;
+};
+
 struct fuse_getxattr_in {
 	uint32_t	size;
 	uint32_t	padding;
diff --git a/tools/virtiofsd/fuse_common.h b/tools/virtiofsd/fuse_common.h
index fa9671872e..84e78c2a56 100644
--- a/tools/virtiofsd/fuse_common.h
+++ b/tools/virtiofsd/fuse_common.h
@@ -372,6 +372,12 @@ struct fuse_file_info {
  */
 #define FUSE_CAP_HANDLE_KILLPRIV_V2 (1 << 28)
 
+/**
+ * Indicates that file server will expect "struct fuse_setxattr_in_v2" type
+ * of struct in setxattr requests
+ */
+#define FUSE_CAP_SETXATTR_V2 (1 << 29)
+
 /**
  * Ioctl flags
  *
diff --git a/tools/virtiofsd/fuse_lowlevel.c b/tools/virtiofsd/fuse_lowlevel.c
index 1aa26c6333..3dcf8a5f8b 100644
--- a/tools/virtiofsd/fuse_lowlevel.c
+++ b/tools/virtiofsd/fuse_lowlevel.c
@@ -1420,6 +1420,34 @@ static void do_statfs(fuse_req_t req, fuse_ino_t nodeid,
     }
 }
 
+static void do_setxattr_v2(fuse_req_t req, fuse_ino_t nodeid,
+                           struct fuse_mbuf_iter *iter)
+{
+    struct fuse_setxattr_in_v2 *arg;
+    const char *name;
+    const char *value;
+
+    arg = fuse_mbuf_iter_advance(iter, sizeof(*arg));
+    name = fuse_mbuf_iter_advance_str(iter);
+    if (!arg || !name) {
+        fuse_reply_err(req, EINVAL);
+        return;
+    }
+
+    value = fuse_mbuf_iter_advance(iter, arg->size);
+    if (!value) {
+        fuse_reply_err(req, EINVAL);
+        return;
+    }
+
+    if (req->se->op.setxattr) {
+        req->se->op.setxattr(req, nodeid, name, value, arg->size, arg->flags,
+                             arg->setxattr_flags);
+    } else {
+        fuse_reply_err(req, ENOSYS);
+    }
+}
+
 static void do_setxattr(fuse_req_t req, fuse_ino_t nodeid,
                         struct fuse_mbuf_iter *iter)
 {
@@ -1427,6 +1455,9 @@ static void do_setxattr(fuse_req_t req, fuse_ino_t nodeid,
     const char *name;
     const char *value;
 
+    if (req->se->conn.want & FUSE_CAP_SETXATTR_V2) {
+        return do_setxattr_v2(req, nodeid, iter);
+    }
     arg = fuse_mbuf_iter_advance(iter, sizeof(*arg));
     name = fuse_mbuf_iter_advance_str(iter);
     if (!arg || !name) {
@@ -1441,7 +1472,8 @@ static void do_setxattr(fuse_req_t req, fuse_ino_t nodeid,
     }
 
     if (req->se->op.setxattr) {
-        req->se->op.setxattr(req, nodeid, name, value, arg->size, arg->flags);
+        req->se->op.setxattr(req, nodeid, name, value, arg->size, arg->flags,
+                             0);
     } else {
         fuse_reply_err(req, ENOSYS);
     }
@@ -1988,6 +2020,9 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid,
     if (arg->flags & FUSE_HANDLE_KILLPRIV_V2) {
         se->conn.capable |= FUSE_CAP_HANDLE_KILLPRIV_V2;
     }
+    if (arg->flags & FUSE_SETXATTR_V2) {
+        se->conn.capable |= FUSE_CAP_SETXATTR_V2;
+    }
 #ifdef HAVE_SPLICE
 #ifdef HAVE_VMSPLICE
     se->conn.capable |= FUSE_CAP_SPLICE_WRITE | FUSE_CAP_SPLICE_MOVE;
@@ -2020,6 +2055,7 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid,
     LL_SET_DEFAULT(se->op.readdirplus, FUSE_CAP_READDIRPLUS);
     LL_SET_DEFAULT(se->op.readdirplus && se->op.readdir,
                    FUSE_CAP_READDIRPLUS_AUTO);
+    LL_SET_DEFAULT(1, FUSE_CAP_SETXATTR_V2);
     se->conn.time_gran = 1;
 
     if (bufsize < FUSE_MIN_READ_BUFFER) {
@@ -2123,6 +2159,10 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid,
         outarg.flags |= FUSE_HANDLE_KILLPRIV_V2;
     }
 
+    if (se->conn.want & FUSE_CAP_SETXATTR_V2) {
+        outarg.flags |= FUSE_SETXATTR_V2;
+    }
+
     fuse_log(FUSE_LOG_DEBUG, "   INIT: %u.%u\n", outarg.major, outarg.minor);
     fuse_log(FUSE_LOG_DEBUG, "   flags=0x%08x\n", outarg.flags);
     fuse_log(FUSE_LOG_DEBUG, "   max_readahead=0x%08x\n", outarg.max_readahead);
diff --git a/tools/virtiofsd/fuse_lowlevel.h b/tools/virtiofsd/fuse_lowlevel.h
index 3bf786b034..4b4e8c9724 100644
--- a/tools/virtiofsd/fuse_lowlevel.h
+++ b/tools/virtiofsd/fuse_lowlevel.h
@@ -798,7 +798,8 @@ struct fuse_lowlevel_ops {
      *   fuse_reply_err
      */
     void (*setxattr)(fuse_req_t req, fuse_ino_t ino, const char *name,
-                     const char *value, size_t size, int flags);
+                     const char *value, size_t size, int flags,
+                     uint32_t setxattr_flags);
 
     /**
      * Get an extended attribute
diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c
index f5fcdeba15..3f5c267604 100644
--- a/tools/virtiofsd/passthrough_ll.c
+++ b/tools/virtiofsd/passthrough_ll.c
@@ -3045,7 +3045,8 @@ out:
 }
 
 static void lo_setxattr(fuse_req_t req, fuse_ino_t ino, const char *in_name,
-                        const char *value, size_t size, int flags)
+                        const char *value, size_t size, int flags,
+                        uint32_t extra_flags)
 {
     char procname[64];
     const char *name;
-- 
2.25.4



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v5 5/5] virtiofsd: Switch creds, drop FSETID for system.posix_acl_access xattr
  2021-03-25 15:38 [PATCH v5 0/5] virtiofsd: Add support to enable/disable posix acls Vivek Goyal
                   ` (3 preceding siblings ...)
  2021-03-25 15:38 ` [PATCH v5 4/5] virtiofsd: Add support for setxattr_v2 Vivek Goyal
@ 2021-03-25 15:38 ` Vivek Goyal
  2021-03-29 15:35   ` Luis Henriques
  2021-03-25 16:03 ` [PATCH v5 0/5] virtiofsd: Add support to enable/disable posix acls no-reply
  5 siblings, 1 reply; 10+ messages in thread
From: Vivek Goyal @ 2021-03-25 15:38 UTC (permalink / raw)
  To: qemu-devel, virtio-fs; +Cc: lhenriques, dgilbert, vgoyal, miklos

When posix access acls are set on a file, it can lead to adjusting file
permissions (mode) as well. If caller does not have CAP_FSETID and it
also does not have membership of owner group, this will lead to clearing
SGID bit in mode.

Current fuse code is written in such a way that it expects file server
to take care of chaning file mode (permission), if there is a need.
Right now, host kernel does not clear SGID bit because virtiofsd is
running as root and has CAP_FSETID. For host kernel to clear SGID,
virtiofsd need to switch to gid of caller in guest and also drop
CAP_FSETID (if caller did not have it to begin with).

If SGID needs to be cleared, client will set the flag
FUSE_SETXATTR_ACL_KILL_SGID in setxattr request. In that case server
should kill sgid.

Currently just switch to uid/gid of the caller and drop CAP_FSETID
and that should do it.

This should fix the xfstest generic/375 test case.

We don't have to switch uid for this to work. That could be one optimization
that pass a parameter to lo_change_cred() to only switch gid and not uid.

Also this will not work whenever (if ever) we support idmapped mounts. In
that case it is possible that uid/gid in request are 0/0 but still we
need to clear SGID. So we will have to pick a non-root sgid and switch
to that instead. That's an TODO item for future when idmapped mount
support is introduced.

Reported-by: Luis Henriques <lhenriques@suse.de>
Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
---
 include/standard-headers/linux/fuse.h |  7 +++++
 tools/virtiofsd/passthrough_ll.c      | 42 +++++++++++++++++++++++++--
 2 files changed, 47 insertions(+), 2 deletions(-)

diff --git a/include/standard-headers/linux/fuse.h b/include/standard-headers/linux/fuse.h
index cc87ff27d0..4eb79399d4 100644
--- a/include/standard-headers/linux/fuse.h
+++ b/include/standard-headers/linux/fuse.h
@@ -180,6 +180,7 @@
  *  - add FUSE_HANDLE_KILLPRIV_V2, FUSE_WRITE_KILL_SUIDGID, FATTR_KILL_SUIDGID
  *  - add FUSE_OPEN_KILL_SUIDGID
  *  - add FUSE_SETXATTR_V2
+ *  - add FUSE_SETXATTR_ACL_KILL_SGID
  */
 
 #ifndef _LINUX_FUSE_H
@@ -450,6 +451,12 @@ struct fuse_file_lock {
  */
 #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 */
diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c
index 3f5c267604..8a48071d0b 100644
--- a/tools/virtiofsd/passthrough_ll.c
+++ b/tools/virtiofsd/passthrough_ll.c
@@ -175,7 +175,7 @@ struct lo_data {
     int user_killpriv_v2, killpriv_v2;
     /* If set, virtiofsd is responsible for setting umask during creation */
     bool change_umask;
-    int user_posix_acl;
+    int user_posix_acl, posix_acl;
 };
 
 static const struct fuse_opt lo_opts[] = {
@@ -716,8 +716,10 @@ static void lo_init(void *userdata, struct fuse_conn_info *conn)
          * in fuse_lowlevel.c
          */
         fuse_log(FUSE_LOG_DEBUG, "lo_init: enabling posix acl\n");
-        conn->want |= FUSE_CAP_POSIX_ACL | FUSE_CAP_DONT_MASK;
+        conn->want |= FUSE_CAP_POSIX_ACL | FUSE_CAP_DONT_MASK |
+                      FUSE_CAP_SETXATTR_V2;
         lo->change_umask = true;
+        lo->posix_acl = true;
     } else {
         /* User either did not specify anything or wants it disabled */
         fuse_log(FUSE_LOG_DEBUG, "lo_init: disabling posix_acl\n");
@@ -3092,12 +3094,48 @@ static void lo_setxattr(fuse_req_t req, fuse_ino_t ino, const char *in_name,
 
     sprintf(procname, "%i", inode->fd);
     if (S_ISREG(inode->filetype) || S_ISDIR(inode->filetype)) {
+        bool switched_creds = false;
+        struct lo_cred old = {};
+
         fd = openat(lo->proc_self_fd, procname, O_RDONLY);
         if (fd < 0) {
             saverr = errno;
             goto out;
         }
+
+        /*
+         * If we are setting posix access acl and if SGID needs to be
+         * cleared, then switch to caller's gid and drop CAP_FSETID
+         * and that should make sure host kernel clears SGID.
+         *
+         * This probably will not work when we support idmapped mounts.
+         * In that case we will need to find a non-root gid and switch
+         * to it. (Instead of gid in request). Fix it when we support
+         * idmapped mounts.
+         */
+        if (lo->posix_acl && !strcmp(name, "system.posix_acl_access")
+            && (extra_flags & FUSE_SETXATTR_ACL_KILL_SGID)) {
+            ret = lo_change_cred(req, &old, false);
+            if (ret) {
+                saverr = ret;
+                goto out;
+            }
+            ret = drop_effective_cap("FSETID", NULL);
+            if (ret != 0) {
+                lo_restore_cred(&old, false);
+                saverr = ret;
+                goto out;
+            }
+            switched_creds = true;
+        }
+
         ret = fsetxattr(fd, name, value, size, flags);
+
+        if (switched_creds) {
+            if (gain_effective_cap("FSETID"))
+                fuse_log(FUSE_LOG_ERR, "Failed to gain CAP_FSETID\n");
+            lo_restore_cred(&old, false);
+        }
     } else {
         /* fchdir should not fail here */
         assert(fchdir(lo->proc_self_fd) == 0);
-- 
2.25.4



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH v5 0/5] virtiofsd: Add support to enable/disable posix acls
  2021-03-25 15:38 [PATCH v5 0/5] virtiofsd: Add support to enable/disable posix acls Vivek Goyal
                   ` (4 preceding siblings ...)
  2021-03-25 15:38 ` [PATCH v5 5/5] virtiofsd: Switch creds, drop FSETID for system.posix_acl_access xattr Vivek Goyal
@ 2021-03-25 16:03 ` no-reply
  5 siblings, 0 replies; 10+ messages in thread
From: no-reply @ 2021-03-25 16:03 UTC (permalink / raw)
  To: vgoyal; +Cc: miklos, qemu-devel, dgilbert, virtio-fs, lhenriques, vgoyal

Patchew URL: https://patchew.org/QEMU/20210325153852.572927-1-vgoyal@redhat.com/



Hi,

This series seems to have some coding style problems. See output below for
more information:

Type: series
Message-id: 20210325153852.572927-1-vgoyal@redhat.com
Subject: [PATCH v5 0/5] virtiofsd: Add support to enable/disable posix acls

=== TEST SCRIPT BEGIN ===
#!/bin/bash
git rev-parse base > /dev/null || exit 0
git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram
./scripts/checkpatch.pl --mailback base..
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
 * [new tag]         patchew/20210325153852.572927-1-vgoyal@redhat.com -> patchew/20210325153852.572927-1-vgoyal@redhat.com
Switched to a new branch 'test'
ea606d9 virtiofsd: Switch creds, drop FSETID for system.posix_acl_access xattr
bc9a877 virtiofsd: Add support for setxattr_v2
d28413e virtiofsd: Add an option to enable/disable posix acls
1eeb11f virtiofsd: Add capability to change/restore umask
0b02a25 virtiofsd: Add umask to seccom allow list

=== OUTPUT BEGIN ===
1/5 Checking commit 0b02a2507048 (virtiofsd: Add umask to seccom allow list)
2/5 Checking commit 1eeb11f00fdb (virtiofsd: Add capability to change/restore umask)
3/5 Checking commit d28413e66e58 (virtiofsd: Add an option to enable/disable posix acls)
WARNING: line over 80 characters
#239: FILE: tools/virtiofsd/passthrough_ll.c:3957:
+        fuse_log(FUSE_LOG_ERR, "Can't enable posix ACLs. xattrs are disabled.\n");

total: 0 errors, 1 warnings, 185 lines checked

Patch 3/5 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
4/5 Checking commit bc9a8776c947 (virtiofsd: Add support for setxattr_v2)
5/5 Checking commit ea606d9de8f0 (virtiofsd: Switch creds, drop FSETID for system.posix_acl_access xattr)
ERROR: braces {} are necessary for all arms of this statement
#137: FILE: tools/virtiofsd/passthrough_ll.c:3135:
+            if (gain_effective_cap("FSETID"))
[...]

total: 1 errors, 0 warnings, 86 lines checked

Patch 5/5 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

=== OUTPUT END ===

Test command exited with code: 1


The full log is available at
http://patchew.org/logs/20210325153852.572927-1-vgoyal@redhat.com/testing.checkpatch/?type=message.
---
Email generated automatically by Patchew [https://patchew.org/].
Please send your feedback to patchew-devel@redhat.com

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v5 5/5] virtiofsd: Switch creds, drop FSETID for system.posix_acl_access xattr
  2021-03-25 15:38 ` [PATCH v5 5/5] virtiofsd: Switch creds, drop FSETID for system.posix_acl_access xattr Vivek Goyal
@ 2021-03-29 15:35   ` Luis Henriques
  2021-03-29 19:51     ` Vivek Goyal
  0 siblings, 1 reply; 10+ messages in thread
From: Luis Henriques @ 2021-03-29 15:35 UTC (permalink / raw)
  To: Vivek Goyal; +Cc: virtio-fs, miklos, qemu-devel, dgilbert

On Thu, Mar 25, 2021 at 11:38:52AM -0400, Vivek Goyal wrote:
> When posix access acls are set on a file, it can lead to adjusting file
> permissions (mode) as well. If caller does not have CAP_FSETID and it
> also does not have membership of owner group, this will lead to clearing
> SGID bit in mode.
> 
> Current fuse code is written in such a way that it expects file server
> to take care of chaning file mode (permission), if there is a need.
> Right now, host kernel does not clear SGID bit because virtiofsd is
> running as root and has CAP_FSETID. For host kernel to clear SGID,
> virtiofsd need to switch to gid of caller in guest and also drop
> CAP_FSETID (if caller did not have it to begin with).
> 
> If SGID needs to be cleared, client will set the flag
> FUSE_SETXATTR_ACL_KILL_SGID in setxattr request. In that case server
> should kill sgid.
> 
> Currently just switch to uid/gid of the caller and drop CAP_FSETID
> and that should do it.
> 
> This should fix the xfstest generic/375 test case.
> 
> We don't have to switch uid for this to work. That could be one optimization
> that pass a parameter to lo_change_cred() to only switch gid and not uid.
> 
> Also this will not work whenever (if ever) we support idmapped mounts. In
> that case it is possible that uid/gid in request are 0/0 but still we
> need to clear SGID. So we will have to pick a non-root sgid and switch
> to that instead. That's an TODO item for future when idmapped mount
> support is introduced.
> 
> Reported-by: Luis Henriques <lhenriques@suse.de>
> Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
> ---
>  include/standard-headers/linux/fuse.h |  7 +++++
>  tools/virtiofsd/passthrough_ll.c      | 42 +++++++++++++++++++++++++--
>  2 files changed, 47 insertions(+), 2 deletions(-)
> 
> diff --git a/include/standard-headers/linux/fuse.h b/include/standard-headers/linux/fuse.h
> index cc87ff27d0..4eb79399d4 100644
> --- a/include/standard-headers/linux/fuse.h
> +++ b/include/standard-headers/linux/fuse.h
> @@ -180,6 +180,7 @@
>   *  - add FUSE_HANDLE_KILLPRIV_V2, FUSE_WRITE_KILL_SUIDGID, FATTR_KILL_SUIDGID
>   *  - add FUSE_OPEN_KILL_SUIDGID
>   *  - add FUSE_SETXATTR_V2
> + *  - add FUSE_SETXATTR_ACL_KILL_SGID
>   */
>  
>  #ifndef _LINUX_FUSE_H
> @@ -450,6 +451,12 @@ struct fuse_file_lock {
>   */
>  #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 */
> diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c
> index 3f5c267604..8a48071d0b 100644
> --- a/tools/virtiofsd/passthrough_ll.c
> +++ b/tools/virtiofsd/passthrough_ll.c
> @@ -175,7 +175,7 @@ struct lo_data {
>      int user_killpriv_v2, killpriv_v2;
>      /* If set, virtiofsd is responsible for setting umask during creation */
>      bool change_umask;
> -    int user_posix_acl;
> +    int user_posix_acl, posix_acl;
>  };
>  
>  static const struct fuse_opt lo_opts[] = {
> @@ -716,8 +716,10 @@ static void lo_init(void *userdata, struct fuse_conn_info *conn)
>           * in fuse_lowlevel.c
>           */
>          fuse_log(FUSE_LOG_DEBUG, "lo_init: enabling posix acl\n");
> -        conn->want |= FUSE_CAP_POSIX_ACL | FUSE_CAP_DONT_MASK;
> +        conn->want |= FUSE_CAP_POSIX_ACL | FUSE_CAP_DONT_MASK |
> +                      FUSE_CAP_SETXATTR_V2;

An annoying thing with this is that if we're using a kernel without
_V2 support the mount will still succeed.  But we'll see:

ls: cannot access '/mnt': Connection refused

and in the userspace:

fuse: error: filesystem requested capabilities 0x20000000 that are not supported by kernel, aborting.

Maybe it would be worth to automatically disable acl support if this
happens (with an error message) but still allow the filesystem to be
used.  Or, which is probably better, to handle the EPROTO error in the
kernel during mount.

Cheers,
--
Luís

>          lo->change_umask = true;
> +        lo->posix_acl = true;
>      } else {
>          /* User either did not specify anything or wants it disabled */
>          fuse_log(FUSE_LOG_DEBUG, "lo_init: disabling posix_acl\n");
> @@ -3092,12 +3094,48 @@ static void lo_setxattr(fuse_req_t req, fuse_ino_t ino, const char *in_name,
>  
>      sprintf(procname, "%i", inode->fd);
>      if (S_ISREG(inode->filetype) || S_ISDIR(inode->filetype)) {
> +        bool switched_creds = false;
> +        struct lo_cred old = {};
> +
>          fd = openat(lo->proc_self_fd, procname, O_RDONLY);
>          if (fd < 0) {
>              saverr = errno;
>              goto out;
>          }
> +
> +        /*
> +         * If we are setting posix access acl and if SGID needs to be
> +         * cleared, then switch to caller's gid and drop CAP_FSETID
> +         * and that should make sure host kernel clears SGID.
> +         *
> +         * This probably will not work when we support idmapped mounts.
> +         * In that case we will need to find a non-root gid and switch
> +         * to it. (Instead of gid in request). Fix it when we support
> +         * idmapped mounts.
> +         */
> +        if (lo->posix_acl && !strcmp(name, "system.posix_acl_access")
> +            && (extra_flags & FUSE_SETXATTR_ACL_KILL_SGID)) {
> +            ret = lo_change_cred(req, &old, false);
> +            if (ret) {
> +                saverr = ret;
> +                goto out;
> +            }
> +            ret = drop_effective_cap("FSETID", NULL);
> +            if (ret != 0) {
> +                lo_restore_cred(&old, false);
> +                saverr = ret;
> +                goto out;
> +            }
> +            switched_creds = true;
> +        }
> +
>          ret = fsetxattr(fd, name, value, size, flags);
> +
> +        if (switched_creds) {
> +            if (gain_effective_cap("FSETID"))
> +                fuse_log(FUSE_LOG_ERR, "Failed to gain CAP_FSETID\n");
> +            lo_restore_cred(&old, false);
> +        }
>      } else {
>          /* fchdir should not fail here */
>          assert(fchdir(lo->proc_self_fd) == 0);
> -- 
> 2.25.4
> 


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v5 5/5] virtiofsd: Switch creds, drop FSETID for system.posix_acl_access xattr
  2021-03-29 15:35   ` Luis Henriques
@ 2021-03-29 19:51     ` Vivek Goyal
  2021-03-30  9:37       ` Luis Henriques
  0 siblings, 1 reply; 10+ messages in thread
From: Vivek Goyal @ 2021-03-29 19:51 UTC (permalink / raw)
  To: Luis Henriques; +Cc: virtio-fs, miklos, qemu-devel, dgilbert

On Mon, Mar 29, 2021 at 04:35:57PM +0100, Luis Henriques wrote:
> On Thu, Mar 25, 2021 at 11:38:52AM -0400, Vivek Goyal wrote:
> > When posix access acls are set on a file, it can lead to adjusting file
> > permissions (mode) as well. If caller does not have CAP_FSETID and it
> > also does not have membership of owner group, this will lead to clearing
> > SGID bit in mode.
> > 
> > Current fuse code is written in such a way that it expects file server
> > to take care of chaning file mode (permission), if there is a need.
> > Right now, host kernel does not clear SGID bit because virtiofsd is
> > running as root and has CAP_FSETID. For host kernel to clear SGID,
> > virtiofsd need to switch to gid of caller in guest and also drop
> > CAP_FSETID (if caller did not have it to begin with).
> > 
> > If SGID needs to be cleared, client will set the flag
> > FUSE_SETXATTR_ACL_KILL_SGID in setxattr request. In that case server
> > should kill sgid.
> > 
> > Currently just switch to uid/gid of the caller and drop CAP_FSETID
> > and that should do it.
> > 
> > This should fix the xfstest generic/375 test case.
> > 
> > We don't have to switch uid for this to work. That could be one optimization
> > that pass a parameter to lo_change_cred() to only switch gid and not uid.
> > 
> > Also this will not work whenever (if ever) we support idmapped mounts. In
> > that case it is possible that uid/gid in request are 0/0 but still we
> > need to clear SGID. So we will have to pick a non-root sgid and switch
> > to that instead. That's an TODO item for future when idmapped mount
> > support is introduced.
> > 
> > Reported-by: Luis Henriques <lhenriques@suse.de>
> > Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
> > ---
> >  include/standard-headers/linux/fuse.h |  7 +++++
> >  tools/virtiofsd/passthrough_ll.c      | 42 +++++++++++++++++++++++++--
> >  2 files changed, 47 insertions(+), 2 deletions(-)
> > 
> > diff --git a/include/standard-headers/linux/fuse.h b/include/standard-headers/linux/fuse.h
> > index cc87ff27d0..4eb79399d4 100644
> > --- a/include/standard-headers/linux/fuse.h
> > +++ b/include/standard-headers/linux/fuse.h
> > @@ -180,6 +180,7 @@
> >   *  - add FUSE_HANDLE_KILLPRIV_V2, FUSE_WRITE_KILL_SUIDGID, FATTR_KILL_SUIDGID
> >   *  - add FUSE_OPEN_KILL_SUIDGID
> >   *  - add FUSE_SETXATTR_V2
> > + *  - add FUSE_SETXATTR_ACL_KILL_SGID
> >   */
> >  
> >  #ifndef _LINUX_FUSE_H
> > @@ -450,6 +451,12 @@ struct fuse_file_lock {
> >   */
> >  #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 */
> > diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c
> > index 3f5c267604..8a48071d0b 100644
> > --- a/tools/virtiofsd/passthrough_ll.c
> > +++ b/tools/virtiofsd/passthrough_ll.c
> > @@ -175,7 +175,7 @@ struct lo_data {
> >      int user_killpriv_v2, killpriv_v2;
> >      /* If set, virtiofsd is responsible for setting umask during creation */
> >      bool change_umask;
> > -    int user_posix_acl;
> > +    int user_posix_acl, posix_acl;
> >  };
> >  
> >  static const struct fuse_opt lo_opts[] = {
> > @@ -716,8 +716,10 @@ static void lo_init(void *userdata, struct fuse_conn_info *conn)
> >           * in fuse_lowlevel.c
> >           */
> >          fuse_log(FUSE_LOG_DEBUG, "lo_init: enabling posix acl\n");
> > -        conn->want |= FUSE_CAP_POSIX_ACL | FUSE_CAP_DONT_MASK;
> > +        conn->want |= FUSE_CAP_POSIX_ACL | FUSE_CAP_DONT_MASK |
> > +                      FUSE_CAP_SETXATTR_V2;
> 
> An annoying thing with this is that if we're using a kernel without
> _V2 support the mount will still succeed.  But we'll see:
> 
> ls: cannot access '/mnt': Connection refused
> 
> and in the userspace:
> 
> fuse: error: filesystem requested capabilities 0x20000000 that are not supported by kernel, aborting.
> 
> Maybe it would be worth to automatically disable acl support if this
> happens (with an error message) but still allow the filesystem to be
> used.

If user specific "-o posix_acl" then it is better to fail explicitly
if posix_acl can't be enabled. If user did not specify anything, then
it makes sense to automatically disable posix acl  and continue.

> Or, which is probably better, to handle the EPROTO error in the
> kernel during mount.

This will have been idea but in fuse, init process handling happens
asynchronously. That is mount returns to user space while init
command might complete at a later point of time. So can't return
-EPROTO at mount time.

So one of the problems seem to be that error message is not very
clear. How about adding following so that user is clear that posix acl
can't be enabled.

Vivek

---
 tools/virtiofsd/passthrough_ll.c |   14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

Index: rhvgoyal-qemu/tools/virtiofsd/passthrough_ll.c
===================================================================
--- rhvgoyal-qemu.orig/tools/virtiofsd/passthrough_ll.c	2021-03-29 14:59:28.483340964 -0400
+++ rhvgoyal-qemu/tools/virtiofsd/passthrough_ll.c	2021-03-29 15:42:21.797482846 -0400
@@ -712,10 +712,18 @@ static void lo_init(void *userdata, stru
     if (lo->user_posix_acl == 1) {
         /*
          * User explicitly asked for this option. Enable it unconditionally.
-         * If connection does not have this capability, it should fail
-         * in fuse_lowlevel.c
+         * If connection does not have this capability, give out message
+         * now. fuse_lowlevel.c will error out.
          */
-        fuse_log(FUSE_LOG_DEBUG, "lo_init: enabling posix acl\n");
+        if (!(conn->capable & FUSE_CAP_POSIX_ACL) ||
+            !(conn->capable & FUSE_CAP_DONT_MASK) ||
+            !(conn->capable & FUSE_CAP_SETXATTR_V2)) {
+            fuse_log(FUSE_LOG_ERR, "lo_init: Can not enable posix acl."
+                     " kernel does not support FUSE_POSIX_ACL, FUSE_DONT_MASK"
+                     " or FUSE_SETXATTR_V2 capability.\n");
+        } else {
+            fuse_log(FUSE_LOG_DEBUG, "lo_init: enabling posix acl\n");
+        }
         conn->want |= FUSE_CAP_POSIX_ACL | FUSE_CAP_DONT_MASK |
                       FUSE_CAP_SETXATTR_V2;
         lo->change_umask = true;




^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v5 5/5] virtiofsd: Switch creds, drop FSETID for system.posix_acl_access xattr
  2021-03-29 19:51     ` Vivek Goyal
@ 2021-03-30  9:37       ` Luis Henriques
  0 siblings, 0 replies; 10+ messages in thread
From: Luis Henriques @ 2021-03-30  9:37 UTC (permalink / raw)
  To: Vivek Goyal; +Cc: virtio-fs, miklos, qemu-devel, dgilbert

On Mon, Mar 29, 2021 at 03:51:51PM -0400, Vivek Goyal wrote:
> On Mon, Mar 29, 2021 at 04:35:57PM +0100, Luis Henriques wrote:
> > On Thu, Mar 25, 2021 at 11:38:52AM -0400, Vivek Goyal wrote:
> > > When posix access acls are set on a file, it can lead to adjusting file
> > > permissions (mode) as well. If caller does not have CAP_FSETID and it
> > > also does not have membership of owner group, this will lead to clearing
> > > SGID bit in mode.
> > > 
> > > Current fuse code is written in such a way that it expects file server
> > > to take care of chaning file mode (permission), if there is a need.
> > > Right now, host kernel does not clear SGID bit because virtiofsd is
> > > running as root and has CAP_FSETID. For host kernel to clear SGID,
> > > virtiofsd need to switch to gid of caller in guest and also drop
> > > CAP_FSETID (if caller did not have it to begin with).
> > > 
> > > If SGID needs to be cleared, client will set the flag
> > > FUSE_SETXATTR_ACL_KILL_SGID in setxattr request. In that case server
> > > should kill sgid.
> > > 
> > > Currently just switch to uid/gid of the caller and drop CAP_FSETID
> > > and that should do it.
> > > 
> > > This should fix the xfstest generic/375 test case.
> > > 
> > > We don't have to switch uid for this to work. That could be one optimization
> > > that pass a parameter to lo_change_cred() to only switch gid and not uid.
> > > 
> > > Also this will not work whenever (if ever) we support idmapped mounts. In
> > > that case it is possible that uid/gid in request are 0/0 but still we
> > > need to clear SGID. So we will have to pick a non-root sgid and switch
> > > to that instead. That's an TODO item for future when idmapped mount
> > > support is introduced.
> > > 
> > > Reported-by: Luis Henriques <lhenriques@suse.de>
> > > Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
> > > ---
> > >  include/standard-headers/linux/fuse.h |  7 +++++
> > >  tools/virtiofsd/passthrough_ll.c      | 42 +++++++++++++++++++++++++--
> > >  2 files changed, 47 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/include/standard-headers/linux/fuse.h b/include/standard-headers/linux/fuse.h
> > > index cc87ff27d0..4eb79399d4 100644
> > > --- a/include/standard-headers/linux/fuse.h
> > > +++ b/include/standard-headers/linux/fuse.h
> > > @@ -180,6 +180,7 @@
> > >   *  - add FUSE_HANDLE_KILLPRIV_V2, FUSE_WRITE_KILL_SUIDGID, FATTR_KILL_SUIDGID
> > >   *  - add FUSE_OPEN_KILL_SUIDGID
> > >   *  - add FUSE_SETXATTR_V2
> > > + *  - add FUSE_SETXATTR_ACL_KILL_SGID
> > >   */
> > >  
> > >  #ifndef _LINUX_FUSE_H
> > > @@ -450,6 +451,12 @@ struct fuse_file_lock {
> > >   */
> > >  #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 */
> > > diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c
> > > index 3f5c267604..8a48071d0b 100644
> > > --- a/tools/virtiofsd/passthrough_ll.c
> > > +++ b/tools/virtiofsd/passthrough_ll.c
> > > @@ -175,7 +175,7 @@ struct lo_data {
> > >      int user_killpriv_v2, killpriv_v2;
> > >      /* If set, virtiofsd is responsible for setting umask during creation */
> > >      bool change_umask;
> > > -    int user_posix_acl;
> > > +    int user_posix_acl, posix_acl;
> > >  };
> > >  
> > >  static const struct fuse_opt lo_opts[] = {
> > > @@ -716,8 +716,10 @@ static void lo_init(void *userdata, struct fuse_conn_info *conn)
> > >           * in fuse_lowlevel.c
> > >           */
> > >          fuse_log(FUSE_LOG_DEBUG, "lo_init: enabling posix acl\n");
> > > -        conn->want |= FUSE_CAP_POSIX_ACL | FUSE_CAP_DONT_MASK;
> > > +        conn->want |= FUSE_CAP_POSIX_ACL | FUSE_CAP_DONT_MASK |
> > > +                      FUSE_CAP_SETXATTR_V2;
> > 
> > An annoying thing with this is that if we're using a kernel without
> > _V2 support the mount will still succeed.  But we'll see:
> > 
> > ls: cannot access '/mnt': Connection refused
> > 
> > and in the userspace:
> > 
> > fuse: error: filesystem requested capabilities 0x20000000 that are not supported by kernel, aborting.
> > 
> > Maybe it would be worth to automatically disable acl support if this
> > happens (with an error message) but still allow the filesystem to be
> > used.
> 
> If user specific "-o posix_acl" then it is better to fail explicitly
> if posix_acl can't be enabled. If user did not specify anything, then
> it makes sense to automatically disable posix acl  and continue.
> 
> > Or, which is probably better, to handle the EPROTO error in the
> > kernel during mount.
> 
> This will have been idea but in fuse, init process handling happens
> asynchronously. That is mount returns to user space while init
> command might complete at a later point of time. So can't return
> -EPROTO at mount time.

Oh, right.  I remember the first time I looked that I found it a bit odd
that fuse_send_init() didn't wait to return an error.  So, my suggestion
isn't feasible.

> So one of the problems seem to be that error message is not very
> clear. How about adding following so that user is clear that posix acl
> can't be enabled.

Thanks, I think this extra information is indeed useful.

Cheers,
--
Luís

> 
> Vivek
> 
> ---
>  tools/virtiofsd/passthrough_ll.c |   14 +++++++++++---
>  1 file changed, 11 insertions(+), 3 deletions(-)
> 
> Index: rhvgoyal-qemu/tools/virtiofsd/passthrough_ll.c
> ===================================================================
> --- rhvgoyal-qemu.orig/tools/virtiofsd/passthrough_ll.c	2021-03-29 14:59:28.483340964 -0400
> +++ rhvgoyal-qemu/tools/virtiofsd/passthrough_ll.c	2021-03-29 15:42:21.797482846 -0400
> @@ -712,10 +712,18 @@ static void lo_init(void *userdata, stru
>      if (lo->user_posix_acl == 1) {
>          /*
>           * User explicitly asked for this option. Enable it unconditionally.
> -         * If connection does not have this capability, it should fail
> -         * in fuse_lowlevel.c
> +         * If connection does not have this capability, give out message
> +         * now. fuse_lowlevel.c will error out.
>           */
> -        fuse_log(FUSE_LOG_DEBUG, "lo_init: enabling posix acl\n");
> +        if (!(conn->capable & FUSE_CAP_POSIX_ACL) ||
> +            !(conn->capable & FUSE_CAP_DONT_MASK) ||
> +            !(conn->capable & FUSE_CAP_SETXATTR_V2)) {
> +            fuse_log(FUSE_LOG_ERR, "lo_init: Can not enable posix acl."
> +                     " kernel does not support FUSE_POSIX_ACL, FUSE_DONT_MASK"
> +                     " or FUSE_SETXATTR_V2 capability.\n");
> +        } else {
> +            fuse_log(FUSE_LOG_DEBUG, "lo_init: enabling posix acl\n");
> +        }
>          conn->want |= FUSE_CAP_POSIX_ACL | FUSE_CAP_DONT_MASK |
>                        FUSE_CAP_SETXATTR_V2;
>          lo->change_umask = true;
> 
> 


^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2021-03-30  9:36 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-03-25 15:38 [PATCH v5 0/5] virtiofsd: Add support to enable/disable posix acls Vivek Goyal
2021-03-25 15:38 ` [PATCH v5 1/5] virtiofsd: Add umask to seccom allow list Vivek Goyal
2021-03-25 15:38 ` [PATCH v5 2/5] virtiofsd: Add capability to change/restore umask Vivek Goyal
2021-03-25 15:38 ` [PATCH v5 3/5] virtiofsd: Add an option to enable/disable posix acls Vivek Goyal
2021-03-25 15:38 ` [PATCH v5 4/5] virtiofsd: Add support for setxattr_v2 Vivek Goyal
2021-03-25 15:38 ` [PATCH v5 5/5] virtiofsd: Switch creds, drop FSETID for system.posix_acl_access xattr Vivek Goyal
2021-03-29 15:35   ` Luis Henriques
2021-03-29 19:51     ` Vivek Goyal
2021-03-30  9:37       ` Luis Henriques
2021-03-25 16:03 ` [PATCH v5 0/5] virtiofsd: Add support to enable/disable posix acls no-reply

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).