99cbc7
From 4f042ede2b84b5f6bdf8a36e0768462816f2c9b1 Mon Sep 17 00:00:00 2001
99cbc7
Message-Id: <4f042ede2b84b5f6bdf8a36e0768462816f2c9b1@dist-git>
99cbc7
From: John Ferlan <jferlan@redhat.com>
99cbc7
Date: Thu, 26 Jul 2018 09:39:32 -0400
99cbc7
Subject: [PATCH] nwfilter: Resolve SEGV for NWFilter Snoop processing
99cbc7
99cbc7
https://bugzilla.redhat.com/show_bug.cgi?id=1599973
99cbc7
99cbc7
Commit id fca9afa08 changed the @req->ifname to use
99cbc7
@req->binding->portdevname fillingin the @req->binding
99cbc7
in a similar way that @req->ifname would have been
99cbc7
filled in during virNWFilterDHCPSnoopReq processing.
99cbc7
99cbc7
However, in doing so it did not take into account some
99cbc7
code paths where the @req->binding should be checked
99cbc7
instead of @req->binding->portdevname. These checks
99cbc7
led to SEGVs in some cases during libvirtd reload
99cbc7
processing in virNWFilterSnoopRemAllReqIter (for
99cbc7
stop during nwfilterStateCleanup processing) and
99cbc7
virNWFilterSnoopReqLeaseDel (for start during
99cbc7
nwfilterStateInitialize processing).
99cbc7
99cbc7
In particular, when reading the nwfilter.leases file
99cbc7
a new @req is created, but the @req->binding is not
99cbc7
filled in. That's left to virNWFilterDHCPSnoopReq
99cbc7
processing which checks if the @req already exists
99cbc7
in the @virNWFilterSnoopState.snoopReqs hash table
99cbc7
after adding a virNWFilterSnoopState.ifnameToKey
99cbc7
entry for the @req->binding->portdevname by a
99cbc7
@ref->ikey value.
99cbc7
99cbc7
NB: virNWFilterSnoopIPLeaseInstallRule and
99cbc7
    virNWFilterDHCPSnoopThread do not need the
99cbc7
    req->binding check since they can only be called
99cbc7
    after the filter->binding is created/assigned.
99cbc7
99cbc7
Signed-off-by: John Ferlan <jferlan@redhat.com>
99cbc7
ACKed-by: Michal Privoznik <mprivozn@redhat.com>
99cbc7
(cherry picked from commit 5229494b01acf97dbc6f3028e9718667e9e1426a)
99cbc7
Reviewed-by: Erik Skultety <eskultet@redhat.com>
99cbc7
---
99cbc7
 src/nwfilter/nwfilter_dhcpsnoop.c | 7 ++++---
99cbc7
 1 file changed, 4 insertions(+), 3 deletions(-)
99cbc7
99cbc7
diff --git a/src/nwfilter/nwfilter_dhcpsnoop.c b/src/nwfilter/nwfilter_dhcpsnoop.c
99cbc7
index 533c45f080..2ae134ed19 100644
99cbc7
--- a/src/nwfilter/nwfilter_dhcpsnoop.c
99cbc7
+++ b/src/nwfilter/nwfilter_dhcpsnoop.c
99cbc7
@@ -846,7 +846,7 @@ virNWFilterSnoopReqLeaseDel(virNWFilterSnoopReqPtr req,
99cbc7
     int ret = 0;
99cbc7
     virNWFilterSnoopIPLeasePtr ipl;
99cbc7
     char *ipstr = NULL;
99cbc7
-    int ipAddrLeft;
99cbc7
+    int ipAddrLeft = 0;
99cbc7
 
99cbc7
     /* protect req->start, req->ifname and the lease */
99cbc7
     virNWFilterSnoopReqLock(req);
99cbc7
@@ -867,7 +867,8 @@ virNWFilterSnoopReqLeaseDel(virNWFilterSnoopReqPtr req,
99cbc7
     if (update_leasefile)
99cbc7
         virNWFilterSnoopLeaseFileSave(ipl);
99cbc7
 
99cbc7
-    ipAddrLeft = virNWFilterIPAddrMapDelIPAddr(req->binding->portdevname, ipstr);
99cbc7
+    if (req->binding)
99cbc7
+        ipAddrLeft = virNWFilterIPAddrMapDelIPAddr(req->binding->portdevname, ipstr);
99cbc7
 
99cbc7
     if (!req->threadkey || !instantiate)
99cbc7
         goto skip_instantiate;
99cbc7
@@ -2037,7 +2038,7 @@ virNWFilterSnoopRemAllReqIter(const void *payload,
99cbc7
     /* protect req->binding->portdevname */
99cbc7
     virNWFilterSnoopReqLock(req);
99cbc7
 
99cbc7
-    if (req->binding->portdevname) {
99cbc7
+    if (req->binding && req->binding->portdevname) {
99cbc7
         ignore_value(virHashRemoveEntry(virNWFilterSnoopState.ifnameToKey,
99cbc7
                                         req->binding->portdevname));
99cbc7
 
99cbc7
-- 
99cbc7
2.18.0
99cbc7