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:
parent
72f684c1ae
commit
635c984c3e
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
22
qemu.spec
22
qemu.spec
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue