]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
ib_core: fix NULL pointer dereference
authorDotan Barak <dotanb@dev.mellanox.co.il>
Tue, 12 Jun 2012 10:34:22 +0000 (13:34 +0300)
committerMukesh Kacker <mukesh.kacker@oracle.com>
Tue, 7 Jul 2015 21:38:10 +0000 (14:38 -0700)
If there was a failure in the initial fill of the Pkey/GID cache,
and some other ULP/module will try to query a Pkey/GID, the NULL
pointer will be dereferenced, thing that will lead to the
following kernel panic:

BUG: unable to handle kernel NULL pointer dereference at 0000000000000058
IP: [<ffffffff814ef21f>] _spin_lock_irqsave+0x1f/0x40
PGD 37b49067 PUD becb3067 PMD 0
Oops: 0002 [#1] SMP
last sysfs file: /sys/module/mlx4_core/initstate
CPU 1
Modules linked in: mlx4_ib(+)(U) ib_sa(U) ib_mad(U) ib_core(U) mlx4_en(U) mlx4_core(U) memtrack(U) netconsole configfs nfs fscache nfsd lockd nfs_acl auth_rpcgss exportfs autofs4 sunrpc ipv6 knem(U) microcode virtio_balloon virtio_net snd_hda_intel snd_hda_codec snd_hwdep snd_seq snd_seq_device snd_pcm snd_timer snd soundcore snd_page_alloc i2c_piix4 i2c_core ext3 jbd mbcache virtio_blk virtio_pci virtio_ring virtio pata_acpi ata_generic ata_piix dm_mirror dm_region_hash dm_log dm_mod [last unloaded: memtrack]

Pid: 20715, comm: modprobe Not tainted 2.6.32-220.el6.x86_64 #1 Red Hat KVM
RIP: 0010:[<ffffffff814ef21f>]  [<ffffffff814ef21f>] _spin_lock_irqsave+0x1f/0x40
RSP: 0018:ffff8800bc331d08  EFLAGS: 00010002
RAX: 0000000000010000 RBX: ffff8800bec00088 RCX: 0000000000000000
RDX: 0000000000000202 RSI: 0000000000000046 RDI: 0000000000000058
RBP: ffff8800bc331d08 R08: 0000000000000000 R09: ffff88011bde8050
R10: ffff8800bc3317d8 R11: 0000000000000002 R12: ffff8800b9520000
R13: ffff8800bec00000 R14: 0000000000000000 R15: ffff8800bec02c00
FS:  00007f2f07fcd700(0000) GS:ffff880028300000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
CR2: 0000000000000058 CR3: 00000000bb708000 CR4: 00000000000006e0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
Process modprobe (pid: 20715, threadinfo ffff8800bc330000, task ffff8801185e0b40)
Stack:
 ffff8800bc331d28 ffffffffa0244ee5 ffff8800bec00000 ffff8800b9520000
<0> ffff8800bc331d68 ffffffffa0246f96 0000000000000370 ffffffffa0359560
<0> ffffffffa024fde0 ffff8800b9520000 ffff8800bec00000 ffff8800bcf36080
Call Trace:
 [<ffffffffa0244ee5>] ib_unregister_event_handler+0x25/0x50 [ib_core]
 [<ffffffffa0246f96>] ib_cache_cleanup_one+0x26/0x1b0 [ib_core]
 [<ffffffffa02450ce>] ib_unregister_device+0x4e/0x1a0 [ib_core]
 [<ffffffffa035fee6>] ? mlx4_ib_mad_init+0xa6/0x170 [mlx4_ib]
 [<ffffffffa0366721>] mlx4_ib_add+0x621/0xb80 [mlx4_ib]
 [<ffffffffa0456e73>] mlx4_add_device+0x73/0x1d0 [mlx4_core]
 [<ffffffffa04570db>] mlx4_register_interface+0x7b/0x100 [mlx4_core]
 [<ffffffffa013112a>] mlx4_ib_init+0x12a/0x188 [mlx4_ib]
 [<ffffffffa0131000>] ? mlx4_ib_init+0x0/0x188 [mlx4_ib]
 [<ffffffff8100204c>] do_one_initcall+0x3c/0x1d0
 [<ffffffff810af641>] sys_init_module+0xe1/0x250
 [<ffffffff8100b0f2>] system_call_fastpath+0x16/0x1b
Code: c9 c3 66 2e 0f 1f 84 00 00 00 00 00 55 48 89 e5 0f 1f 44 00 00 9c 58 0f 1f 44 00 00 48 89 c2 fa 66 0f 1f 44 00 00 b8 00 00 01 00 <f0> 0f c1 07 0f b7 c8 c1 e8 10 39 c1 74 0e f3 90 0f 1f 44 00 00
RIP  [<ffffffff814ef21f>] _spin_lock_irqsave+0x1f/0x40
 RSP <ffff8800bc331d08>
CR2: 0000000000000058
---[ end trace 4cc9b3e738027b7c ]---
Kernel panic - not syncing: Fatal exception
Pid: 20715, comm: modprobe Tainted: G      D    ----------------   2.6.32-220.el6.x86_64 #1
Call Trace:
 [<ffffffff814ec341>] ? panic+0x78/0x143
 [<ffffffff814f04d4>] ? oops_end+0xe4/0x100
 [<ffffffff8104230b>] ? no_context+0xfb/0x260
 [<ffffffffa001a62d>] ? start_xmit+0x5d/0x1d0 [virtio_net]
 [<ffffffff81042595>] ? __bad_area_nosemaphore+0x125/0x1e0
 [<ffffffff810426be>] ? bad_area+0x4e/0x60
 [<ffffffff81042dc3>] ? __do_page_fault+0x3c3/0x480
 [<ffffffffa03d737d>] ? write_msg+0xfd/0x110 [netconsole]
 [<ffffffff81069d15>] ? __call_console_drivers+0x75/0x90
 [<ffffffff8109694f>] ? up+0x2f/0x50
 [<ffffffff81069d7a>] ? _call_console_drivers+0x4a/0x80
 [<ffffffff814f248e>] ? do_page_fault+0x3e/0xa0
 [<ffffffff814ef845>] ? page_fault+0x25/0x30
 [<ffffffff814ef21f>] ? _spin_lock_irqsave+0x1f/0x40
 [<ffffffffa0244ee5>] ? ib_unregister_event_handler+0x25/0x50 [ib_core]
 [<ffffffffa0246f96>] ? ib_cache_cleanup_one+0x26/0x1b0 [ib_core]
 [<ffffffffa02450ce>] ? ib_unregister_device+0x4e/0x1a0 [ib_core]
 [<ffffffffa035fee6>] ? mlx4_ib_mad_init+0xa6/0x170 [mlx4_ib]
 [<ffffffffa0366721>] ? mlx4_ib_add+0x621/0xb80 [mlx4_ib]
 [<ffffffffa0456e73>] ? mlx4_add_device+0x73/0x1d0 [mlx4_core]
 [<ffffffffa04570db>] ? mlx4_register_interface+0x7b/0x100 [mlx4_core]
 [<ffffffffa013112a>] ? mlx4_ib_init+0x12a/0x188 [mlx4_ib]
 [<ffffffffa0131000>] ? mlx4_ib_init+0x0/0x188 [mlx4_ib]
 [<ffffffff8100204c>] ? do_one_initcall+0x3c/0x1d0
 [<ffffffff810af641>] ? sys_init_module+0xe1/0x250
 [<ffffffff8100b0f2>] ? system_call_fastpath+0x16/0x1b

Signed-off-by: Dotan Barak <dotanb@dev.mellanox.co.il>
Reviewed-by: Eli Cohen <eli@mellanox.co.il>
(Ported from Mellanox OFED 2.4)

Signed-off-by: Mukesh Kacker <mukesh.kacker@oracle.com>
drivers/infiniband/core/cache.c

index 80f6cf2449fb9b852533d254ab8e6cbabc706156..e269a01e871f556e0e4bfb46bbe9166cd6f3167c 100644 (file)
@@ -76,19 +76,21 @@ int ib_get_cached_gid(struct ib_device *device,
 {
        struct ib_gid_cache *cache;
        unsigned long flags;
-       int ret = 0;
+       int ret = -EINVAL;
 
        if (port_num < start_port(device) || port_num > end_port(device))
                return -EINVAL;
 
        read_lock_irqsave(&device->cache.lock, flags);
 
-       cache = device->cache.gid_cache[port_num - start_port(device)];
+       if (device->cache.gid_cache) {
+               cache = device->cache.gid_cache[port_num - start_port(device)];
 
-       if (index < 0 || index >= cache->table_len)
-               ret = -EINVAL;
-       else
-               *gid = cache->table[index];
+               if (cache && index >= 0 && index < cache->table_len) {
+                       *gid = cache->table[index];
+                       ret = 0;
+               }
+       }
 
        read_unlock_irqrestore(&device->cache.lock, flags);
 
@@ -138,19 +140,21 @@ int ib_get_cached_pkey(struct ib_device *device,
 {
        struct ib_pkey_cache *cache;
        unsigned long flags;
-       int ret = 0;
+       int ret = -EINVAL;
 
        if (port_num < start_port(device) || port_num > end_port(device))
                return -EINVAL;
 
        read_lock_irqsave(&device->cache.lock, flags);
 
-       cache = device->cache.pkey_cache[port_num - start_port(device)];
+       if (device->cache.pkey_cache) {
+               cache = device->cache.pkey_cache[port_num - start_port(device)];
 
-       if (index < 0 || index >= cache->table_len)
-               ret = -EINVAL;
-       else
-               *pkey = cache->table[index];
+               if (cache && index >= 0 && index < cache->table_len) {
+                       *pkey = cache->table[index];
+                       ret = 0;
+               }
+       }
 
        read_unlock_irqrestore(&device->cache.lock, flags);
 
@@ -236,13 +240,16 @@ int ib_get_cached_lmc(struct ib_device *device,
                      u8                *lmc)
 {
        unsigned long flags;
-       int ret = 0;
+       int ret = -EINVAL;
 
        if (port_num < start_port(device) || port_num > end_port(device))
                return -EINVAL;
 
        read_lock_irqsave(&device->cache.lock, flags);
-       *lmc = device->cache.lmc_cache[port_num - start_port(device)];
+       if (device->cache.lmc_cache) {
+               *lmc = device->cache.lmc_cache[port_num - start_port(device)];
+               ret = 0;
+       }
        read_unlock_irqrestore(&device->cache.lock, flags);
 
        return ret;
@@ -403,12 +410,19 @@ err:
        kfree(device->cache.pkey_cache);
        kfree(device->cache.gid_cache);
        kfree(device->cache.lmc_cache);
+       device->cache.pkey_cache = NULL;
+       device->cache.gid_cache = NULL;
+       device->cache.lmc_cache = NULL;
 }
 
 static void ib_cache_cleanup_one(struct ib_device *device)
 {
        int p;
 
+       if (!(device->cache.pkey_cache && device->cache.gid_cache &&
+             device->cache.lmc_cache))
+               return;
+
        ib_unregister_event_handler(&device->cache.event_handler);
        flush_workqueue(ib_wq);