mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-10-31 10:23:09 +00:00
f5418b427e
When firewalld is stopped, it removes *all* iptables rules and chains, including those added by libvirt. Since restarting firewalld means stopping and then starting it, any time it is restarted, libvirt needs to recreate all the private iptables chains it uses, along with all the rules it adds. We already have code in place to call networkReloadFirewallRules() any time we're notified of a firewalld start, and networkReloadFirewallRules() will call networkPreReloadFirewallRules(), which calls networkSetupPrivateChains(); unfortunately that last call is called using virOnce(), meaning that it will only be called the first time through networkPreReloadFirewallRules() after libvirtd starts - so of course when firewalld is later restarted, the call to networkSetupPrivateChains() is skipped. The neat and tidy way to fix this would be if there was a standard way to reset a pthread_once_t object so that the next time virOnce was called, it would think the function hadn't been called, and call it again. Unfortunately, there isn't any official way of doing that (we *could* just fill it with 0 and hope for the best, but that doesn't seem very safe. So instead, this patch just adds a static variable called chainInitDone, which is set to true after networkSetupPrivateChains() is called for the first time, and then during calls to networkPreReloadFirewallRules(), if chainInitDone is set, we call networkSetupPrivateChains() directly instead of via virOnce(). It may seem unsafe to directly call a function that is meant to be called only once, but I think in this case we're safe - there's nothing in the function that is inherently "once only" - it doesn't initialize anything that can't safely be re-initialized (as long as two threads don't try to do it at the same time), and it only happens when responding to a dbus message that firewalld has been started (and I don't think it's possible for us to be processing two of those at once), and even then only if the initial call to the function has already been completed (so we're safe if we receive a firewalld restart call at a time when we haven't yet called it, or even if another thread is already in the process of executing it. The only problematic bit I can think of is if another thread is in the process of adding an iptable rule at the time we're executing this function, but 1) none of those threads will be trying to add chains, and 2) if there was a concurrency problem with other threads adding iptables rules while firewalld was being restarted, it would still be a problem even without this change. This is yet another patch that fixes an occurrence of this error: COMMAND_FAILED: '/usr/sbin/iptables -w10 -w --table filter --insert LIBVIRT_INP --in-interface virbr0 --protocol tcp --destination-port 67 --jump ACCEPT' failed: iptables: No chain/target/match by that name. In particular, this resolves: https://bugzilla.redhat.com/1813830 Signed-off-by: Laine Stump <laine@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
73 lines
2.1 KiB
C
73 lines
2.1 KiB
C
/*
|
|
* bridge_driver_platform.h: platform specific routines for bridge driver
|
|
*
|
|
* Copyright (C) 2006-2013 Red Hat, Inc.
|
|
* Copyright (C) 2006 Daniel P. Berrange
|
|
*
|
|
* 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/>.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "internal.h"
|
|
#include "virthread.h"
|
|
#include "virdnsmasq.h"
|
|
#include "virnetworkobj.h"
|
|
#include "object_event.h"
|
|
|
|
/* Main driver state */
|
|
struct _virNetworkDriverState {
|
|
virMutex lock;
|
|
|
|
/* Read-only */
|
|
bool privileged;
|
|
|
|
/* pid file FD, ensures two copies of the driver can't use the same root */
|
|
int lockFD;
|
|
|
|
/* Immutable pointer, self-locking APIs */
|
|
virNetworkObjListPtr networks;
|
|
|
|
/* Immutable pointers, Immutable objects */
|
|
char *networkConfigDir;
|
|
char *networkAutostartDir;
|
|
char *stateDir;
|
|
char *pidDir;
|
|
char *dnsmasqStateDir;
|
|
char *radvdStateDir;
|
|
|
|
/* Require lock to get a reference on the object,
|
|
* lockless access thereafter
|
|
*/
|
|
dnsmasqCapsPtr dnsmasqCaps;
|
|
|
|
/* Immutable pointer, self-locking APIs */
|
|
virObjectEventStatePtr networkEventState;
|
|
|
|
virNetworkXMLOptionPtr xmlopt;
|
|
};
|
|
|
|
typedef struct _virNetworkDriverState virNetworkDriverState;
|
|
typedef virNetworkDriverState *virNetworkDriverStatePtr;
|
|
|
|
void networkPreReloadFirewallRules(virNetworkDriverStatePtr driver, bool startup, bool force);
|
|
void networkPostReloadFirewallRules(bool startup);
|
|
|
|
int networkCheckRouteCollision(virNetworkDefPtr def);
|
|
|
|
int networkAddFirewallRules(virNetworkDefPtr def);
|
|
|
|
void networkRemoveFirewallRules(virNetworkDefPtr def);
|