ksmbd: fix race condition between session lookup and expire
commit 53ff5cf89142b978b1a5ca8dc4d4425e6a09745f upstream.
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>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
64301a9354
commit
a2ca5fd3db
3 changed files with 10 additions and 3 deletions
|
|
@ -84,6 +84,8 @@ struct ksmbd_conn *ksmbd_conn_alloc(void)
|
||||||
spin_lock_init(&conn->llist_lock);
|
spin_lock_init(&conn->llist_lock);
|
||||||
INIT_LIST_HEAD(&conn->lock_list);
|
INIT_LIST_HEAD(&conn->lock_list);
|
||||||
|
|
||||||
|
init_rwsem(&conn->session_lock);
|
||||||
|
|
||||||
down_write(&conn_list_lock);
|
down_write(&conn_list_lock);
|
||||||
list_add(&conn->conns_list, &conn_list);
|
list_add(&conn->conns_list, &conn_list);
|
||||||
up_write(&conn_list_lock);
|
up_write(&conn_list_lock);
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,7 @@ struct ksmbd_conn {
|
||||||
struct nls_table *local_nls;
|
struct nls_table *local_nls;
|
||||||
struct unicode_map *um;
|
struct unicode_map *um;
|
||||||
struct list_head conns_list;
|
struct list_head conns_list;
|
||||||
|
struct rw_semaphore session_lock;
|
||||||
/* smb session 1 per user */
|
/* smb session 1 per user */
|
||||||
struct xarray sessions;
|
struct xarray sessions;
|
||||||
unsigned long last_active;
|
unsigned long last_active;
|
||||||
|
|
|
||||||
|
|
@ -183,7 +183,7 @@ static void ksmbd_expire_session(struct ksmbd_conn *conn)
|
||||||
unsigned long id;
|
unsigned long id;
|
||||||
struct ksmbd_session *sess;
|
struct ksmbd_session *sess;
|
||||||
|
|
||||||
down_write(&sessions_table_lock);
|
down_write(&conn->session_lock);
|
||||||
xa_for_each(&conn->sessions, id, sess) {
|
xa_for_each(&conn->sessions, id, sess) {
|
||||||
if (sess->state != SMB2_SESSION_VALID ||
|
if (sess->state != SMB2_SESSION_VALID ||
|
||||||
time_after(jiffies,
|
time_after(jiffies,
|
||||||
|
|
@ -194,7 +194,7 @@ static void ksmbd_expire_session(struct ksmbd_conn *conn)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
up_write(&sessions_table_lock);
|
up_write(&conn->session_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ksmbd_session_register(struct ksmbd_conn *conn,
|
int ksmbd_session_register(struct ksmbd_conn *conn,
|
||||||
|
|
@ -236,7 +236,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) {
|
xa_for_each(&conn->sessions, id, sess) {
|
||||||
unsigned long chann_id;
|
unsigned long chann_id;
|
||||||
struct channel *chann;
|
struct channel *chann;
|
||||||
|
|
@ -253,7 +255,7 @@ void ksmbd_sessions_deregister(struct ksmbd_conn *conn)
|
||||||
ksmbd_session_destroy(sess);
|
ksmbd_session_destroy(sess);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
up_write(&sessions_table_lock);
|
up_write(&conn->session_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn,
|
struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn,
|
||||||
|
|
@ -261,9 +263,11 @@ struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn,
|
||||||
{
|
{
|
||||||
struct ksmbd_session *sess;
|
struct ksmbd_session *sess;
|
||||||
|
|
||||||
|
down_read(&conn->session_lock);
|
||||||
sess = xa_load(&conn->sessions, id);
|
sess = xa_load(&conn->sessions, id);
|
||||||
if (sess)
|
if (sess)
|
||||||
sess->last_active = jiffies;
|
sess->last_active = jiffies;
|
||||||
|
up_read(&conn->session_lock);
|
||||||
return sess;
|
return sess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue