diff mbox series

[ovs-dev] netdev-linux: Fix segfault in update_lag().

Message ID 1530815087-164740-1-git-send-email-tiago.lam@intel.com
State Accepted
Headers show
Series [ovs-dev] netdev-linux: Fix segfault in update_lag(). | expand

Commit Message

Lam, Tiago July 5, 2018, 6:24 p.m. UTC
A bissect shows that commit d22f892 ("netdev-linux: monitor and offload
LAG slaves to TC") introduced netdev_linux_update_lag(), which is now
triggering a crash in the "datapath - ping over bond" test in
system-userspace-testsuite:

  (gdb) bt
  #0  0x00000000009762e7 in netdev_linux_update_lag (change=0x7ffdff013750) at lib/netdev-linux.c:728
  728                 if (is_netdev_linux_class(master_netdev->netdev_class)) {

This fixes the crash by simply returning in case netdev_from_name()
returns NULL, as this should indicate the master is not attached to the
bridge.

Additionally, netdev_linux_update_lag() isn't "clearing" the netdev
reference it gets from netdev_from_name(), meaning its ref_cnt is
incremented but never decremented. Thus, also call netdev_close() before
returning.

CC: John Hurley <john.hurley@netronome.com>
Fixes: d22f8927 ("netdev-linux: monitor and offload LAG slaves to TC")
Signed-off-by: Tiago Lam <tiago.lam@intel.com>
---
 lib/netdev-linux.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

Comments

Ben Pfaff July 5, 2018, 9:13 p.m. UTC | #1
On Thu, Jul 05, 2018 at 07:24:47PM +0100, Tiago Lam wrote:
> A bissect shows that commit d22f892 ("netdev-linux: monitor and offload
> LAG slaves to TC") introduced netdev_linux_update_lag(), which is now
> triggering a crash in the "datapath - ping over bond" test in
> system-userspace-testsuite:

Applied to master, thanks!
diff mbox series

Patch

diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c
index 8e6c637..0c42268 100644
--- a/lib/netdev-linux.c
+++ b/lib/netdev-linux.c
@@ -724,11 +724,15 @@  netdev_linux_update_lag(struct rtnetlink_change *change)
 
             if_indextoname(change->master_ifindex, master_name);
             master_netdev = netdev_from_name(master_name);
+            if (!master_netdev) {
+                return;
+            }
 
             if (is_netdev_linux_class(master_netdev->netdev_class)) {
                 block_id = netdev_get_block_id(master_netdev);
                 if (!block_id) {
-                   return;
+                    netdev_close(master_netdev);
+                    return;
                 }
 
                 lag = xmalloc(sizeof *lag);
@@ -744,6 +748,8 @@  netdev_linux_update_lag(struct rtnetlink_change *change)
                     free(lag);
                 }
             }
+
+            netdev_close(master_netdev);
         }
     } else if (change->master_ifindex == 0) {
         /* Check if this was a lag slave that has been freed. */