Skip to content

Commit 1891abe

Browse files
Marios Makassikisgregkh
authored andcommitted
ksmbd: fix recursive locking in RPC handle list access
[ Upstream commit 88f1708 ] Since commit 305853c ("ksmbd: Fix race condition in RPC handle list access"), ksmbd_session_rpc_method() attempts to lock sess->rpc_lock. This causes hung connections / tasks when a client attempts to open a named pipe. Using Samba's rpcclient tool: $ rpcclient //192.168.1.254 -U user%password $ rpcclient $> srvinfo <connection hung here> Kernel side: "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. task:kworker/0:0 state:D stack:0 pid:5021 tgid:5021 ppid:2 flags:0x00200000 Workqueue: ksmbd-io handle_ksmbd_work Call trace: __schedule from schedule+0x3c/0x58 schedule from schedule_preempt_disabled+0xc/0x10 schedule_preempt_disabled from rwsem_down_read_slowpath+0x1b0/0x1d8 rwsem_down_read_slowpath from down_read+0x28/0x30 down_read from ksmbd_session_rpc_method+0x18/0x3c ksmbd_session_rpc_method from ksmbd_rpc_open+0x34/0x68 ksmbd_rpc_open from ksmbd_session_rpc_open+0x194/0x228 ksmbd_session_rpc_open from create_smb2_pipe+0x8c/0x2c8 create_smb2_pipe from smb2_open+0x10c/0x27ac smb2_open from handle_ksmbd_work+0x238/0x3dc handle_ksmbd_work from process_scheduled_works+0x160/0x25c process_scheduled_works from worker_thread+0x16c/0x1e8 worker_thread from kthread+0xa8/0xb8 kthread from ret_from_fork+0x14/0x38 Exception stack(0x8529ffb0 to 0x8529fff8) The task deadlocks because the lock is already held: ksmbd_session_rpc_open down_write(&sess->rpc_lock) ksmbd_rpc_open ksmbd_session_rpc_method down_read(&sess->rpc_lock) <-- deadlock Adjust ksmbd_session_rpc_method() callers to take the lock when necessary. Fixes: 305853c ("ksmbd: Fix race condition in RPC handle list access") Signed-off-by: Marios Makassikis <mmakassikis@freebox.fr> Acked-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Steve French <stfrench@microsoft.com> Signed-off-by: Li hongliang <1468888505@139.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent b6978c5 commit 1891abe

3 files changed

Lines changed: 22 additions & 6 deletions

File tree

fs/smb/server/mgmt/user_session.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -147,14 +147,11 @@ void ksmbd_session_rpc_close(struct ksmbd_session *sess, int id)
147147
int ksmbd_session_rpc_method(struct ksmbd_session *sess, int id)
148148
{
149149
struct ksmbd_session_rpc *entry;
150-
int method;
151150

152-
down_read(&sess->rpc_lock);
151+
lockdep_assert_held(&sess->rpc_lock);
153152
entry = xa_load(&sess->rpc_handle_list, id);
154-
method = entry ? entry->method : 0;
155-
up_read(&sess->rpc_lock);
156153

157-
return method;
154+
return entry ? entry->method : 0;
158155
}
159156

160157
void ksmbd_session_destroy(struct ksmbd_session *sess)

fs/smb/server/smb2pdu.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4614,8 +4614,15 @@ static int smb2_get_info_file_pipe(struct ksmbd_session *sess,
46144614
* pipe without opening it, checking error condition here
46154615
*/
46164616
id = req->VolatileFileId;
4617-
if (!ksmbd_session_rpc_method(sess, id))
4617+
4618+
lockdep_assert_not_held(&sess->rpc_lock);
4619+
4620+
down_read(&sess->rpc_lock);
4621+
if (!ksmbd_session_rpc_method(sess, id)) {
4622+
up_read(&sess->rpc_lock);
46184623
return -ENOENT;
4624+
}
4625+
up_read(&sess->rpc_lock);
46194626

46204627
ksmbd_debug(SMB, "FileInfoClass %u, FileId 0x%llx\n",
46214628
req->FileInfoClass, req->VolatileFileId);

fs/smb/server/transport_ipc.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -778,6 +778,9 @@ struct ksmbd_rpc_command *ksmbd_rpc_write(struct ksmbd_session *sess, int handle
778778
if (!msg)
779779
return NULL;
780780

781+
lockdep_assert_not_held(&sess->rpc_lock);
782+
783+
down_read(&sess->rpc_lock);
781784
msg->type = KSMBD_EVENT_RPC_REQUEST;
782785
req = (struct ksmbd_rpc_command *)msg->payload;
783786
req->handle = handle;
@@ -786,6 +789,7 @@ struct ksmbd_rpc_command *ksmbd_rpc_write(struct ksmbd_session *sess, int handle
786789
req->flags |= KSMBD_RPC_WRITE_METHOD;
787790
req->payload_sz = payload_sz;
788791
memcpy(req->payload, payload, payload_sz);
792+
up_read(&sess->rpc_lock);
789793

790794
resp = ipc_msg_send_request(msg, req->handle);
791795
ipc_msg_free(msg);
@@ -802,13 +806,17 @@ struct ksmbd_rpc_command *ksmbd_rpc_read(struct ksmbd_session *sess, int handle)
802806
if (!msg)
803807
return NULL;
804808

809+
lockdep_assert_not_held(&sess->rpc_lock);
810+
811+
down_read(&sess->rpc_lock);
805812
msg->type = KSMBD_EVENT_RPC_REQUEST;
806813
req = (struct ksmbd_rpc_command *)msg->payload;
807814
req->handle = handle;
808815
req->flags = ksmbd_session_rpc_method(sess, handle);
809816
req->flags |= rpc_context_flags(sess);
810817
req->flags |= KSMBD_RPC_READ_METHOD;
811818
req->payload_sz = 0;
819+
up_read(&sess->rpc_lock);
812820

813821
resp = ipc_msg_send_request(msg, req->handle);
814822
ipc_msg_free(msg);
@@ -829,6 +837,9 @@ struct ksmbd_rpc_command *ksmbd_rpc_ioctl(struct ksmbd_session *sess, int handle
829837
if (!msg)
830838
return NULL;
831839

840+
lockdep_assert_not_held(&sess->rpc_lock);
841+
842+
down_read(&sess->rpc_lock);
832843
msg->type = KSMBD_EVENT_RPC_REQUEST;
833844
req = (struct ksmbd_rpc_command *)msg->payload;
834845
req->handle = handle;
@@ -837,6 +848,7 @@ struct ksmbd_rpc_command *ksmbd_rpc_ioctl(struct ksmbd_session *sess, int handle
837848
req->flags |= KSMBD_RPC_IOCTL_METHOD;
838849
req->payload_sz = payload_sz;
839850
memcpy(req->payload, payload, payload_sz);
851+
up_read(&sess->rpc_lock);
840852

841853
resp = ipc_msg_send_request(msg, req->handle);
842854
ipc_msg_free(msg);

0 commit comments

Comments
 (0)