2022년 7월 22일 (금) 오후 12:04, Namjae Jeon <linkinjeon@xxxxxxxxxx>님이 작성: > > 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@xxxxxxxxxx> Looks good to me. Reviewed-by: Hyunchul Lee <hyc.lee@xxxxxxxxx> > --- > fs/ksmbd/mgmt/user_session.c | 2 ++ > fs/ksmbd/smb2pdu.c | 8 ++++++-- > 2 files changed, 8 insertions(+), 2 deletions(-) > > diff --git a/fs/ksmbd/mgmt/user_session.c b/fs/ksmbd/mgmt/user_session.c > index 25e9ba3b7550..b9acb6770b03 100644 > --- a/fs/ksmbd/mgmt/user_session.c > +++ b/fs/ksmbd/mgmt/user_session.c > @@ -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; > } > > diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c > index 5a0328a070dc..ae5677a66cb2 100644 > --- a/fs/ksmbd/smb2pdu.c > +++ b/fs/ksmbd/smb2pdu.c > @@ -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; > @@ -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); > } > > /** > -- > 2.25.1 > -- Thanks, Hyunchul