mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-09 06:33:34 +00:00
ksmbd: fix race condition between session lookup and expire
Thread A + Thread B ksmbd_session_lookup | smb2_sess_setup sess = xa_load | | | xa_erase(&conn->sessions, sess->id); | | ksmbd_session_destroy(sess) --> kfree(sess) | // UAF! | sess->last_active = jiffies | + This patch add rwsem to fix race condition between ksmbd_session_lookup and ksmbd_expire_session. Reported-by: luosili <rootlab@huawei.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
parent
8a749fd1a8
commit
53ff5cf891
@ -84,6 +84,8 @@ struct ksmbd_conn *ksmbd_conn_alloc(void)
|
||||
spin_lock_init(&conn->llist_lock);
|
||||
INIT_LIST_HEAD(&conn->lock_list);
|
||||
|
||||
init_rwsem(&conn->session_lock);
|
||||
|
||||
down_write(&conn_list_lock);
|
||||
list_add(&conn->conns_list, &conn_list);
|
||||
up_write(&conn_list_lock);
|
||||
|
@ -50,6 +50,7 @@ struct ksmbd_conn {
|
||||
struct nls_table *local_nls;
|
||||
struct unicode_map *um;
|
||||
struct list_head conns_list;
|
||||
struct rw_semaphore session_lock;
|
||||
/* smb session 1 per user */
|
||||
struct xarray sessions;
|
||||
unsigned long last_active;
|
||||
|
@ -174,7 +174,7 @@ static void ksmbd_expire_session(struct ksmbd_conn *conn)
|
||||
unsigned long id;
|
||||
struct ksmbd_session *sess;
|
||||
|
||||
down_write(&sessions_table_lock);
|
||||
down_write(&conn->session_lock);
|
||||
xa_for_each(&conn->sessions, id, sess) {
|
||||
if (sess->state != SMB2_SESSION_VALID ||
|
||||
time_after(jiffies,
|
||||
@ -185,7 +185,7 @@ static void ksmbd_expire_session(struct ksmbd_conn *conn)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
up_write(&sessions_table_lock);
|
||||
up_write(&conn->session_lock);
|
||||
}
|
||||
|
||||
int ksmbd_session_register(struct ksmbd_conn *conn,
|
||||
@ -227,7 +227,9 @@ void ksmbd_sessions_deregister(struct ksmbd_conn *conn)
|
||||
}
|
||||
}
|
||||
}
|
||||
up_write(&sessions_table_lock);
|
||||
|
||||
down_write(&conn->session_lock);
|
||||
xa_for_each(&conn->sessions, id, sess) {
|
||||
unsigned long chann_id;
|
||||
struct channel *chann;
|
||||
@ -244,7 +246,7 @@ void ksmbd_sessions_deregister(struct ksmbd_conn *conn)
|
||||
ksmbd_session_destroy(sess);
|
||||
}
|
||||
}
|
||||
up_write(&sessions_table_lock);
|
||||
up_write(&conn->session_lock);
|
||||
}
|
||||
|
||||
struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn,
|
||||
@ -252,9 +254,11 @@ struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn,
|
||||
{
|
||||
struct ksmbd_session *sess;
|
||||
|
||||
down_read(&conn->session_lock);
|
||||
sess = xa_load(&conn->sessions, id);
|
||||
if (sess)
|
||||
sess->last_active = jiffies;
|
||||
up_read(&conn->session_lock);
|
||||
return sess;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user