Patch "ksmbd: fix kernel oops from idr_remove()" has been added to the 5.15-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    ksmbd: fix kernel oops from idr_remove()

to the 5.15-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     ksmbd-fix-kernel-oops-from-idr_remove.patch
and it can be found in the queue-5.15 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit e422c48bc373790c7a99f05459d85a5335552b26
Author: Namjae Jeon <linkinjeon@xxxxxxxxxx>
Date:   Fri Jul 22 10:17:06 2022 +0900

    ksmbd: fix kernel oops from idr_remove()
    
    [ Upstream commit 17ea92a9f6d0b9a97aaec5ab748e4591d70a562c ]
    
    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>
    Reviewed-by: Hyunchul Lee <hyc.lee@xxxxxxxxx>
    Signed-off-by: Steve French <stfrench@xxxxxxxxxxxxx>
    Stable-dep-of: 7b4323373d84 ("ksmbd: fix deadlock in ksmbd_find_crypto_ctx()")
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/fs/ksmbd/mgmt/user_session.c b/fs/ksmbd/mgmt/user_session.c
index 0c7b5335c12af..9c4a9c8c02795 100644
--- a/fs/ksmbd/mgmt/user_session.c
+++ b/fs/ksmbd/mgmt/user_session.c
@@ -241,6 +241,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 e17f7a5dd9974..8bfe2a6c05f92 100644
--- a/fs/ksmbd/smb2pdu.c
+++ b/fs/ksmbd/smb2pdu.c
@@ -600,6 +600,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;
@@ -615,8 +616,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);
 }
 
 /**



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux