mirror of
https://github.com/SCST-project/scst.git
synced 2026-08-19 21:56:31 +00:00
ib_srpt: Avoid that very rapidly successive logins from the same initiator cause a crash
Fixes this bug report: BUG: unable to handle kernel NULL pointer dereference at 0000000000000518 IP: [<ffffffff81080112>] __lock_acquire+0x62/0x1d40 PGD 1b226f067 PUD 1b2241067 PMD 0 Oops: 0000 [#1] SMP CPU 0 Modules linked in: ib_srpt scst_vdisk crc32c libcrc32c scst netconsole configfs snd_pcm_oss snd_mixer_oss snd_seq snd_seq_device af_packet rdma_ucm rdma_cm iw_cm ib_addr ib_ipoib ib_cm ib_sa ib_uverbs ib_umad mlx4_ib ib_mad ib_core microcode cpufreq_co nservative cpufreq_userspace cpufreq_powersave acpi_cpufreq mperf dm_mod snd_hda_codec_hdmi snd_hda_codec_analog snd_hda_intel snd_hda_codec snd_hwdep snd_pcm snd_timer snd intel_agp sr_mod mlx4_core sg intel_gtt cdrom i2c_i801 agpgart soundcore i2c_co re snd_page_alloc pcspkr button uhci_hcd ehci_hcd sd_mod crc_t10dif usbcore edd ext3 mbcache jbd fan ata_generic ata_piix pata_marvell ahci libahci libata scsi_mod thermal processor thermal_sys hwmon Pid: 4, comm: kworker/0:0 Not tainted 3.1.5-debug+ #1 System manufacturer P5Q DELUXE/P5Q DELUXE RIP: 0010:[<ffffffff81080112>] [<ffffffff81080112>] __lock_acquire+0x62/0x1d40 RSP: 0018:ffff8801b50c9950 EFLAGS: 00010046 RAX: 0000000000000046 RBX: 0000000000000518 RCX: 0000000000000001 RDX: 0000000000000001 RSI: 0000000000000000 RDI: 0000000000000518 RBP: ffff8801b50c9a40 R08: 0000000000000002 R09: 0000000000000001 R10: 0000000000000000 R11: 0000000000000000 R12: ffff8801b50aae20 R13: 0000000000000000 R14: 0000000000000002 R15: 0000000000000000 FS: 0000000000000000(0000) GS:ffff8801bfc00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b CR2: 0000000000000518 CR3: 00000001b1a4d000 CR4: 00000000000406f0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process kworker/0:0 (pid: 4, threadinfo ffff8801b50c8000, task ffff8801b50aae20) Stack: 0000000000000006 0000000000000001 ffffffff8191ca20 ffff8801b50c99b8 ffffffff81082cae 0000000000000003 ffff8801b50aae20 0000000000000003 0000000000000002 0000000000000000 ffff8801b50c9aa0 0000000000000046 Call Trace: [<ffffffff81082cae>] ? mark_held_locks+0x6e/0x130 [<ffffffff810823c5>] lock_acquire+0x95/0x130 [<ffffffff8103d4ee>] ? try_to_wake_up+0x2e/0x2b0 [<ffffffff813d618c>] ? _raw_spin_lock_irqsave+0x1c/0x60 [<ffffffff813d61bb>] _raw_spin_lock_irqsave+0x4b/0x60 [<ffffffff8103d4ee>] ? try_to_wake_up+0x2e/0x2b0 [<ffffffff8103d4ee>] try_to_wake_up+0x2e/0x2b0 [<ffffffff8103d7a5>] wake_up_process+0x15/0x20 [<ffffffffa0463fda>] srpt_set_ch_state_to_disc+0x5a/0x80 [ib_srpt] [<ffffffffa0464016>] __srpt_close_ch+0x16/0xa0 [ib_srpt] [<ffffffffa04698e6>] srpt_cm_req_recv+0x806/0xbe0 [ib_srpt] [<ffffffffa046ac0d>] srpt_cm_handler+0x7d/0x160 [ib_srpt] [<ffffffffa0315c85>] cm_process_work+0x25/0x110 [ib_cm] [<ffffffffa031716c>] cm_req_handler+0x67c/0xa00 [ib_cm] [<ffffffffa031761d>] cm_work_handler+0x12d/0x1480 [ib_cm] [<ffffffff810629c8>] process_one_work+0x198/0x520 [<ffffffff81062959>] ? process_one_work+0x129/0x520 [<ffffffffa03174f0>] ? cm_req_handler+0xa00/0xa00 [ib_cm] [<ffffffff810646aa>] worker_thread+0x16a/0x350 [<ffffffff81064540>] ? manage_workers+0x250/0x250 [<ffffffff81069656>] kthread+0x96/0xa0 [<ffffffff813e0b74>] kernel_thread_helper+0x4/0x10 [<ffffffff813d6d9d>] ? retint_restore_args+0xe/0xe [<ffffffff810695c0>] ? __init_kthread_worker+0x70/0x70 [<ffffffff813e0b70>] ? gs_change+0xb/0xb Code: 25 00 b6 00 00 4c 89 7d f8 85 c9 48 89 fb 45 0f 45 f0 41 89 f5 85 d2 0f 84 44 0d 00 00 8b 05 5a 3a 6f 00 85 c0 0f 84 c6 01 00 00 8b 03 ba 01 00 00 00 48 3d c0 75 7b 81 44 0f 44 f2 41 83 fd RIP [<ffffffff81080112>] __lock_acquire+0x62/0x1d40 RSP <ffff8801b50c9950> CR2: 0000000000000518 ---[ end trace efbb413a57b805cb ]--- git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@4020 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
+49
-44
@@ -2313,7 +2313,8 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id,
|
||||
struct srp_login_rsp *rsp;
|
||||
struct srp_login_rej *rej;
|
||||
struct ib_cm_rep_param *rep_param;
|
||||
struct srpt_rdma_ch *ch, *tmp_ch;
|
||||
struct srpt_rdma_ch *ch;
|
||||
struct task_struct *thread;
|
||||
u32 it_iu_len;
|
||||
int i;
|
||||
int ret = 0;
|
||||
@@ -2374,33 +2375,6 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id,
|
||||
goto reject;
|
||||
}
|
||||
|
||||
if ((req->req_flags & SRP_MTCH_ACTION) == SRP_MULTICHAN_SINGLE) {
|
||||
rsp->rsp_flags = SRP_LOGIN_RSP_MULTICHAN_NO_CHAN;
|
||||
|
||||
spin_lock_irq(&sdev->spinlock);
|
||||
|
||||
list_for_each_entry_safe(ch, tmp_ch, &sdev->rch_list, list) {
|
||||
if (!memcmp(ch->i_port_id, req->initiator_port_id, 16)
|
||||
&& !memcmp(ch->t_port_id, req->target_port_id, 16)
|
||||
&& param->port == ch->sport->port
|
||||
&& param->listen_id == ch->sport->sdev->cm_id
|
||||
&& ch->cm_id) {
|
||||
if (!__srpt_close_ch(ch))
|
||||
continue;
|
||||
|
||||
TRACE_DBG("Found existing channel %s; cm_id ="
|
||||
" %p", ch->sess_name, ch->cm_id);
|
||||
|
||||
rsp->rsp_flags =
|
||||
SRP_LOGIN_RSP_MULTICHAN_TERMINATED;
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock_irq(&sdev->spinlock);
|
||||
|
||||
} else
|
||||
rsp->rsp_flags = SRP_LOGIN_RSP_MULTICHAN_MAINTAINED;
|
||||
|
||||
if (*(__be64 *)req->target_port_id != cpu_to_be64(srpt_service_guid)
|
||||
|| *(__be64 *)(req->target_port_id + 8) !=
|
||||
cpu_to_be64(srpt_service_guid)) {
|
||||
@@ -2493,20 +2467,43 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id,
|
||||
goto destroy_ib;
|
||||
}
|
||||
|
||||
spin_lock_irq(&sdev->spinlock);
|
||||
list_add_tail(&ch->list, &sdev->rch_list);
|
||||
spin_unlock_irq(&sdev->spinlock);
|
||||
|
||||
ch->thread = kthread_run(srpt_compl_thread, ch, "srpt_%s",
|
||||
ch->sport->sdev->device->name);
|
||||
if (IS_ERR(ch->thread)) {
|
||||
thread = kthread_run(srpt_compl_thread, ch, "srpt_%s",
|
||||
ch->sport->sdev->device->name);
|
||||
if (IS_ERR(thread)) {
|
||||
rej->reason = cpu_to_be32(SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);
|
||||
PRINT_ERROR("failed to create kernel thread %ld",
|
||||
PTR_ERR(ch->thread));
|
||||
ch->thread = NULL;
|
||||
PRINT_ERROR("failed to create kernel thread %ld", PTR_ERR(ch->thread));
|
||||
goto unreg_ch;
|
||||
}
|
||||
|
||||
spin_lock_irq(&sdev->spinlock);
|
||||
if ((req->req_flags & SRP_MTCH_ACTION) == SRP_MULTICHAN_SINGLE) {
|
||||
struct srpt_rdma_ch *ch2;
|
||||
|
||||
rsp->rsp_flags = SRP_LOGIN_RSP_MULTICHAN_NO_CHAN;
|
||||
list_for_each_entry(ch2, &sdev->rch_list, list) {
|
||||
if (!memcmp(ch2->i_port_id, req->initiator_port_id, 16)
|
||||
&& !memcmp(ch2->t_port_id, req->target_port_id, 16)
|
||||
&& param->port == ch2->sport->port
|
||||
&& param->listen_id == ch2->sport->sdev->cm_id
|
||||
&& ch2->cm_id) {
|
||||
if (!__srpt_close_ch(ch2))
|
||||
continue;
|
||||
|
||||
TRACE_DBG("Found and closed existing channel"
|
||||
" %s; cm_id = %p", ch2->sess_name,
|
||||
ch2->cm_id);
|
||||
|
||||
rsp->rsp_flags =
|
||||
SRP_LOGIN_RSP_MULTICHAN_TERMINATED;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
rsp->rsp_flags = SRP_LOGIN_RSP_MULTICHAN_MAINTAINED;
|
||||
}
|
||||
list_add_tail(&ch->list, &sdev->rch_list);
|
||||
ch->thread = thread;
|
||||
spin_unlock_irq(&sdev->spinlock);
|
||||
|
||||
ret = srpt_ch_qp_rtr(ch, ch->qp);
|
||||
if (ret) {
|
||||
rej->reason = cpu_to_be32(SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);
|
||||
@@ -2541,8 +2538,19 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id,
|
||||
rep_param->responder_resources = 4;
|
||||
rep_param->initiator_depth = 4;
|
||||
|
||||
ret = ib_send_cm_rep(cm_id, rep_param);
|
||||
if (ret) {
|
||||
spin_lock_irq(&sdev->spinlock);
|
||||
if (ch->state == CH_CONNECTING)
|
||||
ret = ib_send_cm_rep(cm_id, rep_param);
|
||||
else
|
||||
ret = -ECONNABORTED;
|
||||
spin_unlock_irq(&sdev->spinlock);
|
||||
|
||||
switch (ret) {
|
||||
case 0:
|
||||
break;
|
||||
case -ECONNABORTED:
|
||||
goto out_keep_cm_id;
|
||||
default:
|
||||
rej->reason = cpu_to_be32(SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);
|
||||
PRINT_ERROR("sending SRP_LOGIN_REQ response failed"
|
||||
" (error code = %d)", ret);
|
||||
@@ -2561,6 +2569,7 @@ reject_and_release:
|
||||
(void *)rej, sizeof *rej);
|
||||
|
||||
srpt_close_ch(ch);
|
||||
out_keep_cm_id:
|
||||
/*
|
||||
* Tell the caller not to free cm_id since srpt_free_ch() will do that.
|
||||
*/
|
||||
@@ -2568,10 +2577,6 @@ reject_and_release:
|
||||
goto out;
|
||||
|
||||
unreg_ch:
|
||||
spin_lock_irq(&sdev->spinlock);
|
||||
list_del(&ch->list);
|
||||
spin_unlock_irq(&sdev->spinlock);
|
||||
|
||||
scst_unregister_session(ch->scst_sess, true, NULL);
|
||||
|
||||
destroy_ib:
|
||||
|
||||
Reference in New Issue
Block a user