qemu privilege escalation
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
QEMU |
Fix Released
|
Undecided
|
Stefan Hajnoczi |
Bug Description
If qemu is started as root, with -runas, the extra groups is not dropped correctly
/proc/`pidof qemu`/status
..
Uid: 100 100 100 100
Gid: 100 100 100 100
FDSize: 32
Groups: 0 1 2 3 4 6 10 11 26 27
...
The fix is to add initgroups() or setgroups(1, [gid]) where appropriate to os-posix.c.
The extra gid's allow read or write access to other files (such as /dev etc).
Emulating the qemu code:
# python
...
>>> import os
>>> os.setgid(100)
>>> os.setuid(100)
>>> os.execve(
sh-4.1$ xxd /dev/sda | head -n2
0000000: eb48 9000 0000 0000 0000 0000 0000 0000 .H..............
0000010: 0000 0000 0000 0000 0000 0000 0000 0000 ................
sh-4.1$ ls -l /dev/sda
brw-rw---- 1 root disk 8, 0 Jul 8 11:54 /dev/sda
sh-4.1$ id
uid=100(qemu00) gid=100(users) groups=
CVE References
Changed in qemu: | |
status: | New → Confirmed |
assignee: | nobody → Stefan Hajnoczi (stefanha) |
Andrew Griffiths reports that -runas does not set supplementary group
IDs. This means that gid 0 (root) is not dropped when switching to an
unprivileged user.
Add an initgroups(3) call to use the -runas user's /etc/groups
membership to update the supplementary group IDs.
Signed-off-by: Stefan Hajnoczi <email address hidden>
---
Note this needs compile testing on various POSIX host platforms. Tested on
Linux. Should work on BSD and Solaris. initgroups(3) is SVr4/BSD but not in
POSIX.
os-posix.c | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/os-posix.c b/os-posix.c
index 7dfb278..6f8d488 100644
--- a/os-posix.c
+++ b/os-posix.c
@@ -31,6 +31,7 @@
/*needed for MAP_POPULATE before including qemu-options.h */
#include <sys/mman.h>
#include <pwd.h>
+#include <grp.h>
#include <libgen.h>
/* Needed early for CONFIG_BSD etc. */ process_ uid(void)
fprintf( stderr, "Failed to setgid(%d)\n", user_pwd->pw_gid);
exit( 1); user_pwd- >pw_name, user_pwd->pw_gid) < 0) { user_pwd- >pw_uid) < 0) {
fprintf( stderr, "Failed to setuid(%d)\n", user_pwd->pw_uid);
exit( 1);
@@ -199,6 +200,11 @@ static void change_
}
+ if (initgroups(
+ fprintf(stderr, "Failed to initgroups(\"%s\", %d)\n",
+ user_pwd->pw_name, user_pwd->pw_gid);
+ exit(1);
+ }
if (setuid(
--
1.7.5.4