[PATCH v3] network: introduce a "none" firewall backend type
by Daniel P. Berrangé
There are two scenarios identified after the recent firewall backend
selection was introduced, which result in libvirtd failing to startup
due to an inability to find either iptables/nftables
- On Linux if running unprivileged with $PATH lacking the dir
containing iptables/nftables
- On non-Linux where iptables/nftables never existed
In the former case, it is preferrable to restore the behaviour whereby
the driver starts successfully. Users will get an error reported when
attempting to …
[View More]start any virtual network, due to the lack of permissions
needed to create bridge devices. This makes the missing firewall backend
irrelevant.
In the latter case, the network driver calls the 'nop' platform
implementation which does not attempt to implement any firewall logic,
just allowing the network to start without firewall rules.
To solve this are number of changes are required
* Introduce VIR_FIREWALL_BACKEND_NONE, which does nothing except
report a fatal error from virFirewallApply(). This code path
is unreachable, since we'll never create a virFirewall
object with with VIR_FIREWALL_BACKEND_NONE, so the error reporting
is just a sanity check.
* Ignore the compile time backend defaults and assume use of
the 'none' backend if running unprivileged.
This fixes the first regression, avoiding the failure to start
libvirtd on Linux in unprivileged context, instead allowing use
of the driver and expecting a permission denied when creating a
bridge.
* Reject the use of compile time backend defaults no non-Linux
and hardcode the 'none' backend. The non-Linux platforms have
no firewall implementation at all currently, so there's no
reason to permit the use of 'firewall_backend_priority'
meson option.
This fixes the second regression, avoiding the failure to start
libvirtd on non-Linux hosts due to non-existant Linux binaries.
* Change the Linux platform backend to raise an error if the
firewall backend is 'none'. Again this code path is unreachable
by default since we'll fail to create the bridge before getting
here, but if someone modified network.conf to request the 'none'
backend, this will stop further progress.
* Change the nop platform backend to raise an error if the
firewall backend is 'iptables' or 'nftables'. Again this code
path is unreachable, since we should already have failed to
find the iptables/nftables binaries on non-Linux hosts, so
this is just a sanity check.
* 'none' is not permited as a value in 'firewall_backend_priority'
meson option, since it is conceptually meaningless to ask for
that on Linux.
NB, 'firewall_backend_priority' allows repeated options temporarily,
which we don't want. Meson intends to turn this into a hard error
DEPRECATION: Duplicated values in array option is deprecated. This will become a hard error in the future.
and we can live with the reduced error checking until that happens.
Signed-off-by: Daniel P. Berrangé <berrange(a)redhat.com>
---
Changed in v3:
- Fix various syntax-check errors
- Added note about meson tightening up validation of duplicated
choices
meson.build | 26 +++++++++++++++++++-------
meson_options.txt | 2 +-
po/POTFILES | 1 +
src/network/bridge_driver_conf.c | 19 ++++++++++++++-----
src/network/bridge_driver_linux.c | 10 ++++++++++
src/network/bridge_driver_nop.c | 15 ++++++++++++++-
src/util/virfirewall.c | 6 ++++++
src/util/virfirewall.h | 1 +
8 files changed, 66 insertions(+), 14 deletions(-)
diff --git a/meson.build b/meson.build
index 5c7cd7ec2e..2e8b87280d 100644
--- a/meson.build
+++ b/meson.build
@@ -1647,15 +1647,27 @@ if not get_option('driver_network').disabled() and conf.has('WITH_LIBVIRTD')
conf.set('WITH_NETWORK', 1)
firewall_backend_priority = get_option('firewall_backend_priority')
- if (not firewall_backend_priority.contains('nftables') or
- not firewall_backend_priority.contains('iptables') or
- firewall_backend_priority.length() != 2)
- error('invalid value for firewall_backend_priority option')
+ if firewall_backend_priority.length() == 0
+ if host_machine.system() == 'linux'
+ firewall_backend_priority = ['nftables', 'iptables']
+ else
+ # No firewall impl on non-Linux so far, so force 'none'
+ # as placeholder
+ firewall_backend_priority = ['none']
+ endif
+ else
+ if host_machine.system() != 'linux'
+ error('firewall backend priority only supported on linux hosts')
+ endif
endif
- conf.set('FIREWALL_BACKEND_PRIORITY_0', 'VIR_FIREWALL_BACKEND_' + firewall_backend_priority[0].to_upper())
- conf.set('FIREWALL_BACKEND_PRIORITY_1', 'VIR_FIREWALL_BACKEND_' + firewall_backend_priority[1].to_upper())
- conf.set('FIREWALL_BACKEND_PRIORITY_NUM', firewall_backend_priority.length())
+ backends = []
+ foreach backend: firewall_backend_priority
+ backend = 'VIR_FIREWALL_BACKEND_' + backend.to_upper()
+ backends += backend
+ endforeach
+
+ conf.set('FIREWALL_BACKENDS', ', '.join(backends))
elif get_option('driver_network').enabled()
error('libvirtd must be enabled to build the network driver')
endif
diff --git a/meson_options.txt b/meson_options.txt
index 50d71427cb..2d440c63d8 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -117,7 +117,7 @@ option('dtrace', type: 'feature', value: 'auto', description: 'use dtrace for st
option('firewalld', type: 'feature', value: 'auto', description: 'firewalld support')
# dep:firewalld
option('firewalld_zone', type: 'feature', value: 'auto', description: 'whether to install firewalld libvirt zone')
-option('firewall_backend_priority', type: 'array', choices: ['nftables', 'iptables'], description: 'order in which to try firewall backends')
+option('firewall_backend_priority', type: 'array', choices: ['nftables', 'iptables'], value: [], description: 'order in which to try firewall backends')
option('host_validate', type: 'feature', value: 'auto', description: 'build virt-host-validate')
option('init_script', type: 'combo', choices: ['systemd', 'openrc', 'check', 'none'], value: 'check', description: 'Style of init script to install')
option('loader_nvram', type: 'string', value: '', description: 'Pass list of pairs of <loader>:<nvram> paths. Both pairs and list items are separated by a colon.')
diff --git a/po/POTFILES b/po/POTFILES
index 4bfbb91164..1ed4086d2c 100644
--- a/po/POTFILES
+++ b/po/POTFILES
@@ -143,6 +143,7 @@ src/lxc/lxc_process.c
src/network/bridge_driver.c
src/network/bridge_driver_conf.c
src/network/bridge_driver_linux.c
+src/network/bridge_driver_nop.c
src/network/leaseshelper.c
src/network/network_iptables.c
src/network/network_nftables.c
diff --git a/src/network/bridge_driver_conf.c b/src/network/bridge_driver_conf.c
index e2f3613a41..9da5e790b7 100644
--- a/src/network/bridge_driver_conf.c
+++ b/src/network/bridge_driver_conf.c
@@ -61,6 +61,7 @@ networkGetDnsmasqCaps(virNetworkDriverState *driver)
static int
virNetworkLoadDriverConfig(virNetworkDriverConfig *cfg G_GNUC_UNUSED,
+ bool privileged,
const char *filename)
{
g_autoptr(virConf) conf = NULL;
@@ -68,13 +69,17 @@ virNetworkLoadDriverConfig(virNetworkDriverConfig *cfg G_GNUC_UNUSED,
bool fwBackendSelected = false;
size_t i;
int fwBackends[] = {
- FIREWALL_BACKEND_PRIORITY_0,
- FIREWALL_BACKEND_PRIORITY_1,
+ FIREWALL_BACKENDS
};
- G_STATIC_ASSERT(G_N_ELEMENTS(fwBackends) == VIR_FIREWALL_BACKEND_LAST);
- G_STATIC_ASSERT(G_N_ELEMENTS(fwBackends) == FIREWALL_BACKEND_PRIORITY_NUM);
+ G_STATIC_ASSERT(G_N_ELEMENTS(fwBackends) > 0 &&
+ G_N_ELEMENTS(fwBackends) <= VIR_FIREWALL_BACKEND_LAST);
int nFwBackends = G_N_ELEMENTS(fwBackends);
+ if (!privileged) {
+ fwBackends[0] = VIR_FIREWALL_BACKEND_NONE;
+ nFwBackends = 1;
+ }
+
if (access(filename, R_OK) == 0) {
conf = virConfReadFile(filename, 0);
@@ -104,6 +109,10 @@ virNetworkLoadDriverConfig(virNetworkDriverConfig *cfg G_GNUC_UNUSED,
for (i = 0; i < nFwBackends && !fwBackendSelected; i++) {
switch ((virFirewallBackend)fwBackends[i]) {
+ case VIR_FIREWALL_BACKEND_NONE:
+ fwBackendSelected = true;
+ break;
+
case VIR_FIREWALL_BACKEND_IPTABLES: {
g_autofree char *iptablesInPath = virFindFileInPath(IPTABLES);
@@ -187,7 +196,7 @@ virNetworkDriverConfigNew(bool privileged)
configfile = g_strconcat(configdir, "/network.conf", NULL);
- if (virNetworkLoadDriverConfig(cfg, configfile) < 0)
+ if (virNetworkLoadDriverConfig(cfg, privileged, configfile) < 0)
return NULL;
if (g_mkdir_with_parents(cfg->stateDir, 0777) < 0) {
diff --git a/src/network/bridge_driver_linux.c b/src/network/bridge_driver_linux.c
index 35e6bd1154..fe7c6e193c 100644
--- a/src/network/bridge_driver_linux.c
+++ b/src/network/bridge_driver_linux.c
@@ -47,6 +47,11 @@ networkFirewallSetupPrivateChains(virFirewallBackend backend,
virFirewallLayer layer)
{
switch (backend) {
+ case VIR_FIREWALL_BACKEND_NONE:
+ virReportError(VIR_ERR_NO_SUPPORT, "%s",
+ _("No firewall backend is available"));
+ return -1;
+
case VIR_FIREWALL_BACKEND_IPTABLES:
return iptablesSetupPrivateChains(layer);
@@ -417,6 +422,11 @@ networkAddFirewallRules(virNetworkDef *def,
}
switch (firewallBackend) {
+ case VIR_FIREWALL_BACKEND_NONE:
+ virReportError(VIR_ERR_NO_SUPPORT, "%s",
+ _("No firewall backend is available"));
+ return -1;
+
case VIR_FIREWALL_BACKEND_IPTABLES:
return iptablesAddFirewallRules(def, fwRemoval);
diff --git a/src/network/bridge_driver_nop.c b/src/network/bridge_driver_nop.c
index 537b9234f8..8bf3367bff 100644
--- a/src/network/bridge_driver_nop.c
+++ b/src/network/bridge_driver_nop.c
@@ -19,6 +19,8 @@
#include <config.h>
+#define VIR_FROM_THIS VIR_FROM_NETWORK
+
void networkPreReloadFirewallRules(virNetworkDriverState *driver G_GNUC_UNUSED,
bool startup G_GNUC_UNUSED,
bool force G_GNUC_UNUSED)
@@ -37,9 +39,20 @@ int networkCheckRouteCollision(virNetworkDef *def G_GNUC_UNUSED)
}
int networkAddFirewallRules(virNetworkDef *def G_GNUC_UNUSED,
- virFirewallBackend firewallBackend G_GNUC_UNUSED,
+ virFirewallBackend firewallBackend,
virFirewall **fwRemoval G_GNUC_UNUSED)
{
+ /*
+ * Shouldn't be possible, since virNetworkLoadDriverConfig
+ * ought to fail to find the required binaries when loading,
+ * so this is just a sanity check
+ */
+ if (firewallBackend != VIR_FIREWALL_BACKEND_NONE) {
+ virReportError(VIR_ERR_NO_SUPPORT,
+ _("Firewall backend '%1$s' not available on this platform"),
+ virFirewallBackendTypeToString(firewallBackend));
+ return -1;
+ }
return 0;
}
diff --git a/src/util/virfirewall.c b/src/util/virfirewall.c
index 2219506b18..090dbcdbed 100644
--- a/src/util/virfirewall.c
+++ b/src/util/virfirewall.c
@@ -37,6 +37,7 @@ VIR_LOG_INIT("util.firewall");
VIR_ENUM_IMPL(virFirewallBackend,
VIR_FIREWALL_BACKEND_LAST,
+ "none",
"iptables",
"nftables");
@@ -815,6 +816,11 @@ virFirewallApplyCmd(virFirewall *firewall,
}
switch (virFirewallGetBackend(firewall)) {
+ case VIR_FIREWALL_BACKEND_NONE:
+ virReportError(VIR_ERR_NO_SUPPORT, "%s",
+ _("Firewall backend is not implemented"));
+ return -1;
+
case VIR_FIREWALL_BACKEND_IPTABLES:
if (virFirewallCmdIptablesApply(firewall, fwCmd, &output) < 0)
return -1;
diff --git a/src/util/virfirewall.h b/src/util/virfirewall.h
index 302a6a4e5b..bce51259d2 100644
--- a/src/util/virfirewall.h
+++ b/src/util/virfirewall.h
@@ -44,6 +44,7 @@ typedef enum {
} virFirewallLayer;
typedef enum {
+ VIR_FIREWALL_BACKEND_NONE, /* Always fails */
VIR_FIREWALL_BACKEND_IPTABLES,
VIR_FIREWALL_BACKEND_NFTABLES,
--
2.45.1
[View Less]
10 months
[PATCH] conf: Drop needless NULL checks guarding virBufferEscapeString()
by Michal Privoznik
There's no need to guard virBufferEscapeString() with a call to
NULL as the very first thing the function does is check all three
arguments for NULL.
This patch was generated using the following spatch:
@@
expression X, Y, E;
@@
- if (E)
virBufferEscapeString(X, Y, E);
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
src/conf/capabilities.c | 6 ++--
src/conf/domain_conf.c | 57 +++++++++++-------------------
src/conf/network_conf.c …
[View More] | 6 ++--
src/conf/node_device_conf.c | 57 ++++++++++++------------------
src/conf/snapshot_conf.c | 5 ++-
src/conf/storage_encryption_conf.c | 9 ++---
src/conf/storage_source_conf.c | 3 +-
src/conf/virnwfilterbindingdef.c | 3 +-
8 files changed, 55 insertions(+), 91 deletions(-)
diff --git a/src/conf/capabilities.c b/src/conf/capabilities.c
index fe5e42c167..74e6293766 100644
--- a/src/conf/capabilities.c
+++ b/src/conf/capabilities.c
@@ -693,10 +693,8 @@ virCapabilitiesDomainDataLookupInternal(virCaps *caps,
if (domaintype > VIR_DOMAIN_VIRT_NONE)
virBufferAsprintf(&buf, "domaintype=%s ",
virDomainVirtTypeToString(domaintype));
- if (emulator)
- virBufferEscapeString(&buf, "emulator=%s ", emulator);
- if (machinetype)
- virBufferEscapeString(&buf, "machine=%s ", machinetype);
+ virBufferEscapeString(&buf, "emulator=%s ", emulator);
+ virBufferEscapeString(&buf, "machine=%s ", machinetype);
if (virBufferCurrentContent(&buf) &&
!virBufferCurrentContent(&buf)[0])
virBufferAsprintf(&buf, "%s", _("any configuration"));
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index fde594f811..2f1e99865b 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -5394,8 +5394,7 @@ virDomainDeviceInfoFormat(virBuffer *buf,
if (rombar)
virBufferAsprintf(buf, " bar='%s'", rombar);
}
- if (info->romfile)
- virBufferEscapeString(buf, " file='%s'", info->romfile);
+ virBufferEscapeString(buf, " file='%s'", info->romfile);
virBufferAddLit(buf, "/>\n");
}
@@ -22175,8 +22174,7 @@ virSecurityDeviceLabelDefFormat(virBuffer *buf,
virBufferAddLit(buf, "<seclabel");
- if (def->model)
- virBufferEscapeString(buf, " model='%s'", def->model);
+ virBufferEscapeString(buf, " model='%s'", def->model);
if (def->labelskip)
virBufferAddLit(buf, " labelskip='yes'");
@@ -22371,8 +22369,7 @@ virDomainDiskSourceFormatNetwork(virBuffer *attrBuf,
virBufferAsprintf(childBuf, "<timeout seconds='%llu'/>\n", src->timeout);
if (src->protocol == VIR_STORAGE_NET_PROTOCOL_SSH) {
- if (src->ssh_known_hosts_file)
- virBufferEscapeString(childBuf, "<knownHosts path='%s'/>\n", src->ssh_known_hosts_file);
+ virBufferEscapeString(childBuf, "<knownHosts path='%s'/>\n", src->ssh_known_hosts_file);
if (src->ssh_keyfile || src->ssh_agent) {
virBufferAddLit(childBuf, "<identity");
@@ -23162,8 +23159,7 @@ virDomainControllerDefFormat(virBuffer *buf,
" type='%s' index='%d'",
type, def->idx);
- if (model)
- virBufferEscapeString(&attrBuf, " model='%s'", model);
+ virBufferEscapeString(&attrBuf, " model='%s'", model);
switch (def->type) {
case VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL:
@@ -24581,8 +24577,7 @@ virDomainChrTargetDefFormat(virBuffer *buf,
case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_XEN:
case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO:
- if (def->target.name)
- virBufferEscapeString(buf, " name='%s'", def->target.name);
+ virBufferEscapeString(buf, " name='%s'", def->target.name);
if (def->targetType == VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO &&
def->state != VIR_DOMAIN_CHR_DEVICE_STATE_DEFAULT &&
@@ -26004,9 +25999,8 @@ virDomainGraphicsDefFormat(virBuffer *buf,
break;
}
- if (def->data.vnc.keymap)
- virBufferEscapeString(buf, " keymap='%s'",
- def->data.vnc.keymap);
+ virBufferEscapeString(buf, " keymap='%s'",
+ def->data.vnc.keymap);
if (def->data.vnc.sharePolicy)
virBufferAsprintf(buf, " sharePolicy='%s'",
@@ -26021,13 +26015,11 @@ virDomainGraphicsDefFormat(virBuffer *buf,
break;
case VIR_DOMAIN_GRAPHICS_TYPE_SDL:
- if (def->data.sdl.display)
- virBufferEscapeString(buf, " display='%s'",
- def->data.sdl.display);
+ virBufferEscapeString(buf, " display='%s'",
+ def->data.sdl.display);
- if (def->data.sdl.xauth)
- virBufferEscapeString(buf, " xauth='%s'",
- def->data.sdl.xauth);
+ virBufferEscapeString(buf, " xauth='%s'",
+ def->data.sdl.xauth);
if (def->data.sdl.fullscreen)
virBufferAddLit(buf, " fullscreen='yes'");
@@ -26066,9 +26058,8 @@ virDomainGraphicsDefFormat(virBuffer *buf,
break;
case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP:
- if (def->data.desktop.display)
- virBufferEscapeString(buf, " display='%s'",
- def->data.desktop.display);
+ virBufferEscapeString(buf, " display='%s'",
+ def->data.desktop.display);
if (def->data.desktop.fullscreen)
virBufferAddLit(buf, " fullscreen='yes'");
@@ -26121,9 +26112,8 @@ virDomainGraphicsDefFormat(virBuffer *buf,
break;
}
- if (def->data.spice.keymap)
- virBufferEscapeString(buf, " keymap='%s'",
- def->data.spice.keymap);
+ virBufferEscapeString(buf, " keymap='%s'",
+ def->data.spice.keymap);
if (def->data.spice.defaultMode != VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_ANY)
virBufferAsprintf(buf, " defaultMode='%s'",
@@ -26503,11 +26493,9 @@ virDomainResourceDefFormat(virBuffer *buf,
if (!def)
return;
- if (def->partition)
- virBufferEscapeString(&childBuf, "<partition>%s</partition>\n", def->partition);
+ virBufferEscapeString(&childBuf, "<partition>%s</partition>\n", def->partition);
- if (def->appid)
- virBufferEscapeString(&childBuf, "<fibrechannel appid='%s'/>\n", def->appid);
+ virBufferEscapeString(&childBuf, "<fibrechannel appid='%s'/>\n", def->appid);
virXMLFormatElement(buf, "resource", NULL, &childBuf);
}
@@ -26680,11 +26668,9 @@ virDomainSecDefFormat(virBuffer *buf, virDomainSecDef *sec)
virBufferAsprintf(&childBuf, "<reducedPhysBits>%d</reducedPhysBits>\n",
sev->reduced_phys_bits);
virBufferAsprintf(&childBuf, "<policy>0x%04x</policy>\n", sev->policy);
- if (sev->dh_cert)
- virBufferEscapeString(&childBuf, "<dhCert>%s</dhCert>\n", sev->dh_cert);
+ virBufferEscapeString(&childBuf, "<dhCert>%s</dhCert>\n", sev->dh_cert);
- if (sev->session)
- virBufferEscapeString(&childBuf, "<session>%s</session>\n", sev->session);
+ virBufferEscapeString(&childBuf, "<session>%s</session>\n", sev->session);
break;
}
@@ -27910,9 +27896,8 @@ virDomainDefFormatInternalSetRootName(virDomainDef *def,
for (i = 0; def->os.initenv && def->os.initenv[i]; i++)
virBufferAsprintf(buf, "<initenv name='%s'>%s</initenv>\n",
def->os.initenv[i]->name, def->os.initenv[i]->value);
- if (def->os.initdir)
- virBufferEscapeString(buf, "<initdir>%s</initdir>\n",
- def->os.initdir);
+ virBufferEscapeString(buf, "<initdir>%s</initdir>\n",
+ def->os.initdir);
if (def->os.inituser)
virBufferAsprintf(buf, "<inituser>%s</inituser>\n", def->os.inituser);
if (def->os.initgroup)
diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index cc92ed0b03..f5ccf4bd12 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -2004,10 +2004,8 @@ virNetworkDNSDefFormat(virBuffer *buf,
def->srvs[i].service);
virBufferEscapeString(buf, "protocol='%s'", def->srvs[i].protocol);
- if (def->srvs[i].domain)
- virBufferEscapeString(buf, " domain='%s'", def->srvs[i].domain);
- if (def->srvs[i].target)
- virBufferEscapeString(buf, " target='%s'", def->srvs[i].target);
+ virBufferEscapeString(buf, " domain='%s'", def->srvs[i].domain);
+ virBufferEscapeString(buf, " target='%s'", def->srvs[i].target);
if (def->srvs[i].port)
virBufferAsprintf(buf, " port='%d'", def->srvs[i].port);
if (def->srvs[i].priority)
diff --git a/src/conf/node_device_conf.c b/src/conf/node_device_conf.c
index fe6d9a36b2..d2b578178b 100644
--- a/src/conf/node_device_conf.c
+++ b/src/conf/node_device_conf.c
@@ -176,20 +176,16 @@ virNodeDeviceCapSystemDefFormat(virBuffer *buf,
{
char uuidstr[VIR_UUID_STRING_BUFLEN];
- if (data->system.product_name)
- virBufferEscapeString(buf, "<product>%s</product>\n",
- data->system.product_name);
+ virBufferEscapeString(buf, "<product>%s</product>\n",
+ data->system.product_name);
virBufferAddLit(buf, "<hardware>\n");
virBufferAdjustIndent(buf, 2);
- if (data->system.hardware.vendor_name)
- virBufferEscapeString(buf, "<vendor>%s</vendor>\n",
- data->system.hardware.vendor_name);
- if (data->system.hardware.version)
- virBufferEscapeString(buf, "<version>%s</version>\n",
- data->system.hardware.version);
- if (data->system.hardware.serial)
- virBufferEscapeString(buf, "<serial>%s</serial>\n",
- data->system.hardware.serial);
+ virBufferEscapeString(buf, "<vendor>%s</vendor>\n",
+ data->system.hardware.vendor_name);
+ virBufferEscapeString(buf, "<version>%s</version>\n",
+ data->system.hardware.version);
+ virBufferEscapeString(buf, "<serial>%s</serial>\n",
+ data->system.hardware.serial);
virUUIDFormat(data->system.hardware.uuid, uuidstr);
virBufferAsprintf(buf, "<uuid>%s</uuid>\n", uuidstr);
virBufferAdjustIndent(buf, -2);
@@ -197,15 +193,12 @@ virNodeDeviceCapSystemDefFormat(virBuffer *buf,
virBufferAddLit(buf, "<firmware>\n");
virBufferAdjustIndent(buf, 2);
- if (data->system.firmware.vendor_name)
- virBufferEscapeString(buf, "<vendor>%s</vendor>\n",
- data->system.firmware.vendor_name);
- if (data->system.firmware.version)
- virBufferEscapeString(buf, "<version>%s</version>\n",
- data->system.firmware.version);
- if (data->system.firmware.release_date)
- virBufferEscapeString(buf, "<release_date>%s</release_date>\n",
- data->system.firmware.release_date);
+ virBufferEscapeString(buf, "<vendor>%s</vendor>\n",
+ data->system.firmware.vendor_name);
+ virBufferEscapeString(buf, "<version>%s</version>\n",
+ data->system.firmware.version);
+ virBufferEscapeString(buf, "<release_date>%s</release_date>\n",
+ data->system.firmware.release_date);
virBufferAdjustIndent(buf, -2);
virBufferAddLit(buf, "</firmware>\n");
}
@@ -225,9 +218,8 @@ virNodeDeviceCapMdevTypesFormat(virBuffer *buf,
virMediatedDeviceType *type = mdev_types[i];
virBufferEscapeString(buf, "<type id='%s'>\n", type->id);
virBufferAdjustIndent(buf, 2);
- if (type->name)
- virBufferEscapeString(buf, "<name>%s</name>\n",
- type->name);
+ virBufferEscapeString(buf, "<name>%s</name>\n",
+ type->name);
virBufferEscapeString(buf, "<deviceAPI>%s</deviceAPI>\n",
type->device_api);
virBufferAsprintf(buf,
@@ -454,10 +446,9 @@ virNodeDeviceCapUSBInterfaceDefFormat(virBuffer *buf,
data->usb_if.subclass);
virBufferAsprintf(buf, "<protocol>%d</protocol>\n",
data->usb_if.protocol);
- if (data->usb_if.description)
- virBufferEscapeString(buf,
- "<description>%s</description>\n",
- data->usb_if.description);
+ virBufferEscapeString(buf,
+ "<description>%s</description>\n",
+ data->usb_if.description);
}
@@ -469,9 +460,8 @@ virNodeDeviceCapNetDefFormat(virBuffer *buf,
virBufferEscapeString(buf, "<interface>%s</interface>\n",
data->net.ifname);
- if (data->net.address)
- virBufferEscapeString(buf, "<address>%s</address>\n",
- data->net.address);
+ virBufferEscapeString(buf, "<address>%s</address>\n",
+ data->net.address);
virInterfaceLinkFormat(buf, &data->net.lnk);
if (data->net.features) {
for (i = 0; i < VIR_NET_DEV_FEAT_LAST; i++) {
@@ -533,9 +523,8 @@ virNodeDeviceCapSCSIDefFormat(virBuffer *buf,
virBufferAsprintf(buf, "<target>%d</target>\n",
data->scsi.target);
virBufferAsprintf(buf, "<lun>%d</lun>\n", data->scsi.lun);
- if (data->scsi.type)
- virBufferEscapeString(buf, "<type>%s</type>\n",
- data->scsi.type);
+ virBufferEscapeString(buf, "<type>%s</type>\n",
+ data->scsi.type);
}
diff --git a/src/conf/snapshot_conf.c b/src/conf/snapshot_conf.c
index d7fcded302..039ed77b84 100644
--- a/src/conf/snapshot_conf.c
+++ b/src/conf/snapshot_conf.c
@@ -819,9 +819,8 @@ virDomainSnapshotDefFormatInternal(virBuffer *buf,
virBufferAdjustIndent(buf, 2);
virBufferEscapeString(buf, "<name>%s</name>\n", def->parent.name);
- if (def->parent.description)
- virBufferEscapeString(buf, "<description>%s</description>\n",
- def->parent.description);
+ virBufferEscapeString(buf, "<description>%s</description>\n",
+ def->parent.description);
if (def->state)
virBufferAsprintf(buf, "<state>%s</state>\n",
virDomainSnapshotStateTypeToString(def->state));
diff --git a/src/conf/storage_encryption_conf.c b/src/conf/storage_encryption_conf.c
index 1849df5c6c..b86001ec50 100644
--- a/src/conf/storage_encryption_conf.c
+++ b/src/conf/storage_encryption_conf.c
@@ -317,16 +317,13 @@ virStorageEncryptionInfoDefFormat(virBuffer *buf,
{
virBufferEscapeString(buf, "<cipher name='%s'", enc->cipher_name);
virBufferAsprintf(buf, " size='%u'", enc->cipher_size);
- if (enc->cipher_mode)
- virBufferEscapeString(buf, " mode='%s'", enc->cipher_mode);
- if (enc->cipher_hash)
- virBufferEscapeString(buf, " hash='%s'", enc->cipher_hash);
+ virBufferEscapeString(buf, " mode='%s'", enc->cipher_mode);
+ virBufferEscapeString(buf, " hash='%s'", enc->cipher_hash);
virBufferAddLit(buf, "/>\n");
if (enc->ivgen_name) {
virBufferEscapeString(buf, "<ivgen name='%s'", enc->ivgen_name);
- if (enc->ivgen_hash)
- virBufferEscapeString(buf, " hash='%s'", enc->ivgen_hash);
+ virBufferEscapeString(buf, " hash='%s'", enc->ivgen_hash);
virBufferAddLit(buf, "/>\n");
}
}
diff --git a/src/conf/storage_source_conf.c b/src/conf/storage_source_conf.c
index 959ec5ed40..908bc5fab2 100644
--- a/src/conf/storage_source_conf.c
+++ b/src/conf/storage_source_conf.c
@@ -1347,8 +1347,7 @@ int
virStorageSourcePrivateDataFormatRelPath(virStorageSource *src,
virBuffer *buf)
{
- if (src->relPath)
- virBufferEscapeString(buf, "<relPath>%s</relPath>\n", src->relPath);
+ virBufferEscapeString(buf, "<relPath>%s</relPath>\n", src->relPath);
return 0;
}
diff --git a/src/conf/virnwfilterbindingdef.c b/src/conf/virnwfilterbindingdef.c
index 423ed7a392..fe45c84347 100644
--- a/src/conf/virnwfilterbindingdef.c
+++ b/src/conf/virnwfilterbindingdef.c
@@ -203,8 +203,7 @@ virNWFilterBindingDefFormatBuf(virBuffer *buf,
virBufferAddLit(buf, "</owner>\n");
virBufferEscapeString(buf, "<portdev name='%s'/>\n", def->portdevname);
- if (def->linkdevname)
- virBufferEscapeString(buf, "<linkdev name='%s'/>\n", def->linkdevname);
+ virBufferEscapeString(buf, "<linkdev name='%s'/>\n", def->linkdevname);
virMacAddrFormat(&def->mac, mac);
virBufferAsprintf(buf, "<mac address='%s'/>\n", mac);
--
2.44.2
[View Less]
10 months
[PATCH v2] network: introduce a "none" firewall backend type
by Daniel P. Berrangé
There are two scenarios identified after the recent firewall backend
selection was introduced, which result in libvirtd failing to startup
due to an inability to find either iptables/nftables
- On Linux if running unprivileged with $PATH lacking the dir
containing iptables/nftables
- On non-Linux where iptables/nftables never existed
In the former case, it is preferrable to restore the behaviour whereby
the driver starts successfully. Users will get an error reported when
attempting to …
[View More]start any virtual network, due to the lack of permissions
needed to create bridge devices. This makes the missing firewall backend
irrelevant.
In the latter case, the network driver calls the 'nop' platform
implementation which does not attempt to implement any firewall logic,
just allowing the network to start without firewall rules.
To solve this are number of changes are required
* Introduce VIR_FIREWALL_BACKEND_NONE, which does nothing except
report a fatal error from virFirewallApply(). This code path
is unreachable, since we'll never create a virFirewall
object with with VIR_FIREWALL_BACKEND_NONE, so the error reporting
is just a sanity check.
* Ignore the compile time backend defaults and assume use of
the 'none' backend if running unprivileged.
This fixes the first regression, avoiding the failure to start
libvirtd on Linux in unprivileged context, instead allowing use
of the driver and expecting a permission denied when creating a
bridge.
* Reject the use of compile time backend defaults no non-Linux
and hardcode the 'none' backend. The non-Linux platforms have
no firewall implementation at all currently, so there's no
reason to permit the use of 'firewall_backend_priority'
meson option.
This fixes the second regression, avoiding the failure to start
libvirtd on non-Linux hosts due to non-existant Linux binaries.
* Change the Linux platform backend to raise an error if the
firewall backend is 'none'. Again this code path is unreachable
by default since we'll fail to create the bridge before getting
here, but if someone modified network.conf to request the 'none'
backend, this will stop further progress.
* Change the nop platform backend to raise an error if the
firewall backend is 'iptables' or 'nftables'. Again this code
path is unreachable, since we should already have failed to
find the iptables/nftables binaries on non-Linux hosts, so
this is just a sanity check.
* 'none' is not permited as a value in 'firewall_backend_priority'
meson option, since it is conceptually meaningless to ask for
that on Linux.
Signed-off-by: Daniel P. Berrangé <berrange(a)redhat.com>
---
Changed in v2:
- Fix build problems on FreeBSD (changes proposed by Roman)
meson.build | 26 +++++++++++++++++++-------
meson_options.txt | 2 +-
src/network/bridge_driver_conf.c | 19 ++++++++++++++-----
src/network/bridge_driver_linux.c | 10 ++++++++++
src/network/bridge_driver_nop.c | 15 ++++++++++++++-
src/util/virfirewall.c | 6 ++++++
src/util/virfirewall.h | 1 +
7 files changed, 65 insertions(+), 14 deletions(-)
diff --git a/meson.build b/meson.build
index 5c7cd7ec2e..2e8b87280d 100644
--- a/meson.build
+++ b/meson.build
@@ -1647,15 +1647,27 @@ if not get_option('driver_network').disabled() and conf.has('WITH_LIBVIRTD')
conf.set('WITH_NETWORK', 1)
firewall_backend_priority = get_option('firewall_backend_priority')
- if (not firewall_backend_priority.contains('nftables') or
- not firewall_backend_priority.contains('iptables') or
- firewall_backend_priority.length() != 2)
- error('invalid value for firewall_backend_priority option')
+ if firewall_backend_priority.length() == 0
+ if host_machine.system() == 'linux'
+ firewall_backend_priority = ['nftables', 'iptables']
+ else
+ # No firewall impl on non-Linux so far, so force 'none'
+ # as placeholder
+ firewall_backend_priority = ['none']
+ endif
+ else
+ if host_machine.system() != 'linux'
+ error('firewall backend priority only supported on linux hosts')
+ endif
endif
- conf.set('FIREWALL_BACKEND_PRIORITY_0', 'VIR_FIREWALL_BACKEND_' + firewall_backend_priority[0].to_upper())
- conf.set('FIREWALL_BACKEND_PRIORITY_1', 'VIR_FIREWALL_BACKEND_' + firewall_backend_priority[1].to_upper())
- conf.set('FIREWALL_BACKEND_PRIORITY_NUM', firewall_backend_priority.length())
+ backends = []
+ foreach backend: firewall_backend_priority
+ backend = 'VIR_FIREWALL_BACKEND_' + backend.to_upper()
+ backends += backend
+ endforeach
+
+ conf.set('FIREWALL_BACKENDS', ', '.join(backends))
elif get_option('driver_network').enabled()
error('libvirtd must be enabled to build the network driver')
endif
diff --git a/meson_options.txt b/meson_options.txt
index 50d71427cb..2d440c63d8 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -117,7 +117,7 @@ option('dtrace', type: 'feature', value: 'auto', description: 'use dtrace for st
option('firewalld', type: 'feature', value: 'auto', description: 'firewalld support')
# dep:firewalld
option('firewalld_zone', type: 'feature', value: 'auto', description: 'whether to install firewalld libvirt zone')
-option('firewall_backend_priority', type: 'array', choices: ['nftables', 'iptables'], description: 'order in which to try firewall backends')
+option('firewall_backend_priority', type: 'array', choices: ['nftables', 'iptables'], value: [], description: 'order in which to try firewall backends')
option('host_validate', type: 'feature', value: 'auto', description: 'build virt-host-validate')
option('init_script', type: 'combo', choices: ['systemd', 'openrc', 'check', 'none'], value: 'check', description: 'Style of init script to install')
option('loader_nvram', type: 'string', value: '', description: 'Pass list of pairs of <loader>:<nvram> paths. Both pairs and list items are separated by a colon.')
diff --git a/src/network/bridge_driver_conf.c b/src/network/bridge_driver_conf.c
index e2f3613a41..9da5e790b7 100644
--- a/src/network/bridge_driver_conf.c
+++ b/src/network/bridge_driver_conf.c
@@ -61,6 +61,7 @@ networkGetDnsmasqCaps(virNetworkDriverState *driver)
static int
virNetworkLoadDriverConfig(virNetworkDriverConfig *cfg G_GNUC_UNUSED,
+ bool privileged,
const char *filename)
{
g_autoptr(virConf) conf = NULL;
@@ -68,13 +69,17 @@ virNetworkLoadDriverConfig(virNetworkDriverConfig *cfg G_GNUC_UNUSED,
bool fwBackendSelected = false;
size_t i;
int fwBackends[] = {
- FIREWALL_BACKEND_PRIORITY_0,
- FIREWALL_BACKEND_PRIORITY_1,
+ FIREWALL_BACKENDS
};
- G_STATIC_ASSERT(G_N_ELEMENTS(fwBackends) == VIR_FIREWALL_BACKEND_LAST);
- G_STATIC_ASSERT(G_N_ELEMENTS(fwBackends) == FIREWALL_BACKEND_PRIORITY_NUM);
+ G_STATIC_ASSERT(G_N_ELEMENTS(fwBackends) > 0 &&
+ G_N_ELEMENTS(fwBackends) <= VIR_FIREWALL_BACKEND_LAST);
int nFwBackends = G_N_ELEMENTS(fwBackends);
+ if (!privileged) {
+ fwBackends[0] = VIR_FIREWALL_BACKEND_NONE;
+ nFwBackends = 1;
+ }
+
if (access(filename, R_OK) == 0) {
conf = virConfReadFile(filename, 0);
@@ -104,6 +109,10 @@ virNetworkLoadDriverConfig(virNetworkDriverConfig *cfg G_GNUC_UNUSED,
for (i = 0; i < nFwBackends && !fwBackendSelected; i++) {
switch ((virFirewallBackend)fwBackends[i]) {
+ case VIR_FIREWALL_BACKEND_NONE:
+ fwBackendSelected = true;
+ break;
+
case VIR_FIREWALL_BACKEND_IPTABLES: {
g_autofree char *iptablesInPath = virFindFileInPath(IPTABLES);
@@ -187,7 +196,7 @@ virNetworkDriverConfigNew(bool privileged)
configfile = g_strconcat(configdir, "/network.conf", NULL);
- if (virNetworkLoadDriverConfig(cfg, configfile) < 0)
+ if (virNetworkLoadDriverConfig(cfg, privileged, configfile) < 0)
return NULL;
if (g_mkdir_with_parents(cfg->stateDir, 0777) < 0) {
diff --git a/src/network/bridge_driver_linux.c b/src/network/bridge_driver_linux.c
index 35e6bd1154..fe7c6e193c 100644
--- a/src/network/bridge_driver_linux.c
+++ b/src/network/bridge_driver_linux.c
@@ -47,6 +47,11 @@ networkFirewallSetupPrivateChains(virFirewallBackend backend,
virFirewallLayer layer)
{
switch (backend) {
+ case VIR_FIREWALL_BACKEND_NONE:
+ virReportError(VIR_ERR_NO_SUPPORT, "%s",
+ _("No firewall backend is available"));
+ return -1;
+
case VIR_FIREWALL_BACKEND_IPTABLES:
return iptablesSetupPrivateChains(layer);
@@ -417,6 +422,11 @@ networkAddFirewallRules(virNetworkDef *def,
}
switch (firewallBackend) {
+ case VIR_FIREWALL_BACKEND_NONE:
+ virReportError(VIR_ERR_NO_SUPPORT, "%s",
+ _("No firewall backend is available"));
+ return -1;
+
case VIR_FIREWALL_BACKEND_IPTABLES:
return iptablesAddFirewallRules(def, fwRemoval);
diff --git a/src/network/bridge_driver_nop.c b/src/network/bridge_driver_nop.c
index 537b9234f8..2114d521d1 100644
--- a/src/network/bridge_driver_nop.c
+++ b/src/network/bridge_driver_nop.c
@@ -19,6 +19,8 @@
#include <config.h>
+#define VIR_FROM_THIS VIR_FROM_NETWORK
+
void networkPreReloadFirewallRules(virNetworkDriverState *driver G_GNUC_UNUSED,
bool startup G_GNUC_UNUSED,
bool force G_GNUC_UNUSED)
@@ -37,9 +39,20 @@ int networkCheckRouteCollision(virNetworkDef *def G_GNUC_UNUSED)
}
int networkAddFirewallRules(virNetworkDef *def G_GNUC_UNUSED,
- virFirewallBackend firewallBackend G_GNUC_UNUSED,
+ virFirewallBackend firewallBackend,
virFirewall **fwRemoval G_GNUC_UNUSED)
{
+ /*
+ * Shouldn't be possible, since virNetworkLoadDriverConfig
+ * ought to fail to find the required binaries when loading,
+ * so this is just a sanity check
+ */
+ if (firewallBackend != VIR_FIREWALL_BACKEND_NONE) {
+ virReportError(VIR_ERR_NO_SUPPORT,
+ _("Firewall backend '%s' not available on this platform"),
+ virFirewallBackendTypeToString(firewallBackend));
+ return -1;
+ }
return 0;
}
diff --git a/src/util/virfirewall.c b/src/util/virfirewall.c
index 2219506b18..d374f54b64 100644
--- a/src/util/virfirewall.c
+++ b/src/util/virfirewall.c
@@ -37,6 +37,7 @@ VIR_LOG_INIT("util.firewall");
VIR_ENUM_IMPL(virFirewallBackend,
VIR_FIREWALL_BACKEND_LAST,
+ "none",
"iptables",
"nftables");
@@ -815,6 +816,11 @@ virFirewallApplyCmd(virFirewall *firewall,
}
switch (virFirewallGetBackend(firewall)) {
+ case VIR_FIREWALL_BACKEND_NONE:
+ virReportError(VIR_ERR_NO_SUPPORT,
+ _("Firewall backend is not implemented"));
+ return -1;
+
case VIR_FIREWALL_BACKEND_IPTABLES:
if (virFirewallCmdIptablesApply(firewall, fwCmd, &output) < 0)
return -1;
diff --git a/src/util/virfirewall.h b/src/util/virfirewall.h
index 302a6a4e5b..bce51259d2 100644
--- a/src/util/virfirewall.h
+++ b/src/util/virfirewall.h
@@ -44,6 +44,7 @@ typedef enum {
} virFirewallLayer;
typedef enum {
+ VIR_FIREWALL_BACKEND_NONE, /* Always fails */
VIR_FIREWALL_BACKEND_IPTABLES,
VIR_FIREWALL_BACKEND_NFTABLES,
--
2.45.1
[View Less]
10 months
[PATCH 0/3] ci: update the CI dashboard
by Daniel P. Berrangé
Daniel P. Berrangé (3):
docs: trim many projects from CI dashboard
docs: fix link to virttools-web pipeline status
docs: add libosinfo & virt-viewer to CI dashboard
docs/ci-dashboard.rst | 78 ++++++++++++++++++-------------------------
1 file changed, 32 insertions(+), 46 deletions(-)
--
2.45.1
10 months
[PATCH] gitlab: add missing job inheritance for codestyle
by Daniel P. Berrangé
The previous fix:
commit b069efe29c950d1a45e88ef7dc924d3ee223103a
Author: Daniel P. Berrangé <berrange(a)redhat.com>
Date: Fri Jun 14 19:57:06 2024 +0100
gitlab: fix codestyle CI job
was incomplete, as the job inheritance was also
broken.
Signed-off-by: Daniel P. Berrangé <berrange(a)redhat.com>
---
.gitlab-ci.yml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 635e731f82..6de867e1f2 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-…
[View More]ci.yml
@@ -106,6 +106,7 @@ pages:
codestyle_job:
stage: sanity_checks
+ extends: .gitlab_native_build_job
needs:
- job: x86_64-opensuse-leap-15-container
optional: true
--
2.45.1
[View Less]
10 months
[PATCH 0/2] Make affinity setting a bit more debug friendly
by Michal Privoznik
*** BLURB HERE ***
Michal Prívozník (2):
qemu_process: Issue an info message when subtracting isolcpus
virprocess: Debug affinity map in virProcessSetAffinity()
src/qemu/qemu_process.c | 6 ++++++
src/util/virprocess.c | 6 ++++--
2 files changed, 10 insertions(+), 2 deletions(-)
--
2.43.2
10 months
[PATCH] gitlab: fix codestyle CI job
by Daniel P. Berrangé
Jobs whose names start with a '.' as treated as templates, so
not actually run in a pipeline.
Signed-off-by: Daniel P. Berrangé <berrange(a)redhat.com>
---
.gitlab-ci.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index d9d8b1e3cd..635e731f82 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -104,7 +104,7 @@ pages:
paths:
- public
-.codestyle_job:
+codestyle_job:
stage: sanity_checks
needs:
- job: x86_64-opensuse-leap-15-container
--
2.45.1
10 months, 1 week
Re: [libvirt PATCH 00/28] native support for nftables in virtual
network driver
by Roman Bogorodskiy
Laine Stump wrote:
> On 6/10/24 2:54 PM, Roman Bogorodskiy wrote:
> > Laine Stump wrote:
> >
> > > This patch series enables libvirt to use nftables rules rather than
> > > iptables *when setting up virtual networks* (it does *not* add
> > > nftables support to the nwfilter driver). It accomplishes this by
> > > abstracting several iptables functions (from viriptables.[ch] called
> > > by the virtual network driver into a …
[View More]rudimentary "virNetfilter API"
> > > (in virnetfilter.[ch], having the virtual network driver call the
> > > virNetFilter API rather than calling the existing iptables functions
> > > directly, and then finally adding an equivalent virNftables backend
> > > that can be used instead of iptables (selected manually via a
> > > network.conf setting, or automatically if iptables isn't found on the
> > > host).
> >
> > Hi,
> >
> > Apparently, I'm late to the discussion.
> >
> > I noticed that now I cannot use the bridge driver on FreeBSD as it's
> > failing to initialize both iptables and nftables backends (which is
> > expect).
>
> Yeah, previously we wouldn't check if iptables was available until someone
> tried to start a network that would need to use it, and would then log an
> error (and just fail starting that network, but the network driver would
> remain running). But now we figure out which firewall backend to use
> immediately when the driver is loaded, and if we fail to fin a workable
> backend we fail the entire driver init.r
>
> How did you use the network driver before? With a <forward mode='open'/>
> network? Truthfully I hadn't ever considered the case of someone using it
> with only network types that didn't need firewall rules. I wonder if there
> are other platforms we support that have a usable network driver for
> <forward mode='open'/> (MacOS?)
I'm using it with the following network configuration:
virsh # net-dumpxml default
<network>
<name>default</name>
<uuid>2a1415c9-325b-41e4-82c6-e805162d8934</uuid>
<forward mode='nat'/>
<bridge name='virbr0' stp='on' delay='0'/>
<mac address='52:54:00:24:fa:43'/>
<ip address='192.168.122.1' netmask='255.255.255.0'>
<dhcp>
<range start='192.168.122.2' end='192.168.122.254'/>
</dhcp>
</ip>
</network>
So basically all the mechanics like creating tap devices, bridges,
serving dhcp, etc, all these work for me. On top of that I had a few
iterations of manual firewall configurations (with both ipfw and pf)
to implement NAT on guests.
Unfortunately, I don't have access to that setup anymore and I haven't
re-created it yet. IIRC, it could probably show some warnings about
missing iptables, but it didn't affect anything for me.
> >
> > What would be a good way to address that? I see at least two options:
> >
> > 1. Add a Noop firewall driver
> > 2. Implement a "real" FreeBSD driver based either on pf or ipfw (that's
> > been on my TODO list forever, but I somehow got stuck on the very first
> > step on choosing between pf and ipfw).
>
> Why not both? :-)
>
> > This obviously will take much
> > more time.
> >
> > Maybe there are other options I'm missing.
>
> Obviously (2) would be nicest, but I guess in the short term some variation
> of (1) would be quicker.
>
> Another possibility could be to restore the old behavior of saving the error
> and only reporting it when a network requiring a firewall is loaded, but I
> think I remember a discussion about this during review of an earlier
> revision of the patches, and we agreed that it made the problem easier to
> find if it was reported immediately and the driver load failed.
>
> I suppose in the long run the build-time option firewall_backend_priority
> should be used to control which backends are included in the build (rather
> than just which ones are checked at runtime), so that FreeBSD could
> completely skip all the iptables and nftables code (and firewalld when
> that's done), and Linux platforms could skip pf and ipfw.
>
> >
> > What do you think?
>
> I'm about to be offline for 3 weeks, but in the meantime if you'd like to
> try making a NULL backend that is only an option if it's listed in
> firewall_backend_priority (you'll need to remove the compile-time check that
> all possible backends are accounted for - I think that is the first of the
> two G_STATIC_ASSERTS at the top of virNetworkLoadDriverConfig()), always
> initializes successfully in bridge_driver_conf.c if it is listed in the
> options, and then in networkAddFirewallRules add a check to log an error and
> fail if backend == NULL (something about attempting to start a network type
> that would require firewall rules, but the system not having any of the
> supported types of firewallbackend or something - it's too late now and my
> brain is too fried and sleepy to think of good wording :-)). As long as it
> isn't a valid selection on Linux builds that are done with
> firewall_backend_priority=nftables,iptables, but *is* a valid selection if
> the setting is "firewall_backend_priority=null" that shouldn't be *too*
> controversial.
Ok, I think I can try making the NULL backend.
> Later we can talk about pf and ipfw backends :-)
Yeah, that sounds good. My main problem with the choice is that ipfw is
the most actively supported firewall, but it relies quite heavily on the
rule numbering, which makes it a little hard to integrate with
user-specific rules (i.e. defined outside of libvirt). The "pf" seem to
be better in this regard (at least to my taste), but it's not "native"
FreeBSD firewall and is not as active (at least, to my impression).
Roman
[View Less]
10 months, 1 week
[PATCH 0/3] Couple of memleak fixes
by Michal Privoznik
The third patch MIGHT fix the following issue:
https://issues.redhat.com/browse/RHEL-22574
but at this point it's still unclear. I'll append appropriate
'Resolves:' line when I learn more.
Michal Prívozník (3):
virfirewall: Fir a memleak in virFirewallParseXML()
virnetworkobj: Free fwRemoval before setting another one in
virNetworkObjSetFwRemoval()
remote_daemon_dispatch: Unref sasl session when closing client
connection
src/conf/virnetworkobj.c | 1 +
src/remote/…
[View More]remote_daemon_dispatch.c | 4 ++++
src/util/virfirewall.c | 2 +-
3 files changed, 6 insertions(+), 1 deletion(-)
--
2.44.2
[View Less]
10 months, 1 week
[PATCH] network: introduce a "none" firewall backend type
by Daniel P. Berrangé
There are two scenarios identified after the recent firewall backend
selection was introduced, which result in libvirtd failing to startup
due to an inability to find either iptables/nftables
- On Linux if running unprivileged with $PATH lacking the dir
containing iptables/nftables
- On non-Linux where iptables/nftables never existed
In the former case, it is preferrable to restore the behaviour whereby
the driver starts successfully. Users will get an error reported when
attempting to …
[View More]start any virtual network, due to the lack of permissions
needed to create bridge devices. This makes the missing firewall backend
irrelevant.
In the latter case, the network driver calls the 'nop' platform
implementation which does not attempt to implement any firewall logic,
just allowing the network to start without firewall rules.
To solve this are number of changes are required
* Introduce VIR_FIREWALL_BACKEND_NONE, which does nothing except
report a fatal error from virFirewallApply(). This code path
is unreachable, since we'll never create a virFirewall
object with with VIR_FIREWALL_BACKEND_NONE, so the error reporting
is just a sanity check.
* Ignore the compile time backend defaults and assume use of
the 'none' backend if running unprivileged.
This fixes the first regression, avoiding the failure to start
libvirtd on Linux in unprivileged context, instead allowing use
of the driver and expecting a permission denied when creating a
bridge.
* Reject the use of compile time backend defaults no non-Linux
and hardcode the 'none' backend. The non-Linux platforms have
no firewall implementation at all currently, so there's no
reason to permit the use of 'firewall_backend_priority'
meson option.
This fixes the second regression, avoiding the failure to start
libvirtd on non-Linux hosts due to non-existant Linux binaries.
* Change the Linux platform backend to raise an error if the
firewall backend is 'none'. Again this code path is unreachable
by default since we'll fail to create the bridge before getting
here, but if someone modified network.conf to request the 'none'
backend, this will stop further progress.
* Change the nop platform backend to raise an error if the
firewall backend is 'iptables' or 'nftables'. Again this code
path is unreachable, since we should already have failed to
find the iptables/nftables binaries on non-Linux hosts, so
this is just a sanity check.
* 'none' is not permited as a value in 'firewall_backend_priority'
meson option, since it is conceptually meaningless to ask for
that on Linux.
Signed-off-by: Daniel P. Berrangé <berrange(a)redhat.com>
---
meson.build | 26 +++++++++++++++++++-------
meson_options.txt | 2 +-
src/network/bridge_driver_conf.c | 19 ++++++++++++++-----
src/network/bridge_driver_linux.c | 10 ++++++++++
src/network/bridge_driver_nop.c | 13 ++++++++++++-
src/util/virfirewall.c | 6 ++++++
src/util/virfirewall.h | 1 +
7 files changed, 63 insertions(+), 14 deletions(-)
diff --git a/meson.build b/meson.build
index 5c7cd7ec2e..2e8b87280d 100644
--- a/meson.build
+++ b/meson.build
@@ -1647,15 +1647,27 @@ if not get_option('driver_network').disabled() and conf.has('WITH_LIBVIRTD')
conf.set('WITH_NETWORK', 1)
firewall_backend_priority = get_option('firewall_backend_priority')
- if (not firewall_backend_priority.contains('nftables') or
- not firewall_backend_priority.contains('iptables') or
- firewall_backend_priority.length() != 2)
- error('invalid value for firewall_backend_priority option')
+ if firewall_backend_priority.length() == 0
+ if host_machine.system() == 'linux'
+ firewall_backend_priority = ['nftables', 'iptables']
+ else
+ # No firewall impl on non-Linux so far, so force 'none'
+ # as placeholder
+ firewall_backend_priority = ['none']
+ endif
+ else
+ if host_machine.system() != 'linux'
+ error('firewall backend priority only supported on linux hosts')
+ endif
endif
- conf.set('FIREWALL_BACKEND_PRIORITY_0', 'VIR_FIREWALL_BACKEND_' + firewall_backend_priority[0].to_upper())
- conf.set('FIREWALL_BACKEND_PRIORITY_1', 'VIR_FIREWALL_BACKEND_' + firewall_backend_priority[1].to_upper())
- conf.set('FIREWALL_BACKEND_PRIORITY_NUM', firewall_backend_priority.length())
+ backends = []
+ foreach backend: firewall_backend_priority
+ backend = 'VIR_FIREWALL_BACKEND_' + backend.to_upper()
+ backends += backend
+ endforeach
+
+ conf.set('FIREWALL_BACKENDS', ', '.join(backends))
elif get_option('driver_network').enabled()
error('libvirtd must be enabled to build the network driver')
endif
diff --git a/meson_options.txt b/meson_options.txt
index 50d71427cb..2d440c63d8 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -117,7 +117,7 @@ option('dtrace', type: 'feature', value: 'auto', description: 'use dtrace for st
option('firewalld', type: 'feature', value: 'auto', description: 'firewalld support')
# dep:firewalld
option('firewalld_zone', type: 'feature', value: 'auto', description: 'whether to install firewalld libvirt zone')
-option('firewall_backend_priority', type: 'array', choices: ['nftables', 'iptables'], description: 'order in which to try firewall backends')
+option('firewall_backend_priority', type: 'array', choices: ['nftables', 'iptables'], value: [], description: 'order in which to try firewall backends')
option('host_validate', type: 'feature', value: 'auto', description: 'build virt-host-validate')
option('init_script', type: 'combo', choices: ['systemd', 'openrc', 'check', 'none'], value: 'check', description: 'Style of init script to install')
option('loader_nvram', type: 'string', value: '', description: 'Pass list of pairs of <loader>:<nvram> paths. Both pairs and list items are separated by a colon.')
diff --git a/src/network/bridge_driver_conf.c b/src/network/bridge_driver_conf.c
index e2f3613a41..9da5e790b7 100644
--- a/src/network/bridge_driver_conf.c
+++ b/src/network/bridge_driver_conf.c
@@ -61,6 +61,7 @@ networkGetDnsmasqCaps(virNetworkDriverState *driver)
static int
virNetworkLoadDriverConfig(virNetworkDriverConfig *cfg G_GNUC_UNUSED,
+ bool privileged,
const char *filename)
{
g_autoptr(virConf) conf = NULL;
@@ -68,13 +69,17 @@ virNetworkLoadDriverConfig(virNetworkDriverConfig *cfg G_GNUC_UNUSED,
bool fwBackendSelected = false;
size_t i;
int fwBackends[] = {
- FIREWALL_BACKEND_PRIORITY_0,
- FIREWALL_BACKEND_PRIORITY_1,
+ FIREWALL_BACKENDS
};
- G_STATIC_ASSERT(G_N_ELEMENTS(fwBackends) == VIR_FIREWALL_BACKEND_LAST);
- G_STATIC_ASSERT(G_N_ELEMENTS(fwBackends) == FIREWALL_BACKEND_PRIORITY_NUM);
+ G_STATIC_ASSERT(G_N_ELEMENTS(fwBackends) > 0 &&
+ G_N_ELEMENTS(fwBackends) <= VIR_FIREWALL_BACKEND_LAST);
int nFwBackends = G_N_ELEMENTS(fwBackends);
+ if (!privileged) {
+ fwBackends[0] = VIR_FIREWALL_BACKEND_NONE;
+ nFwBackends = 1;
+ }
+
if (access(filename, R_OK) == 0) {
conf = virConfReadFile(filename, 0);
@@ -104,6 +109,10 @@ virNetworkLoadDriverConfig(virNetworkDriverConfig *cfg G_GNUC_UNUSED,
for (i = 0; i < nFwBackends && !fwBackendSelected; i++) {
switch ((virFirewallBackend)fwBackends[i]) {
+ case VIR_FIREWALL_BACKEND_NONE:
+ fwBackendSelected = true;
+ break;
+
case VIR_FIREWALL_BACKEND_IPTABLES: {
g_autofree char *iptablesInPath = virFindFileInPath(IPTABLES);
@@ -187,7 +196,7 @@ virNetworkDriverConfigNew(bool privileged)
configfile = g_strconcat(configdir, "/network.conf", NULL);
- if (virNetworkLoadDriverConfig(cfg, configfile) < 0)
+ if (virNetworkLoadDriverConfig(cfg, privileged, configfile) < 0)
return NULL;
if (g_mkdir_with_parents(cfg->stateDir, 0777) < 0) {
diff --git a/src/network/bridge_driver_linux.c b/src/network/bridge_driver_linux.c
index 35e6bd1154..fe7c6e193c 100644
--- a/src/network/bridge_driver_linux.c
+++ b/src/network/bridge_driver_linux.c
@@ -47,6 +47,11 @@ networkFirewallSetupPrivateChains(virFirewallBackend backend,
virFirewallLayer layer)
{
switch (backend) {
+ case VIR_FIREWALL_BACKEND_NONE:
+ virReportError(VIR_ERR_NO_SUPPORT, "%s",
+ _("No firewall backend is available"));
+ return -1;
+
case VIR_FIREWALL_BACKEND_IPTABLES:
return iptablesSetupPrivateChains(layer);
@@ -417,6 +422,11 @@ networkAddFirewallRules(virNetworkDef *def,
}
switch (firewallBackend) {
+ case VIR_FIREWALL_BACKEND_NONE:
+ virReportError(VIR_ERR_NO_SUPPORT, "%s",
+ _("No firewall backend is available"));
+ return -1;
+
case VIR_FIREWALL_BACKEND_IPTABLES:
return iptablesAddFirewallRules(def, fwRemoval);
diff --git a/src/network/bridge_driver_nop.c b/src/network/bridge_driver_nop.c
index 537b9234f8..7797be1ba8 100644
--- a/src/network/bridge_driver_nop.c
+++ b/src/network/bridge_driver_nop.c
@@ -37,9 +37,20 @@ int networkCheckRouteCollision(virNetworkDef *def G_GNUC_UNUSED)
}
int networkAddFirewallRules(virNetworkDef *def G_GNUC_UNUSED,
- virFirewallBackend firewallBackend G_GNUC_UNUSED,
+ virFirewallBackend firewallBackend,
virFirewall **fwRemoval G_GNUC_UNUSED)
{
+ /*
+ * Shouldn't be possible, since virNetworkLoadDriverConfig
+ * ought to fail to find the required binaries when loading,
+ * so this is just a sanity check
+ */
+ if (firewallBackend != VIR_FIREWALL_NONE) {
+ virReportError(VIR_ERR_NO_SUPPORT, "%s",
+ _("Firewall backend '%s' not available on this platform"),
+ virFirewallBackendTypeToSTring(firewallBackend));
+ return -1;
+ }
return 0;
}
diff --git a/src/util/virfirewall.c b/src/util/virfirewall.c
index 2219506b18..d374f54b64 100644
--- a/src/util/virfirewall.c
+++ b/src/util/virfirewall.c
@@ -37,6 +37,7 @@ VIR_LOG_INIT("util.firewall");
VIR_ENUM_IMPL(virFirewallBackend,
VIR_FIREWALL_BACKEND_LAST,
+ "none",
"iptables",
"nftables");
@@ -815,6 +816,11 @@ virFirewallApplyCmd(virFirewall *firewall,
}
switch (virFirewallGetBackend(firewall)) {
+ case VIR_FIREWALL_BACKEND_NONE:
+ virReportError(VIR_ERR_NO_SUPPORT,
+ _("Firewall backend is not implemented"));
+ return -1;
+
case VIR_FIREWALL_BACKEND_IPTABLES:
if (virFirewallCmdIptablesApply(firewall, fwCmd, &output) < 0)
return -1;
diff --git a/src/util/virfirewall.h b/src/util/virfirewall.h
index 302a6a4e5b..bce51259d2 100644
--- a/src/util/virfirewall.h
+++ b/src/util/virfirewall.h
@@ -44,6 +44,7 @@ typedef enum {
} virFirewallLayer;
typedef enum {
+ VIR_FIREWALL_BACKEND_NONE, /* Always fails */
VIR_FIREWALL_BACKEND_IPTABLES,
VIR_FIREWALL_BACKEND_NFTABLES,
--
2.45.1
[View Less]
10 months, 1 week