Skip to content

Commit

Permalink
ksmbd: fix kernel oops from idr_remove()
Browse files Browse the repository at this point in the history
There is a report that kernel oops happen from idr_remove().

kernel: BUG: kernel NULL pointer dereference, address: 0000000000000010
kernel: RIP: 0010:idr_remove+0x1/0x20
kernel:  __ksmbd_close_fd+0xb2/0x2d0 [ksmbd]
kernel:  ksmbd_vfs_read+0x91/0x190 [ksmbd]
kernel:  ksmbd_fd_put+0x29/0x40 [ksmbd]
kernel:  smb2_read+0x210/0x390 [ksmbd]
kernel:  __process_request+0xa4/0x180 [ksmbd]
kernel:  __handle_ksmbd_work+0xf0/0x290 [ksmbd]
kernel:  handle_ksmbd_work+0x2d/0x50 [ksmbd]
kernel:  process_one_work+0x21d/0x3f0
kernel:  worker_thread+0x50/0x3d0
kernel:  rescuer_thread+0x390/0x390
kernel:  kthread+0xee/0x120
kthread_complete_and_exit+0x20/0x20
kernel:  ret_from_fork+0x22/0x30

While accessing files, If connection is disconnected, windows send
session setup request included previous session destroy. But while still
processing requests on previous session, this request destroy file
table, which mean file table idr will be freed and set to NULL.
So kernel oops happen from ft->idr in __ksmbd_close_fd().
This patch don't directly destroy session in destroy_previous_session().
It just set to KSMBD_SESS_EXITING so that connection will be
terminated after finishing the rest of requests.

Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
  • Loading branch information
Namjae Jeon authored and Steve French committed Jul 27, 2022
1 parent 8e06b31 commit 17ea92a
Show file tree
Hide file tree
Showing 2 changed files with 8 additions and 2 deletions.
2 changes: 2 additions & 0 deletions fs/ksmbd/mgmt/user_session.c
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,8 @@ struct ksmbd_session *ksmbd_session_lookup_all(struct ksmbd_conn *conn,
sess = ksmbd_session_lookup(conn, id);
if (!sess && conn->binding)
sess = ksmbd_session_lookup_slowpath(id);
if (sess && sess->state != SMB2_SESSION_VALID)
sess = NULL;
return sess;
}

Expand Down
8 changes: 6 additions & 2 deletions fs/ksmbd/smb2pdu.c
Original file line number Diff line number Diff line change
Expand Up @@ -593,6 +593,7 @@ static void destroy_previous_session(struct ksmbd_conn *conn,
{
struct ksmbd_session *prev_sess = ksmbd_session_lookup_slowpath(id);
struct ksmbd_user *prev_user;
struct channel *chann;

if (!prev_sess)
return;
Expand All @@ -608,8 +609,11 @@ static void destroy_previous_session(struct ksmbd_conn *conn,
}

put_session(prev_sess);
xa_erase(&conn->sessions, prev_sess->id);
ksmbd_session_destroy(prev_sess);
prev_sess->state = SMB2_SESSION_EXPIRED;
write_lock(&prev_sess->chann_lock);
list_for_each_entry(chann, &prev_sess->ksmbd_chann_list, chann_list)
chann->conn->status = KSMBD_SESS_EXITING;
write_unlock(&prev_sess->chann_lock);
}

/**
Expand Down

0 comments on commit 17ea92a

Please sign in to comment.