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