Fix building docs with f19 texinfo

CVE-2013-2007: Fix qemu-ga file creation permissions (bz #956082, bz #969455)
Fix rtl8139 + windows 7 + large transfers (bz #970240)
This commit is contained in:
Cole Robinson 2013-06-11 15:45:31 -04:00
parent 72f684c1ae
commit 635c984c3e
4 changed files with 391 additions and 1 deletions

View File

@ -0,0 +1,55 @@
From b5f2618ac3459fbd31f503933df6d47db0a55286 Mon Sep 17 00:00:00 2001
From: Cole Robinson <crobinso@redhat.com>
Date: Wed, 15 May 2013 17:56:22 -0400
Subject: [PATCH] docs: Fix generating qemu-doc.html with texinfo 5
LC_ALL=C makeinfo --no-headers --no-split --number-sections --html qemu-doc.texi -o qemu-doc.html
./qemu-options.texi:1521: unknown command `list'
./qemu-options.texi:1521: table requires an argument: the formatter for @item
./qemu-options.texi:1521: warning: @table has text but no @item
This is for 1.4 stable only; master isn't affected, as it was fixed by
another commit (which isn't appropriate for stable):
commit 5d6768e3b8908a60f0a3016b7fa24194f6b47c80
Author: MORITA Kazutaka <morita.kazutaka@lab.ntt.co.jp>
Date: Fri Feb 22 12:39:51 2013 +0900
sheepdog: accept URIs
Signed-off-by: Cole Robinson <crobinso@redhat.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
qemu-options.hx | 19 +++++++------------
1 file changed, 7 insertions(+), 12 deletions(-)
diff --git a/qemu-options.hx b/qemu-options.hx
index 1021ab7..878d9c7 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1990,18 +1990,13 @@ QEMU supports using either local sheepdog devices or remote networked
devices.
Syntax for specifying a sheepdog device
-@table @list
-``sheepdog:<vdiname>''
-
-``sheepdog:<vdiname>:<snapid>''
-
-``sheepdog:<vdiname>:<tag>''
-
-``sheepdog:<host>:<port>:<vdiname>''
-
-``sheepdog:<host>:<port>:<vdiname>:<snapid>''
-
-``sheepdog:<host>:<port>:<vdiname>:<tag>''
+@table @code
+@item sheepdog:<vdiname>
+@item sheepdog:<vdiname>:<snapid>
+@item sheepdog:<vdiname>:<tag>
+@item sheepdog:<host>:<port>:<vdiname>
+@item sheepdog:<host>:<port>:<vdiname>:<snapid>
+@item sheepdog:<host>:<port>:<vdiname>:<tag>
@end table
Example

View File

@ -0,0 +1,265 @@
From 90f53d5951c6a4fc8def3e2af0f90c31ac9a717c Mon Sep 17 00:00:00 2001
From: Laszlo Ersek <lersek@redhat.com>
Date: Wed, 24 Apr 2013 13:13:18 +0200
Subject: [PATCH] qga: set umask 0077 when daemonizing (CVE-2013-2007)
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)
Conflicts:
qga/commands-posix.c
qga/main.c
---
error.c | 28 ++++++++++++
error.h | 15 +++++++
qemu-ga.c | 2 +-
qga/commands-posix.c | 122 +++++++++++++++++++++++++++++++++++++++++++++++++--
4 files changed, 163 insertions(+), 4 deletions(-)
diff --git a/error.c b/error.c
index 1f05fc4..128d88c 100644
--- a/error.c
+++ b/error.c
@@ -43,6 +43,34 @@ void error_set(Error **errp, ErrorClass err_class, const char *fmt, ...)
*errp = err;
}
+void error_set_errno(Error **errp, int os_errno, ErrorClass err_class,
+ const char *fmt, ...)
+{
+ Error *err;
+ char *msg1;
+ va_list ap;
+
+ if (errp == NULL) {
+ return;
+ }
+ assert(*errp == NULL);
+
+ err = g_malloc0(sizeof(*err));
+
+ va_start(ap, fmt);
+ msg1 = g_strdup_vprintf(fmt, ap);
+ if (os_errno != 0) {
+ err->msg = g_strdup_printf("%s: %s", msg1, strerror(os_errno));
+ g_free(msg1);
+ } else {
+ err->msg = msg1;
+ }
+ va_end(ap);
+ err->err_class = err_class;
+
+ *errp = err;
+}
+
Error *error_copy(const Error *err)
{
Error *err_new;
diff --git a/error.h b/error.h
index 96fc203..4d52e73 100644
--- a/error.h
+++ b/error.h
@@ -30,6 +30,21 @@ typedef struct Error Error;
void error_set(Error **err, ErrorClass err_class, const char *fmt, ...) GCC_FMT_ATTR(3, 4);
/**
+ * Set an indirect pointer to an error given a ErrorClass value and a
+ * printf-style human message, followed by a strerror() string if
+ * @os_error is not zero.
+ */
+void error_set_errno(Error **err, int os_error, ErrorClass err_class, const char *fmt, ...) GCC_FMT_ATTR(4, 5);
+
+/**
+ * Same as error_set(), but sets a generic error
+ */
+#define error_setg(err, fmt, ...) \
+ error_set(err, ERROR_CLASS_GENERIC_ERROR, fmt, ## __VA_ARGS__)
+#define error_setg_errno(err, os_error, fmt, ...) \
+ error_set_errno(err, os_error, ERROR_CLASS_GENERIC_ERROR, fmt, ## __VA_ARGS__)
+
+/**
* Returns true if an indirect pointer to an error is pointing to a valid
* error object.
*/
diff --git a/qemu-ga.c b/qemu-ga.c
index b747470..45514a2 100644
--- a/qemu-ga.c
+++ b/qemu-ga.c
@@ -421,7 +421,7 @@ static void become_daemon(const char *pidfile)
}
}
- umask(0);
+ umask(S_IRWXG | S_IRWXO);
sid = setsid();
if (sid < 0) {
goto fail;
diff --git a/qga/commands-posix.c b/qga/commands-posix.c
index ce90421..7510669 100644
--- a/qga/commands-posix.c
+++ b/qga/commands-posix.c
@@ -15,6 +15,9 @@
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/wait.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"
@@ -125,9 +128,122 @@ 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_setg(err, "invalid file open mode '%s'", mode_str);
+ 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_setg_errno(&local_err, errno, "failed to open file '%s' "
+ "(mode: '%s')", path, mode);
+ } else {
+ qemu_set_cloexec(fd);
+
+ if ((oflag & O_CREAT) && fchmod(fd, DEFAULT_NEW_FILE_MODE) == -1) {
+ error_setg_errno(&local_err, errno, "failed to set permission "
+ "0%03o on new file '%s' (mode: '%s')",
+ (unsigned)DEFAULT_NEW_FILE_MODE, path, mode);
+ } else {
+ FILE *f;
+
+ f = fdopen(fd, mode);
+ if (f == NULL) {
+ error_setg_errno(&local_err, errno, "failed to associate "
+ "stdio stream with file descriptor %d, "
+ "file '%s' (mode: '%s')", fd, path, mode);
+ } 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;
@@ -135,9 +251,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;
}

View File

@ -0,0 +1,50 @@
From f4bc1dee14b12c20c7464dc2b61446366a013dd6 Mon Sep 17 00:00:00 2001
From: Stefan Hajnoczi <stefanha@redhat.com>
Date: Wed, 22 May 2013 14:50:18 +0200
Subject: [PATCH] rtl8139: flush queued packets when RxBufPtr is written
Net queues support efficient "receive disable". For example, tap's file
descriptor will not be polled while its peer has receive disabled. This
saves CPU cycles for needlessly copying and then dropping packets which
the peer cannot receive.
rtl8139 is missing the qemu_flush_queued_packets() call that wakes the
queue up when receive becomes possible again.
As a result, the Windows 7 guest driver reaches a state where the
rtl8139 cannot receive packets. The driver has actually refilled the
receive buffer but we never resume reception.
The bug can be reproduced by running a large FTP 'get' inside a Windows
7 guest:
$ qemu -netdev tap,id=tap0,...
-device rtl8139,netdev=tap0
The Linux guest driver does not trigger the bug, probably due to a
different buffer management strategy.
Reported-by: Oliver Francke <oliver.francke@filoo.de>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
(cherry picked from commit 00b7ade807b5ce6779ddd86ce29c5521ec5c529a)
Conflicts:
hw/net/rtl8139.c
---
hw/rtl8139.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index 844f1b8..0edfeca 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -2578,6 +2578,9 @@ static void rtl8139_RxBufPtr_write(RTL8139State *s, uint32_t val)
/* this value is off by 16 */
s->RxBufPtr = MOD2(val + 0x10, s->RxBufferSize);
+ /* more buffer space may be available so try to receive */
+ qemu_flush_queued_packets(&s->nic->nc);
+
DPRINTF(" CAPR write: rx buffer length %d head 0x%04x read 0x%04x\n",
s->RxBufferSize, s->RxBufAddr, s->RxBufPtr);
}

View File

@ -109,7 +109,7 @@
Summary: QEMU is a FAST! processor emulator
Name: qemu
Version: 1.2.2
Release: 11%{?dist}
Release: 12%{?dist}
# Epoch because we pushed a qemu-1.0 package. AIUI this can't ever be dropped
Epoch: 2
License: GPLv2+ and LGPLv2+ and BSD
@ -556,6 +556,13 @@ Patch0722: 0722-console-remove-DisplayAllocator.patch
# CVE-2013-1922: qemu-nbd block format auto-detection vulnerability (bz
# #952574, bz #923219)
Patch0723: 0723-Add-f-FMT-format-FMT-arg-to-qemu-nbd.patch
# Fix building docs with f19 texinfo
Patch0724: 0724-docs-Fix-generating-qemu-doc.html-with-texinfo-5.patch
# CVE-2013-2007: Fix qemu-ga file creation permissions (bz #956082, bz
# #969455)
Patch0725: 0725-qga-set-umask-0077-when-daemonizing-CVE-2013-2007.patch
# Fix rtl8139 + windows 7 + large transfers (bz #970240)
Patch0726: 0726-rtl8139-flush-queued-packets-when-RxBufPtr-is-writte.patch
BuildRequires: SDL-devel
@ -1399,6 +1406,13 @@ CAC emulation development files.
# CVE-2013-1922: qemu-nbd block format auto-detection vulnerability (bz
# #952574, bz #923219)
%patch0723 -p1
# Fix building docs with f19 texinfo
%patch0724 -p1
# CVE-2013-2007: Fix qemu-ga file creation permissions (bz #956082, bz
# #969455)
%patch0725 -p1
# Fix rtl8139 + windows 7 + large transfers (bz #970240)
%patch0726 -p1
%build
@ -2008,6 +2022,12 @@ getent passwd qemu >/dev/null || \
%{_libdir}/pkgconfig/libcacard.pc
%changelog
* Tue Jun 11 2013 Cole Robinson <crobinso@redhat.com> - 2:1.2.2-12
- Fix building docs with f19 texinfo
- CVE-2013-2007: Fix qemu-ga file creation permissions (bz #956082, bz
#969455)
- Fix rtl8139 + windows 7 + large transfers (bz #970240)
* Sat Apr 20 2013 Cole Robinson <crobinso@redhat.com> - 2:1.2.2-11
- Fix booting 3.8 kernels with qemu-system-arm (bz #922796)
- Fix crash with -vga qxl, sdl, and F19 guest (bz #949126)