[libvirt] [PATCH] iptablesSetupPrivateChains: Be forgiving if a table does not exist
Michal Privoznik
mprivozn at redhat.com
Mon Mar 11 10:27:33 UTC 2019
On 3/11/19 11:05 AM, Daniel P. Berrangé wrote:
> On Mon, Mar 11, 2019 at 09:37:52AM +0100, Michal Privoznik wrote:
>> The way this function works is that for both iptables and
>> ip6tables (or their firewalld friends) and for every table
>> ("filter", "nat", "mangle") it lists chains defined for the table
>> and then calls iptablesPrivateChainCreate() over the list. The
>> callback is then supposed to find libvirt private chains and if
>> not found create rules to add them. So far so good. Problem is if
>> one of the tables doesn't exist (e.g. due to a module missing).
>> For instance, on my system I don't have CONFIG_IP6_NF_MANGLE
>> enabled therefore I'm lacking "mangle" table for ip6tables. This
>> means that the whole operation of setting up private chains fails
>> because the whole transaction is run as "do not ignore errors".
>>
>> The solution is to have two transactions, the first one which
>> just lists chains can run ignoring errors, and the second one
>> which then installs the private chains will run normally.
>
> This is just going to push the failure to a later point.
Is it? I mean sure, if you have some nwfilters that will apply some
rules to the missing table. But if you don't have such filters?
>
> This causes iptablesPrivateChainCreate() to skip setup of the
> libvirt global chain, so when we try to add rules to the libvirt
> global chain later we'll find it doesn't exist.
I my limited setup, where I use the default network (which has just IPv4
enabled) and one domain using that network, no nwfilters this patch
fixes the problem for me and I don't see any subsequent errors. I don't
see any appealing argument to require IPv6 support in that case.
>
>> In the code, this approach is pushed to another level - every
>> table for which private chains are created is run as a separate
>> transaction. The reason is that it saves us one more variable
>> where we would track if the second transaction was started
>> already or not; and also, it doesn't matter.
>>
>> Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
>> ---
>> src/util/viriptables.c | 12 +++++++++++-
>> 1 file changed, 11 insertions(+), 1 deletion(-)
>>
>> diff --git a/src/util/viriptables.c b/src/util/viriptables.c
>> index d67b640a3b..ea24b03ec8 100644
>> --- a/src/util/viriptables.c
>> +++ b/src/util/viriptables.c
>> @@ -101,6 +101,16 @@ iptablesPrivateChainCreate(virFirewallPtr fw,
>> tmp++;
>> }
>>
>> + /* This function is running in the context of the very first transaction,
>> + * which does nothing more than just lists current tables and chains. But
>> + * since some tables might not be there (e.g. because of a module missing),
>> + * the transaction is run with IGNORE_ERRORS flag. But obviously, we don't
>> + * want to ignore errors here, where we are constructing our own chains and
>> + * rules. The only way to resolve this is to start a new transaction so
>> + * that all those AddRule() calls below add rules to new transaction/group.
>> + */
>> + virFirewallStartTransaction(fw, 0);
>> +
>> for (i = 0; i < data->nchains; i++) {
>> const char *from;
>> if (!virHashLookup(chains, data->chains[i].child)) {
>> @@ -160,7 +170,7 @@ iptablesSetupPrivateChains(void)
>>
>> fw = virFirewallNew();
>>
>> - virFirewallStartTransaction(fw, 0);
>> + virFirewallStartTransaction(fw, VIR_FIREWALL_TRANSACTION_IGNORE_ERRORS);
>
> This applies to all the chains, so if someone is missing more builtin
> top level chains we'll potentially fail to create any of our global
> chains which feels pretty undesirable to me.
Hm.. maybe I'm missing something, but when I was debugging this I saw
IGNORE_ERRORS being applied only for those "rules" [1] from the first
group/transaction. Any other rules that the callback added were run
normally, without ignoring errors.
>
> Why shouldn't we just consider that missing kernel build option to be
> a user bug ?
Well, as I say above, if you only have IPv4 network then the current
code is going to fail the moment it gets to the first IPv6 "rule" [1].
But if we decide to require IPv6, then we need to document that.
Michal
1: I say rules, but they aren't rules really, they merely just list chains.
More information about the libvir-list
mailing list