diff options
author | Natanael Copa <ncopa@alpinelinux.org> | 2013-06-05 10:00:39 +0000 |
---|---|---|
committer | Natanael Copa <ncopa@alpinelinux.org> | 2013-06-05 10:02:17 +0000 |
commit | 563e2f3d73036c1b799204edd5a7742c90ee711d (patch) | |
tree | b5ecf93d4ea8776efc1f03aeeae8172217445e57 | |
parent | b788ec62197e39498bd1b173060ec07359a24b2b (diff) | |
download | aports-563e2f3d73036c1b799204edd5a7742c90ee711d.tar.bz2 aports-563e2f3d73036c1b799204edd5a7742c90ee711d.tar.xz |
main/qemu: security fix CVE-2013-2007
-rw-r--r-- | main/qemu/APKBUILD | 6 | ||||
-rw-r--r-- | main/qemu/CVE-2013-2007.patch | 203 |
2 files changed, 207 insertions, 2 deletions
diff --git a/main/qemu/APKBUILD b/main/qemu/APKBUILD index 40796f7fe9..dde72288d1 100644 --- a/main/qemu/APKBUILD +++ b/main/qemu/APKBUILD @@ -1,7 +1,7 @@ # Maintainer: Natanael Copa <ncopa@alpinelinux.org> pkgname=qemu pkgver=0.15.1 -pkgrel=0 +pkgrel=1 pkgdesc="QEMU is a generic machine emulator and virtualizer" url="http://www.nongnu.org/qemu/" arch="all" @@ -35,6 +35,7 @@ $pkgname-img source="http://wiki.qemu.org/download/qemu-$pkgver.tar.gz 80-kvm.rules qemu-libm.patch + CVE-2013-2007.patch " prepare() { @@ -116,4 +117,5 @@ img() { md5sums="34f17737baaf1b3495c89cd6d4a607ed qemu-0.15.1.tar.gz 66660f143235201249dc0648b39b86ee 80-kvm.rules -70a4336c31600ce00838b056f0d08452 qemu-libm.patch" +70a4336c31600ce00838b056f0d08452 qemu-libm.patch +bbbe4d5b26b1204ce1f7bd7e2e17dfb8 CVE-2013-2007.patch" diff --git a/main/qemu/CVE-2013-2007.patch b/main/qemu/CVE-2013-2007.patch new file mode 100644 index 0000000000..30130e432b --- /dev/null +++ b/main/qemu/CVE-2013-2007.patch @@ -0,0 +1,203 @@ +From 0c29addea85130133632d25361d02524db83a24c Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek <lersek@redhat.com> +Date: Wed, 5 Jun 2013 09:08:05 +0000 +Subject: [PATCH] qga: set umask 0077 when daemonizing (CVE-2013-2007) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The qemu guest agent creates a bunch of files with insecure permissions +when started in daemon mode. For example: + + -rw-rw-rw- 1 root root /var/log/qemu-ga.log + -rw-rw-rw- 1 root root /var/run/qga.state + -rw-rw-rw- 1 root root /var/log/qga-fsfreeze-hook.log + +In addition, at least all files created with the "guest-file-open" QMP +command, and all files created with shell output redirection (or +otherwise) by utilities invoked by the fsfreeze hook script are affected. + +For now mask all file mode bits for "group" and "others" in +become_daemon(). + +Temporarily, for compatibility reasons, stick with the 0666 file-mode in +case of files newly created by the "guest-file-open" QMP call. Do so +without changing the umask temporarily. + +Signed-off-by: Laszlo Ersek <lersek@redhat.com> +Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> +(cherry picked from commit c689b4f1bac352dcfd6ecb9a1d45337de0f1de67) + +[AF: Use error_set() instead of error_setg*()] +Signed-off-by: Andreas Färber <address@hidden> +(cherry picked from commit ea82ad5c9ed15992f12c0e25a286980a3759f0f9) + +Conflicts: + qga/commands-posix.c +--- + qemu-ga.c | 2 +- + qga/guest-agent-commands.c | 117 +++++++++++++++++++++++++++++++++++++++++++-- + 2 files changed, 115 insertions(+), 4 deletions(-) + +diff --git a/qemu-ga.c b/qemu-ga.c +index 4932013..ae1fb60 100644 +--- a/qemu-ga.c ++++ b/qemu-ga.c +@@ -186,7 +186,7 @@ static void become_daemon(const char *pidfile) + goto fail; + } + +- umask(0); ++ umask(S_IRWXG | S_IRWXO); + sid = setsid(); + if (sid < 0) { + goto fail; +diff --git a/qga/guest-agent-commands.c b/qga/guest-agent-commands.c +index 6da9904..2f4b9ac 100644 +--- a/qga/guest-agent-commands.c ++++ b/qga/guest-agent-commands.c +@@ -23,6 +23,9 @@ + + #include <sys/types.h> + #include <sys/ioctl.h> ++#include <stdio.h> ++#include <string.h> ++#include <sys/stat.h> + #include "qga/guest-agent-core.h" + #include "qga-qmp-commands.h" + #include "qerror.h" +@@ -134,9 +137,117 @@ static GuestFileHandle *guest_file_handle_find(int64_t id) + return NULL; + } + ++typedef const char * const ccpc; ++ ++/* http://pubs.opengroup.org/onlinepubs/9699919799/functions/fopen.html */ ++static const struct { ++ ccpc *forms; ++ int oflag_base; ++} guest_file_open_modes[] = { ++ { (ccpc[]){ "r", "rb", NULL }, O_RDONLY }, ++ { (ccpc[]){ "w", "wb", NULL }, O_WRONLY | O_CREAT | O_TRUNC }, ++ { (ccpc[]){ "a", "ab", NULL }, O_WRONLY | O_CREAT | O_APPEND }, ++ { (ccpc[]){ "r+", "rb+", "r+b", NULL }, O_RDWR }, ++ { (ccpc[]){ "w+", "wb+", "w+b", NULL }, O_RDWR | O_CREAT | O_TRUNC }, ++ { (ccpc[]){ "a+", "ab+", "a+b", NULL }, O_RDWR | O_CREAT | O_APPEND } ++}; ++ ++static int ++find_open_flag(const char *mode_str, Error **err) ++{ ++ unsigned mode; ++ ++ for (mode = 0; mode < ARRAY_SIZE(guest_file_open_modes); ++mode) { ++ ccpc *form; ++ ++ form = guest_file_open_modes[mode].forms; ++ while (*form != NULL && strcmp(*form, mode_str) != 0) { ++ ++form; ++ } ++ if (*form != NULL) { ++ break; ++ } ++ } ++ ++ if (mode == ARRAY_SIZE(guest_file_open_modes)) { ++ error_set(err, QERR_UNSUPPORTED); ++ return -1; ++ } ++ return guest_file_open_modes[mode].oflag_base | O_NOCTTY | O_NONBLOCK; ++} ++ ++#define DEFAULT_NEW_FILE_MODE (S_IRUSR | S_IWUSR | \ ++ S_IRGRP | S_IWGRP | \ ++ S_IROTH | S_IWOTH) ++ ++static FILE * ++safe_open_or_create(const char *path, const char *mode, Error **err) ++{ ++ Error *local_err = NULL; ++ int oflag; ++ ++ oflag = find_open_flag(mode, &local_err); ++ if (local_err == NULL) { ++ int fd; ++ ++ /* If the caller wants / allows creation of a new file, we implement it ++ * with a two step process: open() + (open() / fchmod()). ++ * ++ * First we insist on creating the file exclusively as a new file. If ++ * that succeeds, we're free to set any file-mode bits on it. (The ++ * motivation is that we want to set those file-mode bits independently ++ * of the current umask.) ++ * ++ * If the exclusive creation fails because the file already exists ++ * (EEXIST is not possible for any other reason), we just attempt to ++ * open the file, but in this case we won't be allowed to change the ++ * file-mode bits on the preexistent file. ++ * ++ * The pathname should never disappear between the two open()s in ++ * practice. If it happens, then someone very likely tried to race us. ++ * In this case just go ahead and report the ENOENT from the second ++ * open() to the caller. ++ * ++ * If the caller wants to open a preexistent file, then the first ++ * open() is decisive and its third argument is ignored, and the second ++ * open() and the fchmod() are never called. ++ */ ++ fd = open(path, oflag | ((oflag & O_CREAT) ? O_EXCL : 0), 0); ++ if (fd == -1 && errno == EEXIST) { ++ oflag &= ~(unsigned)O_CREAT; ++ fd = open(path, oflag); ++ } ++ ++ if (fd == -1) { ++ error_set(&local_err, QERR_OPEN_FILE_FAILED, path); ++ } else { ++ qemu_set_cloexec(fd); ++ ++ if ((oflag & O_CREAT) && fchmod(fd, DEFAULT_NEW_FILE_MODE) == -1) { ++ error_set(&local_err, QERR_QGA_COMMAND_FAILED, "fchmod() failed"); ++ } else { ++ FILE *f; ++ ++ f = fdopen(fd, mode); ++ if (f == NULL) { ++ error_set(&local_err, QERR_QGA_COMMAND_FAILED, "fdopen() failed"); ++ } else { ++ return f; ++ } ++ } ++ ++ close(fd); ++ } ++ } ++ ++ error_propagate(err, local_err); ++ return NULL; ++} ++ + int64_t qmp_guest_file_open(const char *path, bool has_mode, const char *mode, Error **err) + { + FILE *fh; ++ Error *local_err = NULL; + int fd; + int64_t ret = -1; + +@@ -144,9 +255,9 @@ int64_t qmp_guest_file_open(const char *path, bool has_mode, const char *mode, E + mode = "r"; + } + slog("guest-file-open called, filepath: %s, mode: %s", path, mode); +- fh = fopen(path, mode); +- if (!fh) { +- error_set(err, QERR_OPEN_FILE_FAILED, path); ++ fh = safe_open_or_create(path, mode, &local_err); ++ if (local_err != NULL) { ++ error_propagate(err, local_err); + return -1; + } + +-- +1.8.0 + + |