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:
+13
-1
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
+7
-11
@@ -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 @@ binding_session:
|
||||
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);
|
||||
|
||||
Reference in New Issue
Block a user