[libvirt] [PATCH 1/4] nwfilter: add nwfilter hash
Nikolay Shirokovskiy
nshirokovskiy at virtuozzo.com
Mon Oct 22 07:11:11 UTC 2018
On 19.10.2018 18:33, Laine Stump wrote:
> On 10/18/18 2:49 AM, Nikolay Shirokovskiy wrote:
>> For filter without references to other filters hash is just sha-256 of filter's
>> xml. For filters with references hash is sha-256 of string consisting of
>> filter's self hash and hashes of directly referenced filters.
>
>
> I didn't read the entire patch, but if you're just comparing hashes of
> the filters' XML, then you aren't actually checking to see if *someone
> else* outside libvirt has modified the actual rules in ebtables/iptables
> (and someday not *too* far away nbtables, or maybe firewalld "rich
> rules"). That is the really important thing we need to check for. One of
> the reasons for a libvirtd restart to delete and reload all the rules is
> to clean up after some third party has "moved our cheese" and our filter
> rules no longer work as expected, and just checking that our own
> internal data is unchanged doesn't help that problem.
Agree. I mentioned the same issue in the cover letter. Need to rework
series)
>
>
> (BTW, on a slightly related topic - since I've lately been thinking
> about making libvirt work properly on systems with nbtables and in
> particular firewalld with an nbtables backend, I've been wondering if
> our whole model of "deleting old rules" based on our current idea of the
> libvirt xml ==> eb/iptables backend isn't improper. Maybe we should be
> saving the actual rules that we sent out in the status, and undoing
> those. The rules we need to delete could be *very* different from what
> the new libvirtd is generating (e.g. we decided we didn't need one of
> the rules anymore so it's no longer generated, or we're now using
> nbtables/ebpf/sub-etha-senso-tables or whatever).
The approach of not keeping firewall rules status is that libvirt keeps
all rules in 4 chains: libvirt-O-$IFACE, libvirt-I-$IFACE, libvirt-J-$IFACE,
libvirt-O-$IFACE (the last two are temporary) and their subchains. This
names are fixed so we can always cleanup all rules installed by libvirt.
Not sure of nbtables though - can we clean chains installed thru iptables/ebtables
thru nbtables.
Nikolay
>
>
>>
>> If filter is not complete that is some of filters it's referencing directly or
>> indirectly are missing the hash is set to NULL as well as if there was OOM on
>> hash caculation. So having NULL hash is regular situation.
>>
>> Signed-off-by: Nikolay Shirokovskiy <nshirokovskiy at virtuozzo.com>
>> ---
>> src/conf/virnwfilterobj.c | 145 +++++++++++++++++++++++++++++++++
>> src/conf/virnwfilterobj.h | 9 ++
>> src/libvirt_private.syms | 3 +
>> src/nwfilter/nwfilter_driver.c | 3 +
>> src/nwfilter/nwfilter_gentech_driver.c | 2 +
>> 5 files changed, 162 insertions(+)
>>
>> diff --git a/src/conf/virnwfilterobj.c b/src/conf/virnwfilterobj.c
>> index 0136a0d..4cc81df 100644
>> --- a/src/conf/virnwfilterobj.c
>> +++ b/src/conf/virnwfilterobj.c
>> @@ -28,6 +28,7 @@
>> #include "virlog.h"
>> #include "virnwfilterobj.h"
>> #include "virstring.h"
>> +#include "vircrypto.h"
>>
>> #define VIR_FROM_THIS VIR_FROM_NWFILTER
>>
>> @@ -40,6 +41,8 @@ struct _virNWFilterObj {
>>
>> virNWFilterDefPtr def;
>> virNWFilterDefPtr newDef;
>> +
>> + char *hash;
>> };
>>
>> struct _virNWFilterObjList {
>> @@ -82,6 +85,13 @@ virNWFilterObjGetNewDef(virNWFilterObjPtr obj)
>> }
>>
>>
>> +char*
>> +virNWFilterObjGetHash(virNWFilterObjPtr obj)
>> +{
>> + return obj->hash;
>> +}
>> +
>> +
>> bool
>> virNWFilterObjWantRemoved(virNWFilterObjPtr obj)
>> {
>> @@ -307,6 +317,139 @@ virNWFilterDefEqual(const virNWFilterDef *def1,
>> }
>>
>>
>> +static void
>> +virNWFilterObjInvalidateHash(virNWFilterObjListPtr nwfilters,
>> + virNWFilterObjPtr obj)
>> +{
>> + virNWFilterDefPtr def = obj->def;
>> + size_t i;
>> +
>> + if (!obj->hash)
>> + return;
>> +
>> + if (obj->newDef) {
>> + VIR_FREE(obj->hash);
>> + return;
>> + }
>> +
>> + for (i = 0; i < def->nentries; i++) {
>> + virNWFilterObjPtr child;
>> + char *filterref;
>> +
>> + if (def->filterEntries[i]->rule ||
>> + !def->filterEntries[i]->include)
>> + continue;
>> +
>> + filterref = def->filterEntries[i]->include->filterref;
>> +
>> + if (!(child = virNWFilterObjListFindByName(nwfilters, filterref))) {
>> + VIR_FREE(obj->hash);
>> + return;
>> + }
>> +
>> + virNWFilterObjInvalidateHash(nwfilters, child);
>> +
>> + if (!child->hash) {
>> + VIR_FREE(obj->hash);
>> + virNWFilterObjUnlock(child);
>> + return;
>> + }
>> +
>> + virNWFilterObjUnlock(child);
>> + }
>> +}
>> +
>> +
>> +void
>> +virNWFilterObjListInvalidateHash(virNWFilterObjListPtr nwfilters)
>> +{
>> + size_t i;
>> + virNWFilterObjPtr obj;
>> +
>> + for (i = 0; i < nwfilters->count; i++) {
>> + obj = nwfilters->objs[i];
>> + virNWFilterObjLock(obj);
>> + virNWFilterObjInvalidateHash(nwfilters, obj);
>> + virNWFilterObjUnlock(obj);
>> + }
>> +}
>> +
>> +
>> +static void
>> +virNWFilterObjUpdateHash(virNWFilterObjListPtr nwfilters,
>> + virNWFilterObjPtr obj)
>> +{
>> + virNWFilterDefPtr def = obj->newDef ? obj->newDef : obj->def;
>> + size_t i;
>> + char *hash;
>> + char *xml;
>> + virBuffer buf = VIR_BUFFER_INITIALIZER;
>> +
>> + if (obj->hash)
>> + return;
>> +
>> + if (!(xml = virNWFilterDefFormat(def)))
>> + return;
>> +
>> + if (virCryptoHashString(VIR_CRYPTO_HASH_SHA256, xml, &hash))
>> + goto cleanup;
>> +
>> + virBufferAsprintf(&buf, "%s\n", hash);
>> + VIR_FREE(hash);
>> +
>> + for (i = 0; i < def->nentries; i++) {
>> + char *filterref;
>> + virNWFilterObjPtr child;
>> +
>> + if (def->filterEntries[i]->rule ||
>> + !def->filterEntries[i]->include)
>> + continue;
>> +
>> + filterref = def->filterEntries[i]->include->filterref;
>> +
>> + if (!(child = virNWFilterObjListFindByName(nwfilters, filterref)))
>> + goto cleanup;
>> +
>> + virNWFilterObjUpdateHash(nwfilters, child);
>> +
>> + if (!child->hash) {
>> + virNWFilterObjUnlock(child);
>> + goto cleanup;
>> + }
>> +
>> + virBufferAsprintf(&buf, "%s\n", child->hash);
>> +
>> + virNWFilterObjUnlock(child);
>> + }
>> +
>> + if (virBufferCheckError(&buf) < 0)
>> + goto cleanup;
>> +
>> + hash = virBufferContentAndReset(&buf);
>> + ignore_value(virCryptoHashString(VIR_CRYPTO_HASH_SHA256, hash, &obj->hash));
>> + VIR_FREE(hash);
>> +
>> + cleanup:
>> + virBufferFreeAndReset(&buf);
>> + VIR_FREE(xml);
>> +}
>> +
>> +
>> +void
>> +virNWFilterObjListUpdateHash(virNWFilterObjListPtr nwfilters)
>> +{
>> + size_t i;
>> + virNWFilterObjPtr obj;
>> +
>> + for (i = 0; i < nwfilters->count; i++) {
>> + obj = nwfilters->objs[i];
>> + virNWFilterObjLock(obj);
>> + virNWFilterObjUpdateHash(nwfilters, obj);
>> + virNWFilterObjUnlock(obj);
>> + }
>> +}
>> +
>> +
>> virNWFilterObjPtr
>> virNWFilterObjListAssignDef(virNWFilterObjListPtr nwfilters,
>> virNWFilterDefPtr def)
>> @@ -555,6 +698,8 @@ virNWFilterObjListLoadAllConfigs(virNWFilterObjListPtr nwfilters,
>> virNWFilterObjUnlock(obj);
>> }
>>
>> + virNWFilterObjListUpdateHash(nwfilters);
>> +
>> VIR_DIR_CLOSE(dir);
>> return ret;
>> }
>> diff --git a/src/conf/virnwfilterobj.h b/src/conf/virnwfilterobj.h
>> index 4a54dd5..1c41a3e 100644
>> --- a/src/conf/virnwfilterobj.h
>> +++ b/src/conf/virnwfilterobj.h
>> @@ -50,6 +50,9 @@ virNWFilterObjGetDef(virNWFilterObjPtr obj);
>> virNWFilterDefPtr
>> virNWFilterObjGetNewDef(virNWFilterObjPtr obj);
>>
>> +char*
>> +virNWFilterObjGetHash(virNWFilterObjPtr obj);
>> +
>> bool
>> virNWFilterObjWantRemoved(virNWFilterObjPtr obj);
>>
>> @@ -114,4 +117,10 @@ virNWFilterObjLock(virNWFilterObjPtr obj);
>> void
>> virNWFilterObjUnlock(virNWFilterObjPtr obj);
>>
>> +void
>> +virNWFilterObjListInvalidateHash(virNWFilterObjListPtr nwfilters);
>> +
>> +void
>> +virNWFilterObjListUpdateHash(virNWFilterObjListPtr nwfilters);
>> +
>> #endif /* VIRNWFILTEROBJ_H */
>> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
>> index 335210c..a7cfe80 100644
>> --- a/src/libvirt_private.syms
>> +++ b/src/libvirt_private.syms
>> @@ -1077,6 +1077,7 @@ virNWFilterBindingObjListRemove;
>>
>> # conf/virnwfilterobj.h
>> virNWFilterObjGetDef;
>> +virNWFilterObjGetHash;
>> virNWFilterObjGetNewDef;
>> virNWFilterObjListAssignDef;
>> virNWFilterObjListExport;
>> @@ -1085,10 +1086,12 @@ virNWFilterObjListFindByUUID;
>> virNWFilterObjListFindInstantiateFilter;
>> virNWFilterObjListFree;
>> virNWFilterObjListGetNames;
>> +virNWFilterObjListInvalidateHash;
>> virNWFilterObjListLoadAllConfigs;
>> virNWFilterObjListNew;
>> virNWFilterObjListNumOfNWFilters;
>> virNWFilterObjListRemove;
>> +virNWFilterObjListUpdateHash;
>> virNWFilterObjLock;
>> virNWFilterObjTestUnassignDef;
>> virNWFilterObjUnlock;
>> diff --git a/src/nwfilter/nwfilter_driver.c b/src/nwfilter/nwfilter_driver.c
>> index 1ab906f..5591c0b 100644
>> --- a/src/nwfilter/nwfilter_driver.c
>> +++ b/src/nwfilter/nwfilter_driver.c
>> @@ -570,6 +570,8 @@ nwfilterDefineXML(virConnectPtr conn,
>> def = NULL;
>> objdef = virNWFilterObjGetDef(obj);
>>
>> + virNWFilterObjListUpdateHash(driver->nwfilters);
>> +
>> if (virNWFilterSaveConfig(driver->configDir, objdef) < 0) {
>> virNWFilterObjListRemove(driver->nwfilters, obj);
>> goto cleanup;
>> @@ -616,6 +618,7 @@ nwfilterUndefine(virNWFilterPtr nwfilter)
>> goto cleanup;
>>
>> virNWFilterObjListRemove(driver->nwfilters, obj);
>> + virNWFilterObjListInvalidateHash(driver->nwfilters);
>> obj = NULL;
>> ret = 0;
>>
>> diff --git a/src/nwfilter/nwfilter_gentech_driver.c b/src/nwfilter/nwfilter_gentech_driver.c
>> index e5dea91..d64621b 100644
>> --- a/src/nwfilter/nwfilter_gentech_driver.c
>> +++ b/src/nwfilter/nwfilter_gentech_driver.c
>> @@ -1066,6 +1066,8 @@ virNWFilterBuildAll(virNWFilterDriverStatePtr driver,
>> virNWFilterBuildIter,
>> &data);
>> } else {
>> + virNWFilterObjListInvalidateHash(driver->nwfilters);
>> + virNWFilterObjListUpdateHash(driver->nwfilters);
>> data.step = STEP_SWITCH;
>> virNWFilterBindingObjListForEach(driver->bindings,
>> virNWFilterBuildIter,
>
>
More information about the libvir-list
mailing list