4 ksmbd SMB3 server fixes, most also for stable

-----BEGIN PGP SIGNATURE-----
 
 iQGzBAABCgAdFiEE6fsu8pdIjtWE/DpLiiy9cAdyT1EFAmgPw1IACgkQiiy9cAdy
 T1Fl4AwAlbLrqQHArI03OEUNhS6iV7Q13ZeXrMpi3jIzdKpLmMlc6ze+HcfB58QX
 PM1vQm+/1htfempeRxCHVM0XWLv3Y4Oya1Qk3AsvT9Uv0zqq3hwqG4FybG39VVfd
 4lxmsT1mzHBE/nT2gtb8iU1XqOVvJ8FM7lPubslPWMdCYpFMjmKretBUpzQOeh9J
 IYQdWjd/gDjAZ10DnX8BPlJlW7pnXoRf7QMNlj6GD79Bs0ZwBWcytNN3bO1f04hD
 q03X9LQBuXqOm+yxBRMojK+QF6XOa1xbZBrk3LcPEVWWgzfOhcyTDTP15Dw90Sgs
 3GGMxP52agHnNf1hKMM00qaWHeEIyGdD5mfWcbTbquPI9cYdZ+wVcWP3qGDYEGfI
 9e0J+o09kWj13WW65VA44k2qFQdxiO6JyFzOrDSY1KTd0ud4wG64UUAhOiq9nY7X
 sLxzCk8G1rVgefcfqL7WJL7EPaq1a5ESFqYIi7uK6nrK/8nH9FTyF9+q1qcS+I00
 nOgRymu0
 =jTh7
 -----END PGP SIGNATURE-----

Merge tag 'v6.15-rc4-ksmbd-server-fixes' of git://git.samba.org/ksmbd

Pull smb server fixes from Steve French:

 - Fix three potential use after frees: in session logoff, in krb5 auth,
   and in RPC open

 - Fix missing rc check in session setup authentication

* tag 'v6.15-rc4-ksmbd-server-fixes' of git://git.samba.org/ksmbd:
  ksmbd: fix use-after-free in session logoff
  ksmbd: fix use-after-free in kerberos authentication
  ksmbd: fix use-after-free in ksmbd_session_rpc_open
  smb: server: smb2pdu: check return value of xa_store()
This commit is contained in:
Linus Torvalds 2025-04-28 16:56:01 -07:00
commit ca91b95001
4 changed files with 35 additions and 18 deletions

View File

@ -550,7 +550,19 @@ int ksmbd_krb5_authenticate(struct ksmbd_session *sess, char *in_blob,
retval = -ENOMEM;
goto out;
}
sess->user = user;
if (!sess->user) {
/* First successful authentication */
sess->user = user;
} else {
if (!ksmbd_compare_user(sess->user, user)) {
ksmbd_debug(AUTH, "different user tried to reuse session\n");
retval = -EPERM;
ksmbd_free_user(user);
goto out;
}
ksmbd_free_user(user);
}
memcpy(sess->sess_key, resp->payload, resp->session_key_len);
memcpy(out_blob, resp->payload + resp->session_key_len,

View File

@ -59,10 +59,12 @@ static void ksmbd_session_rpc_clear_list(struct ksmbd_session *sess)
struct ksmbd_session_rpc *entry;
long index;
down_write(&sess->rpc_lock);
xa_for_each(&sess->rpc_handle_list, index, entry) {
xa_erase(&sess->rpc_handle_list, index);
__session_rpc_close(sess, entry);
}
up_write(&sess->rpc_lock);
xa_destroy(&sess->rpc_handle_list);
}
@ -92,7 +94,7 @@ int ksmbd_session_rpc_open(struct ksmbd_session *sess, char *rpc_name)
{
struct ksmbd_session_rpc *entry, *old;
struct ksmbd_rpc_command *resp;
int method;
int method, id;
method = __rpc_method(rpc_name);
if (!method)
@ -102,26 +104,29 @@ int ksmbd_session_rpc_open(struct ksmbd_session *sess, char *rpc_name)
if (!entry)
return -ENOMEM;
down_read(&sess->rpc_lock);
entry->method = method;
entry->id = ksmbd_ipc_id_alloc();
if (entry->id < 0)
entry->id = id = ksmbd_ipc_id_alloc();
if (id < 0)
goto free_entry;
old = xa_store(&sess->rpc_handle_list, entry->id, entry, KSMBD_DEFAULT_GFP);
old = xa_store(&sess->rpc_handle_list, id, entry, KSMBD_DEFAULT_GFP);
if (xa_is_err(old))
goto free_id;
resp = ksmbd_rpc_open(sess, entry->id);
resp = ksmbd_rpc_open(sess, id);
if (!resp)
goto erase_xa;
up_read(&sess->rpc_lock);
kvfree(resp);
return entry->id;
return id;
erase_xa:
xa_erase(&sess->rpc_handle_list, entry->id);
free_id:
ksmbd_rpc_id_free(entry->id);
free_entry:
kfree(entry);
up_read(&sess->rpc_lock);
return -EINVAL;
}
@ -129,9 +134,11 @@ void ksmbd_session_rpc_close(struct ksmbd_session *sess, int id)
{
struct ksmbd_session_rpc *entry;
down_write(&sess->rpc_lock);
entry = xa_erase(&sess->rpc_handle_list, id);
if (entry)
__session_rpc_close(sess, entry);
up_write(&sess->rpc_lock);
}
int ksmbd_session_rpc_method(struct ksmbd_session *sess, int id)
@ -439,6 +446,7 @@ static struct ksmbd_session *__session_create(int protocol)
sess->sequence_number = 1;
rwlock_init(&sess->tree_conns_lock);
atomic_set(&sess->refcnt, 2);
init_rwsem(&sess->rpc_lock);
ret = __init_smb2_session(sess);
if (ret)

View File

@ -63,6 +63,7 @@ struct ksmbd_session {
rwlock_t tree_conns_lock;
atomic_t refcnt;
struct rw_semaphore rpc_lock;
};
static inline int test_session_flag(struct ksmbd_session *sess, int bit)

View File

@ -1445,7 +1445,7 @@ static int ntlm_authenticate(struct ksmbd_work *work,
{
struct ksmbd_conn *conn = work->conn;
struct ksmbd_session *sess = work->sess;
struct channel *chann = NULL;
struct channel *chann = NULL, *old;
struct ksmbd_user *user;
u64 prev_id;
int sz, rc;
@ -1557,7 +1557,12 @@ static int ntlm_authenticate(struct ksmbd_work *work,
return -ENOMEM;
chann->conn = conn;
xa_store(&sess->ksmbd_chann_list, (long)conn, chann, KSMBD_DEFAULT_GFP);
old = xa_store(&sess->ksmbd_chann_list, (long)conn, chann,
KSMBD_DEFAULT_GFP);
if (xa_is_err(old)) {
kfree(chann);
return xa_err(old);
}
}
}
@ -1602,11 +1607,6 @@ static int krb5_authenticate(struct ksmbd_work *work,
if (prev_sess_id && prev_sess_id != sess->id)
destroy_previous_session(conn, sess->user, prev_sess_id);
if (sess->state == SMB2_SESSION_VALID) {
ksmbd_free_user(sess->user);
sess->user = NULL;
}
retval = ksmbd_krb5_authenticate(sess, in_blob, in_len,
out_blob, &out_len);
if (retval) {
@ -2249,10 +2249,6 @@ int smb2_session_logoff(struct ksmbd_work *work)
sess->state = SMB2_SESSION_EXPIRED;
up_write(&conn->session_lock);
if (sess->user) {
ksmbd_free_user(sess->user);
sess->user = NULL;
}
ksmbd_all_conn_set_status(sess_id, KSMBD_SESS_NEED_SETUP);
rsp->StructureSize = cpu_to_le16(4);