Rebased to version 1.2.13.1

Fix getVersion() after installing qemu (bz #1000116)
Fix autosocket setup with qemu:///session (bz #1044561, bz #1105274)
Ignore storage volumes with non-ascii in names (bz #1066564)
Don't generate invalid system nodedev XML (bz #1184131)
Fix crash via race when unrefing rpc identity object (bz #1203030)
Fix domcapabilities failure with ppc64le (bz #1209948)
Fix regression with 'virsh event ' (bz #1212620)
Add {Haswell,Broadwell}-noTSX CPU models (bz #1182650)
Don't lose VMs on libvirtd restart if qemu is uninstalled (bz #1099847)
Ignore storage volumes that libvirt can't open (bz #1103308)
This commit is contained in:
Cole Robinson 2015-04-28 12:20:27 -04:00
parent a99455b301
commit e18130141c
13 changed files with 23 additions and 1033 deletions

View File

@ -1,46 +0,0 @@
From: Laine Stump <laine@laine.org>
Date: Tue, 10 Mar 2015 02:09:24 -0400
Subject: [PATCH] qemu: don't fill in nicindexes for session mode libvirtd
Commit 4bbe1029f fixed a problem in commit f7afeddc by moving the call
to virNetDevGetIndex() to a location common to all interface types (so
that the nicindex array would be filled in for macvtap as well as tap
interfaces), but the location was *too* common, as the original call
to virNetDevGetIndex() had been in a section qualified by "if
(cfg->privileged)". The result was that the "fixed" libvirtd would try
to call virNetDevGetIndex() even for session mode libvirtd, and end up
failing with the log message:
Unable to open control socket: Operation not permitted
To remedy that, this patch qualifies the call to virNetDevGetIndex()
in its new location with cfg->privileged.
This resolves https://bugzilla.redhat.com/show_bug.cgi?id=1198244
(cherry picked from commit 705242f8809dc2222c35c64d5408dd6b0cc94cf8)
---
src/qemu/qemu_command.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 24b2ad9..6526ba8 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -7766,6 +7766,7 @@ qemuBuildInterfaceCommandLine(virCommandPtr cmd,
char **tapfdName = NULL;
char **vhostfdName = NULL;
int actualType = virDomainNetGetActualType(net);
+ virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
virNetDevBandwidthPtr actualBandwidth;
size_t i;
@@ -7841,7 +7842,7 @@ qemuBuildInterfaceCommandLine(virCommandPtr cmd,
/* network and bridge use a tap device, and direct uses a
* macvtap device
*/
- if (nicindexes && nnicindexes && net->ifname) {
+ if (cfg->privileged && nicindexes && nnicindexes && net->ifname) {
if (virNetDevGetIndex(net->ifname, &nicindex) < 0 ||
VIR_APPEND_ELEMENT(*nicindexes, *nnicindexes, nicindex) < 0)
goto cleanup;

View File

@ -1,35 +0,0 @@
From: Lubomir Rintel <lkundrak@v3.sk>
Date: Wed, 8 Apr 2015 19:16:52 +0200
Subject: [PATCH] lxc: create the required directories upon driver start
/var/run may reside on a tmpfs and we fail to create the PID file if
/var/run/lxc does not exist.
Since commit 0a8addc1, the lxc driver's state directory isn't
automatically created before starting a domain. Now, the lxc driver
makes sure the state directory exists when it initializes.
Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>
(cherry picked from commit da33a1ac1f6c0ae2ebe72bc385bbc7c407026956)
---
src/lxc/lxc_driver.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index 3a28dd5..8a00721 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -1650,6 +1650,13 @@ static int lxcStateInitialize(bool privileged,
if (!(caps = virLXCDriverGetCapabilities(lxc_driver, false)))
goto cleanup;
+ if (virFileMakePath(cfg->stateDir) < 0) {
+ virReportSystemError(errno,
+ _("Failed to mkdir %s"),
+ cfg->stateDir);
+ goto cleanup;
+ }
+
/* Get all the running persistent or transient configs first */
if (virDomainObjListLoadAllConfigs(lxc_driver->domains,
cfg->stateDir,

View File

@ -1,62 +0,0 @@
From: Peter Krempa <pkrempa@redhat.com>
Date: Wed, 25 Mar 2015 08:56:07 +0100
Subject: [PATCH] rpc: Don't unref identity object while callbacks still can be
executed
While this thread is cleaning up the client and connection objects:
#2 virFileReadAll (path=0x7f28780012b0 "/proc/1319/stat", maxlen=maxlen@entry=1024, buf=buf@entry=0x7f289c60fc40) at util/virfile.c:1287
#3 0x00007f28adbb1539 in virProcessGetStartTime (pid=<optimized out>, timestamp=timestamp@entry=0x7f289c60fc98) at util/virprocess.c:838
#4 0x00007f28adb91981 in virIdentityGetSystem () at util/viridentity.c:151
#5 0x00007f28ae73f17c in remoteClientFreeFunc (data=<optimized out>) at remote.c:1131
#6 0x00007f28adcb7f33 in virNetServerClientDispose (obj=0x7f28aecad180) at rpc/virnetserverclient.c:858
#7 0x00007f28adba8eeb in virObjectUnref (anyobj=<optimized out>) at util/virobject.c:265
#8 0x00007f28ae74ad05 in virNetServerHandleJob (jobOpaque=<optimized out>, opaque=0x7f28aec93ff0) at rpc/virnetserver.c:205
#9 0x00007f28adbbef4e in virThreadPoolWorker (opaque=opaque@entry=0x7f28aec88030) at util/virthreadpool.c:145
In stack frame #6 the client->identity object got unref'd, but the code
that removes the event callbacks in frame #5 did not run yet as we are
trying to obtain the system identity (frames #4, #3, #2).
In other thead:
#0 virObjectUnref (anyobj=anyobj@entry=0x7f288c162c60) at util/virobject.c:264
klass = 0xdeadbeef
obj = 0x7f288c162c60
#1 0x00007f28ae71c709 in remoteRelayDomainEventCheckACL (client=<optimized out>, conn=<optimized out>, dom=dom@entry=0x7f28aecaafc0) at remote.c:164
#2 0x00007f28ae71fc83 in remoteRelayDomainEventTrayChange (conn=<optimized out>, dom=0x7f28aecaafc0, ... ) at remote.c:717
#3 0x00007f28adc04e53 in virDomainEventDispatchDefaultFunc (conn=0x7f287c0009a0, event=0x7f28aecab1a0, ...) at conf/domain_event.c:1455
#4 0x00007f28adc03831 in virObjectEventStateDispatchCallbacks (callbacks=<optimized out>, ....) at conf/object_event.c:724
#5 virObjectEventStateQueueDispatch (callbacks=0x7f288c083730, queue=0x7fff51f90030, state=0x7f288c18da20) at conf/object_event.c:738
#6 virObjectEventStateFlush (state=0x7f288c18da20) at conf/object_event.c:816
#7 virObjectEventTimer (timer=<optimized out>, opaque=0x7f288c18da20) at conf/object_event.c:562
#8 0x00007f28adb859cd in virEventPollDispatchTimeouts () at util/vireventpoll.c:459
Frame #0 is unrefing an invalid identity object while frame #2 hints
that the client is still dispatching the event.
For untrimmed backtrace see the bugzilla attachment.
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1203030
(cherry picked from commit a98129c0ee52b6a8fdd39988a6d090057f149ae9)
---
src/rpc/virnetserverclient.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/rpc/virnetserverclient.c b/src/rpc/virnetserverclient.c
index b2a4fdf..541055f 100644
--- a/src/rpc/virnetserverclient.c
+++ b/src/rpc/virnetserverclient.c
@@ -850,12 +850,12 @@ void virNetServerClientDispose(void *obj)
PROBE(RPC_SERVER_CLIENT_DISPOSE,
"client=%p", client);
- virObjectUnref(client->identity);
-
if (client->privateData &&
client->privateDataFreeFunc)
client->privateDataFreeFunc(client->privateData);
+ virObjectUnref(client->identity);
+
#if WITH_SASL
virObjectUnref(client->sasl);
#endif

View File

@ -1,267 +0,0 @@
From: Michal Privoznik <mprivozn@redhat.com>
Date: Thu, 2 Apr 2015 14:41:17 +0200
Subject: [PATCH] virNetSocketNewConnectUNIX: Use flocks when spawning a daemon
https://bugzilla.redhat.com/show_bug.cgi?id=1200149
Even though we have a mutex mechanism so that two clients don't spawn
two daemons, it's not strong enough. It can happen that while one
client is spawning the daemon, the other one fails to connect.
Basically two possible errors can happen:
error: Failed to connect socket to '/home/mprivozn/.cache/libvirt/libvirt-sock': Connection refused
or:
error: Failed to connect socket to '/home/mprivozn/.cache/libvirt/libvirt-sock': No such file or directory
The problem in both cases is, the daemon is only starting up, while we
are trying to connect (and fail). We should postpone the connecting
phase until the daemon is started (by the other thread that is
spawning it). In order to do that, create a file lock 'libvirt-lock'
in the directory where session daemon would create its socket. So even
when called from multiple processes, spawning a daemon will serialize
on the file lock. So only the first to come will spawn the daemon.
Tested-by: Richard W. M. Jones <rjones@redhat.com>
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
(cherry picked from commit be78814ae07f092d9c4e71fd82dd1947aba2f029)
---
src/rpc/virnetsocket.c | 164 +++++++++++++++++--------------------------------
1 file changed, 55 insertions(+), 109 deletions(-)
diff --git a/src/rpc/virnetsocket.c b/src/rpc/virnetsocket.c
index 6b019cc..b824285 100644
--- a/src/rpc/virnetsocket.c
+++ b/src/rpc/virnetsocket.c
@@ -123,7 +123,7 @@ VIR_ONCE_GLOBAL_INIT(virNetSocket)
#ifndef WIN32
-static int virNetSocketForkDaemon(const char *binary, int passfd)
+static int virNetSocketForkDaemon(const char *binary)
{
int ret;
virCommandPtr cmd = virCommandNewArgList(binary,
@@ -136,10 +136,6 @@ static int virNetSocketForkDaemon(const char *binary, int passfd)
virCommandAddEnvPassBlockSUID(cmd, "XDG_RUNTIME_DIR", NULL);
virCommandClearCaps(cmd);
virCommandDaemonize(cmd);
- if (passfd) {
- virCommandPassFD(cmd, passfd, VIR_COMMAND_PASS_FD_CLOSE_PARENT);
- virCommandPassListenFDs(cmd);
- }
ret = virCommandRun(cmd, NULL);
virCommandFree(cmd);
return ret;
@@ -543,45 +539,26 @@ int virNetSocketNewConnectUNIX(const char *path,
const char *binary,
virNetSocketPtr *retsock)
{
- char *binname = NULL;
- char *pidpath = NULL;
- int fd, passfd = -1;
- int pidfd = -1;
+ char *lockpath = NULL;
+ int lockfd = -1;
+ int fd = -1;
+ int retries = 100;
virSocketAddr localAddr;
virSocketAddr remoteAddr;
+ char *rundir = NULL;
memset(&localAddr, 0, sizeof(localAddr));
memset(&remoteAddr, 0, sizeof(remoteAddr));
remoteAddr.len = sizeof(remoteAddr.data.un);
- if (spawnDaemon && !binary) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("Auto-spawn of daemon requested, but no binary specified"));
- return -1;
- }
-
- if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
- virReportSystemError(errno, "%s", _("Failed to create socket"));
- goto error;
- }
-
- remoteAddr.data.un.sun_family = AF_UNIX;
- if (virStrcpyStatic(remoteAddr.data.un.sun_path, path) == NULL) {
- virReportSystemError(ENOMEM, _("Path %s too long for unix socket"), path);
- goto error;
- }
- if (remoteAddr.data.un.sun_path[0] == '@')
- remoteAddr.data.un.sun_path[0] = '\0';
-
- retry:
- if (connect(fd, &remoteAddr.data.sa, remoteAddr.len) < 0) {
- int status = 0;
- pid_t pid = 0;
+ if (spawnDaemon) {
+ const char *binname;
- if (!spawnDaemon) {
- virReportSystemError(errno, _("Failed to connect socket to '%s'"),
- path);
+ if (spawnDaemon && !binary) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Auto-spawn of daemon requested, "
+ "but no binary specified"));
goto error;
}
@@ -592,90 +569,63 @@ int virNetSocketNewConnectUNIX(const char *path,
goto error;
}
- if (virPidFileConstructPath(false, NULL, binname, &pidpath) < 0)
+ if (!(rundir = virGetUserRuntimeDirectory()))
goto error;
- pidfd = virPidFileAcquirePath(pidpath, false, getpid());
- if (pidfd < 0) {
- /*
- * This can happen in a very rare case of two clients spawning two
- * daemons at the same time, and the error in the logs that gets
- * reset here can be a clue to some future debugging.
- */
- virResetLastError();
- spawnDaemon = false;
- goto retry;
- }
-
- if ((passfd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
- virReportSystemError(errno, "%s", _("Failed to create socket"));
+ if (virFileMakePathWithMode(rundir, 0700) < 0) {
+ virReportSystemError(errno,
+ _("Cannot create user runtime directory '%s'"),
+ rundir);
goto error;
}
- /*
- * We already even acquired the pidfile, so no one else should be using
- * @path right now. So we're OK to unlink it and paying attention to
- * the return value makes no real sense here. Only if it's not an
- * abstract socket, of course.
- */
- if (path[0] != '@')
- unlink(path);
-
- /*
- * We have to fork() here, because umask() is set per-process, chmod()
- * is racy and fchmod() has undefined behaviour on sockets according to
- * POSIX, so it doesn't work outside Linux.
- */
- if ((pid = virFork()) < 0)
+ if (virAsprintf(&lockpath, "%s/%s.lock", rundir, binname) < 0)
goto error;
- if (pid == 0) {
- umask(0077);
- if (bind(passfd, &remoteAddr.data.sa, remoteAddr.len) < 0)
- _exit(EXIT_FAILURE);
-
- _exit(EXIT_SUCCESS);
- }
-
- if (virProcessWait(pid, &status, false) < 0)
+ if ((lockfd = open(lockpath, O_RDWR | O_CREAT, 0600)) < 0 ||
+ virSetCloseExec(lockfd) < 0) {
+ virReportSystemError(errno, _("Unable to create lock '%s'"), lockpath);
goto error;
-
- if (status != EXIT_SUCCESS) {
- /*
- * OK, so the child failed to bind() the socket. This may mean that
- * another daemon was starting at the same time and succeeded with
- * its bind() (even though it should not happen because we using a
- * pidfile for the race). So we'll try connecting again, but this
- * time without spawning the daemon.
- */
- spawnDaemon = false;
- virPidFileDeletePath(pidpath);
- VIR_FORCE_CLOSE(pidfd);
- VIR_FORCE_CLOSE(passfd);
- goto retry;
}
- if (listen(passfd, 0) < 0) {
- virReportSystemError(errno, "%s",
- _("Failed to listen on socket that's about "
- "to be passed to the daemon"));
+ if (virFileLock(lockfd, false, 0, 1, true) < 0) {
+ virReportSystemError(errno, _("Unable to lock '%s'"), lockpath);
goto error;
}
+ }
+
+ if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
+ virReportSystemError(errno, "%s", _("Failed to create socket"));
+ goto error;
+ }
- if (connect(fd, &remoteAddr.data.sa, remoteAddr.len) < 0) {
+ remoteAddr.data.un.sun_family = AF_UNIX;
+ if (virStrcpyStatic(remoteAddr.data.un.sun_path, path) == NULL) {
+ virReportSystemError(ENOMEM, _("Path %s too long for unix socket"), path);
+ goto error;
+ }
+ if (remoteAddr.data.un.sun_path[0] == '@')
+ remoteAddr.data.un.sun_path[0] = '\0';
+
+ while (retries &&
+ connect(fd, &remoteAddr.data.sa, remoteAddr.len) < 0) {
+ if (!(spawnDaemon && errno == ENOENT)) {
virReportSystemError(errno, _("Failed to connect socket to '%s'"),
path);
goto error;
}
- /*
- * Do we need to eliminate the super-rare race here any more? It would
- * need incorporating the following VIR_FORCE_CLOSE() into a
- * virCommandHook inside a virNetSocketForkDaemon().
- */
- VIR_FORCE_CLOSE(pidfd);
- if (virNetSocketForkDaemon(binary, passfd) < 0)
+ if (virNetSocketForkDaemon(binary) < 0)
goto error;
+
+ retries--;
+ usleep(5000);
+ }
+
+ if (lockfd) {
+ unlink(lockpath);
+ VIR_FORCE_CLOSE(lockfd);
+ VIR_FREE(lockpath);
}
localAddr.len = sizeof(localAddr.data);
@@ -687,19 +637,15 @@ int virNetSocketNewConnectUNIX(const char *path,
if (!(*retsock = virNetSocketNew(&localAddr, &remoteAddr, true, fd, -1, 0)))
goto error;
- VIR_FREE(pidpath);
-
return 0;
error:
- if (pidfd >= 0)
- virPidFileDeletePath(pidpath);
- VIR_FREE(pidpath);
+ if (lockfd)
+ unlink(lockpath);
+ VIR_FREE(lockpath);
+ VIR_FREE(rundir);
VIR_FORCE_CLOSE(fd);
- VIR_FORCE_CLOSE(passfd);
- VIR_FORCE_CLOSE(pidfd);
- if (spawnDaemon)
- unlink(path);
+ VIR_FORCE_CLOSE(lockfd);
return -1;
}
#else

View File

@ -1,58 +0,0 @@
From: Cole Robinson <crobinso@redhat.com>
Date: Mon, 6 Apr 2015 13:59:46 -0400
Subject: [PATCH] virsh: Improve change-media success message
$ sudo virsh change-media f19 hdc /mnt/data/devel/media/Fedora-16-x86_64-Live-KDE.iso
succeeded to complete action update on media
Change the message to:
Successfully {inserted,ejected,changed} media.
https://bugzilla.redhat.com/show_bug.cgi?id=967946
(cherry picked from commit e3aa4c91c8b54cdfb1c312a142fd9fb79daec65a)
---
tools/virsh-domain.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index 80a96b2..c737ad4 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -12104,6 +12104,7 @@ cmdChangeMedia(vshControl *ctl, const vshCmd *cmd)
bool ret = false;
int prepare_type = 0;
const char *action = NULL;
+ const char *success_msg = NULL;
bool config = vshCommandOptBool(cmd, "config");
bool live = vshCommandOptBool(cmd, "live");
bool current = vshCommandOptBool(cmd, "current");
@@ -12120,16 +12121,19 @@ cmdChangeMedia(vshControl *ctl, const vshCmd *cmd)
if (eject) {
prepare_type = VSH_PREPARE_DISK_XML_EJECT;
action = "eject";
+ success_msg = _("Successfully ejected media.");
}
if (insert) {
prepare_type = VSH_PREPARE_DISK_XML_INSERT;
action = "insert";
+ success_msg = _("Successfully inserted media.");
}
if (update || (!eject && !insert)) {
prepare_type = VSH_PREPARE_DISK_XML_UPDATE;
action = "update";
+ success_msg = _("Successfully updated media.");
}
VSH_EXCLUSIVE_OPTIONS_VAR(current, live);
@@ -12174,7 +12178,7 @@ cmdChangeMedia(vshControl *ctl, const vshCmd *cmd)
goto cleanup;
}
- vshPrint(ctl, _("succeeded to complete action %s on media\n"), action);
+ vshPrint(ctl, "%s", success_msg);
ret = true;
cleanup:

View File

@ -1,41 +0,0 @@
From: =?UTF-8?q?J=C3=A1n=20Tomko?= <jtomko@redhat.com>
Date: Tue, 14 Apr 2015 12:06:44 +0200
Subject: [PATCH] tests: rename testStripIPv6BracketsData to testStripData
For reuse with other Strip* functions.
(cherry picked from commit e892842dfd3c7bad8fbfbfcf0501d01804e9e7c3)
---
tests/virstringtest.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/tests/virstringtest.c b/tests/virstringtest.c
index a0bfd61..9d0b438 100644
--- a/tests/virstringtest.c
+++ b/tests/virstringtest.c
@@ -522,14 +522,14 @@ testVirStringFreeListCount(const void *opaque ATTRIBUTE_UNUSED)
}
-struct testStripIPv6BracketsData {
+struct testStripData {
const char *string;
const char *result;
};
static int testStripIPv6Brackets(const void *args)
{
- const struct testStripIPv6BracketsData *data = args;
+ const struct testStripData *data = args;
int ret = -1;
char *res = NULL;
@@ -766,7 +766,7 @@ mymain(void)
#define TEST_STRIP_IPV6_BRACKETS(str, res) \
do { \
- struct testStripIPv6BracketsData stripData = { \
+ struct testStripData stripData = { \
.string = str, \
.result = res, \
}; \

View File

@ -1,155 +0,0 @@
From: =?UTF-8?q?J=C3=A1n=20Tomko?= <jtomko@redhat.com>
Date: Tue, 14 Apr 2015 12:30:16 +0200
Subject: [PATCH] Add functions dealing with control characters in strings
Add virStringHasControlChars that checks if the string has
any control characters other than \t\r\n,
and virStringStripControlChars that removes them in-place.
(cherry picked from commit 2a530a3e50d9314950cff0a5790c81910b0750a9)
---
src/libvirt_private.syms | 2 ++
src/util/virstring.c | 42 ++++++++++++++++++++++++++++++++++++++++++
src/util/virstring.h | 2 ++
tests/virstringtest.c | 39 +++++++++++++++++++++++++++++++++++++++
4 files changed, 85 insertions(+)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index ba05cc6..5d54861 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2091,6 +2091,7 @@ virStrdup;
virStringArrayHasString;
virStringFreeList;
virStringFreeListCount;
+virStringHasControlChars;
virStringIsEmpty;
virStringJoin;
virStringListLength;
@@ -2100,6 +2101,7 @@ virStringSortCompare;
virStringSortRevCompare;
virStringSplit;
virStringSplitCount;
+virStringStripControlChars;
virStringStripIPv6Brackets;
virStrncpy;
virStrndup;
diff --git a/src/util/virstring.c b/src/util/virstring.c
index 3dad9dd..1cd4987 100644
--- a/src/util/virstring.c
+++ b/src/util/virstring.c
@@ -968,3 +968,45 @@ virStringStripIPv6Brackets(char *str)
str[len - 2] = '\0';
}
}
+
+
+static const char control_chars[] =
+ "\x01\x02\x03\x04\x05\x06\x07"
+ "\x08" /* \t \n */ "\x0B\x0C" /* \r */ "\x0E\x0F"
+ "\x10\x11\x12\x13\x14\x15\x16\x17"
+ "\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F";
+
+bool
+virStringHasControlChars(const char *str)
+{
+ if (!str)
+ return false;
+
+ return str[strcspn(str, control_chars)] != '\0';
+}
+
+
+/**
+ * virStringStripControlChars:
+ * @str: the string to strip
+ *
+ * Modify the string in-place to remove the control characters
+ * in the interval: [0x01, 0x20)
+ */
+void
+virStringStripControlChars(char *str)
+{
+ size_t len, i, j;
+
+ if (!str)
+ return;
+
+ len = strlen(str);
+ for (i = 0, j = 0; i < len; i++) {
+ if (index(control_chars, str[i]))
+ continue;
+
+ str[j++] = str[i];
+ }
+ str[j] = '\0';
+}
diff --git a/src/util/virstring.h b/src/util/virstring.h
index 2ec60fa..e6dcb32 100644
--- a/src/util/virstring.h
+++ b/src/util/virstring.h
@@ -271,5 +271,7 @@ char *virStringReplace(const char *haystack,
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
void virStringStripIPv6Brackets(char *str);
+bool virStringHasControlChars(const char *str);
+void virStringStripControlChars(char *str);
#endif /* __VIR_STRING_H__ */
diff --git a/tests/virstringtest.c b/tests/virstringtest.c
index 9d0b438..38d0126 100644
--- a/tests/virstringtest.c
+++ b/tests/virstringtest.c
@@ -551,6 +551,29 @@ static int testStripIPv6Brackets(const void *args)
return ret;
}
+static int testStripControlChars(const void *args)
+{
+ const struct testStripData *data = args;
+ int ret = -1;
+ char *res = NULL;
+
+ if (VIR_STRDUP(res, data->string) < 0)
+ goto cleanup;
+
+ virStringStripControlChars(res);
+
+ if (STRNEQ_NULLABLE(res, data->result)) {
+ fprintf(stderr, "Returned '%s', expected '%s'\n",
+ NULLSTR(res), NULLSTR(data->result));
+ goto cleanup;
+ }
+
+ ret = 0;
+
+ cleanup:
+ VIR_FREE(res);
+ return ret;
+}
static int
mymain(void)
@@ -783,6 +806,22 @@ mymain(void)
TEST_STRIP_IPV6_BRACKETS(":hello]", ":hello]");
TEST_STRIP_IPV6_BRACKETS(":[]:", ":[]:");
+#define TEST_STRIP_CONTROL_CHARS(str, res) \
+ do { \
+ struct testStripData stripData = { \
+ .string = str, \
+ .result = res, \
+ }; \
+ if (virtTestRun("Strip control chars from " #str, \
+ testStripControlChars, &stripData) < 0) \
+ ret = -1; \
+ } while (0)
+
+ TEST_STRIP_CONTROL_CHARS(NULL, NULL);
+ TEST_STRIP_CONTROL_CHARS("\nhello \r hello\t", "\nhello \r hello\t");
+ TEST_STRIP_CONTROL_CHARS("\x01H\x02" "E\x03L\x04L\x05O", "HELLO");
+ TEST_STRIP_CONTROL_CHARS("\x01\x02\x03\x04HELL\x05O", "HELLO");
+ TEST_STRIP_CONTROL_CHARS("\nhello \x01\x07hello\t", "\nhello hello\t");
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}

View File

@ -1,36 +0,0 @@
From: =?UTF-8?q?J=C3=A1n=20Tomko?= <jtomko@redhat.com>
Date: Tue, 14 Apr 2015 12:30:34 +0200
Subject: [PATCH] Strip control characters from sysfs attributes
Including them in the XML makes them unparsable.
https://bugzilla.redhat.com/show_bug.cgi?id=1184131
(cherry picked from commit 557107500b22d4a5ba7d1b09f5f516512dfca67b)
---
src/node_device/node_device_udev.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c
index 03c7a0b..eb6209b 100644
--- a/src/node_device/node_device_udev.c
+++ b/src/node_device/node_device_udev.c
@@ -194,7 +194,9 @@ static int udevGetUintProperty(struct udev_device *udev_device,
/* This function allocates memory from the heap for the property
- * value. That memory must be later freed by some other code. */
+ * value. That memory must be later freed by some other code.
+ * Any control characters that cannot be printed in the XML are stripped
+ * from the string */
static int udevGetDeviceSysfsAttr(struct udev_device *udev_device,
const char *attr_name,
char **attr_value)
@@ -239,6 +241,8 @@ static int udevGetStringSysfsAttr(struct udev_device *udev_device,
ret = udevGetDeviceSysfsAttr(udev_device, attr_name, &tmp);
+ virStringStripControlChars(tmp);
+
if (tmp != NULL && (STREQ(tmp, ""))) {
VIR_FREE(tmp);
tmp = NULL;

View File

@ -1,29 +0,0 @@
From: =?UTF-8?q?J=C3=A1n=20Tomko?= <jtomko@redhat.com>
Date: Tue, 14 Apr 2015 12:30:55 +0200
Subject: [PATCH] Ignore storage volumes with control codes in their names
To prevent generating invalid XML.
https://bugzilla.redhat.com/show_bug.cgi?id=1066564
(cherry picked from commit 60db2bc80fb5048b227c77c5138fe0e2c97e9c14)
---
src/storage/storage_backend_fs.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/storage/storage_backend_fs.c b/src/storage/storage_backend_fs.c
index 2af5dd7..861d4f6 100644
--- a/src/storage/storage_backend_fs.c
+++ b/src/storage/storage_backend_fs.c
@@ -861,6 +861,12 @@ virStorageBackendFileSystemRefresh(virConnectPtr conn ATTRIBUTE_UNUSED,
while ((direrr = virDirRead(dir, &ent, pool->def->target.path)) > 0) {
int ret;
+ if (virStringHasControlChars(ent->d_name)) {
+ VIR_WARN("Ignoring file with control characters under '%s'",
+ pool->def->target.path);
+ continue;
+ }
+
if (VIR_ALLOC(vol) < 0)
goto error;

View File

@ -1,144 +0,0 @@
From: Peter Krempa <pkrempa@redhat.com>
Date: Tue, 24 Mar 2015 10:53:29 +0100
Subject: [PATCH] util: buffer: Add support for adding text blocks with
indentation
The current auto-indentation buffer code applies indentation only on
complete strings. To allow adding a string containing newlines and
having it properly indented this patch adds virBufferAddStr.
(cherry picked from commit 6ff59cbc8367856f12f4eef5755eeccade36d8cf)
---
src/libvirt_private.syms | 1 +
src/util/virbuffer.c | 29 ++++++++++++++++++++++++++++
src/util/virbuffer.h | 1 +
tests/virbuftest.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 80 insertions(+)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 5d54861..6674c67 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1083,6 +1083,7 @@ virBitmapToData;
virBufferAdd;
virBufferAddBuffer;
virBufferAddChar;
+virBufferAddStr;
virBufferAdjustIndent;
virBufferAsprintf;
virBufferCheckErrorInternal;
diff --git a/src/util/virbuffer.c b/src/util/virbuffer.c
index 96a0f16..b5639a8 100644
--- a/src/util/virbuffer.c
+++ b/src/util/virbuffer.c
@@ -752,3 +752,32 @@ virBufferTrim(virBufferPtr buf, const char *str, int len)
buf->use -= len < 0 ? len2 : len;
buf->content[buf->use] = '\0';
}
+
+
+/**
+ * virBufferAddStr:
+ * @buf: the buffer to append to
+ * @str: string to append
+ *
+ * Appends @str to @buffer. Applies autoindentation on the separate lines of
+ * @str.
+ */
+void
+virBufferAddStr(virBufferPtr buf,
+ const char *str)
+{
+ const char *end;
+
+ if (!buf || !str || buf->error)
+ return;
+
+ while (*str) {
+ if ((end = strchr(str, '\n'))) {
+ virBufferAdd(buf, str, (end - str) + 1);
+ str = end + 1;
+ } else {
+ virBufferAdd(buf, str, -1);
+ break;
+ }
+ }
+}
diff --git a/src/util/virbuffer.h b/src/util/virbuffer.h
index 24e81c7..144a1ba 100644
--- a/src/util/virbuffer.h
+++ b/src/util/virbuffer.h
@@ -96,5 +96,6 @@ void virBufferAdjustIndent(virBufferPtr buf, int indent);
int virBufferGetIndent(const virBuffer *buf, bool dynamic);
void virBufferTrim(virBufferPtr buf, const char *trim, int len);
+void virBufferAddStr(virBufferPtr buf, const char *str);
#endif /* __VIR_BUFFER_H__ */
diff --git a/tests/virbuftest.c b/tests/virbuftest.c
index f964feb..21cb18b 100644
--- a/tests/virbuftest.c
+++ b/tests/virbuftest.c
@@ -310,6 +310,43 @@ static int testBufAddBuffer(const void *data ATTRIBUTE_UNUSED)
return ret;
}
+struct testBufAddStrData {
+ const char *data;
+ const char *expect;
+};
+
+static int
+testBufAddStr(const void *opaque ATTRIBUTE_UNUSED)
+{
+ const struct testBufAddStrData *data = opaque;
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+ char *actual;
+ int ret = -1;
+
+ virBufferAddLit(&buf, "<c>\n");
+ virBufferAdjustIndent(&buf, 2);
+ virBufferAddStr(&buf, data->data);
+ virBufferAdjustIndent(&buf, -2);
+ virBufferAddLit(&buf, "</c>");
+
+ if (!(actual = virBufferContentAndReset(&buf))) {
+ TEST_ERROR("buf is empty");
+ goto cleanup;
+ }
+
+ if (STRNEQ_NULLABLE(actual, data->expect)) {
+ TEST_ERROR("testBufAddStr(): Strings don't match:\n");
+ virtTestDifference(stderr, data->expect, actual);
+ goto cleanup;
+ }
+
+ ret = 0;
+
+ cleanup:
+ VIR_FREE(actual);
+ return ret;
+}
+
static int
mymain(void)
@@ -330,6 +367,18 @@ mymain(void)
DO_TEST("Trim", testBufTrim, 0);
DO_TEST("AddBuffer", testBufAddBuffer, 0);
+#define DO_TEST_ADD_STR(DATA, EXPECT) \
+ do { \
+ struct testBufAddStrData info = { DATA, EXPECT }; \
+ if (virtTestRun("Buf: AddStr", testBufAddStr, &info) < 0) \
+ ret = -1; \
+ } while (0)
+
+ DO_TEST_ADD_STR("", "<c>\n</c>");
+ DO_TEST_ADD_STR("<a/>", "<c>\n <a/></c>");
+ DO_TEST_ADD_STR("<a/>\n", "<c>\n <a/>\n</c>");
+ DO_TEST_ADD_STR("<b>\n <a/>\n</b>\n", "<c>\n <b>\n <a/>\n </b>\n</c>");
+
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}

View File

@ -1,133 +0,0 @@
From: =?UTF-8?q?J=C3=A1n=20Tomko?= <jtomko@redhat.com>
Date: Mon, 30 Mar 2015 12:41:40 +0200
Subject: [PATCH] Strip control codes in virBufferEscapeString
These cannot be represented in XML.
We have been stripping them, but only if the string had
characters that needed escaping: <>"'&
Extend the strcspn check to include control codes, and strip
them even if we don't do any escaping.
https://bugzilla.redhat.com/show_bug.cgi?id=1184131
https://bugzilla.redhat.com/show_bug.cgi?id=1066564
(cherry picked from commit aeb5262e4397528d582682471cb8075141189465)
---
src/util/virbuffer.c | 14 +++++++++++---
tests/virbuftest.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 60 insertions(+), 3 deletions(-)
diff --git a/src/util/virbuffer.c b/src/util/virbuffer.c
index b5639a8..431fd9f 100644
--- a/src/util/virbuffer.c
+++ b/src/util/virbuffer.c
@@ -434,6 +434,13 @@ virBufferEscapeString(virBufferPtr buf, const char *format, const char *str)
int len;
char *escaped, *out;
const char *cur;
+ const char forbidden_characters[] = {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ /*\t*/ /*\n*/ 0x0B, 0x0C, /*\r*/ 0x0E, 0x0F, 0x10,
+ 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+ 0x19, '"', '&', '\'', '<', '>',
+ '\0'
+ };
if ((format == NULL) || (buf == NULL) || (str == NULL))
return;
@@ -442,7 +449,7 @@ virBufferEscapeString(virBufferPtr buf, const char *format, const char *str)
return;
len = strlen(str);
- if (strcspn(str, "<>&'\"") == len) {
+ if (strcspn(str, forbidden_characters) == len) {
virBufferAsprintf(buf, format, str);
return;
}
@@ -486,8 +493,7 @@ virBufferEscapeString(virBufferPtr buf, const char *format, const char *str)
*out++ = 'o';
*out++ = 's';
*out++ = ';';
- } else if (((unsigned char)*cur >= 0x20) || (*cur == '\n') || (*cur == '\t') ||
- (*cur == '\r')) {
+ } else if (!strchr(forbidden_characters, *cur)) {
/*
* default case, just copy !
* Note that character over 0x80 are likely to give problem
@@ -495,6 +501,8 @@ virBufferEscapeString(virBufferPtr buf, const char *format, const char *str)
* it's hard to handle properly we have to assume it's UTF-8 too
*/
*out++ = *cur;
+ } else {
+ /* silently ignore control characters */
}
cur++;
}
diff --git a/tests/virbuftest.c b/tests/virbuftest.c
index 21cb18b..10398d5 100644
--- a/tests/virbuftest.c
+++ b/tests/virbuftest.c
@@ -349,6 +349,39 @@ testBufAddStr(const void *opaque ATTRIBUTE_UNUSED)
static int
+testBufEscapeStr(const void *opaque ATTRIBUTE_UNUSED)
+{
+ const struct testBufAddStrData *data = opaque;
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+ char *actual;
+ int ret = -1;
+
+ virBufferAddLit(&buf, "<c>\n");
+ virBufferAdjustIndent(&buf, 2);
+ virBufferEscapeString(&buf, "<el>%s</el>\n", data->data);
+ virBufferAdjustIndent(&buf, -2);
+ virBufferAddLit(&buf, "</c>");
+
+ if (!(actual = virBufferContentAndReset(&buf))) {
+ TEST_ERROR("buf is empty");
+ goto cleanup;
+ }
+
+ if (STRNEQ_NULLABLE(actual, data->expect)) {
+ TEST_ERROR("testBufEscapeStr(): Strings don't match:\n");
+ virtTestDifference(stderr, data->expect, actual);
+ goto cleanup;
+ }
+
+ ret = 0;
+
+ cleanup:
+ VIR_FREE(actual);
+ return ret;
+}
+
+
+static int
mymain(void)
{
int ret = 0;
@@ -379,6 +412,22 @@ mymain(void)
DO_TEST_ADD_STR("<a/>\n", "<c>\n <a/>\n</c>");
DO_TEST_ADD_STR("<b>\n <a/>\n</b>\n", "<c>\n <b>\n <a/>\n </b>\n</c>");
+#define DO_TEST_ESCAPE(data, expect) \
+ do { \
+ struct testBufAddStrData info = { data, expect }; \
+ if (virtTestRun("Buf: EscapeStr", testBufEscapeStr, &info) < 0) \
+ ret = -1; \
+ } while (0)
+
+ DO_TEST_ESCAPE("<td></td><td></td>",
+ "<c>\n <el>&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;</el>\n</c>");
+ DO_TEST_ESCAPE("\007\"&&\"\x15",
+ "<c>\n <el>&quot;&amp;&amp;&quot;</el>\n</c>");
+ DO_TEST_ESCAPE(",,'..',,",
+ "<c>\n <el>,,&apos;..&apos;,,</el>\n</c>");
+ DO_TEST_ESCAPE("\x01\x01\x02\x03\x05\x08",
+ "<c>\n <el></el>\n</c>");
+
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}

View File

@ -337,6 +337,12 @@
%endif
# Advertise OVMF and AAVMF from nightly firmware repo
%if 0%{?fedora}
%define with_loader_nvram --with-loader-nvram="/usr/share/edk2.git/ovmf-x64/OVMF_CODE-pure-efi.fd:/usr/share/edk2.git/ovmf-x64/OVMF_VARS-pure-efi.fd:/usr/share/edk2.git/aarch64/QEMU_EFI-pflash.raw:/usr/share/edk2.git/aarch64/vars-template-pflash.raw"
%endif
# The RHEL-5 Xen package has some feature backports. This
# flag is set to enable use of those special bits on RHEL-5
%if 0%{?rhel} == 5
@ -364,8 +370,8 @@
Summary: Library providing a simple virtualization API
Name: libvirt
Version: 1.2.13
Release: 3%{?dist}%{?extra_release}
Version: 1.2.13.1
Release: 1%{?dist}%{?extra_release}
License: LGPLv2+
Group: Development/Libraries
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
@ -376,24 +382,6 @@ URL: http://libvirt.org/
%endif
Source: http://libvirt.org/sources/%{?mainturl}libvirt-%{version}.tar.gz
# Fix connecting to qemu:///session (bz #1198244)
Patch0001: 0001-qemu-don-t-fill-in-nicindexes-for-session-mode-libvi.patch
# Fix LXC domain startup (bz #1210397)
Patch0002: 0002-lxc-create-the-required-directories-upon-driver-star.patch
# Fix crash via identify object cleanup race (bz #1203030)
Patch0003: 0003-rpc-Don-t-unref-identity-object-while-callbacks-stil.patch
# Fix race starting multiple session daemons (bz #1200149)
Patch0004: 0004-virNetSocketNewConnectUNIX-Use-flocks-when-spawning-.patch
# Fix change-media success messages
Patch0005: 0005-virsh-Improve-change-media-success-message.patch
# Strip invalid control codes from XML (bz #1066564, bz #1184131)
Patch0006: 0006-tests-rename-testStripIPv6BracketsData-to-testStripD.patch
Patch0007: 0007-Add-functions-dealing-with-control-characters-in-str.patch
Patch0008: 0008-Strip-control-characters-from-sysfs-attributes.patch
Patch0009: 0009-Ignore-storage-volumes-with-control-codes-in-their-n.patch
Patch0010: 0010-util-buffer-Add-support-for-adding-text-blocks-with-.patch
Patch0011: 0011-Strip-control-codes-in-virBufferEscapeString.patch
%if %{with_libvirtd}
Requires: libvirt-daemon = %{version}-%{release}
%if %{with_network}
@ -1528,6 +1516,7 @@ rm -f po/stamp-po
%{with_packager_version} \
--with-qemu-user=%{qemu_user} \
--with-qemu-group=%{qemu_group} \
%{?with_loader_nvram} \
%{?enable_werror} \
--enable-expensive-tests \
%{init_scripts}
@ -1979,9 +1968,6 @@ exit 0
%dir %attr(0700, root, root) %{_localstatedir}/log/libvirt/qemu/
%ghost %dir %attr(0700, root, root) %{_localstatedir}/run/libvirt/qemu/
%dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/
%dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/channel/
%dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/channel/target/
%dir %attr(0711, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/nvram/
%dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/cache/libvirt/qemu/
%{_datadir}/augeas/lenses/libvirtd_qemu.aug
%{_datadir}/augeas/lenses/tests/test_libvirtd_qemu.aug
@ -2082,9 +2068,6 @@ exit 0
%config(noreplace) %{_sysconfdir}/logrotate.d/libvirtd.qemu
%ghost %dir %attr(0700, root, root) %{_localstatedir}/run/libvirt/qemu/
%dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/
%dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/channel/
%dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/channel/target/
%dir %attr(0711, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/nvram/
%dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/cache/libvirt/qemu/
%{_datadir}/augeas/lenses/libvirtd_qemu.aug
%{_datadir}/augeas/lenses/tests/test_libvirtd_qemu.aug
@ -2297,6 +2280,19 @@ exit 0
%doc examples/systemtap
%changelog
* Tue Apr 28 2015 Cole Robinson <crobinso@redhat.com> - 1.2.13.1-1
- Rebased to version 1.2.13.1
- Fix getVersion() after installing qemu (bz #1000116)
- Fix autosocket setup with qemu:///session (bz #1044561, bz #1105274)
- Ignore storage volumes with non-ascii in names (bz #1066564)
- Don't generate invalid system nodedev XML (bz #1184131)
- Fix crash via race when unrefing rpc identity object (bz #1203030)
- Fix domcapabilities failure with ppc64le (bz #1209948)
- Fix regression with 'virsh event ' (bz #1212620)
- Add {Haswell,Broadwell}-noTSX CPU models (bz #1182650)
- Don't lose VMs on libvirtd restart if qemu is uninstalled (bz #1099847)
- Ignore storage volumes that libvirt can't open (bz #1103308)
* Wed Apr 15 2015 Cole Robinson <crobinso@redhat.com> - 1.2.13-3
- Fix LXC domain startup (bz #1210397)
- Fix crash via identify object cleanup race (bz #1203030)

View File

@ -1 +1 @@
237e0d9c7f8a31ec3cf0df9a41da2137 libvirt-1.2.13.tar.gz
ed36872b34ad3b2e01744b189c039d5c libvirt-1.2.13.1.tar.gz