修订版 | 449e8171f96a6a944d1f3b7d3627ae059eae21ca (tree) |
---|---|
时间 | 2022-01-26 19:32:05 |
作者 | Vivek Goyal <vgoyal@redh...> |
Commiter | Dr. David Alan Gilbert |
virtiofsd: Drop membership of all supplementary groups (CVE-2022-0358)
At the start, drop membership of all supplementary groups. This is
not required.
If we have membership of "root" supplementary group and when we switch
uid/gid using setresuid/setsgid, we still retain membership of existing
supplemntary groups. And that can allow some operations which are not
normally allowed.
For example, if root in guest creates a dir as follows.
$ mkdir -m 03777 test_dir
This sets SGID on dir as well as allows unprivileged users to write into
this dir.
And now as unprivileged user open file as follows.
$ su test
$ fd = open("test_dir/priviledge_id", O_RDWR|O_CREAT|O_EXCL, 02755);
This will create SGID set executable in test_dir/.
And that's a problem because now an unpriviliged user can execute it,
get egid=0 and get access to resources owned by "root" group. This is
privilege escalation.
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=2044863
Fixes: CVE-2022-0358
Reported-by: JIETAO XIAO <shawtao1125@gmail.com>
Suggested-by: Miklos Szeredi <mszeredi@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
Message-Id: <YfBGoriS38eBQrAb@redhat.com>
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
@@ -54,6 +54,7 @@ | ||
54 | 54 | #include <sys/wait.h> |
55 | 55 | #include <sys/xattr.h> |
56 | 56 | #include <syslog.h> |
57 | +#include <grp.h> | |
57 | 58 | |
58 | 59 | #include "qemu/cutils.h" |
59 | 60 | #include "passthrough_helpers.h" |
@@ -1161,6 +1162,30 @@ static void lo_lookup(fuse_req_t req, fuse_ino_t parent, const char *name) | ||
1161 | 1162 | #define OURSYS_setresuid SYS_setresuid |
1162 | 1163 | #endif |
1163 | 1164 | |
1165 | +static void drop_supplementary_groups(void) | |
1166 | +{ | |
1167 | + int ret; | |
1168 | + | |
1169 | + ret = getgroups(0, NULL); | |
1170 | + if (ret == -1) { | |
1171 | + fuse_log(FUSE_LOG_ERR, "getgroups() failed with error=%d:%s\n", | |
1172 | + errno, strerror(errno)); | |
1173 | + exit(1); | |
1174 | + } | |
1175 | + | |
1176 | + if (!ret) { | |
1177 | + return; | |
1178 | + } | |
1179 | + | |
1180 | + /* Drop all supplementary groups. We should not need it */ | |
1181 | + ret = setgroups(0, NULL); | |
1182 | + if (ret == -1) { | |
1183 | + fuse_log(FUSE_LOG_ERR, "setgroups() failed with error=%d:%s\n", | |
1184 | + errno, strerror(errno)); | |
1185 | + exit(1); | |
1186 | + } | |
1187 | +} | |
1188 | + | |
1164 | 1189 | /* |
1165 | 1190 | * Change to uid/gid of caller so that file is created with |
1166 | 1191 | * ownership of caller. |
@@ -3926,6 +3951,8 @@ int main(int argc, char *argv[]) | ||
3926 | 3951 | |
3927 | 3952 | qemu_init_exec_dir(argv[0]); |
3928 | 3953 | |
3954 | + drop_supplementary_groups(); | |
3955 | + | |
3929 | 3956 | pthread_mutex_init(&lo.mutex, NULL); |
3930 | 3957 | lo.inodes = g_hash_table_new(lo_key_hash, lo_key_equal); |
3931 | 3958 | lo.root.fd = -1; |