scst: Fix a race between scst_del_threads() and the sysfs API

kthread_stop() not only stops a thread but also frees the associated
task struct. Avoid that functions that iterate over the thread list
can encounter an invalid task structure pointer. This patch fixes the
following kernel crash:

general protection fault: 0000 [#2] PREEMPT SMP
RIP: 0010:[<ffffffff81080e9c>]  [<ffffffff81080e9c>] __task_pid_nr_ns+0x9c/0x1b0
Call Trace:
[<ffffffffa045ed7d>] task_pid_vnr+0xd/0x10 [scst]
[<ffffffffa0460418>] scst_tgt_dev_thread_pid_show+0x78/0xd0 [scst]
[<ffffffffa045929f>] scst_show+0xf/0x20 [scst]
[<ffffffff81231acb>] sysfs_kf_seq_show+0xab/0x130
[<ffffffff81230176>] kernfs_seq_show+0x26/0x30
[<ffffffff811daf10>] seq_read+0xe0/0x3e0
[<ffffffff81230ab5>] kernfs_fop_read+0x125/0x180
[<ffffffff811b0138>] __vfs_read+0x28/0xe0
[<ffffffff811b07ca>] vfs_read+0x8a/0x140
[<ffffffff811b1669>] SyS_read+0x49/0xb0
[<ffffffff814ffd32>] system_call_fastpath+0x16/0x7a

Signed-off-by: Bart Van Assche <bart.vanassche@sandisk.com>
This commit is contained in:
Bart Van Assche
2015-05-06 12:54:29 +02:00
parent 38cd0a345d
commit af94d2ce4f

View File

@@ -1950,6 +1950,7 @@ void scst_del_threads(struct scst_cmd_threads *cmd_threads, int num)
thread_list_entry) {
if (!ct2->being_stopped) {
ct = ct2;
list_del(&ct->thread_list_entry);
ct->being_stopped = true;
cmd_threads->nr_threads--;
break;
@@ -1964,10 +1965,6 @@ void scst_del_threads(struct scst_cmd_threads *cmd_threads, int num)
if (rc != 0 && rc != -EINTR)
TRACE_MGMT_DBG("kthread_stop() failed: %d", rc);
spin_lock(&cmd_threads->thr_lock);
list_del(&ct->thread_list_entry);
spin_unlock(&cmd_threads->thr_lock);
kfree(ct);
}