d73434f
From 449e8171f96a6a944d1f3b7d3627ae059eae21ca Mon Sep 17 00:00:00 2001
d73434f
From: Vivek Goyal <vgoyal@redhat.com>
d73434f
Date: Tue, 25 Jan 2022 13:51:14 -0500
d73434f
Subject: [PATCH] virtiofsd: Drop membership of all supplementary groups
d73434f
 (CVE-2022-0358)
d73434f
d73434f
At the start, drop membership of all supplementary groups. This is
d73434f
not required.
d73434f
d73434f
If we have membership of "root" supplementary group and when we switch
d73434f
uid/gid using setresuid/setsgid, we still retain membership of existing
d73434f
supplemntary groups. And that can allow some operations which are not
d73434f
normally allowed.
d73434f
d73434f
For example, if root in guest creates a dir as follows.
d73434f
d73434f
$ mkdir -m 03777 test_dir
d73434f
d73434f
This sets SGID on dir as well as allows unprivileged users to write into
d73434f
this dir.
d73434f
d73434f
And now as unprivileged user open file as follows.
d73434f
d73434f
$ su test
d73434f
$ fd = open("test_dir/priviledge_id", O_RDWR|O_CREAT|O_EXCL, 02755);
d73434f
d73434f
This will create SGID set executable in test_dir/.
d73434f
d73434f
And that's a problem because now an unpriviliged user can execute it,
d73434f
get egid=0 and get access to resources owned by "root" group. This is
d73434f
privilege escalation.
d73434f
d73434f
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=2044863
d73434f
Fixes: CVE-2022-0358
d73434f
Reported-by: JIETAO XIAO <shawtao1125@gmail.com>
d73434f
Suggested-by: Miklos Szeredi <mszeredi@redhat.com>
d73434f
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
d73434f
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
d73434f
Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
d73434f
Message-Id: <YfBGoriS38eBQrAb@redhat.com>
d73434f
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
d73434f
  dgilbert: Fixed missing {}'s style nit
d73434f
---
d73434f
 tools/virtiofsd/passthrough_ll.c | 27 +++++++++++++++++++++++++++
d73434f
 1 file changed, 27 insertions(+)
d73434f
d73434f
diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c
d73434f
index 64b5b4fbb1..b3d0674f6d 100644
d73434f
--- a/tools/virtiofsd/passthrough_ll.c
d73434f
+++ b/tools/virtiofsd/passthrough_ll.c
d73434f
@@ -54,6 +54,7 @@
d73434f
 #include <sys/wait.h>
d73434f
 #include <sys/xattr.h>
d73434f
 #include <syslog.h>
d73434f
+#include <grp.h>
d73434f
 
d73434f
 #include "qemu/cutils.h"
d73434f
 #include "passthrough_helpers.h"
d73434f
@@ -1161,6 +1162,30 @@ static void lo_lookup(fuse_req_t req, fuse_ino_t parent, const char *name)
d73434f
 #define OURSYS_setresuid SYS_setresuid
d73434f
 #endif
d73434f
 
d73434f
+static void drop_supplementary_groups(void)
d73434f
+{
d73434f
+    int ret;
d73434f
+
d73434f
+    ret = getgroups(0, NULL);
d73434f
+    if (ret == -1) {
d73434f
+        fuse_log(FUSE_LOG_ERR, "getgroups() failed with error=%d:%s\n",
d73434f
+                 errno, strerror(errno));
d73434f
+        exit(1);
d73434f
+    }
d73434f
+
d73434f
+    if (!ret) {
d73434f
+        return;
d73434f
+    }
d73434f
+
d73434f
+    /* Drop all supplementary groups. We should not need it */
d73434f
+    ret = setgroups(0, NULL);
d73434f
+    if (ret == -1) {
d73434f
+        fuse_log(FUSE_LOG_ERR, "setgroups() failed with error=%d:%s\n",
d73434f
+                 errno, strerror(errno));
d73434f
+        exit(1);
d73434f
+    }
d73434f
+}
d73434f
+
d73434f
 /*
d73434f
  * Change to uid/gid of caller so that file is created with
d73434f
  * ownership of caller.
d73434f
@@ -3926,6 +3951,8 @@ int main(int argc, char *argv[])
d73434f
 
d73434f
     qemu_init_exec_dir(argv[0]);
d73434f
 
d73434f
+    drop_supplementary_groups();
d73434f
+
d73434f
     pthread_mutex_init(&lo.mutex, NULL);
d73434f
     lo.inodes = g_hash_table_new(lo_key_hash, lo_key_equal);
d73434f
     lo.root.fd = -1;
d73434f
-- 
d73434f
GitLab
d73434f