|
|
397dc2 |
From dc8cf11686c075166a3029e974a6caeefe521d75 Mon Sep 17 00:00:00 2001
|
|
|
397dc2 |
Message-Id: <dc8cf11686c075166a3029e974a6caeefe521d75@dist-git>
|
|
|
397dc2 |
From: Laine Stump <laine@redhat.com>
|
|
|
397dc2 |
Date: Fri, 15 Jan 2021 22:51:50 -0500
|
|
|
397dc2 |
Subject: [PATCH] util: synchronize with firewalld before we start calling
|
|
|
397dc2 |
iptables directly
|
|
|
397dc2 |
|
|
|
397dc2 |
When it is starting up, firewalld will delete all existing iptables
|
|
|
397dc2 |
rules and chains before adding its own rules. If libvirtd were to try
|
|
|
397dc2 |
to directly add iptables rules during the time before firewalld has
|
|
|
397dc2 |
finished initializing, firewalld would end up deleting the rules that
|
|
|
397dc2 |
libvirtd has just added.
|
|
|
397dc2 |
|
|
|
397dc2 |
Currently this isn't a problem, since libvirtd only adds iptables
|
|
|
397dc2 |
rules via the firewalld "passthrough command" API, and so firewalld is
|
|
|
397dc2 |
able to properly serialize everything. However, we will soon be
|
|
|
397dc2 |
changing libvirtd to add its iptables and ebtables rules by directly
|
|
|
397dc2 |
calling iptables/ebtables rather than via firewalld, thus removing the
|
|
|
397dc2 |
serialization of libvirtd adding rules vs. firewalld deleting rules.
|
|
|
397dc2 |
|
|
|
397dc2 |
This will especially apparent (if we don't fix it in advance, as this
|
|
|
397dc2 |
patch does) when libvirtd is responding to the dbus NameOwnerChanged
|
|
|
397dc2 |
event, which is used to learn when firewalld has been restarted. In
|
|
|
397dc2 |
that case, dbus sends the event before firewalld has been able to
|
|
|
397dc2 |
complete its initialization, so when libvirt responds to the event by
|
|
|
397dc2 |
adding back its iptables rules (with direct calls to
|
|
|
397dc2 |
/usr/bin/iptables), some of those rules are added before firewalld has
|
|
|
397dc2 |
a chance to do its "remove everything" startup protocol. The usual
|
|
|
397dc2 |
result of this is that libvirt will successfully add its private
|
|
|
397dc2 |
chains (e.g. LIBVIRT_INP, etc), but then fail when it tries to add a
|
|
|
397dc2 |
rule jumping to one of those chains (because in the interim, firewalld
|
|
|
397dc2 |
has deleted the new chains).
|
|
|
397dc2 |
|
|
|
397dc2 |
The solution is for libvirt to preface it's direct calling to iptables
|
|
|
397dc2 |
with a iptables command sent via firewalld's passthrough command
|
|
|
397dc2 |
API. Since commands sent to firewalld are completed synchronously, and
|
|
|
397dc2 |
since firewalld won't service them until it has completed its own
|
|
|
397dc2 |
initialization, this will assure that by the time libvirt starts
|
|
|
397dc2 |
calling iptables to add rules, that firewalld will not be following up
|
|
|
397dc2 |
by deleting any of those rules.
|
|
|
397dc2 |
|
|
|
397dc2 |
To minimize the amount of extra overhead, we request the simplest
|
|
|
397dc2 |
iptables command possible: "iptables -V" (and aside from logging a
|
|
|
397dc2 |
debug message, we ignore the result, for good measure).
|
|
|
397dc2 |
|
|
|
397dc2 |
(This patch is being done *before* the patch that switches to calling
|
|
|
397dc2 |
iptables directly, so that everything will function properly with any
|
|
|
397dc2 |
fractional part of the series applied).
|
|
|
397dc2 |
|
|
|
397dc2 |
https://bugzilla.redhat.com/1607929
|
|
|
397dc2 |
|
|
|
397dc2 |
Signed-off-by: Laine Stump <laine@redhat.com>
|
|
|
397dc2 |
Reviewed-by: Daniel Henrique Barboza <danielhb413@gmail.com>
|
|
|
397dc2 |
(cherry picked from commit 070690538a1ed301b004c542d94b13ee9bffc9d6)
|
|
|
397dc2 |
|
|
|
397dc2 |
Conflicts: src/util/viriptables.c:
|
|
|
397dc2 |
one line of code in context moved during g_autoptr conversion.
|
|
|
397dc2 |
Signed-off-by: Laine Stump <laine@redhat.com>
|
|
|
397dc2 |
Message-Id: <20210116035151.1066734-8-laine@redhat.com>
|
|
|
397dc2 |
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
|
|
|
397dc2 |
---
|
|
|
397dc2 |
src/libvirt_private.syms | 1 +
|
|
|
397dc2 |
src/util/virfirewall.c | 30 ++++++++++++++++++++++++++++++
|
|
|
397dc2 |
src/util/virfirewall.h | 2 ++
|
|
|
397dc2 |
src/util/viriptables.c | 7 +++++++
|
|
|
397dc2 |
4 files changed, 40 insertions(+)
|
|
|
397dc2 |
|
|
|
397dc2 |
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
|
|
|
397dc2 |
index edc53ce899..9d87e2a27b 100644
|
|
|
397dc2 |
--- a/src/libvirt_private.syms
|
|
|
397dc2 |
+++ b/src/libvirt_private.syms
|
|
|
397dc2 |
@@ -2080,6 +2080,7 @@ virFileCacheSetPriv;
|
|
|
397dc2 |
# util/virfirewall.h
|
|
|
397dc2 |
virFirewallAddRuleFull;
|
|
|
397dc2 |
virFirewallApply;
|
|
|
397dc2 |
+virFirewallBackendSynchronize;
|
|
|
397dc2 |
virFirewallFree;
|
|
|
397dc2 |
virFirewallNew;
|
|
|
397dc2 |
virFirewallRemoveRule;
|
|
|
397dc2 |
diff --git a/src/util/virfirewall.c b/src/util/virfirewall.c
|
|
|
397dc2 |
index 520d515c11..66d20d3f17 100644
|
|
|
397dc2 |
--- a/src/util/virfirewall.c
|
|
|
397dc2 |
+++ b/src/util/virfirewall.c
|
|
|
397dc2 |
@@ -653,6 +653,36 @@ virFirewallApplyRuleFirewallD(virFirewallRulePtr rule,
|
|
|
397dc2 |
return virFirewallDApplyRule(rule->layer, rule->args, rule->argsLen, ignoreErrors, output);
|
|
|
397dc2 |
}
|
|
|
397dc2 |
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+void
|
|
|
397dc2 |
+virFirewallBackendSynchronize(void)
|
|
|
397dc2 |
+{
|
|
|
397dc2 |
+ const char *arg = "-V";
|
|
|
397dc2 |
+ g_autofree char *output = NULL;
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+ switch (currentBackend) {
|
|
|
397dc2 |
+ case VIR_FIREWALL_BACKEND_DIRECT:
|
|
|
397dc2 |
+ /* nobody to synchronize with */
|
|
|
397dc2 |
+ break;
|
|
|
397dc2 |
+ case VIR_FIREWALL_BACKEND_FIREWALLD:
|
|
|
397dc2 |
+ /* Send a simple rule via firewalld's passthrough iptables
|
|
|
397dc2 |
+ * command so that we'll be sure firewalld has fully
|
|
|
397dc2 |
+ * initialized and caught up with its internal queue of
|
|
|
397dc2 |
+ * iptables commands. Waiting for this will prevent our own
|
|
|
397dc2 |
+ * directly-executed iptables commands from being run while
|
|
|
397dc2 |
+ * firewalld is still initializing.
|
|
|
397dc2 |
+ */
|
|
|
397dc2 |
+ ignore_value(virFirewallDApplyRule(VIR_FIREWALL_LAYER_IPV4,
|
|
|
397dc2 |
+ (char **)&arg, 1, true, &output));
|
|
|
397dc2 |
+ VIR_DEBUG("Result of 'iptables -V' via firewalld: %s", NULLSTR(output));
|
|
|
397dc2 |
+ break;
|
|
|
397dc2 |
+ case VIR_FIREWALL_BACKEND_AUTOMATIC:
|
|
|
397dc2 |
+ case VIR_FIREWALL_BACKEND_LAST:
|
|
|
397dc2 |
+ break;
|
|
|
397dc2 |
+ }
|
|
|
397dc2 |
+}
|
|
|
397dc2 |
+
|
|
|
397dc2 |
+
|
|
|
397dc2 |
static int
|
|
|
397dc2 |
virFirewallApplyRule(virFirewallPtr firewall,
|
|
|
397dc2 |
virFirewallRulePtr rule,
|
|
|
397dc2 |
diff --git a/src/util/virfirewall.h b/src/util/virfirewall.h
|
|
|
397dc2 |
index fda3cdec01..3db0864380 100644
|
|
|
397dc2 |
--- a/src/util/virfirewall.h
|
|
|
397dc2 |
+++ b/src/util/virfirewall.h
|
|
|
397dc2 |
@@ -111,4 +111,6 @@ void virFirewallStartRollback(virFirewallPtr firewall,
|
|
|
397dc2 |
|
|
|
397dc2 |
int virFirewallApply(virFirewallPtr firewall);
|
|
|
397dc2 |
|
|
|
397dc2 |
+void virFirewallBackendSynchronize(void);
|
|
|
397dc2 |
+
|
|
|
397dc2 |
G_DEFINE_AUTOPTR_CLEANUP_FUNC(virFirewall, virFirewallFree);
|
|
|
397dc2 |
diff --git a/src/util/viriptables.c b/src/util/viriptables.c
|
|
|
397dc2 |
index 6b3a025880..41544b7f36 100644
|
|
|
397dc2 |
--- a/src/util/viriptables.c
|
|
|
397dc2 |
+++ b/src/util/viriptables.c
|
|
|
397dc2 |
@@ -154,6 +154,13 @@ iptablesSetupPrivateChains(virFirewallLayer layer)
|
|
|
397dc2 |
|
|
|
397dc2 |
fw = virFirewallNew();
|
|
|
397dc2 |
|
|
|
397dc2 |
+ /* When the backend is firewalld, we need to make sure that
|
|
|
397dc2 |
+ * firewalld has been fully started and completed its
|
|
|
397dc2 |
+ * initialization, otherwise firewalld might delete our rules soon
|
|
|
397dc2 |
+ * after we add them!
|
|
|
397dc2 |
+ */
|
|
|
397dc2 |
+ virFirewallBackendSynchronize();
|
|
|
397dc2 |
+
|
|
|
397dc2 |
virFirewallStartTransaction(fw, 0);
|
|
|
397dc2 |
|
|
|
397dc2 |
for (i = 0; i < G_N_ELEMENTS(data); i++)
|
|
|
397dc2 |
--
|
|
|
397dc2 |
2.30.0
|
|
|
397dc2 |
|