Move the structure to virnwfilterobj.c and create necessary accessor API's
for the various fields.
Also make virNWFilterObjFree static since there's no external callers.
Signed-off-by: John Ferlan <jferlan@redhat.com>
Rather than dereferencing obj->def->XXX or nwfilters->objs[i]->X
create local virNWFilterObjPtr and virNWFilterDefPtr variables.
Future adjustments will be privatizing the object more, so this just
prepares the code for that reality.
Signed-off-by: John Ferlan <jferlan@redhat.com>
When processing a virNWFilterPtr use 'nwfilter' as a variable name.
When processing a virNWFilterObjPtr use 'obj' as a variable name.
Signed-off-by: John Ferlan <jferlan@redhat.com>
Mostly code motion to move nwfilterConnectListNWFilters into nwfilterobj.c
and rename to virNWFilterObjGetNames.
Also includes a couple of variable name adjustments to keep code consistent
with other drivers.
Signed-off-by: John Ferlan <jferlan@redhat.com>
Mostly code motion from nwfilter_driver to virnwfilterobj with one caveat
to add the virNWFilterObjListFilter typedef and pass it as an 'aclfilter'
argument to allow for future possible test driver adjustments to count
the number of filters (similar to how node device has done this).
Signed-off-by: John Ferlan <jferlan@redhat.com>
Move all the NWFilterObj API's into their own module virnwfilterobj
from the nwfilter_conf
Purely code motion at this point, plus adjustments to cleanly build.
I'm tired of mistyping this all the time, so let's do it the same all
the time (similar to how we changed all "Pci" to "PCI" awhile back).
(NB: I've left alone some things in the esx and vbox drivers because
I'm unable to compile them and they weren't obviously *not* a part of
some API. I also didn't change a couple of variables named,
e.g. "somethingIptables", because they were derived from the name of
the "iptables" command)
When building using -Og, gcc sees that some variables can be used
uninitialized It can be debatable whether it is possible with our
codeflow, but functions should be self-contained and initializations are
always good. The return instead of goto is due to actualType being used
in the cleanup.
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
Below is backtraces of two deadlocked threads:
thread #1:
virDomainConfVMNWFilterTeardown
virNWFilterTeardownFilter
lock updateMutex <------------
_virNWFilterTeardownFilter
try to lock interface <----------
thread #2:
learnIPAddressThread
lock interface <-------
virNWFilterInstantiateFilterLate
try to lock updateMutex <----------
The problem is fixed by unlocking interface before calling
virNWFilterInstantiateFilterLate to avoid updateMutex and interface ordering
deadlocks. Otherwise we are going to instantiate the filter while holding
interface lock, which will try to lock updateMutex, and if some other thread
instantiating a filter in parallel is holding updateMutex and is trying to
lock interface, both will deadlock.
Also it is safe to unlock interface before virNWFilterInstantiateFilterLate
because learnIPAddressThread stopped capturing packets and applied necessary
rules on the interface, while instantiating a new filter doesn't require a
locked interface.
Signed-off-by: Maxim Nestratov <mnestratov@virtuozzo.com>
In virNWFilterObjLoad we can still fail after virNWFilterObjAssignDef,
but we don't unlock and free the created virNWFilterObjPtr in the
cleanup path.
The bit we are trying to do after AssignDef is just STRDUP in the
configFile path. However caching the configFile in the NWFilterObj
is largely redundant and doesn't follow the same pattern we use
for domain and network objects.
So just remove all the configFile caching which fixes the latent
bug as a side effect.
This allows setting the address in host and/or network order and makes
the naming consistent. Now you don't need to call [hn]to[nh]l()
functions as that is taken care of by these functions. Also, now
the *NetOrder take the address in network order, the other functions in
host order so the naming and usage is consistent. Some places were
having the address in network order and calling ntohl() just so the
original function can call htonl() again. This makes it nicer to read.
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
Our existing virHashForEach method iterates through all items disregarding the
fact, that some of the iterators might have actually failed. Errors are usually
dispatched through an error element in opaque data which then causes the
original caller of virHashForEach to return -1. In that case, virHashForEach
could return as soon as one of the iterators fail. This patch changes the
iterator return type and adjusts all of its instances accordingly, so the
actual refactor of virHashForEach method can be dealt with later.
Signed-off-by: Erik Skultety <eskultet@redhat.com>
VIR_DEBUG and VIR_WARN will automatically add a new line to the message,
having "\n" at the end or at the beginning of the message results in
empty lines.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
We allocate 16 bytes for IPv4 address and 55 bytes for interface
key, therefore we should read up to 15/54 bytes and let the last byte
reserved for terminating null byte in sscanf.
https://bugzilla.redhat.com/show_bug.cgi?id=1226400
https://bugzilla.redhat.com/show_bug.cgi?id=1211436
This reverts commit b7829f959b.
The previous fix was not correct. Like everywhere else, a driver is a
global variable allocated in stateInitialize function (or something
similar for stateless drivers). Later, when a driver API is called,
it's possible that the global variable is accessed and dereferenced.
Now, some drivers require root privileges because they undertake some
actions reserved only for the system admin (e.g. manipulating host
firewall). And here's the trouble, the NWFilter state initializer
exited too early when finding out it's running unprivileged, leaving
the global NWFilter driver variable uninitialized. Any subsequent
API call that tried to lock the driver resulted in dereferencing the
driver and thus crash.
On the other hand, in order to not resurrect the bug the original
commit was fixing, Let's forbid the nwfilter define in session mode.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Conflicts:
src/nwfilter/nwfilter_driver.c: Context. Code changed a bit
since 2013.
We want all threads to be set as workers or to have a job assigned to
them, which can easily be achieved in virThreadCreate wrapper to
pthread_create. Let's make sure we always use the wrapper.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
For stateless, client side drivers, it is never correct to
probe for secondary drivers. It is only ever appropriate to
use the secondary driver that is associated with the
hypervisor in question. As a result the ESX & HyperV drivers
have both been forced to do hacks where they register no-op
drivers for the ones they don't implement.
For stateful, server side drivers, we always just want to
use the same built-in shared driver. The exception is
virtualbox which is really a stateless driver and so wants
to use its own server side secondary drivers. To deal with
this virtualbox has to be built as 3 separate loadable
modules to allow registration to work in the right order.
This can all be simplified by introducing a new struct
recording the precise set of secondary drivers each
hypervisor driver wants
struct _virConnectDriver {
virHypervisorDriverPtr hypervisorDriver;
virInterfaceDriverPtr interfaceDriver;
virNetworkDriverPtr networkDriver;
virNodeDeviceDriverPtr nodeDeviceDriver;
virNWFilterDriverPtr nwfilterDriver;
virSecretDriverPtr secretDriver;
virStorageDriverPtr storageDriver;
};
Instead of registering the hypervisor driver, we now
just register a virConnectDriver instead. This allows
us to remove all probing of secondary drivers. Once we
have chosen the primary driver, we immediately know the
correct secondary drivers to use.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Make use of the ebtables functionality to be able to filter certain
parameters of icmpv6 packets. Extend the XML parser for icmpv6 types,
type ranges, codes, and code ranges. Extend the nwfilter documentation,
schema, and test cases.
Being able to filter icmpv6 types and codes helps extending the DHCP
snooper for IPv6 and filtering at least some parameters of IPv6's NDP
(Neighbor Discovery Protocol) packets. However, the filtering will not
be as good as the filtering of ARP packets since we cannot
check on IP addresses in the payload of the NDP packets.
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
Since virNWFilterFree will call virObjectUnref anyway, let's just use that
directly so as to avoid the possibility that we inadvertently clear out
a pending error message when using the public API.
On some places in the libvirt code we have:
f(a,z)
instead of
f(a, z)
This trivial patch fixes couple of such occurrences.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Introduced in commit 70571ccc (v1.2.4). Caught by valgrind:
==9816== 170 (32 direct, 138 indirect) bytes in 1 blocks are definitely lost in loss record 646 of 821
==9816== at 0x4A081D4: calloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==9816== by 0x50836FB: virAlloc (viralloc.c:144)
==9816== by 0x50AEC2B: virFirewallNew (virfirewall.c:204)
==9816== by 0x1E2308ED: ebiptablesDriverProbeStateMatch (nwfilter_ebiptables_driver.c:3715)
==9816== by 0x1E2309AD: ebiptablesDriverInit (nwfilter_ebiptables_driver.c:3742)
* src/nwfilter/nwfilter_ebiptables_driver.c
(ebiptablesDriverProbeStateMatch): Properly clean up.
Signed-off-by: Eric Blake <eblake@redhat.com>
Replace:
if (virBufferError(&buf)) {
virBufferFreeAndReset(&buf);
virReportOOMError();
...
}
with:
if (virBufferCheckError(&buf) < 0)
...
This should not be a functional change (unless some callers
misused the virBuffer APIs - a different error would be reported
then)
Refactor the ebiptablesTearNewRules function so that the teardown of temporary
filters can also be called by the ebiptablesAllTeardown function.
This fixes a problem that leaves temporary filters behind when a VM shuts down
while its filters are modified.
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
v1->v2:
- test cases adjusted to expect more commands
Remove all the left over code related to the direct invocation
of firewall-cmd/iptables/ip6tables/ebtables. This is all handled
by the virFirewallPtr APIs now.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Conver the ebiptablesDriverProbeStateMatch initialization
check to use the virFirewall APIs for querying iptables
version.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Convert the nwfilter ebtablesApplyNewRules method to use the
virFirewall object APIs instead of creating shell scripts
using virBuffer APIs. This provides a performance improvement
through allowing direct use of firewalld dbus APIs and will
facilitate automated testing.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Convert the nwfilter ebtablesApplyDropAllRules method to use the
virFirewall object APIs instead of creating shell scripts
using virBuffer APIs. This provides a performance improvement
through allowing direct use of firewalld dbus APIs and will
facilitate automated testing.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Convert the nwfilter ebtablesApplyDHCPOnlyRules method to use the
virFirewall object APIs instead of creating shell scripts
using virBuffer APIs. This provides a performance improvement
through allowing direct use of firewalld dbus APIs and will
facilitate automated testing.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Convert the nwfilter ebtablesApplyBasicRules method to use the
virFirewall object APIs instead of creating shell scripts
using virBuffer APIs. This provides a performance improvement
through allowing direct use of firewalld dbus APIs and will
facilitate automated testing.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Convert the nwfilter ebiptablesTearNewRules method to use the
virFirewall object APIs instead of creating shell scripts
using virBuffer APIs. This provides a performance improvement
through allowing direct use of firewalld dbus APIs and will
facilitate automated testing.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Convert the nwfilter ebtablesRemoveBasicRules method to use the
virFirewall object APIs instead of creating shell scripts
using virBuffer APIs. This provides a performance improvement
through allowing direct use of firewalld dbus APIs and will
facilitate automated testing.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Convert the nwfilter ebiptablesTearOldRules method to use the
virFirewall object APIs instead of creating shell scripts
using virBuffer APIs. This provides a performance improvement
through allowing direct use of firewalld dbus APIs and will
facilitate automated testing.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Convert the nwfilter ebiptablesAllTeardown method to use the
virFirewall object APIs instead of creating shell scripts
using virBuffer APIs. This provides a performance improvement
through allowing direct use of firewalld dbus APIs and will
facilitate automated testing.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
The nwfilter ebiptables driver will build up commands to run in
two phases. The first phase contains all of the command, except
for the '-A' part. Instead it has a '%c' placeholder, along with
a '%s' placeholder for a position arg. The second phase than
substitutes these placeholders. The only values ever used for
these substitutions though is '-A' and '', so it is entirely
pointless. Remove the second phase entirely, since it will make
it harder to convert to the new firewall APIs
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
The current nwfilter tech driver API has a 'createRuleInstance' method
which populates virNWFilterRuleInstPtr with a command line string
containing variable placeholders. The 'applyNewRules' method then
expands the variables and executes the commands. This split of
responsibility won't work when switching to the virFirewallPtr
APIs, since we can't just build up command line strings. This patch
this merges the functionality of 'createRuleInstance' into the
applyNewRules method.
The virNWFilterRuleInstPtr struct is changed from holding an array
of opaque pointers, into holding generic metadata about the rules
to be processed. In essence this is the result of taking a linked
set of virNWFilterDefPtr's and flattening the tree to get a list
of virNWFilterRuleDefPtr's. At the same time we must keep track of
any nested virNWFilterObjPtr instances, so that the locks are held
for the duration of the 'applyNewRules' method.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Later refactoring will change use of the virNWFilterRuleInstPtr struct.
Prepare for this by pushing use of the virNWFilterRuleInstPtr parameter
out of the ebtablesCreateRuleInstance and iptablesCreateRuleInstance
methods. Instead they simply string(s) with the constructed rule data.
The ebiptablesCreateRuleInstance method will make use of the
virNWFilterRuleInstPtr struct instead.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Add virNWFilterRuleIsProtocol{Ethernet,IPv4,IPv6} helper methods
to avoid having to write a giant switch statements with many cases.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
The 'displayRuleInstance' callback in the nwfilter tech driver
is never invoked, so can be deleted.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
The virNWFilterHashTable struct contains a virHashTable and
then a 'char **names' field which keeps a copy of all the
hash keys. Presumably this was intended to record the ordering
of the hash keys. No code ever uses this and the ordering is
mangled whenever a variable is removed from the hash, because
the last element in the list is copied into the middle of the
list when shrinking the array.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
The 'virDomainNetType' is unused in every impl of the
virNWFilterRuleCreateInstance driver method. Remove it
from the code to avoid the dependancy on the external
enum.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
The virNWFilterTechDriver struct is nothing to do with the nwfilter
XML configuration. It stores data specific to the driver implementation
so should be in a header in the driver directory instead.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Now that we ditched our custom pthread impl for Win32, we can
use PTHREAD_MUTEX_INITIALIZER for static mutexes. This avoids
the need to use a virOnce one-time global initializer in a
number of places.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
I almost wrote a hash value free function that just called
VIR_FREE, then realized I couldn't be the first person to
do that. Sure enough, it was worth factoring into a common
helper routine.
* src/util/virhash.h (virHashValueFree): New function.
* src/util/virhash.c (virHashValueFree): Implement it.
* src/util/virobject.h (virObjectFreeHashData): New function.
* src/libvirt_private.syms (virhash.h, virobject.h): Export them.
* src/nwfilter/nwfilter_learnipaddr.c (virNWFilterLearnInit): Use
common function.
* src/qemu/qemu_capabilities.c (virQEMUCapsCacheNew): Likewise.
* src/qemu/qemu_command.c (qemuDomainCCWAddressSetCreate):
Likewise.
* src/qemu/qemu_monitor.c (qemuMonitorGetBlockInfo): Likewise.
* src/qemu/qemu_process.c (qemuProcessWaitForMonitor): Likewise.
* src/util/virclosecallbacks.c (virCloseCallbacksNew): Likewise.
* src/util/virkeyfile.c (virKeyFileParseGroup): Likewise.
* tests/qemumonitorjsontest.c
(testQemuMonitorJSONqemuMonitorJSONGetBlockInfo): Likewise.
Signed-off-by: Eric Blake <eblake@redhat.com>
https://bugzilla.redhat.com/show_bug.cgi?id=1071181
Commit 49b59a15 fixed one problem but masks another one related to pointer
freeing.
Avoid putting of the virNWFilterSnoopReq once the thread has been started.
It belongs to the thread and the thread will call virNWFilterSnoopReqPut() on it.
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
The CMD_STOPONERR macro uses its parameter as a boolean, so should
be passed true rather than 1.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
The 'int isTempChain' parameter to various nwfilter methods
only takes two values so should be a bool type.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Many nwfilter methods have an int return value but only ever
return 0 and their callers never check the return value either.
These methods can all be void.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Many nwfilter methods have an 'int stopOnError' parameter but
with 1 exception, the callers always pass '1'. The parameter
can therefore be removed from all except one method. That method
will be changed to 'bool stopOnError'
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
A lot of methods have a 'bool incoming' parameter but then
do (incoming) ? ... : .... The round brackets here add nothing
to the code so can be removed.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Many methods in the nwfilter code have an 'int incoming' parameter
that only takes 0 or 1, so should use a bool instead.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Any source file which calls the logging APIs now needs
to have a VIR_LOG_INIT("source.name") declaration at
the start of the file. This provides a static variable
of the virLogSource type.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
The virNWFilterVarCombIterNext method will free its
parameter when it gets to the end of the iterator.
This is somewhat misleading design, making it appear
as if the caller has a memory leak. Remove the free'ing
of the parameter and ensure that the calling method
ebiptablesCreateRuleInstanceIterate free's it instead.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
The ebiptablesAddRuleInst method would leak an instance
of ebiptablesRuleInstPtr if it hit OOM when adding it
to the list of instances. Remove the pointless helper
method virNWFilterRuleInstAddData and just inline the
call to VIR_APPEND_ELEMENT and free the instance on
failure.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Thre was a syntax error in checking virRegisterStateDriver in
the remote driver, and bogus checking of a void return type
of virDomainConfNWFilterRegister in nwfilter.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Coverity found an issue in lxc_driver and uml_driver that we don't
check the return value of register functions.
I've also updated all other places and unify the way we check the
return value.
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=862887
Add a netmask for the source and destination IP address for the
ebtables --arp-ip-src and --arp-ip-dst options. Extend the XML
parser with support for XML attributes for these netmasks similar
to already supported netmasks. Extend the documentation.
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1072292
Fix a problem related to rule priorities that did not allow to
have rules applied that had a higher priority than the chain they
were in. In this case the chain did not exist yet when the rule
was instantiated. The solution is to adjust the priority of rules
if the priority of the chain is of higher value. That way the chain
will be created before the rule.
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
https://bugzilla.redhat.com/show_bug.cgi?id=1071095
Add a missing goto err_exit in the error path where an unsupported
value is assigned to the CTRL_IP_LEARNING key.
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
The nwfilter conf update mutex previously serialized
updates to the internal data structures for firewall
rules, and updates to the firewall itself. The latter
was recently turned into a read/write lock, and filter
instantiation allowed to proceed in parallel. It was
believed that this was ok, since each filter is created
on a separate iptables/ebtables chain.
It turns out that there is a subtle lock ordering problem
on virNWFilterObjPtr instances. __virNWFilterInstantiateFilter
will hold a lock on the virNWFilterObjPtr it is instantiating.
This in turn invokes virNWFilterInstantiate which then invokes
virNWFilterDetermineMissingVarsRec which then invokes
virNWFilterObjFindByName. This iterates over every single
virNWFilterObjPtr in the list, locking them and checking their
name. So if 2 or more threads try to instantiate a filter in
parallel, they'll all hold 1 lock at the top level in the
__virNWFilterInstantiateFilter method which will cause the
other thread to deadlock in virNWFilterObjFindByName.
The fix is to add an exclusive mutex to serialize the
execution of __virNWFilterInstantiateFilter.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Jenkins pointed out that the previous commit violates syntax
check when cppi is installed.
* src/nwfilter/nwfilter_dhcpsnoop.c (SNOOP_POLL_MAX_TIMEOUT_MS):
Update indentation.
Signed-off-by: Eric Blake <eblake@redhat.com>
Libpcap 1.5 requires a larger buffer than previous pcap versions.
Adjust the size of the buffer to 128kb.
This patch should address symptoms in BZ 1071181 and BZ 731059
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
Cap the poll timeout in the DHCP Snooping code to a max. of 10 seconds
to not hold up the libvirt shutdown longer than this.
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
While auditing all callers of virCommandRun, I noticed that nwfilter
code never paid attention to commands with a non-zero status; they
were merely passing a pointer to avoid spamming the logs with a
message about commands that might indeed fail. But proving this
required chasing through a lot of code; refactoring things to
localize the decision of whether to ignore non-zero status makes
it easier to prove that later changes to virFork don't negatively
affect this code.
While at it, I also noticed that ebiptablesRemoveRules would
actually report success if the child process failed for a
reason other than non-zero status, such as OOM.
* src/nwfilter/nwfilter_ebiptables_driver.c (ebiptablesExecCLI):
Change parameter from pointer to bool.
(ebtablesApplyBasicRules, ebtablesApplyDHCPOnlyRules)
(ebtablesApplyDropAllRules, ebtablesCleanAll)
(ebiptablesApplyNewRules, ebiptablesTearNewRules)
(ebiptablesTearOldRules, ebiptablesAllTeardown)
(ebiptablesDriverInitWithFirewallD)
(ebiptablesDriverTestCLITools, ebiptablesDriverProbeStateMatch):
Adjust all clients.
(ebiptablesRemoveRules): Likewise, and fix return value on failure.
Signed-off-by: Eric Blake <eblake@redhat.com>
The NWFilter code has as a deadlock race condition between
the virNWFilter{Define,Undefine} APIs and starting of guest
VMs due to mis-matched lock ordering.
In the virNWFilter{Define,Undefine} codepaths the lock ordering
is
1. nwfilter driver lock
2. virt driver lock
3. nwfilter update lock
4. domain object lock
In the VM guest startup paths the lock ordering is
1. virt driver lock
2. domain object lock
3. nwfilter update lock
As can be seen the domain object and nwfilter update locks are
not acquired in a consistent order.
The fix used is to push the nwfilter update lock upto the top
level resulting in a lock ordering for virNWFilter{Define,Undefine}
of
1. nwfilter driver lock
2. nwfilter update lock
3. virt driver lock
4. domain object lock
and VM start using
1. nwfilter update lock
2. virt driver lock
3. domain object lock
This has the effect of serializing VM startup once again, even if
no nwfilters are applied to the guest. There is also the possibility
of deadlock due to a call graph loop via virNWFilterInstantiate
and virNWFilterInstantiateFilterLate.
These two problems mean the lock must be turned into a read/write
lock instead of a plain mutex at the same time. The lock is used to
serialize changes to the "driver->nwfilters" hash, so the write lock
only needs to be held by the define/undefine methods. All other
methods can rely on a read lock which allows good concurrency.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
The VIR_WARNINGS_NO_CAST_ALIGN / VIR_WARNINGS_RESET should
not have any trailing ';' since they are pragmas. The use
of a ';' results in an empty statement which confuses CIL.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
The nwfilterStateInitialize() would only assign sysbus inside
a WITH_DBUS conditional, thus leaving a subsequent check for sysbus
and nwfilterDriverInstallDBusMatches() as a no-op
Rather than try to add WITH_DBUS conditions which ended up conflicting
with the usage of HAVE_FIREWALLD conditionals, just remove the WITH_DBUS
since virdbus.c has entry points for with and without conditions.
Most of our code base uses space after comma but not before;
fix the remaining uses before adding a syntax check.
* src/nwfilter/nwfilter_ebiptables_driver.c: Consistently use
commas.
* src/nwfilter/nwfilter_gentech_driver.c: Likewise.
* src/nwfilter/nwfilter_learnipaddr.c: Likewise.
* src/conf/nwfilter_conf.c: Likewise.
Signed-off-by: Eric Blake <eblake@redhat.com>
When opening a new connection to the driver, nwfilterOpen
only succeeds if the driverState has been allocated.
Move the privilege check in driver initialization before
the state allocation to disable the driver.
This changes the nwfilter-define error from:
error: cannot create config directory (null): Bad address
To:
this function is not supported by the connection driver:
virNWFilterDefineXML
https://bugzilla.redhat.com/show_bug.cgi?id=1029266
'const fooPtr' is the same as 'foo * const' (the pointer won't
change, but it's contents can). But in general, if an interface
is trying to be const-correct, it should be using 'const foo *'
(the pointer is to data that can't be changed).
Fix up offenders in nwfilter code.
This patch does nothing about the stupidity evident in having
__virNWFilterInstantiateFilter, _virNWFilterInstantiateFilter,
and virNWFilterInstantiateFilter, which differ only by leading
underscores, and which infringes on the namespace reserved to
the implementation - that would need to be a separate cleanup.
* src/nwfilter/nwfilter_dhcpsnoop.h (virNWFilterDHCPSnoopReq): Use
intended type.
* src/nwfilter/nwfilter_gentech_driver.h
(virNWFilterInstantiateFilter)
(virNWFilterUpdateInstantiateFilter)
(virNWFilterInstantiataeFilterLate, virNWFilterTeardownFilter)
(virNWFilterCreateVarHashmap): Likewise.
* src/nwfilter/nwfilter_learnipaddr.h (virNWFilterLearnIPAddress):
Likewise.
* src/conf/nwfilter_conf.h (virNWFilterApplyBasicRules)
(virNWFilterApplyDHCPOnlyRules): Likewise.
(virNWFilterDefFormat): Make const-correct.
* src/conf/nwfilter_params.h (virNWFilterVarValueCopy)
(virNWFilterVarValueGetSimple, virNWFilterVarValueGetCardinality)
(virNWFilterVarValueEqual, virNWFilterVarAccessEqual)
(virNWFilterVarAccessGetVarName, virNWFilterVarAccessGetType)
(virNWFilterVarAccessGetIterId, virNWFilterVarAccessGetIndex)
(virNWFilterVarAccessIsAvailable)
(virNWFilterVarCombIterGetVarValue): Use intended type.
(virNWFilterVarValueGetNthValue): Make const-correct.
* src/nwfilter/nwfilter_dhcpsnoop.c (virNWFilterSnoopReqLeaseDel)
(virNWFilterSnoopIFKeyFMT, virNWFilterDHCPSnoopReq)
(virNWFilterSnoopPruneIter, virNWFilterSnoopRemAllReqIter)
(virNWFilterDHCPSnoopReq): Fix fallout.
* src/nwfilter/nwfilter_gentech_driver.c
(virNWFilterVarHashmapAddStdValues, virNWFilterCreateVarHashmap)
(virNWFilterInstantiate, __virNWFilterInstantiateFilter)
(_virNWFilterInstantiateFilter, virNWFilterInstantiateFilterLate)
(virNWFilterInstantiateFilter)
(virNWFilterUpdateInstantiateFilter)
(virNWFilterRollbackUpdateFilter, virNWFilterTeardownFilter):
Likewise.
* src/nwfilter/nwfilter_learnipaddr.c (virNWFilterLearnIPAddress):
Likewise.
* src/conf/nwfilter_params.c (virNWFilterVarValueCopy)
(virNWFilterVarValueGetSimple)
(virNWFilterVarValueGetCardinality, virNWFilterVarValueEqual)
(virNWFilterVarCombIterAddVariable)
(virNWFilterVarCombIterGetVarValue, virNWFilterVarValueCompare)
(virNWFilterFormatParamAttributes, virNWFilterVarAccessEqual)
(virNWFilterVarAccessGetVarName, virNWFilterVarAccessGetType)
(virNWFilterVarAccessGetIterId, virNWFilterVarAccessGetIndex)
(virNWFilterVarAccessGetIntIterId)
(virNWFilterVarAccessIsAvailable)
(virNWFilterVarValueGetNthValue): Likewise.
* src/nwfilter/nwfilter_ebiptables_driver.c (ebtablesApplyBasicRules)
(ebtablesApplyDHCPOnlyRules, ebiptablesRuleOrderSort)
(ebiptablesRuleOrderSortPtr): Likewise.
* src/conf/nwfilter_conf.c (virNWFilterDefEqual)
(virNWFilterDefFormat): Likewise.
Signed-off-by: Eric Blake <eblake@redhat.com>
'const fooPtr' is the same as 'foo * const' (the pointer won't
change, but it's contents can). But in general, if an interface
is trying to be const-correct, it should be using 'const foo *'
(the pointer is to data that can't be changed).
Fix up virhash to provide a const-correct interface: all actions
that don't modify the table take a const table. Note that in
one case (virHashSearch), we actually strip const away - we aren't
modifying the contents of the table, so much as associated data
for ensuring that the code uses the table correctly (if this were
C++, it would be a case for the 'mutable' keyword).
* src/util/virhash.h (virHashKeyComparator, virHashEqual): Use
intended type.
(virHashSize, virHashTableSize, virHashLookup, virHashSearch):
Make const-correct.
* src/util/virhash.c (virHashEqualData, virHashEqual)
(virHashLookup, virHashSize, virHashTableSize, virHashSearch)
(virHashComputeKey): Fix fallout.
* src/conf/nwfilter_params.c
(virNWFilterFormatParameterNameSorter): Likewise.
* src/nwfilter/nwfilter_ebiptables_driver.c
(ebiptablesFilterOrderSort): Likewise.
* tests/virhashtest.c (testHashGetItemsCompKey)
(testHashGetItemsCompValue): Likewise.
Signed-off-by: Eric Blake <eblake@redhat.com>
Previous commit
commit 7ada155cdf
Author: Gao feng <gaofeng@cn.fujitsu.com>
Date: Wed Sep 11 11:15:02 2013 +0800
DBus: introduce virDBusIsServiceEnabled
Made the cgroups code fallback to non-systemd based setup
when dbus is not running. It was too big a hammer though,
as it did not check what error code was received when the
dbus connection failed. Thus it silently ignored serious
errors from dbus such as "too many client connections",
which should always be treated as fatal.
We only want to ignore errors if the dbus unix socket does
not exist, or if nothing is listening on it.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
The virConnectPtr is passed around loads of nwfilter code in
order to provide it as a parameter to the callback registered
by the virt drivers. None of the virt drivers use this param
though, so it serves no purpose.
Avoiding the need to pass a virConnectPtr means that the
nwfilterStateReload method no longer needs to open a bogus
QEMU driver connection. This addresses a race condition that
can lead to a crash on startup.
The nwfilter driver starts before the QEMU driver and registers
some callbacks with DBus to detect firewalld reload. If the
firewalld reload happens while the QEMU driver is still starting
up though, the nwfilterStateReload method will open a connection
to the partially initialized QEMU driver and cause a crash.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
The nwfilter driver only needs a reference to its private
state object, not a full virConnectPtr. Update the domUpdateCBStruct
struct to have a 'void *opaque' field instead of a virConnectPtr.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
The VIR_FREE() macro will cast away any const-ness. This masked a
number of places where we passed a 'const char *' string to
VIR_FREE. Fortunately in all of these cases, the variable was not
in fact const data, but a heap allocated string. Fix all the
variable declarations to reflect this.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
When the daemon is compiled with firewalld support but the DBus message
bus isn't started in the system, the initialization of the nwfilter
driver fails even if there are fallback options.
Since iptables version 1.4.16 '-m state --state NEW' is converted to
'-m conntrack --ctstate NEW'. Therefore, when encountering this or later
versions of iptables use '-m conntrack --ctstate'.
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Ensure that all APIs which list nwfilter objects filter
them against the access control system.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
This patch is in relation to Bug 966449:
https://bugzilla.redhat.com/show_bug.cgi?id=966449
This is a patch addressing the coredump.
Thread 1 must be calling nwfilterDriverRemoveDBusMatches(). It does so with
nwfilterDriverLock held. In the patch below I am now moving the
nwfilterDriverLock(driverState) further up so that the initialization, which
seems to either take a long time or is entirely stuck, occurs with the lock
held and the shutdown cannot occur at the same time.
Remove the lock in virNWFilterDriverIsWatchingFirewallD to avoid
double-locking.
https://bugzilla.redhat.com/show_bug.cgi?id=903480
During domain destruction it's possible that the learnIPAddressThread has
already removed the interface prior to the teardown filter path being run.
The teardown code would only be telling the thread to terminate.
Remove error reporting when calling the virNWFilterDHCPSnoopEnd
function with an interface for which no thread is snooping traffic.
Document the usage of this function.
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
Linux netfilter at some point (Linux 2.6.39) inverted the meaning of the
'--ctdir reply' and newer netfilter implementations now expect
'--ctdir original' instead and vice-versa.
We check for the kernel version and assume that all Linux kernels with version
2.6.39 have the newer inverted logic.
Any distro backporting the Linux kernel patch that inverts the --ctdir logic
(Linux commit 96120d86f) must also backport this patch for Linux and
adapt the kernel version being tested for.
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
The source code base needs to be adapted as well. Some files
include virutil.h just for the string related functions (here,
the include is substituted to match the new file), some include
virutil.h without any need (here, the include is removed), and
some require both.
Ensure that all drivers implementing public APIs use a
naming convention for their implementation that matches
the public API name.
eg for the public API virDomainCreate make sure QEMU
uses qemuDomainCreate and not qemuDomainStart
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
It will simplify later work if the sub-drivers have dedicated
APIs / field names. ie virNetworkDriver should have
virDrvNetworkOpen and virDrvNetworkClose methods
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Ensure that the driver struct field names match the public
API names. For an API virXXXX we must have a driver struct
field xXXXX. ie strip the leading 'vir' and lowercase any
leading uppercase letters.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
There are a number of places which generate cast alignment
warnings, which are difficult or impossible to address. Use
pragmas to disable the warnings in these few places
conf/nwfilter_conf.c: In function 'virNWFilterRuleDetailsParse':
conf/nwfilter_conf.c:1806:16: warning: cast increases required alignment of target type [-Wcast-align]
item = (nwItemDesc *)((char *)nwf + att[idx].dataIdx);
conf/nwfilter_conf.c: In function 'virNWFilterRuleDefDetailsFormat':
conf/nwfilter_conf.c:3238:16: warning: cast increases required alignment of target type [-Wcast-align]
item = (nwItemDesc *)((char *)def + att[i].dataIdx);
storage/storage_backend_mpath.c: In function 'virStorageBackendCreateVols':
storage/storage_backend_mpath.c:247:17: warning: cast increases required alignment of target type [-Wcast-align]
names = (struct dm_names *)(((char *)names) + next);
nwfilter/nwfilter_dhcpsnoop.c: In function 'virNWFilterSnoopDHCPDecode':
nwfilter/nwfilter_dhcpsnoop.c:994:15: warning: cast increases required alignment of target type [-Wcast-align]
pip = (struct iphdr *) pep->eh_data;
nwfilter/nwfilter_dhcpsnoop.c:1004:11: warning: cast increases required alignment of target type [-Wcast-align]
pup = (struct udphdr *) ((char *) pip + (pip->ihl << 2));
nwfilter/nwfilter_learnipaddr.c: In function 'procDHCPOpts':
nwfilter/nwfilter_learnipaddr.c:327:33: warning: cast increases required alignment of target type [-Wcast-align]
uint32_t *tmp = (uint32_t *)&dhcpopt->value;
nwfilter/nwfilter_learnipaddr.c: In function 'learnIPAddressThread':
nwfilter/nwfilter_learnipaddr.c:501:43: warning: cast increases required alignment of target type [-Wcast-align]
struct iphdr *iphdr = (struct iphdr*)(packet +
nwfilter/nwfilter_learnipaddr.c:538:43: warning: cast increases required alignment of target type [-Wcast-align]
struct iphdr *iphdr = (struct iphdr*)(packet +
nwfilter/nwfilter_learnipaddr.c:544:48: warning: cast increases required alignment of target type [-Wcast-align]
struct udphdr *udphdr= (struct udphdr *)
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Between revision 65fb9d49 and before this patch, an upgrade of libvirt while
VMs are running and instantiating iptables filtering rules due to nwfilter
rules, may leave stray iptables rules behind when shutting VMs down.
Left-over iptables rules may look like this:
Chain FP-vnet0 (1 references)
target prot opt source destination
DROP tcp -- 0.0.0.0/0 0.0.0.0/0 tcp spt:122
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
[...]
Chain libvirt-out (1 references)
target prot opt source destination
FO-vnet0 all -- 0.0.0.0/0 0.0.0.0/0 [goto] PHYSDEV match --physdev-out vnet0
The reason is that the recent nwfilter code only removed filtering rules in
the libvirt-out chain that contain the --physdev-is-bridged parameter.
Older rules didn't match and were not removed.
Note that the user-defined chain FO-vnet0 could not be removed due to the
reference from the rule in libvirt-out.
Often the work around may be done through
service iptables restart
kill -SIGHUP $(pidof libvirtd)
This patch now also removes older libvirt versions' iptables rules.
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
As a step towards making virDomainObjList thread-safe turn it
into an opaque virObject, preventing any direct access to its
internals.
As part of this a new method virDomainObjListForEach is
introduced to replace all existing usage of virHashForEach
Although the nwfilter driver skips startup when running in a
session libvirtd, it did not skip reload or shutdown. This
caused errors to be reported when sending SIGHUP to libvirtd,
and caused an abort() in libdbus on shutdown due to trying
to remove a dbus filter that was never added
When starting a VM, /var/log/messages was spammed with the following message:
xt_physdev: using --physdev-out in the OUTPUT, FORWARD and POSTROUTING chains for non-bridged traffic is not supported anymore.
With each extra VM I start, the messages get amplified
exponentially. This results in longer starting times every new VM,
relative the the previously started VM. When I ran a test with
starting 100 equal VM's, the first VM started in about 2 seconds, the
100th VM took 48 seconds to start. I'm running a vanilla 3.7.1 kernel,
but I have the same issue on VM hosts with kernel 3.2.28 or 3.2.0,
running libvirt 0.9.12 and 0.9.8 respectively.
Looking into the warning, it seemed that iptables need an extra argument,
--physdev-is-bridged, in commands like:
iptables -A libvirt-out -m physdev --physdev-is-bridged --physdev-out vnet99 -g FP-vnet99
With that, the warnings in /var/log/messages are gone and running the
test again proved the 100th VM started in 3.8 seconds.
The virDomainObj, qemuAgent, qemuMonitor, lxcMonitor classes
all require a mutex, so can be switched to use virObjectLockable
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Currently to deal with auto-shutdown libvirtd must periodically
poll all stateful drivers. Thus sucks because it requires
acquiring both the driver lock and locks on every single virtual
machine. Instead pass in a "inhibit" callback to virStateInitialize
which drivers can invoke whenever they want to inhibit shutdown
due to existance of active VMs.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
The only important state that should prevent libvirtd shutdown
is from running VMs. Networks, host devices, network filters
and storage pools are all long lived resources that have no
significant in-memory state. They should not block shutdown.
Also removed some unreachable code found by coverity:
libvirt-0.10.2/src/nwfilter/nwfilter_driver.c:259: unreachable: This
code cannot be reached: "nwfilterDriverUnlock(driver...".
The virStateInitialize method and several cgroups methods were
using an 'int privileged' parameter or similar for dual-state
values. These are better represented with the bool type.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Commit cb022152 went overboard and introduced a dead conditional
while trying to get rid of a potential NULL dereference.
* src/nwfilter/nwfilter_dhcpsnoop.c (virNWFilterSnoopReqNew):
Remove redundant conditional.
This can't lead to a crash since virNWFilterSnoopReqNew is only called
with a static array as the argument, but if we check for NULL we should
do it right.
The libvirt coding standard is to use 'function(...args...)'
instead of 'function (...args...)'. A non-trivial number of
places did not follow this rule and are fixed in this patch.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
https://www.gnu.org/licenses/gpl-howto.html recommends that
the 'If not, see <url>.' phrase be a separate sentence.
* tests/securityselinuxhelper.c: Remove doubled line.
* tests/securityselinuxtest.c: Likewise.
* globally: s/; If/. If/
virNWFilterSnoopAdjustPoll() uses a struct pollfd but poll.h is never included
nwfilter/nwfilter_dhcpsnoop.c:1297: error: 'struct pollfd' declared inside parameter list
Commit 2a41bc9 dropped a dependency on gawk, but we can go one step
further and avoid awk altogether.
* src/nwfilter/nwfilter_ebiptables_driver.c
(iptablesLinkIPTablesBaseChain): Simplify command.
(ebiptablesDriverInit, ebiptablesDriverShutdown): Drop awk probe.
FreeBSD and OpenBSD have a <net/if.h> that is not self-contained;
and mingw lacks the header altogether. But gnulib has just taken
care of that for us, so we might as well simplify our code. In
the process, I got a syntax-check failure if we don't also take
the gnulib execinfo module.
* .gnulib: Update to latest, for execinfo and net_if.
* bootstrap.conf (gnulib_modules): Add execinfo and net_if modules.
* configure.ac: Let gnulib check for headers. Simplify check for
'struct ifreq', while also including enough prereq headers.
* src/internal.h (IF_NAMESIZE): Drop, now that gnulib guarantees it.
* src/nwfilter/nwfilter_learnipaddr.h: Use correct header for
IF_NAMESIZE.
* src/util/virnetdev.c (includes): Assume <net/if.h> exists.
* src/util/virnetdevbridge.c (includes): Likewise.
* src/util/virnetdevtap.c (includes): Likewise.
* src/util/logging.c (includes): Assume <execinfo.h> exists.
(virLogStackTraceToFd): Handle gnulib's fallback implementation.
Some DHCP servers send their DHCP replies to the broadcast MAC address
rather than to the MAC address of the VM. The existing DHCP snooping
code assumes that the reply always goes to the MAC address of the VM
thus filtering the traffic of some DHCP servers' replies.
The below patch adapts the code to
1) filter DHCP replies by comparing the MAC address in the reply against
the MAC address of the VM (held in the snoop request)
2) adapts the pcap filter for traffic towards the VM to accept DHCP replies
sent to any MAC address; for further filtering we rely on 1)
3) creates initial rules that are active while waiting for DHCP replies;
these rules now accept DHCP replies to the VM's MAC address or to the
MAC broadcast address
The loop processing the trusted DHCP server generated one too
many rules and added one final rules that accepted responses
from all DHCP servers. Below patch fixes this.