RDMA/irdma: Fix possible crash due to NULL netdev in notifier
authorMustafa Ismail <mustafa.ismail@intel.com>
Mon, 25 Apr 2022 18:17:03 +0000 (13:17 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 12 May 2022 10:30:15 +0000 (12:30 +0200)
commit 1c9043ae0667a43bd87beeebbdd4bed674713629 upstream.

For some net events in irdma_net_event notifier, the netdev can be NULL
which will cause a crash in rdma_vlan_dev_real_dev.  Fix this by moving
all processing to the NETEVENT_NEIGH_UPDATE case where the netdev is
guaranteed to not be NULL.

Fixes: 6702bc147448 ("RDMA/irdma: Fix netdev notifications for vlan's")
Link: https://lore.kernel.org/r/20220425181703.1634-4-shiraz.saleem@intel.com
Signed-off-by: Mustafa Ismail <mustafa.ismail@intel.com>
Signed-off-by: Shiraz Saleem <shiraz.saleem@intel.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/infiniband/hw/irdma/utils.c

index fee179f..85d4212 100644 (file)
@@ -258,18 +258,16 @@ int irdma_net_event(struct notifier_block *notifier, unsigned long event,
        u32 local_ipaddr[4] = {};
        bool ipv4 = true;
 
-       real_dev = rdma_vlan_dev_real_dev(netdev);
-       if (!real_dev)
-               real_dev = netdev;
-
-       ibdev = ib_device_get_by_netdev(real_dev, RDMA_DRIVER_IRDMA);
-       if (!ibdev)
-               return NOTIFY_DONE;
-
-       iwdev = to_iwdev(ibdev);
-
        switch (event) {
        case NETEVENT_NEIGH_UPDATE:
+               real_dev = rdma_vlan_dev_real_dev(netdev);
+               if (!real_dev)
+                       real_dev = netdev;
+               ibdev = ib_device_get_by_netdev(real_dev, RDMA_DRIVER_IRDMA);
+               if (!ibdev)
+                       return NOTIFY_DONE;
+
+               iwdev = to_iwdev(ibdev);
                p = (__be32 *)neigh->primary_key;
                if (neigh->tbl->family == AF_INET6) {
                        ipv4 = false;
@@ -290,13 +288,12 @@ int irdma_net_event(struct notifier_block *notifier, unsigned long event,
                        irdma_manage_arp_cache(iwdev->rf, neigh->ha,
                                               local_ipaddr, ipv4,
                                               IRDMA_ARP_DELETE);
+               ib_device_put(ibdev);
                break;
        default:
                break;
        }
 
-       ib_device_put(ibdev);
-
        return NOTIFY_DONE;
 }