From 47183f2b16adf54b4aa3af781f94ea705e7be195 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Mon, 10 Oct 2016 18:51:06 +0000 Subject: [PATCH] ib_srpt: Fix a race condition in the initialization code Initialize port information before registering the CM ID. One of the functions called by the CM handler (srpt_cm_req_recv()) namely uses the SCST target pointer so that pointer must be initialized before the CM ID is registered. This patch avoids that SRP login during ib_srpt initialization sporadically triggers the following bug: ib_srpt: Rejecting login with reason 0x10001 BUG: unable to handle kernel NULL pointer dereference at 0000000000000100 IP: [] srpt_cm_req_recv+0xf3f/0xf60 [ib_srpt] Call Trace: [] srpt_ib_cm_req_recv+0xe5/0x110 [ib_srpt] [] cm_process_work+0x1e/0x130 [ib_cm] [] cm_req_handler+0x398/0x460 [ib_cm] [] cm_work_handler+0xb5/0x208 [ib_cm] [] process_one_work+0x16c/0x350 [] worker_thread+0x17a/0x410 [] kthread+0x96/0xa0 [] kernel_thread_helper+0x4/0x10 git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@7003 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- srpt/src/ib_srpt.c | 48 ++++++++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/srpt/src/ib_srpt.c b/srpt/src/ib_srpt.c index 0a492f7f0..8e6d92855 100644 --- a/srpt/src/ib_srpt.c +++ b/srpt/src/ib_srpt.c @@ -4401,6 +4401,29 @@ static void srpt_add_one(struct ib_device *device) } } + WARN_ON(sdev->device->phys_port_cnt > ARRAY_SIZE(sdev->port)); + + for (i = 1; i <= sdev->device->phys_port_cnt; i++) { + sport = &sdev->port[i - 1]; + sport->sdev = sdev; + sport->port = i; + srpt_init_sport(sport, sdev->device); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) && !defined(BACKPORT_LINUX_WORKQUEUE_TO_2_6_19) + /* + * A vanilla 2.6.19 or older kernel without backported OFED + * kernel headers. + */ + INIT_WORK(&sport->work, srpt_refresh_port_work, sport); +#else + INIT_WORK(&sport->work, srpt_refresh_port_work); +#endif + if (srpt_refresh_port(sport)) { + pr_err("MAD registration failed for %s-%d.\n", + sdev->device->name, i); + goto err_ring; + } + } + if (!srpt_service_guid) srpt_service_guid = be64_to_cpu(device->node_guid) & ~be64_to_cpu(IB_SERVICE_ID_AGN_MASK); @@ -4441,37 +4464,12 @@ static void srpt_add_one(struct ib_device *device) goto err_cm; } - WARN_ON(sdev->device->phys_port_cnt > ARRAY_SIZE(sdev->port)); - - for (i = 1; i <= sdev->device->phys_port_cnt; i++) { - sport = &sdev->port[i - 1]; - sport->sdev = sdev; - sport->port = i; - srpt_init_sport(sport, sdev->device); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) && !defined(BACKPORT_LINUX_WORKQUEUE_TO_2_6_19) - /* - * A vanilla 2.6.19 or older kernel without backported OFED - * kernel headers. - */ - INIT_WORK(&sport->work, srpt_refresh_port_work, sport); -#else - INIT_WORK(&sport->work, srpt_refresh_port_work); -#endif - if (srpt_refresh_port(sport)) { - pr_err("MAD registration failed for %s-%d.\n", - sdev->device->name, i); - goto err_event; - } - } - atomic_inc(&srpt_device_count); out: ib_set_client_data(device, &srpt_client, sdev); return; -err_event: - ib_unregister_event_handler(&sdev->event_handler); err_cm: ib_destroy_cm_id(sdev->cm_id); err_ring: