[libvirt] [PATCH v4 0/7] Network events API
by Cédric Bosdonnat
This patch serie include changes to respond to Eric and Daniel's comments.
The event namespace part of the ID is only handled at the object event's
level, though we need to strip it out of virObjectEventStateEventID to get
the remote driver properly deregister.
Cédric Bosdonnat (7):
Added Network events API and virNetworkEventLifecycle.
test driver: implemented network events
Add network events unit tests
Add network events to the remote driver
Added network events to the bridged network driver
Fixed indentation in src/conf/*_event*
Added default case with error for object event dispatching
daemon/libvirtd.h | 1 +
daemon/remote.c | 139 +++++++++++++++++
include/libvirt/libvirt.h.in | 80 ++++++++++
src/Makefile.am | 5 +
src/conf/domain_event.c | 286 ++++++++++++++++++++---------------
src/conf/domain_event.h | 271 +++++++++++++++++++--------------
src/conf/network_event.c | 154 +++++++++++++++++++
src/conf/network_event.h | 51 +++++++
src/conf/object_event.c | 50 +++---
src/conf/object_event.h | 1 +
src/conf/object_event_private.h | 20 ++-
src/driver.h | 14 ++
src/libvirt.c | 125 +++++++++++++++
src/libvirt_private.syms | 2 +
src/libvirt_public.syms | 7 +
src/network/bridge_driver.c | 90 +++++++++++
src/network/bridge_driver_platform.h | 3 +
src/remote/remote_driver.c | 127 ++++++++++++++++
src/remote/remote_protocol.x | 46 +++++-
src/test/test_driver.c | 62 ++++++++
tests/objecteventtest.c | 167 ++++++++++++++++++++
21 files changed, 1444 insertions(+), 257 deletions(-)
create mode 100644 src/conf/network_event.c
create mode 100644 src/conf/network_event.h
--
1.8.4.4
10 years, 10 months
[libvirt] [PATCHv2 0/7] lxc: honor mount namespaces
by Eric Blake
We are still awaiting a CVE number to be assigned, but Reco
reported in Debian bug #732394 that a malicious guest could
cause virDomainShutdown and virDomainReboot to cause the
host to misbehave, if the host blindly follows symlinks in
its own mount namespace instead of the guest's namespace.
I have not yet tried to patch the bugs in virDomainDeviceAttach
dereferencing /dev from the wrong namespace, which also suffers
from the same vulnerability, but virProcessRunInMountNamespace
should also be usable in that situation.
While working on this series, I found several issues with
virFork and virt-login-shell; since those are also related
to correct namespace usage, I've bundled everything into
one series; but the CVE is not fixed until patch 7/7 plus
the future patch to /dev. I've done some pretty decent
testing on the new virt-login-shell, but did not get as
much testing on virDomainReboot. Since this series does
address a CVE, and also regressions caused by our previous
CVE fix in the same area of code (CVE-2013-4400 is
unfortunately a poor example of shipping "fixes" without
testing that the code still worked), I'd definitely
appreciate a close review.
Patch 6/7 is interesting: it uses virFork to use the mount
namespace without impacting the parent process. However,
since setns() is thread-safe, I wonder if it would be
simpler to instead use pthread_create to do the callback
within the same process instead of having to create a
separate process, as that would make for easier coordination
for passing the results back to the remaining threads that
have not changed namespace. Thankfully, I think we came
up with a good abstraction - I'm fairly confident that
6/7 could be rewritten to use pthread_create without
changing the function signatures, in which case patch
7/7 would not need any changes to pick up the changed
backend.
Eric Blake (7):
virt-login-shell: fix regressions in behavior
virFork: simplify semantics
virt-login-shell: use single instead of double fork
virt-login-shell: saner exit value
virsh: report exit status of failed lxc-enter-namespace
lxc: add virProcessRunInMountNamespace
lxc: security fix for virInitctlSetRunLevel
src/internal.h | 7 +++
src/libvirt.c | 2 +-
src/libvirt_private.syms | 1 +
src/lxc/lxc_driver.c | 38 ++++++------
src/util/vircommand.c | 128 +++++++++++++++-----------------------
src/util/vircommand.h | 2 +-
src/util/virfile.c | 25 ++------
src/util/virinitctl.c | 28 ++++-----
src/util/virinitctl.h | 5 +-
src/util/virprocess.c | 81 ++++++++++++++++++++++--
src/util/virprocess.h | 11 ++++
tools/virsh-domain.c | 34 ++++++----
tools/virsh.pod | 3 +-
tools/virt-login-shell.c | 151 ++++++++++++++++++++-------------------------
tools/virt-login-shell.pod | 23 ++++++-
15 files changed, 299 insertions(+), 240 deletions(-)
--
1.8.4.2
10 years, 10 months
[libvirt] [PATCH 00/24] libvirt.c error handling audit
by Eric Blake
This series is in response to:
https://www.redhat.com/archives/libvir-list/2013-December/msg01101.html
It turned into a much bigger cleanup project, where I ended up
with a lot of changes; hopefully the division into multiple
patches makes review easier, and the end result diffstat shows
that the code base is more compact when all is said and done.
Eric Blake (24):
maint: consistent formatting in libvirt.c
maint: improve debug of libvirt-{qemu,lxc} apis
maint: move debug statements first in public API
maint: improve error condition style in public API
maint: don't leave garbage on early API exit
maint: reset error on entrance to public API
maint: avoid nested public calls
maint: improve VIR_ERR_NO_SUPPORT usage
maint: improve VIR_ERR_OPERATION_DENIED usage
maint: improve VIR_ERR_INVALID_CONN usage
maint: inline VIR_IS_CONNECT macro
maint: improve VIR_ERR_INVALID_DOMAIN usage
maint: inline VIR_IS*_DOMAIN macro
maint: improve VIR_ERR_INVALID_NETWORK usage
maint: improve VIR_ERR_INVALID_INTERFACE usage
maint: improve VIR_ERR_INVALID_STORAGE_POOL usage
maint: improve VIR_ERR_INVALID_STORAGE_VOL usage
maint: improve VIR_ERR_INVALID_NODE_DEVICE usage
maint: improve VIR_ERR_INVALID_SECRET usage
maint: improve VIR_ERR_INVALID_STREAM usage
maint: improve VIR_ERR_INVALID_NWFILTER usage
maint: improve VIR_ERR_INVALID_DOMAIN_SNAPSHOT usage
maint: clean up error reporting in migration
maint: replace remaining virLib*Error with better names
cfg.mk | 10 -
docs/api_extension.html.in | 7 +-
po/POTFILES.in | 1 -
src/datatypes.c | 104 +-
src/datatypes.h | 318 ++-
src/internal.h | 9 +
src/libvirt-lxc.c | 38 +-
src/libvirt-qemu.c | 65 +-
src/libvirt.c | 5342 +++++++++++++--------------------------
src/locking/lock_daemon.c | 16 +-
src/lxc/lxc_driver.c | 2 +-
src/qemu/qemu_migration.c | 10 +-
src/security/security_manager.c | 46 +-
src/util/virerror.c | 2 +-
src/util/virerror.h | 8 +
src/util/virinitctl.c | 4 +-
src/util/virtypedparam.c | 14 +-
src/util/viruuid.h | 20 +-
src/xen/xen_driver.c | 11 +-
19 files changed, 2250 insertions(+), 3777 deletions(-)
--
1.8.4.2
10 years, 10 months
[libvirt] [PATCH 1/1] virsh nodecpustats erroneously returns stats for offline cpus on Linux
by Pradipta Kr. Banerjee
From: "Pradipta Kr. Banerjee" <bpradip(a)in.ibm.com>
virsh nodecpustats erroneously returns stats for offline cpus on Linux
To retrieve node cpu statistics on Linux system, the
linuxNodeGetCPUstats function performs a minimal match of the input
cpuid with the cpuid read from /proc/cpustat. On systems with larger
cpus this can result in erroneous data.
For eg if /proc/stat has similar data
cpu 3645648 485 361475 3691194868 176595 40645 69850 0 1526172 0
cpu0 494045 62 42763 138516619 16107 2339 2431 0 248345 0
cpu4 402646 59 34745 138617562 17738 1413 1196 0 193948 0
cpu8 318662 32 32119 138715131 7903 927 982 0 115429 0
cpu12 247004 33 30465 138791438 5251 759 913 0 51938 0
and cpu 1,2 are offline, then
'virsh nodecpustats 1' displays data for cpu12
whereas virsh nodecpustats 2 correctly throws the following error
"error: Unable to get node cpu stats
error: Invalid cpuNum in linuxNodeGetCPUStats"
This patch fixes the above mentioned problem
Signed-off-by: Pradipta Kr. Banerjee <bpradip(a)in.ibm.com>
---
src/nodeinfo.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/src/nodeinfo.c b/src/nodeinfo.c
index 1838547..c9e5ff1 100644
--- a/src/nodeinfo.c
+++ b/src/nodeinfo.c
@@ -614,6 +614,8 @@ linuxNodeGetCPUStats(FILE *procstat,
unsigned long long usr, ni, sys, idle, iowait;
unsigned long long irq, softirq, steal, guest, guest_nice;
char cpu_header[3 + INT_BUFSIZE_BOUND(cpuNum)];
+ char cpu_header_read[3 + INT_BUFSIZE_BOUND(cpuNum)];
+ char cpu_header_fmt[8];
if ((*nparams) == 0) {
/* Current number of cpu stats supported by linux */
@@ -631,8 +633,11 @@ linuxNodeGetCPUStats(FILE *procstat,
if (cpuNum == VIR_NODE_CPU_STATS_ALL_CPUS) {
strcpy(cpu_header, "cpu");
+ snprintf(cpu_header_fmt, sizeof(cpu_header_fmt), "%%%ds", 3);
} else {
snprintf(cpu_header, sizeof(cpu_header), "cpu%d", cpuNum);
+ snprintf(cpu_header_fmt, sizeof(cpu_header_fmt), "%%%ds",
+ (int)(3 + INT_BUFSIZE_BOUND(cpuNum)));
}
while (fgets(line, sizeof(line), procstat) != NULL) {
@@ -649,6 +654,14 @@ linuxNodeGetCPUStats(FILE *procstat,
continue;
}
+ /*
+ * Process with stats gathering only if the cpuid from /proc/stat
+ * matches exactly with the input cpuid
+ */
+ sscanf(buf, cpu_header_fmt, cpu_header_read);
+ if (STRNEQ(cpu_header, cpu_header_read))
+ continue;
+
for (i = 0; i < *nparams; i++) {
virNodeCPUStatsPtr param = ¶ms[i];
--
1.8.3.1
10 years, 10 months
[libvirt] [PATCH] LXC: don't set socket create selinux context in virLXCProcessConnectMonitor
by Gao feng
the unix socket /var/run/libvirt/lxc/domain.sock is not created
under the selinux context which configured by <seclabel>.
If we try to connect the domain.sock under the selinux context
of domain in virtLXCProcessConnectMonitor,selinux will deny
this connect operation.
type=AVC msg=audit(1387953696.067:662): avc: denied { connectto } for pid=21206 comm="libvirtd" path="/usr/local/var/run/libvirt/lxc/systemd.sock" scontext=unconfined_u:system_r:svirt_lxc_net_t:s0:c770,c848 tcontext=unconfined_u:system_r:unconfined_t:s0-s0:c0.c1023 tclass=unix_stream_socket
Since there is no harm to access doamin.sock outof domain's
context, this patch removes the setsockcreatecon in
virLXCProcessConnectMonitor.
Signed-off-by: Gao feng <gaofeng(a)cn.fujitsu.com>
---
src/lxc/lxc_process.c | 12 ------------
1 file changed, 12 deletions(-)
diff --git a/src/lxc/lxc_process.c b/src/lxc/lxc_process.c
index cc9c1a2..b336ade 100644
--- a/src/lxc/lxc_process.c
+++ b/src/lxc/lxc_process.c
@@ -640,9 +640,6 @@ static virLXCMonitorPtr virLXCProcessConnectMonitor(virLXCDriverPtr driver,
virLXCMonitorPtr monitor = NULL;
virLXCDriverConfigPtr cfg = virLXCDriverGetConfig(driver);
- if (virSecurityManagerSetSocketLabel(driver->securityManager, vm->def) < 0)
- goto cleanup;
-
/* Hold an extra reference because we can't allow 'vm' to be
* deleted while the monitor is active */
virObjectRef(vm);
@@ -652,15 +649,6 @@ static virLXCMonitorPtr virLXCProcessConnectMonitor(virLXCDriverPtr driver,
if (monitor == NULL)
virObjectUnref(vm);
- if (virSecurityManagerClearSocketLabel(driver->securityManager, vm->def) < 0) {
- if (monitor) {
- virObjectUnref(monitor);
- monitor = NULL;
- }
- goto cleanup;
- }
-
-cleanup:
virObjectUnref(cfg);
return monitor;
}
--
1.8.4.2
10 years, 10 months
[libvirt] [PATCH V2 1/1] Add hw random number generator (/dev/hwrng) to cgroup ACL
by Pradipta Kr. Banerjee
From: "Pradipta Kr. Banerjee" <bpradip(a)in.ibm.com>
Creating a qemu VM with /dev/hwrng as backend RNG device throws the
following error - "Could not open '/dev/hwrng': Permission denied"
This patch fixes the issue
Signed-off-by: Pradipta Kr. Banerjee <bpradip(a)in.ibm.com>
---
src/qemu/qemu_cgroup.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
index f0cacd0..8e2076e 100644
--- a/src/qemu/qemu_cgroup.c
+++ b/src/qemu/qemu_cgroup.c
@@ -533,6 +533,18 @@ qemuSetupDevicesCgroup(virQEMUDriverPtr driver,
goto cleanup;
}
+ if (vm->def->rng &&
+ (vm->def->rng->backend == VIR_DOMAIN_RNG_BACKEND_RANDOM)) {
+ VIR_DEBUG("Setting Cgroup ACL for RNG device");
+ rv = virCgroupAllowDevicePath(priv->cgroup, vm->def->rng->source.file,
+ VIR_CGROUP_DEVICE_RW);
+ virDomainAuditCgroupPath(vm, priv->cgroup, "allow",
+ vm->def->rng->source.file, "rw", rv == 0);
+ if (rv < 0 &&
+ !virLastErrorIsSystemErrno(ENOENT))
+ goto cleanup;
+ }
+
ret = 0;
cleanup:
virObjectUnref(cfg);
--
1.8.3.1
10 years, 10 months
[libvirt] [PATCH 0/5] qemu: Fix job usage in several APIs
by Jiri Denemark
When fixing https://bugzilla.redhat.com/show_bug.cgi?id=1043069 I
realized qemuDomainBlockStats is not the only API that does not acquire
a job early enough. Generally, every API that is going to begin a job
should do that before fetching data from vm->def. The following 5 APIs
failed to do so and moreover used the data fetched early from vm->def
after starting a job. In some circumstances this can lead to a crash.
Jiri Denemark (5):
qemu: Do not access stale data in virDomainBlockStats
qemu: Avoid using stale data in virDomainGetBlockInfo
qemu: Fix job usage in qemuDomainBlockJobImpl
qemu: Fix job usage in qemuDomainBlockCopy
qemu: Fix job usage in virDomainGetBlockIoTune
src/qemu/qemu_driver.c | 92 ++++++++++++++++++++++++--------------------------
1 file changed, 44 insertions(+), 48 deletions(-)
--
1.8.5.2
10 years, 10 months
[libvirt] [PATCH] Read PCI class from sysfs class file instead of config space.
by Thadeu Lima de Souza Cascardo
When determining if a device is behind a PCI bridge, the PCI device
class is checked by reading the config space. However, there are some
devices which have the wrong class on the config space, but the class is
initialized by Linux correctly as a PCI BRIDGE. This class can be read
by the sysfs file '/sys/bus/pci/devices/xxxx:xx:xx.x/class'.
One example of such bridge is IBM PCI Bridge 1014:03b9, which is
identified as a Host Bridge when reading the config space.
Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo(a)linux.vnet.ibm.com>
---
The new test cases succeed with this patch. The second test fails
without the changes to src/util/virpci.c.
---
src/util/virpci.c | 41 +++++++++++++++++++++++++++--
tests/virpcimock.c | 33 ++++++++++++++++++++++++
tests/virpcitest.c | 34 ++++++++++++++++++++++++
tests/virpcitestdata/0001:00:00.0.config | Bin 0 -> 4096 bytes
tests/virpcitestdata/0001:01:00.0.config | Bin 0 -> 4096 bytes
tests/virpcitestdata/0001:01:00.1.config | Bin 0 -> 4096 bytes
tests/virpcitestdata/0005:80:00.0.config | Bin 0 -> 4096 bytes
tests/virpcitestdata/0005:90:01.0.config | Bin 0 -> 256 bytes
tests/virpcitestdata/0005:90:01.1.config | Bin 0 -> 256 bytes
tests/virpcitestdata/0005:90:01.2.config | Bin 0 -> 256 bytes
10 files changed, 105 insertions(+), 3 deletions(-)
create mode 100644 tests/virpcitestdata/0001:00:00.0.config
create mode 100644 tests/virpcitestdata/0001:01:00.0.config
create mode 100644 tests/virpcitestdata/0001:01:00.1.config
create mode 100644 tests/virpcitestdata/0005:80:00.0.config
create mode 100644 tests/virpcitestdata/0005:90:01.0.config
create mode 100644 tests/virpcitestdata/0005:90:01.1.config
create mode 100644 tests/virpcitestdata/0005:90:01.2.config
diff --git a/src/util/virpci.c b/src/util/virpci.c
index 8ec642f..8c10a93 100644
--- a/src/util/virpci.c
+++ b/src/util/virpci.c
@@ -344,6 +344,37 @@ virPCIDeviceRead32(virPCIDevicePtr dev, int cfgfd, unsigned int pos)
}
static int
+virPCIDeviceReadClass(virPCIDevicePtr dev, uint16_t *device_class)
+{
+ char *path = NULL;
+ char *id_str;
+ int ret = 0;
+ unsigned int value;
+
+ if (virPCIFile(&path, dev->name, "class") < 0)
+ return -1;
+
+ /* class string is '0xNNNNNN\n' ... i.e. 9 bytes */
+ if (virFileReadAll(path, 9, &id_str) < 0) {
+ VIR_FREE(path);
+ return -1;
+ }
+
+ VIR_FREE(path);
+
+ id_str[8] = '\0';
+ ret = virStrToLong_ui(id_str, NULL, 16, &value);
+ if (ret == 0)
+ *device_class = (value >> 8) & 0xFFFF;
+ else
+ VIR_WARN("Unusual value in " PCI_SYSFS "devices/%s/class: %s",
+ dev->name, id_str);
+
+ VIR_FREE(id_str);
+ return ret;
+}
+
+static int
virPCIDeviceWrite(virPCIDevicePtr dev,
int cfgfd,
unsigned int pos,
@@ -645,8 +676,8 @@ virPCIDeviceIsParent(virPCIDevicePtr dev, virPCIDevicePtr check, void *data)
return 0;
/* Is it a bridge? */
- device_class = virPCIDeviceRead16(check, fd, PCI_CLASS_DEVICE);
- if (device_class != PCI_CLASS_BRIDGE_PCI)
+ ret = virPCIDeviceReadClass(check, &device_class);
+ if (ret == -1 || device_class != PCI_CLASS_BRIDGE_PCI)
goto cleanup;
/* Is it a plane? */
@@ -2110,6 +2141,7 @@ virPCIDeviceDownstreamLacksACS(virPCIDevicePtr dev)
unsigned int pos;
int fd;
int ret = 0;
+ uint16_t device_class;
if ((fd = virPCIDeviceConfigOpen(dev, true)) < 0)
return -1;
@@ -2119,8 +2151,11 @@ virPCIDeviceDownstreamLacksACS(virPCIDevicePtr dev)
goto cleanup;
}
+ if (virPCIDeviceReadClass(dev, &device_class))
+ goto cleanup;
+
pos = dev->pcie_cap_pos;
- if (!pos || virPCIDeviceRead16(dev, fd, PCI_CLASS_DEVICE) != PCI_CLASS_BRIDGE_PCI)
+ if (!pos || device_class != PCI_CLASS_BRIDGE_PCI)
goto cleanup;
flags = virPCIDeviceRead16(dev, fd, pos + PCI_EXP_FLAGS);
diff --git a/tests/virpcimock.c b/tests/virpcimock.c
index a5cef46..49759b0 100644
--- a/tests/virpcimock.c
+++ b/tests/virpcimock.c
@@ -29,6 +29,7 @@
# include <fcntl.h>
# include <sys/stat.h>
# include <stdarg.h>
+# include <dirent.h>
# include "viralloc.h"
# include "virstring.h"
# include "virfile.h"
@@ -42,6 +43,7 @@ static int (*real__xstat)(int ver, const char *path, struct stat *sb);
static char *(*realcanonicalize_file_name)(const char *path);
static int (*realopen)(const char *path, int flags, ...);
static int (*realclose)(int fd);
+static DIR * (*realopendir)(const char *name);
/* Don't make static, since it causes problems with clang
* when passed as an arg to virAsprintf()
@@ -112,6 +114,7 @@ struct pciDevice {
char *id;
int vendor;
int device;
+ int class;
struct pciDriver *driver; /* Driver attached. NULL if attached to no driver */
};
@@ -351,6 +354,10 @@ pci_device_new_from_stub(const struct pciDevice *data)
ABORT("@tmp overflow");
make_file(devpath, "device", tmp, -1);
+ if (snprintf(tmp, sizeof(tmp), "0x%.4x", dev->class) < 0)
+ ABORT("@tmp overflow");
+ make_file(devpath, "class", tmp, -1);
+
if (pci_device_autobind(dev) < 0)
ABORT("Unable to bind: %s", data->id);
@@ -747,6 +754,7 @@ init_syms(void)
LOAD_SYM(canonicalize_file_name);
LOAD_SYM(open);
LOAD_SYM(close);
+ LOAD_SYM(opendir);
}
static void
@@ -776,6 +784,13 @@ init_env(void)
MAKE_PCI_DEVICE("0000:00:01.0", 0x8086, 0x0044);
MAKE_PCI_DEVICE("0000:00:02.0", 0x8086, 0x0046);
MAKE_PCI_DEVICE("0000:00:03.0", 0x8086, 0x0048);
+ MAKE_PCI_DEVICE("0001:00:00.0", 0x1014, 0x03b9, .class = 0x060400);
+ MAKE_PCI_DEVICE("0001:01:00.0", 0x8086, 0x105e);
+ MAKE_PCI_DEVICE("0001:01:00.1", 0x8086, 0x105e);
+ MAKE_PCI_DEVICE("0005:80:00.0", 0x10b5, 0x8112, .class = 0x060400);
+ MAKE_PCI_DEVICE("0005:90:01.0", 0x1033, 0x0035);
+ MAKE_PCI_DEVICE("0005:90:01.1", 0x1033, 0x0035);
+ MAKE_PCI_DEVICE("0005:90:01.2", 0x1033, 0x00e0);
}
@@ -934,6 +949,24 @@ open(const char *path, int flags, ...)
return ret;
}
+DIR *
+opendir(const char *path)
+{
+ DIR *ret;
+ char *newpath = NULL;
+
+ init_syms();
+
+ if (STRPREFIX(path, PCI_SYSFS_PREFIX) &&
+ getrealpath(&newpath, path) < 0)
+ return NULL;
+
+ ret = realopendir(newpath ? newpath : path);
+
+ VIR_FREE(newpath);
+ return ret;
+}
+
int
close(int fd)
{
diff --git a/tests/virpcitest.c b/tests/virpcitest.c
index 5fe6d49..82a173a 100644
--- a/tests/virpcitest.c
+++ b/tests/virpcitest.c
@@ -183,6 +183,31 @@ cleanup:
return ret;
}
+struct testPCIDevData {
+ unsigned int domain;
+ unsigned int bus;
+ unsigned int slot;
+ unsigned int function;
+};
+
+static int
+testVirPCIDeviceIsAssignable(const void *opaque)
+{
+ const struct testPCIDevData *data = opaque;
+ int ret = -1;
+ virPCIDevicePtr dev;
+
+ if (!(dev = virPCIDeviceNew(data->domain, data->bus, data->slot, data->function)))
+ goto cleanup;
+
+ if (virPCIDeviceIsAssignable(dev, true))
+ ret = 0;
+
+ virPCIDeviceFree(dev);
+cleanup:
+ return ret;
+}
+
# define FAKESYSFSDIRTEMPLATE abs_builddir "/fakesysfsdir-XXXXXX"
static int
@@ -209,10 +234,19 @@ mymain(void)
ret = -1; \
} while (0)
+# define DO_TEST_PCI(fnc, domain, bus, slot, function) \
+ do { \
+ struct testPCIDevData data = { domain, bus, slot, function }; \
+ if (virtTestRun(#fnc, fnc, &data) < 0) \
+ ret = -1; \
+ } while (0)
+
DO_TEST(testVirPCIDeviceNew);
DO_TEST(testVirPCIDeviceDetach);
DO_TEST(testVirPCIDeviceReset);
DO_TEST(testVirPCIDeviceReattach);
+ DO_TEST_PCI(testVirPCIDeviceIsAssignable, 5, 0x90, 1, 0);
+ DO_TEST_PCI(testVirPCIDeviceIsAssignable, 1, 1, 0, 0);
if (getenv("LIBVIRT_SKIP_CLEANUP") == NULL)
virFileDeleteTree(fakesysfsdir);
diff --git a/tests/virpcitestdata/0001:00:00.0.config b/tests/virpcitestdata/0001:00:00.0.config
new file mode 100644
index 0000000000000000000000000000000000000000..808d48993cfc0f41223fcb5f49deffc594f136b7
GIT binary patch
literal 4096
zcmeH@I}XAy5Jca`5~RZg60MJb!~ys;a0<jx5^hCDNy!mt=t)n(8Yfir2x&(4YG(bB
z{ig90wibyn0^=hytn<`78f&|D=zEvd5U8+Sxa1hw*nI*%I6fEDtkd58IUH=(-@Ei&
z`ONZ@#r(MD|GagrnWu5_32tAW*RPg6sv;l)A|L`HAOa#F0wN#+A|L`H@J9q*PZkdc
literal 0
HcmV?d00001
diff --git a/tests/virpcitestdata/0001:01:00.0.config b/tests/virpcitestdata/0001:01:00.0.config
new file mode 100644
index 0000000000000000000000000000000000000000..f63aacbea08fc83b345e1ee404756145e7d349a5
GIT binary patch
literal 4096
zcmZo`h!bFD5MW?qU|>>UXkY*WAi>nY$iN6<qW}>B2WF7K379CR5||9#X~qjmCm0kM
z6j>iMK<#Fl0AdIL{c(^7NNY$jIHrJ{?<fFO0H%Qc6alFM0YL>exUYeN42%s7Ec~1x
z877=QWd`bav)TXue_{D2AeEzFGz3ONU^E0qLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!n
I24e^S0CUn1m;e9(
literal 0
HcmV?d00001
diff --git a/tests/virpcitestdata/0001:01:00.1.config b/tests/virpcitestdata/0001:01:00.1.config
new file mode 100644
index 0000000000000000000000000000000000000000..db9e3876a528266bb5a6e9651d7cd18b45b7d71f
GIT binary patch
literal 4096
zcmZo`h!bFD5MW?qU|>>UXkcJqU;z?r4T=nmKsG865pZAziJX85Gr<@GPcvRnI>Dg8
zpvd~50qPj02_PQ`0R3^02S{s3F*v4xobM<ARRE?K85l)Csz5+cfer3!pdbTd0|N^`
zCrE|~GcZ8HK)?*t@n*CC|Np}BPaq<r<Y)+thQMeDjE2By2#kinXb6mkz-S1JhQMeD
NjE2By2n@au000k05W)Ze
literal 0
HcmV?d00001
diff --git a/tests/virpcitestdata/0005:80:00.0.config b/tests/virpcitestdata/0005:80:00.0.config
new file mode 100644
index 0000000000000000000000000000000000000000..cc4f94a849ed3d0a47f5b47331aaecdea88765c3
GIT binary patch
literal 4096
zcmdlgAk@gtAi%JSfrX8Mfsp|Q8YawV_`sl`#L)Di>BE1RD1>%^ae>Mi1DK*fTmcO}
zuqbOn1DJ*p0t|%^rUDm(pbry}Ey&Qo0}^ro5pYlpXVI6zg5+oV+Kg)3K=~il6$8f`
z_5Z+y{a~<pH2w!eEDW3*M&p0r!hSH=JR1LlAr=PC4WsctaA7|fY#xpO!4L}r=Z4Yv
IADFNQ0PH*z9smFU
literal 0
HcmV?d00001
diff --git a/tests/virpcitestdata/0005:90:01.0.config b/tests/virpcitestdata/0005:90:01.0.config
new file mode 100644
index 0000000000000000000000000000000000000000..a60599bd342d3ebcdc7b8367ca36ad337f602fde
GIT binary patch
literal 256
zcmXpOFlAt45MXi^VCG@qXkY+>CJ=!Q7z5RUfCHEW5{!&mj0{Y5Fz#TaS&cX3;ByxM
DCDjDB
literal 0
HcmV?d00001
diff --git a/tests/virpcitestdata/0005:90:01.1.config b/tests/virpcitestdata/0005:90:01.1.config
new file mode 100644
index 0000000000000000000000000000000000000000..beee76534041a7020c08ae9ac03d9a349c6ea12e
GIT binary patch
literal 256
ycmXpOFlAt45MXi^VCG@qU|?VnU}yr8Sb;H6EeJS(Ng%<*sKv;@R0rb@MH&E<&;s)S
literal 0
HcmV?d00001
diff --git a/tests/virpcitestdata/0005:90:01.2.config b/tests/virpcitestdata/0005:90:01.2.config
new file mode 100644
index 0000000000000000000000000000000000000000..cfd72e4d7165bff2751ecbdc570ce7f1e0646226
GIT binary patch
literal 256
zcmXpOc)-BMAi%_;z|6zo!oa|wz|aIFu>xbDS`csmlR$!5K#7rosSd`)Mk^@TV-u#E
T7_0Gy9FS#<5E~CbC<F-rZiWW}
literal 0
HcmV?d00001
--
1.7.1
10 years, 10 months
[libvirt] [PATCH] Fix bridge configuration when OUTPUT policy is DROP on the host
by Lénaïc Huard
When the host is configured with very restrictive firewall (default policy
is DROP for all chains, including OUTPUT), the bridge driver for Linux
adds netfilter entries to allow DHCP and DNS requests to go from the VM
to the dnsmasq of the host.
The issue that this commit fixes is the fact that a DROP policy on the OUTPUT
chain blocks the DHCP replies from the host’s dnsmasq to the VM.
As DHCP replies are sent in UDP, they are not caught by any --ctstate ESTABLISHED
rule and so, need to be explicitly allowed.
Signed-off-by: Lénaïc Huard <lenaic(a)lhuard.fr.eu.org>
---
src/libvirt_private.syms | 2 ++
src/network/bridge_driver_linux.c | 35 +++++++++++++---------
src/util/viriptables.c | 61 +++++++++++++++++++++++++++++++++++++++
src/util/viriptables.h | 7 +++++
4 files changed, 92 insertions(+), 13 deletions(-)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 2dbb8f8..c26ce29 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1290,6 +1290,7 @@ iptablesAddForwardRejectOut;
iptablesAddOutputFixUdpChecksum;
iptablesAddTcpInput;
iptablesAddUdpInput;
+iptablesAddUdpOutput;
iptablesRemoveDontMasquerade;
iptablesRemoveForwardAllowCross;
iptablesRemoveForwardAllowIn;
@@ -1301,6 +1302,7 @@ iptablesRemoveForwardRejectOut;
iptablesRemoveOutputFixUdpChecksum;
iptablesRemoveTcpInput;
iptablesRemoveUdpInput;
+iptablesRemoveUdpOutput;
# util/virjson.h
diff --git a/src/network/bridge_driver_linux.c b/src/network/bridge_driver_linux.c
index 066779a..dcdd033 100644
--- a/src/network/bridge_driver_linux.c
+++ b/src/network/bridge_driver_linux.c
@@ -564,6 +564,13 @@ int networkAddGeneralFirewallRules(virNetworkObjPtr network)
goto err2;
}
+ if (iptablesAddUdpOutput(AF_INET, network->def->bridge, 68) < 0) {
+ virReportError(VIR_ERR_SYSTEM_ERROR,
+ _("failed to add iptables rule to allow DHCP replies to '%s'"),
+ network->def->bridge);
+ goto err3;
+ }
+
/* If we are doing local DHCP service on this network, attempt to
* add a rule that will fixup the checksum of DHCP response
* packets back to the guests (but report failure without
@@ -582,14 +589,14 @@ int networkAddGeneralFirewallRules(virNetworkObjPtr network)
virReportError(VIR_ERR_SYSTEM_ERROR,
_("failed to add iptables rule to allow DNS requests from '%s'"),
network->def->bridge);
- goto err3;
+ goto err4;
}
if (iptablesAddUdpInput(AF_INET, network->def->bridge, 53) < 0) {
virReportError(VIR_ERR_SYSTEM_ERROR,
_("failed to add iptables rule to allow DNS requests from '%s'"),
network->def->bridge);
- goto err4;
+ goto err5;
}
/* allow TFTP requests through to dnsmasq if necessary */
@@ -598,7 +605,7 @@ int networkAddGeneralFirewallRules(virNetworkObjPtr network)
virReportError(VIR_ERR_SYSTEM_ERROR,
_("failed to add iptables rule to allow TFTP requests from '%s'"),
network->def->bridge);
- goto err5;
+ goto err6;
}
/* Catch all rules to block forwarding to/from bridges */
@@ -607,14 +614,14 @@ int networkAddGeneralFirewallRules(virNetworkObjPtr network)
virReportError(VIR_ERR_SYSTEM_ERROR,
_("failed to add iptables rule to block outbound traffic from '%s'"),
network->def->bridge);
- goto err6;
+ goto err7;
}
if (iptablesAddForwardRejectIn(AF_INET, network->def->bridge) < 0) {
virReportError(VIR_ERR_SYSTEM_ERROR,
_("failed to add iptables rule to block inbound traffic to '%s'"),
network->def->bridge);
- goto err7;
+ goto err8;
}
/* Allow traffic between guests on the same bridge */
@@ -622,31 +629,33 @@ int networkAddGeneralFirewallRules(virNetworkObjPtr network)
virReportError(VIR_ERR_SYSTEM_ERROR,
_("failed to add iptables rule to allow cross bridge traffic on '%s'"),
network->def->bridge);
- goto err8;
+ goto err9;
}
/* add IPv6 general rules, if needed */
if (networkAddGeneralIp6tablesRules(network) < 0) {
- goto err9;
+ goto err10;
}
return 0;
/* unwind in reverse order from the point of failure */
-err9:
+err10:
iptablesRemoveForwardAllowCross(AF_INET, network->def->bridge);
-err8:
+err9:
iptablesRemoveForwardRejectIn(AF_INET, network->def->bridge);
-err7:
+err8:
iptablesRemoveForwardRejectOut(AF_INET, network->def->bridge);
-err6:
+err7:
if (ipv4def && ipv4def->tftproot) {
iptablesRemoveUdpInput(AF_INET, network->def->bridge, 69);
}
-err5:
+err6:
iptablesRemoveUdpInput(AF_INET, network->def->bridge, 53);
-err4:
+err5:
iptablesRemoveTcpInput(AF_INET, network->def->bridge, 53);
+err4:
+ iptablesRemoveUdpOutput(AF_INET, network->def->bridge, 68);
err3:
iptablesRemoveUdpInput(AF_INET, network->def->bridge, 67);
err2:
diff --git a/src/util/viriptables.c b/src/util/viriptables.c
index a1711bb..9b78d86 100644
--- a/src/util/viriptables.c
+++ b/src/util/viriptables.c
@@ -184,6 +184,28 @@ iptablesInput(int family,
NULL);
}
+static int
+iptablesOutput(int family,
+ const char *iface,
+ int port,
+ int action,
+ int tcp)
+{
+ char portstr[32];
+
+ snprintf(portstr, sizeof(portstr), "%d", port);
+ portstr[sizeof(portstr) - 1] = '\0';
+
+ return iptablesAddRemoveRule("filter", "OUTPUT",
+ family,
+ action,
+ "--out-interface", iface,
+ "--protocol", tcp ? "tcp" : "udp",
+ "--destination-port", portstr,
+ "--jump", "ACCEPT",
+ NULL);
+}
+
/**
* iptablesAddTcpInput:
* @ctx: pointer to the IP table context
@@ -262,6 +284,45 @@ iptablesRemoveUdpInput(int family,
return iptablesInput(family, iface, port, REMOVE, 0);
}
+/**
+ * iptablesAddUdpOutput:
+ * @ctx: pointer to the IP table context
+ * @iface: the interface name
+ * @port: the UDP port to add
+ *
+ * Add an output to the IP table allowing access to the given @port from
+ * the given @iface interface for UDP packets
+ *
+ * Returns 0 in case of success or an error code in case of error
+ */
+
+int
+iptablesAddUdpOutput(int family,
+ const char *iface,
+ int port)
+{
+ return iptablesOutput(family, iface, port, ADD, 0);
+}
+
+/**
+ * iptablesRemoveUdpOutput:
+ * @ctx: pointer to the IP table context
+ * @iface: the interface name
+ * @port: the UDP port to remove
+ *
+ * Removes an output from the IP table, hence forbidding access to the given
+ * @port from the given @iface interface for UDP packets
+ *
+ * Returns 0 in case of success or an error code in case of error
+ */
+int
+iptablesRemoveUdpOutput(int family,
+ const char *iface,
+ int port)
+{
+ return iptablesOutput(family, iface, port, REMOVE, 0);
+}
+
static char *iptablesFormatNetwork(virSocketAddr *netaddr,
unsigned int prefix)
diff --git a/src/util/viriptables.h b/src/util/viriptables.h
index 6dfb992..2f9a212 100644
--- a/src/util/viriptables.h
+++ b/src/util/viriptables.h
@@ -40,6 +40,13 @@ int iptablesRemoveUdpInput (int family,
const char *iface,
int port);
+int iptablesAddUdpOutput (int family,
+ const char *iface,
+ int port);
+int iptablesRemoveUdpOutput (int family,
+ const char *iface,
+ int port);
+
int iptablesAddForwardAllowOut (virSocketAddr *netaddr,
unsigned int prefix,
const char *iface,
--
1.8.5.1
10 years, 10 months