aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNatanael Copa <ncopa@alpinelinux.org>2013-06-05 10:00:39 +0000
committerNatanael Copa <ncopa@alpinelinux.org>2013-06-05 10:02:17 +0000
commit563e2f3d73036c1b799204edd5a7742c90ee711d (patch)
treeb5ecf93d4ea8776efc1f03aeeae8172217445e57
parentb788ec62197e39498bd1b173060ec07359a24b2b (diff)
downloadaports-563e2f3d73036c1b799204edd5a7742c90ee711d.tar.bz2
aports-563e2f3d73036c1b799204edd5a7742c90ee711d.tar.xz
main/qemu: security fix CVE-2013-2007
ref #2059 fixes #2063
-rw-r--r--main/qemu/APKBUILD6
-rw-r--r--main/qemu/CVE-2013-2007.patch203
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
+
+