cryptospore / rpms / qemu-kvm

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