Hello community, here is the log from the commit of package libvirt for openSUSE:Factory checked in at 2018-02-13 10:27:04 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/libvirt (Old) and /work/SRC/openSUSE:Factory/.libvirt.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "libvirt" Tue Feb 13 10:27:04 2018 rev:250 rq:575802 version:4.0.0 Changes: -------- --- /work/SRC/openSUSE:Factory/libvirt/libvirt.changes 2018-01-30 15:38:46.922352045 +0100 +++ /work/SRC/openSUSE:Factory/.libvirt.new/libvirt.changes 2018-02-13 10:27:05.794080712 +0100 @@ -1,0 +2,15 @@ +Fri Feb 9 13:28:14 UTC 2018 - [email protected] + +- Remove all uses of python2 during the build (bsc#1080034) + 6b3d716e-keycodemap-py3.patch + apibuild-py3.patch +- Determine hostname early to avoid code injection + in lxc driver. (bsc#1080042) + 759b4d1b-virlog-determine-the-hostname-on-startup-CVE-2018-67.patch + c2dc6698-fix-deadlock-obtaining-hostname.patch +- Add basic support of connectGetAllDomainStats for lxc driver + (fate#323742) + 0001-Extract-stats-functions-from-the-qemu-driver.patch + 0002-lxc-implement-connectGetAllDomainStats.patch + +------------------------------------------------------------------- New: ---- 0001-Extract-stats-functions-from-the-qemu-driver.patch 0002-lxc-implement-connectGetAllDomainStats.patch 6b3d716e-keycodemap-py3.patch 759b4d1b-virlog-determine-the-hostname-on-startup-CVE-2018-67.patch apibuild-py3.patch c2dc6698-fix-deadlock-obtaining-hostname.patch ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ libvirt.spec ++++++ --- /var/tmp/diff_new_pack.nJG3X3/_old 2018-02-13 10:27:07.130032578 +0100 +++ /var/tmp/diff_new_pack.nJG3X3/_new 2018-02-13 10:27:07.134032433 +0100 @@ -236,7 +236,7 @@ BuildRequires: libxslt BuildRequires: ncurses-devel BuildRequires: perl -BuildRequires: python +BuildRequires: python3 BuildRequires: readline-devel # perl XPath is needed since we have a patch touching files that cause # hvsupport.html to be regenerated @@ -322,6 +322,9 @@ Patch2: 68eed56b-conf-smbios-oem-strings.patch Patch3: 76977061-qemu-smbios-oem-strings.patch Patch4: 0c710a37-libxl-resume-lock-on-mig-failure.patch +Patch5: 6b3d716e-keycodemap-py3.patch +Patch6: 759b4d1b-virlog-determine-the-hostname-on-startup-CVE-2018-67.patch +Patch7: c2dc6698-fix-deadlock-obtaining-hostname.patch # Patches pending upstream review Patch100: libxl-dom-reset.patch Patch101: network-don-t-use-dhcp-authoritative-on-static-netwo.patch @@ -332,6 +335,9 @@ Patch153: ppc64le-canonical-name.patch Patch154: libxl-set-migration-constraints.patch Patch155: libxl-set-cach-mode.patch +Patch156: 0001-Extract-stats-functions-from-the-qemu-driver.patch +Patch157: 0002-lxc-implement-connectGetAllDomainStats.patch +Patch158: apibuild-py3.patch # Our patches Patch200: suse-libvirtd-disable-tls.patch Patch201: suse-libvirtd-sysconfig-settings.patch @@ -912,6 +918,12 @@ %patch2 -p1 %patch3 -p1 %patch4 -p1 +# it is submodule in git +pushd src/keycodemapdb +%patch5 -p1 +popd +%patch6 -p1 +%patch7 -p1 %patch100 -p1 %patch101 -p1 %patch150 -p1 @@ -920,6 +932,9 @@ %patch153 -p1 %patch154 -p1 %patch155 -p1 +%patch156 -p1 +%patch157 -p1 +%patch158 -p1 %patch200 -p1 %patch201 -p1 %patch202 -p1 @@ -1064,6 +1079,7 @@ autoreconf -f -i export CFLAGS="%{optflags}" +export PYTHON=%{_bindir}/python3 %configure --disable-static \ %{?arg_xen} \ %{?arg_qemu} \ ++++++ 0001-Extract-stats-functions-from-the-qemu-driver.patch ++++++ >From 6609ed5a377c3beaf8389e870b6851856cee42c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Bosdonnat?= <[email protected]> Date: Thu, 4 Jan 2018 12:04:07 +0100 Subject: [PATCH 1/3] Extract stats functions from the qemu driver Some of the qemu functions getting statistics can easily be reused in other drivers. Create a conf/domain_stats.[ch] pair to host some of them. --- src/Makefile.am | 1 + src/conf/domain_stats.c | 139 +++++++++++++++++++++++++++++++++++++++++ src/conf/domain_stats.h | 64 +++++++++++++++++++ src/libvirt_private.syms | 4 ++ src/qemu/qemu_driver.c | 158 +++-------------------------------------------- src/util/vircgroup.c | 46 ++++++++++++++ src/util/vircgroup.h | 4 ++ 7 files changed, 265 insertions(+), 151 deletions(-) create mode 100644 src/conf/domain_stats.c create mode 100644 src/conf/domain_stats.h diff --git a/src/Makefile.am b/src/Makefile.am index 166c9a8e9..25f913a5f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -404,6 +404,7 @@ DOMAIN_CONF_SOURCES = \ conf/domain_conf.c conf/domain_conf.h \ conf/domain_audit.c conf/domain_audit.h \ conf/domain_nwfilter.c conf/domain_nwfilter.h \ + conf/domain_stats.c conf/domain_stats.h \ conf/virsavecookie.c conf/virsavecookie.h \ conf/snapshot_conf.c conf/snapshot_conf.h \ conf/numa_conf.c conf/numa_conf.h \ diff --git a/src/conf/domain_stats.c b/src/conf/domain_stats.c new file mode 100644 index 000000000..beb3c09d5 --- /dev/null +++ b/src/conf/domain_stats.c @@ -0,0 +1,139 @@ +/* + * domain_stats.c: domain stats extraction helpers + * + * Copyright (C) 2006-2016 Red Hat, Inc. + * Copyright (C) 2006-2008 Daniel P. Berrange + * Copyright (c) 2018 SUSE LINUX Products GmbH, Nuernberg, Germany. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + * + * Author: Daniel P. Berrange <[email protected]> + */ + +#include <config.h> + +#include <stdio.h> + +#include "virlog.h" +#include "domain_stats.h" +#include "virtypedparam.h" +#include "virnetdevtap.h" +#include "virnetdevopenvswitch.h" + +#define VIR_FROM_THIS VIR_FROM_DOMAIN + +VIR_LOG_INIT("conf.domain_stats"); + +int +virDomainStatsGetState(virDomainObjPtr dom, + virDomainStatsRecordPtr record, + int *maxparams) +{ + if (virTypedParamsAddInt(&record->params, + &record->nparams, + maxparams, + "state.state", + dom->state.state) < 0) + return -1; + + if (virTypedParamsAddInt(&record->params, + &record->nparams, + maxparams, + "state.reason", + dom->state.reason) < 0) + return -1; + + return 0; +} + +#define STATS_ADD_NET_PARAM(record, maxparams, num, name, value) \ +do { \ + char param_name[VIR_TYPED_PARAM_FIELD_LENGTH]; \ + snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, \ + "net.%zu.%s", num, name); \ + if (value >= 0 && virTypedParamsAddULLong(&(record)->params, \ + &(record)->nparams, \ + maxparams, \ + param_name, \ + value) < 0) \ + return -1; \ +} while (0) + +int +virDomainStatsGetInterface(virDomainObjPtr dom, + virDomainStatsRecordPtr record, + int *maxparams) +{ + size_t i; + struct _virDomainInterfaceStats tmp; + int ret = -1; + + if (!virDomainObjIsActive(dom)) + return 0; + + VIR_DOMAIN_STATS_ADD_COUNT_PARAM(record, maxparams, "net", dom->def->nnets); + + /* Check the path is one of the domain's network interfaces. */ + for (i = 0; i < dom->def->nnets; i++) { + virDomainNetDefPtr net = dom->def->nets[i]; + virDomainNetType actualType; + + if (!net->ifname) + continue; + + memset(&tmp, 0, sizeof(tmp)); + + actualType = virDomainNetGetActualType(net); + + VIR_DOMAIN_STATS_ADD_NAME_PARAM(record, maxparams, + "net", "name", i, net->ifname); + + if (actualType == VIR_DOMAIN_NET_TYPE_VHOSTUSER) { + if (virNetDevOpenvswitchInterfaceStats(net->ifname, &tmp) < 0) { + virResetLastError(); + continue; + } + } else { + if (virNetDevTapInterfaceStats(net->ifname, &tmp, + !virDomainNetTypeSharesHostView(net)) < 0) { + virResetLastError(); + continue; + } + } + + STATS_ADD_NET_PARAM(record, maxparams, i, + "rx.bytes", tmp.rx_bytes); + STATS_ADD_NET_PARAM(record, maxparams, i, + "rx.pkts", tmp.rx_packets); + STATS_ADD_NET_PARAM(record, maxparams, i, + "rx.errs", tmp.rx_errs); + STATS_ADD_NET_PARAM(record, maxparams, i, + "rx.drop", tmp.rx_drop); + STATS_ADD_NET_PARAM(record, maxparams, i, + "tx.bytes", tmp.tx_bytes); + STATS_ADD_NET_PARAM(record, maxparams, i, + "tx.pkts", tmp.tx_packets); + STATS_ADD_NET_PARAM(record, maxparams, i, + "tx.errs", tmp.tx_errs); + STATS_ADD_NET_PARAM(record, maxparams, i, + "tx.drop", tmp.tx_drop); + } + + ret = 0; + cleanup: + return ret; +} + +#undef STATS_ADD_NET_PARAM diff --git a/src/conf/domain_stats.h b/src/conf/domain_stats.h new file mode 100644 index 000000000..42f8cb6d3 --- /dev/null +++ b/src/conf/domain_stats.h @@ -0,0 +1,64 @@ +/* + * domain_stats.h: domain stats extraction helpers + * + * Copyright (C) 2006-2016 Red Hat, Inc. + * Copyright (C) 2006-2008 Daniel P. Berrange + * Copyright (c) 2018 SUSE LINUX Products GmbH, Nuernberg, Germany. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + * + * Author: Daniel P. Berrange <[email protected]> + */ +#ifndef __DOMAIN_STATS_H +# define __DOMAIN_STATS_H + +# include "internal.h" +# include "domain_conf.h" + + +# define VIR_DOMAIN_STATS_ADD_COUNT_PARAM(record, maxparams, type, count) \ +do { \ + char param_name[VIR_TYPED_PARAM_FIELD_LENGTH]; \ + snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, "%s.count", type); \ + if (virTypedParamsAddUInt(&(record)->params, \ + &(record)->nparams, \ + maxparams, \ + param_name, \ + count) < 0) \ + goto cleanup; \ +} while (0) + +# define VIR_DOMAIN_STATS_ADD_NAME_PARAM(record, maxparams, type, subtype, num, name) \ +do { \ + char param_name[VIR_TYPED_PARAM_FIELD_LENGTH]; \ + snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, \ + "%s.%zu.%s", type, num, subtype); \ + if (virTypedParamsAddString(&(record)->params, \ + &(record)->nparams, \ + maxparams, \ + param_name, \ + name) < 0) \ + goto cleanup; \ +} while (0) + +int virDomainStatsGetState(virDomainObjPtr dom, + virDomainStatsRecordPtr record, + int *maxparams); + +int virDomainStatsGetInterface(virDomainObjPtr dom, + virDomainStatsRecordPtr record, + int *maxparams); + +#endif /* __DOMAIN_STATS_H */ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index bc8cc1fba..2e22abcec 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -630,6 +630,9 @@ virDomainConfNWFilterRegister; virDomainConfNWFilterTeardown; virDomainConfVMNWFilterTeardown; +# conf/domain_stats.h +virDomainStatsGetInterface; +virDomainStatsGetState; # conf/interface_conf.h virInterfaceDefFormat; @@ -1468,6 +1471,7 @@ virCgroupGetMemoryUsage; virCgroupGetMemSwapHardLimit; virCgroupGetMemSwapUsage; virCgroupGetPercpuStats; +virCgroupGetStatsCpu; virCgroupHasController; virCgroupHasEmptyTasks; virCgroupKill; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index a203c9297..f60436e4c 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -72,6 +72,7 @@ #include "viralloc.h" #include "viruuid.h" #include "domain_conf.h" +#include "domain_stats.h" #include "domain_audit.h" #include "node_device_conf.h" #include "virpci.h" @@ -19380,21 +19381,7 @@ qemuDomainGetStatsState(virQEMUDriverPtr driver ATTRIBUTE_UNUSED, int *maxparams, unsigned int privflags ATTRIBUTE_UNUSED) { - if (virTypedParamsAddInt(&record->params, - &record->nparams, - maxparams, - "state.state", - dom->state.state) < 0) - return -1; - - if (virTypedParamsAddInt(&record->params, - &record->nparams, - maxparams, - "state.reason", - dom->state.reason) < 0) - return -1; - - return 0; + return virDomainStatsGetState(dom, record, maxparams); } @@ -19417,37 +19404,7 @@ qemuDomainGetStatsCpu(virQEMUDriverPtr driver ATTRIBUTE_UNUSED, unsigned int privflags ATTRIBUTE_UNUSED) { qemuDomainObjPrivatePtr priv = dom->privateData; - unsigned long long cpu_time = 0; - unsigned long long user_time = 0; - unsigned long long sys_time = 0; - int err = 0; - - if (!priv->cgroup) - return 0; - - err = virCgroupGetCpuacctUsage(priv->cgroup, &cpu_time); - if (!err && virTypedParamsAddULLong(&record->params, - &record->nparams, - maxparams, - "cpu.time", - cpu_time) < 0) - return -1; - - err = virCgroupGetCpuacctStat(priv->cgroup, &user_time, &sys_time); - if (!err && virTypedParamsAddULLong(&record->params, - &record->nparams, - maxparams, - "cpu.user", - user_time) < 0) - return -1; - if (!err && virTypedParamsAddULLong(&record->params, - &record->nparams, - maxparams, - "cpu.system", - sys_time) < 0) - return -1; - - return 0; + return virCgroupGetStatsCpu(priv->cgroup, record, maxparams); } static int @@ -19624,44 +19581,6 @@ qemuDomainGetStatsVcpu(virQEMUDriverPtr driver, return ret; } -#define QEMU_ADD_COUNT_PARAM(record, maxparams, type, count) \ -do { \ - char param_name[VIR_TYPED_PARAM_FIELD_LENGTH]; \ - snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, "%s.count", type); \ - if (virTypedParamsAddUInt(&(record)->params, \ - &(record)->nparams, \ - maxparams, \ - param_name, \ - count) < 0) \ - goto cleanup; \ -} while (0) - -#define QEMU_ADD_NAME_PARAM(record, maxparams, type, subtype, num, name) \ -do { \ - char param_name[VIR_TYPED_PARAM_FIELD_LENGTH]; \ - snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, \ - "%s.%zu.%s", type, num, subtype); \ - if (virTypedParamsAddString(&(record)->params, \ - &(record)->nparams, \ - maxparams, \ - param_name, \ - name) < 0) \ - goto cleanup; \ -} while (0) - -#define QEMU_ADD_NET_PARAM(record, maxparams, num, name, value) \ -do { \ - char param_name[VIR_TYPED_PARAM_FIELD_LENGTH]; \ - snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, \ - "net.%zu.%s", num, name); \ - if (value >= 0 && virTypedParamsAddULLong(&(record)->params, \ - &(record)->nparams, \ - maxparams, \ - param_name, \ - value) < 0) \ - return -1; \ -} while (0) - static int qemuDomainGetStatsInterface(virQEMUDriverPtr driver ATTRIBUTE_UNUSED, virDomainObjPtr dom, @@ -19669,68 +19588,9 @@ qemuDomainGetStatsInterface(virQEMUDriverPtr driver ATTRIBUTE_UNUSED, int *maxparams, unsigned int privflags ATTRIBUTE_UNUSED) { - size_t i; - struct _virDomainInterfaceStats tmp; - int ret = -1; - - if (!virDomainObjIsActive(dom)) - return 0; - - QEMU_ADD_COUNT_PARAM(record, maxparams, "net", dom->def->nnets); - - /* Check the path is one of the domain's network interfaces. */ - for (i = 0; i < dom->def->nnets; i++) { - virDomainNetDefPtr net = dom->def->nets[i]; - virDomainNetType actualType; - - if (!net->ifname) - continue; - - memset(&tmp, 0, sizeof(tmp)); - - actualType = virDomainNetGetActualType(net); - - QEMU_ADD_NAME_PARAM(record, maxparams, - "net", "name", i, net->ifname); - - if (actualType == VIR_DOMAIN_NET_TYPE_VHOSTUSER) { - if (virNetDevOpenvswitchInterfaceStats(net->ifname, &tmp) < 0) { - virResetLastError(); - continue; - } - } else { - if (virNetDevTapInterfaceStats(net->ifname, &tmp, - !virDomainNetTypeSharesHostView(net)) < 0) { - virResetLastError(); - continue; - } - } - - QEMU_ADD_NET_PARAM(record, maxparams, i, - "rx.bytes", tmp.rx_bytes); - QEMU_ADD_NET_PARAM(record, maxparams, i, - "rx.pkts", tmp.rx_packets); - QEMU_ADD_NET_PARAM(record, maxparams, i, - "rx.errs", tmp.rx_errs); - QEMU_ADD_NET_PARAM(record, maxparams, i, - "rx.drop", tmp.rx_drop); - QEMU_ADD_NET_PARAM(record, maxparams, i, - "tx.bytes", tmp.tx_bytes); - QEMU_ADD_NET_PARAM(record, maxparams, i, - "tx.pkts", tmp.tx_packets); - QEMU_ADD_NET_PARAM(record, maxparams, i, - "tx.errs", tmp.tx_errs); - QEMU_ADD_NET_PARAM(record, maxparams, i, - "tx.drop", tmp.tx_drop); - } - - ret = 0; - cleanup: - return ret; + return virDomainStatsGetInterface(dom, record, maxparams); } -#undef QEMU_ADD_NET_PARAM - #define QEMU_ADD_BLOCK_PARAM_UI(record, maxparams, num, name, value) \ do { \ char param_name[VIR_TYPED_PARAM_FIELD_LENGTH]; \ @@ -19852,10 +19712,10 @@ qemuDomainGetStatsOneBlock(virQEMUDriverPtr driver, if (disk->info.alias) alias = qemuDomainStorageAlias(disk->info.alias, backing_idx); - QEMU_ADD_NAME_PARAM(record, maxparams, "block", "name", block_idx, + VIR_DOMAIN_STATS_ADD_NAME_PARAM(record, maxparams, "block", "name", block_idx, disk->dst); if (virStorageSourceIsLocalStorage(src) && src->path) - QEMU_ADD_NAME_PARAM(record, maxparams, "block", "path", + VIR_DOMAIN_STATS_ADD_NAME_PARAM(record, maxparams, "block", "path", block_idx, src->path); if (backing_idx) QEMU_ADD_BLOCK_PARAM_UI(record, maxparams, block_idx, "backingIndex", @@ -19971,7 +19831,7 @@ qemuDomainGetStatsBlock(virQEMUDriverPtr driver, * after the iteration than it is to iterate twice; but we still * want count listed first. */ count_index = record->nparams; - QEMU_ADD_COUNT_PARAM(record, maxparams, "block", 0); + VIR_DOMAIN_STATS_ADD_COUNT_PARAM(record, maxparams, "block", 0); for (i = 0; i < dom->def->ndisks; i++) { virDomainDiskDefPtr disk = dom->def->disks[i]; @@ -20005,10 +19865,6 @@ qemuDomainGetStatsBlock(virQEMUDriverPtr driver, #undef QEMU_ADD_BLOCK_PARAM_ULL -#undef QEMU_ADD_NAME_PARAM - -#undef QEMU_ADD_COUNT_PARAM - static int qemuDomainGetStatsPerfOneEvent(virPerfPtr perf, virPerfEventType type, diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c index 0a31947b0..04ef4c1a7 100644 --- a/src/util/vircgroup.c +++ b/src/util/vircgroup.c @@ -4122,6 +4122,44 @@ virCgroupControllerAvailable(int controller) return ret; } +int +virCgroupGetStatsCpu(virCgroupPtr cgroup, + virDomainStatsRecordPtr record, + int *maxparams) +{ + unsigned long long cpu_time = 0; + unsigned long long user_time = 0; + unsigned long long sys_time = 0; + int err = 0; + + if (!cgroup) + return 0; + + err = virCgroupGetCpuacctUsage(cgroup, &cpu_time); + if (!err && virTypedParamsAddULLong(&record->params, + &record->nparams, + maxparams, + "cpu.time", + cpu_time) < 0) + return -1; + + err = virCgroupGetCpuacctStat(cgroup, &user_time, &sys_time); + if (!err && virTypedParamsAddULLong(&record->params, + &record->nparams, + maxparams, + "cpu.user", + user_time) < 0) + return -1; + if (!err && virTypedParamsAddULLong(&record->params, + &record->nparams, + maxparams, + "cpu.system", + sys_time) < 0) + return -1; + + return 0; +} + #else /* !VIR_CGROUP_SUPPORTED */ bool @@ -4899,6 +4937,14 @@ virCgroupControllerAvailable(int controller ATTRIBUTE_UNUSED) { return false; } + +int +virCgroupGetStatsCpu(virCgroupPtr cgroup, + virDomainStatsRecordPtr record, + int *maxparams) +{ + return 0; +} #endif /* !VIR_CGROUP_SUPPORTED */ diff --git a/src/util/vircgroup.h b/src/util/vircgroup.h index d83392767..2ebdf9505 100644 --- a/src/util/vircgroup.h +++ b/src/util/vircgroup.h @@ -297,4 +297,8 @@ int virCgroupSetOwner(virCgroupPtr cgroup, int virCgroupHasEmptyTasks(virCgroupPtr cgroup, int controller); bool virCgroupControllerAvailable(int controller); + +int virCgroupGetStatsCpu(virCgroupPtr cgroup, + virDomainStatsRecordPtr record, + int *maxparams); #endif /* __VIR_CGROUP_H__ */ -- 2.15.1 ++++++ 0002-lxc-implement-connectGetAllDomainStats.patch ++++++ >From 1a2be7098cf5acfd893153abb52b65e69631dcec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Bosdonnat?= <[email protected]> Date: Tue, 2 Jan 2018 14:44:39 +0100 Subject: [PATCH 2/3] lxc: implement connectGetAllDomainStats LXC containers can also provide some statistics. Allow users to fetch them using the existing API. --- src/lxc/lxc_driver.c | 138 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index b3447100f..10667c134 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -81,6 +81,7 @@ #include "viraccessapichecklxc.h" #include "virhostdev.h" #include "netdev_bandwidth_conf.h" +#include "domain_stats.h" #define VIR_FROM_THIS VIR_FROM_LXC @@ -5485,6 +5486,142 @@ lxcDomainHasManagedSaveImage(virDomainPtr dom, unsigned int flags) return ret; } +static int +lxcDomainGetStatsCpu(virDomainObjPtr dom, + virDomainStatsRecordPtr record, + int *maxparams) +{ + virLXCDomainObjPrivatePtr priv = dom->privateData; + return virCgroupGetStatsCpu(priv->cgroup, record, maxparams); +} + +typedef int +(*lxcDomainGetStatsFunc)(virDomainObjPtr dom, + virDomainStatsRecordPtr record, + int *maxparams); + +struct lxcDomainGetStatsWorker { + lxcDomainGetStatsFunc func; + unsigned int stats; +}; + +static struct lxcDomainGetStatsWorker lxcDomainGetStatsWorkers[] = { + { virDomainStatsGetState, VIR_DOMAIN_STATS_STATE }, + { lxcDomainGetStatsCpu, VIR_DOMAIN_STATS_CPU_TOTAL }, + { virDomainStatsGetInterface, VIR_DOMAIN_STATS_INTERFACE }, + { NULL, 0 } +}; + +static int +lxcDomainGetStats(virConnectPtr conn, + virDomainObjPtr dom, + unsigned int stats, + virDomainStatsRecordPtr *record) +{ + int maxparams = 0; + virDomainStatsRecordPtr tmp; + size_t i; + int ret = -1; + + if (VIR_ALLOC(tmp) < 0) + goto cleanup; + + for (i = 0; lxcDomainGetStatsWorkers[i].func; i++) { + if (stats & lxcDomainGetStatsWorkers[i].stats) { + if (lxcDomainGetStatsWorkers[i].func(dom, tmp, &maxparams) < 0) + goto cleanup; + } + } + + if (!(tmp->dom = virGetDomain(conn, dom->def->name, + dom->def->uuid, dom->def->id))) + goto cleanup; + + *record = tmp; + tmp = NULL; + ret = 0; + + cleanup: + if (tmp) { + virTypedParamsFree(tmp->params, tmp->nparams); + VIR_FREE(tmp); + } + + return ret; +} + +static int +lxcConnectGetAllDomainStats(virConnectPtr conn, + virDomainPtr *doms, + unsigned int ndoms, + unsigned int stats, + virDomainStatsRecordPtr **retStats, + unsigned int flags) +{ + virLXCDriverPtr driver = conn->privateData; + virDomainObjPtr *vms = NULL; + virDomainObjPtr vm; + size_t nvms; + virDomainStatsRecordPtr *tmpstats = NULL; + int nstats = 0; + size_t i; + int ret = -1; + unsigned int lflags = flags & (VIR_CONNECT_LIST_DOMAINS_FILTERS_ACTIVE | + VIR_CONNECT_LIST_DOMAINS_FILTERS_PERSISTENT | + VIR_CONNECT_LIST_DOMAINS_FILTERS_STATE); + + virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ACTIVE | + VIR_CONNECT_LIST_DOMAINS_FILTERS_PERSISTENT | + VIR_CONNECT_LIST_DOMAINS_FILTERS_STATE, -1); + + if (virConnectGetAllDomainStatsEnsureACL(conn) < 0) + return -1; + + /* TODO Check stats support */ + + if (ndoms) { + if (virDomainObjListConvert(driver->domains, conn, doms, ndoms, &vms, + &nvms, virConnectGetAllDomainStatsCheckACL, + lflags, true) < 0) + return -1; + } else { + if (virDomainObjListCollect(driver->domains, conn, &vms, &nvms, + virConnectGetAllDomainStatsCheckACL, + lflags) < 0) + return -1; + } + + if (VIR_ALLOC_N(tmpstats, nvms + 1) < 0) + return -1; + + for (i = 0; i < nvms; i++) { + virDomainStatsRecordPtr tmp = NULL; + vm = vms[i]; + + virObjectLock(vm); + + if (lxcDomainGetStats(conn, vm, stats, &tmp) < 0) { + virObjectUnlock(vm); + goto cleanup; + } + + if (tmp) + tmpstats[nstats++] = tmp; + + virObjectUnlock(vm); + } + + *retStats = tmpstats; + tmpstats = NULL; + + ret = nstats; + + cleanup: + virDomainStatsRecordListFree(tmpstats); + virObjectListFreeCount(vms, nvms); + + return ret; +} /* Function Tables */ static virHypervisorDriver lxcHypervisorDriver = { @@ -5579,6 +5716,7 @@ static virHypervisorDriver lxcHypervisorDriver = { .nodeGetFreePages = lxcNodeGetFreePages, /* 1.2.6 */ .nodeAllocPages = lxcNodeAllocPages, /* 1.2.9 */ .domainHasManagedSaveImage = lxcDomainHasManagedSaveImage, /* 1.2.13 */ + .connectGetAllDomainStats = lxcConnectGetAllDomainStats, /* 3.11.0 */ }; static virConnectDriver lxcConnectDriver = { -- 2.15.1 ++++++ 6b3d716e-keycodemap-py3.patch ++++++ >From 6b3d716e2b6472eb7189d3220552280ef3d832ce Mon Sep 17 00:00:00 2001 From: Daniel P. Berrange <[email protected]> Date: Fri, 12 Jan 2018 13:53:44 +0000 Subject: [PATCH] Fix compat with py3 dict keys/values data types Signed-off-by: Daniel P. Berrange <[email protected]> --- tools/keymap-gen | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tools/keymap-gen b/tools/keymap-gen index d4594b4..f0269e3 100755 --- a/tools/keymap-gen +++ b/tools/keymap-gen @@ -356,19 +356,19 @@ class LanguageSrcGenerator(LanguageGenerator): if frommapname in database.ENUM_COLUMNS: fromtype = self.TYPE_ENUM - elif type(tolinux.keys()[0]) == str: + elif type(list(tolinux.keys())[0]) == str: fromtype = self.TYPE_STRING else: fromtype = self.TYPE_INT if tomapname in database.ENUM_COLUMNS: totype = self.TYPE_ENUM - elif type(fromlinux.values()[0]) == str: + elif type(list(fromlinux.values())[0]) == str: totype = self.TYPE_STRING else: totype = self.TYPE_INT - keys = tolinux.keys() + keys = list(tolinux.keys()) keys.sort() if fromtype == self.TYPE_INT: keys = range(keys[-1] + 1) @@ -402,7 +402,7 @@ class LanguageSrcGenerator(LanguageGenerator): raise Exception("Unknown map %s, expected one of %s" % ( mapname, ", ".join(database.mapto.keys()))) - keys = database.mapto[Database.MAP_LINUX].keys() + keys = list(database.mapto[Database.MAP_LINUX].keys()) keys.sort() names = [database.mapname[Database.MAP_LINUX].get(key, "unnamed") for key in keys] @@ -411,7 +411,7 @@ class LanguageSrcGenerator(LanguageGenerator): if mapname in database.ENUM_COLUMNS: totype = self.TYPE_ENUM - elif type(database.mapto[mapname].values()[0]) == str: + elif type(list(database.mapto[mapname].values())[0]) == str: totype = self.TYPE_STRING else: totype = self.TYPE_INT @@ -440,7 +440,7 @@ class LanguageSrcGenerator(LanguageGenerator): if varname is None: varname = "name_map_%s_to_%s" % (frommapname, tomapname) - keys = tolinux.keys() + keys = list(tolinux.keys()) keys.sort() if type(keys[0]) == int: keys = range(keys[-1] + 1) @@ -470,7 +470,7 @@ class LanguageSrcGenerator(LanguageGenerator): raise Exception("Unknown map %s, expected one of %s" % ( mapname, ", ".join(database.mapname.keys()))) - keys = database.mapto[Database.MAP_LINUX].keys() + keys = list(database.mapto[Database.MAP_LINUX].keys()) keys.sort() names = [database.mapname[Database.MAP_LINUX].get(key, "unnamed") for key in keys] @@ -514,7 +514,7 @@ class LanguageDocGenerator(LanguageGenerator): raise Exception("Unknown map %s, expected one of %s" % ( mapname, ", ".join(database.mapname.keys()))) - keys = database.mapto[Database.MAP_LINUX].keys() + keys = list(database.mapto[Database.MAP_LINUX].keys()) keys.sort() names = [database.mapname[Database.MAP_LINUX].get(key, "unnamed") for key in keys] @@ -537,7 +537,7 @@ class LanguageDocGenerator(LanguageGenerator): mapname, ", ".join(database.mapfrom.keys()))) tolinux = database.mapfrom[mapname] - keys = tolinux.keys() + keys = list(tolinux.keys()) keys.sort() if mapname in database.mapname: names = database.mapname[mapname] -- libgit2 0.26.0 ++++++ 759b4d1b-virlog-determine-the-hostname-on-startup-CVE-2018-67.patch ++++++ >From 759b4d1b0fe5f4d84d98b99153dfa7ac289dd167 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel <[email protected]> Date: Sat, 27 Jan 2018 23:43:58 +0100 Subject: [PATCH] virlog: determine the hostname on startup CVE-2018-6764 At later point it might not be possible or even safe to use getaddrinfo(). It can in turn result in a load of NSS module. Notably, on a LXC container startup we may find ourselves with the guest filesystem already having replaced the host one. Loading a NSS module from the guest tree would allow a malicous guest to escape the confinement of its container environment because libvirt will not yet have locked it down. --- src/util/virlog.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/util/virlog.c b/src/util/virlog.c index 68439b919..9105337ce 100644 --- a/src/util/virlog.c +++ b/src/util/virlog.c @@ -64,6 +64,7 @@ VIR_LOG_INIT("util.log"); static regex_t *virLogRegex; +static char *virLogHostname; #define VIR_LOG_DATE_REGEX "[0-9]{4}-[0-9]{2}-[0-9]{2}" @@ -271,6 +272,12 @@ virLogOnceInit(void) VIR_FREE(virLogRegex); } + /* We get and remember the hostname early, because at later time + * it might not be possible to load NSS modules via getaddrinfo() + * (e.g. at container startup the host filesystem will not be + * accessible anymore. */ + virLogHostname = virGetHostnameQuiet(); + virLogUnlock(); return 0; } @@ -466,17 +473,14 @@ static int virLogHostnameString(char **rawmsg, char **msg) { - char *hostname = virGetHostnameQuiet(); char *hoststr; - if (!hostname) + if (!virLogHostname) return -1; - if (virAsprintfQuiet(&hoststr, "hostname: %s", hostname) < 0) { - VIR_FREE(hostname); + if (virAsprintfQuiet(&hoststr, "hostname: %s", virLogHostname) < 0) { return -1; } - VIR_FREE(hostname); if (virLogFormatString(msg, 0, NULL, VIR_LOG_INFO, hoststr) < 0) { VIR_FREE(hoststr); -- 2.15.1 ++++++ apibuild-py3.patch ++++++ ++++ 989 lines (skipped) ++++++ c2dc6698-fix-deadlock-obtaining-hostname.patch ++++++ >From c2dc6698c88fb591639e542c8ecb0076c54f3dfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <[email protected]> Date: Mon, 12 Feb 2018 10:03:08 +0000 Subject: [PATCH] log: fix deadlock obtaining hostname (related CVE-2018-6764) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The fix for CVE-2018-6764 introduced a potential deadlock scenario that gets triggered by the NSS module when virGetHostname() calls getaddrinfo to resolve the hostname: #0 0x00007f6e714b57e7 in futex_wait #1 futex_wait_simple #2 __pthread_once_slow #3 0x00007f6e71d16e7d in virOnce #4 0x00007f6e71d0997c in virLogInitialize #5 0x00007f6e71d0a09a in virLogVMessage #6 0x00007f6e71d09ffd in virLogMessage #7 0x00007f6e71d0db22 in virObjectNew #8 0x00007f6e71d0dbf1 in virObjectLockableNew #9 0x00007f6e71d0d3e5 in virMacMapNew #10 0x00007f6e71cdc50a in findLease #11 0x00007f6e71cdcc56 in _nss_libvirt_gethostbyname4_r #12 0x00007f6e724631fc in gaih_inet #13 0x00007f6e72464697 in __GI_getaddrinfo #14 0x00007f6e71d19e81 in virGetHostnameImpl #15 0x00007f6e71d1a057 in virGetHostnameQuiet #16 0x00007f6e71d09936 in virLogOnceInit #17 0x00007f6e71d09952 in virLogOnce #18 0x00007f6e714b5829 in __pthread_once_slow #19 0x00007f6e71d16e7d in virOnce #20 0x00007f6e71d0997c in virLogInitialize #21 0x00007f6e71d0a09a in virLogVMessage #22 0x00007f6e71d09ffd in virLogMessage #23 0x00007f6e71d0db22 in virObjectNew #24 0x00007f6e71d0dbf1 in virObjectLockableNew #25 0x00007f6e71d0d3e5 in virMacMapNew #26 0x00007f6e71cdc50a in findLease #27 0x00007f6e71cdc839 in _nss_libvirt_gethostbyname3_r #28 0x00007f6e71cdc724 in _nss_libvirt_gethostbyname2_r #29 0x00007f6e7248f72f in __gethostbyname2_r #30 0x00007f6e7248f494 in gethostbyname2 #31 0x000056348c30c36d in hosts_keys #32 0x000056348c30b7d2 in main Fortunately the extra stuff virGetHostname does is totally irrelevant to the needs of the logging code, so we can just inline a call to the native hostname() syscall directly. Signed-off-by: Daniel P. Berrangé <[email protected]> --- cfg.mk | 2 +- src/util/virlog.c | 20 ++++++++++++++------ 2 files changed, 15 insertions(+), 7 deletions(-) Index: libvirt-4.0.0/cfg.mk =================================================================== --- libvirt-4.0.0.orig/cfg.mk +++ libvirt-4.0.0/cfg.mk @@ -1183,7 +1183,7 @@ _src2=src/(util/vircommand|libvirt|lxc/l exclude_file_name_regexp--sc_prohibit_fork_wrappers = \ (^($(_src2)|tests/testutils|daemon/libvirtd)\.c$$) -exclude_file_name_regexp--sc_prohibit_gethostname = ^src/util/virutil\.c$$ +exclude_file_name_regexp--sc_prohibit_gethostname = ^src/util/vir(util|log)\.c$$ exclude_file_name_regexp--sc_prohibit_internal_functions = \ ^src/(util/(viralloc|virutil|virfile)\.[hc]|esx/esx_vi\.c)$$ Index: libvirt-4.0.0/src/util/virlog.c =================================================================== --- libvirt-4.0.0.orig/src/util/virlog.c +++ libvirt-4.0.0/src/util/virlog.c @@ -64,7 +64,7 @@ VIR_LOG_INIT("util.log"); static regex_t *virLogRegex; -static char *virLogHostname; +static char virLogHostname[HOST_NAME_MAX+1]; #define VIR_LOG_DATE_REGEX "[0-9]{4}-[0-9]{2}-[0-9]{2}" @@ -261,6 +261,8 @@ virLogPriorityString(virLogPriority lvl) static int virLogOnceInit(void) { + int r; + if (virMutexInit(&virLogMutex) < 0) return -1; @@ -275,8 +277,17 @@ virLogOnceInit(void) /* We get and remember the hostname early, because at later time * it might not be possible to load NSS modules via getaddrinfo() * (e.g. at container startup the host filesystem will not be - * accessible anymore. */ - virLogHostname = virGetHostnameQuiet(); + * accessible anymore. + * Must not use virGetHostname though as that causes re-entrancy + * problems if it triggers logging codepaths + */ + r = gethostname(virLogHostname, sizeof(virLogHostname)); + if (r == -1) { + ignore_value(virStrcpy(virLogHostname, + "(unknown)", sizeof(virLogHostname))); + } else { + NUL_TERMINATE(virLogHostname); + } virLogUnlock(); return 0; @@ -475,9 +486,6 @@ virLogHostnameString(char **rawmsg, { char *hoststr; - if (!virLogHostname) - return -1; - if (virAsprintfQuiet(&hoststr, "hostname: %s", virLogHostname) < 0) { return -1; }
