mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-06 05:06:29 +00:00
four fixes, also for stable
-----BEGIN PGP SIGNATURE----- iQGzBAABCgAdFiEE6fsu8pdIjtWE/DpLiiy9cAdyT1EFAmcsXSUACgkQiiy9cAdy T1FyOgv+Ks1lfl+6D/G89zFl5XOtCm8njsedJu9y3jR7hzophX2osfmodACMVX6B 0VLu0jzquvUo18VNlL+wF7YFH+Mc6zrevEnjBay9Xa05YyRqK5c7qjpiWEgXPN7/ ROQfC2slCAFjymhw+9qY+PGZYg3x0fyGdJC/gBNSFnu2ufag367Li+0fTKQTXFwz F24S5eI+M9OWNgMnMYoNt+77f0n0JkKbQznq9nTEvUsbTWZFSEfmVczfSY0ltdOH RER9zoyTU3zbPuMZqK+Jb7c2247ahsLzDEBAUG0Wn77wSaiWXU5dmVD5bWsDTp25 5p9uLpkr3irDWwJGkCrkpm2Tva/50IHPEFQ4kllVlm6ffoao/dxBCwFf/MEvJXzI OgU+HpXyZdq6NF1hcB4xUlcbHvGCa6pEcYkcM7PwLml+6SKIwEsEGpnJ23kxGR3+ MGYMCITatRuvZstfEDolNyrO2+gPMd3ODnLhfjfjT47Kh38e7yxrLr4cmxbPAA+s EVdm2N08 =zTn6 -----END PGP SIGNATURE----- Merge tag 'v6.12-rc6-ksmbd-fixes' of git://git.samba.org/ksmbd Pull smb server fixes from Steve French: "Four fixes, all also marked for stable: - fix two potential use after free issues - fix OOM issue with many simultaneous requests - fix missing error check in RPC pipe handling" * tag 'v6.12-rc6-ksmbd-fixes' of git://git.samba.org/ksmbd: ksmbd: check outstanding simultaneous SMB operations ksmbd: fix slab-use-after-free in smb3_preauth_hash_rsp ksmbd: fix slab-use-after-free in ksmbd_smb2_session_create ksmbd: Fix the missing xa_store error check
This commit is contained in:
commit
1eb714c660
@ -70,6 +70,7 @@ struct ksmbd_conn *ksmbd_conn_alloc(void)
|
||||
atomic_set(&conn->req_running, 0);
|
||||
atomic_set(&conn->r_count, 0);
|
||||
atomic_set(&conn->refcnt, 1);
|
||||
atomic_set(&conn->mux_smb_requests, 0);
|
||||
conn->total_credits = 1;
|
||||
conn->outstanding_credits = 0;
|
||||
|
||||
|
@ -107,6 +107,7 @@ struct ksmbd_conn {
|
||||
__le16 signing_algorithm;
|
||||
bool binding;
|
||||
atomic_t refcnt;
|
||||
atomic_t mux_smb_requests;
|
||||
};
|
||||
|
||||
struct ksmbd_conn_ops {
|
||||
|
@ -90,7 +90,7 @@ static int __rpc_method(char *rpc_name)
|
||||
|
||||
int ksmbd_session_rpc_open(struct ksmbd_session *sess, char *rpc_name)
|
||||
{
|
||||
struct ksmbd_session_rpc *entry;
|
||||
struct ksmbd_session_rpc *entry, *old;
|
||||
struct ksmbd_rpc_command *resp;
|
||||
int method;
|
||||
|
||||
@ -106,16 +106,19 @@ int ksmbd_session_rpc_open(struct ksmbd_session *sess, char *rpc_name)
|
||||
entry->id = ksmbd_ipc_id_alloc();
|
||||
if (entry->id < 0)
|
||||
goto free_entry;
|
||||
xa_store(&sess->rpc_handle_list, entry->id, entry, GFP_KERNEL);
|
||||
old = xa_store(&sess->rpc_handle_list, entry->id, entry, GFP_KERNEL);
|
||||
if (xa_is_err(old))
|
||||
goto free_id;
|
||||
|
||||
resp = ksmbd_rpc_open(sess, entry->id);
|
||||
if (!resp)
|
||||
goto free_id;
|
||||
goto erase_xa;
|
||||
|
||||
kvfree(resp);
|
||||
return entry->id;
|
||||
free_id:
|
||||
erase_xa:
|
||||
xa_erase(&sess->rpc_handle_list, entry->id);
|
||||
free_id:
|
||||
ksmbd_rpc_id_free(entry->id);
|
||||
free_entry:
|
||||
kfree(entry);
|
||||
@ -175,6 +178,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 (atomic_read(&sess->refcnt) == 0 &&
|
||||
@ -188,6 +192,7 @@ static void ksmbd_expire_session(struct ksmbd_conn *conn)
|
||||
}
|
||||
}
|
||||
up_write(&conn->session_lock);
|
||||
up_write(&sessions_table_lock);
|
||||
}
|
||||
|
||||
int ksmbd_session_register(struct ksmbd_conn *conn,
|
||||
@ -229,7 +234,6 @@ 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) {
|
||||
@ -249,6 +253,7 @@ void ksmbd_sessions_deregister(struct ksmbd_conn *conn)
|
||||
}
|
||||
}
|
||||
up_write(&conn->session_lock);
|
||||
up_write(&sessions_table_lock);
|
||||
}
|
||||
|
||||
struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn,
|
||||
|
@ -238,11 +238,11 @@ static void __handle_ksmbd_work(struct ksmbd_work *work,
|
||||
} while (is_chained == true);
|
||||
|
||||
send:
|
||||
if (work->sess)
|
||||
ksmbd_user_session_put(work->sess);
|
||||
if (work->tcon)
|
||||
ksmbd_tree_connect_put(work->tcon);
|
||||
smb3_preauth_hash_rsp(work);
|
||||
if (work->sess)
|
||||
ksmbd_user_session_put(work->sess);
|
||||
if (work->sess && work->sess->enc && work->encrypted &&
|
||||
conn->ops->encrypt_resp) {
|
||||
rc = conn->ops->encrypt_resp(work);
|
||||
@ -270,6 +270,7 @@ static void handle_ksmbd_work(struct work_struct *wk)
|
||||
|
||||
ksmbd_conn_try_dequeue_request(work);
|
||||
ksmbd_free_work_struct(work);
|
||||
atomic_dec(&conn->mux_smb_requests);
|
||||
/*
|
||||
* Checking waitqueue to dropping pending requests on
|
||||
* disconnection. waitqueue_active is safe because it
|
||||
@ -291,6 +292,15 @@ static int queue_ksmbd_work(struct ksmbd_conn *conn)
|
||||
struct ksmbd_work *work;
|
||||
int err;
|
||||
|
||||
err = ksmbd_init_smb_server(conn);
|
||||
if (err)
|
||||
return 0;
|
||||
|
||||
if (atomic_inc_return(&conn->mux_smb_requests) >= conn->vals->max_credits) {
|
||||
atomic_dec_return(&conn->mux_smb_requests);
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
work = ksmbd_alloc_work_struct();
|
||||
if (!work) {
|
||||
pr_err("allocation for work failed\n");
|
||||
@ -301,12 +311,6 @@ static int queue_ksmbd_work(struct ksmbd_conn *conn)
|
||||
work->request_buf = conn->request_buf;
|
||||
conn->request_buf = NULL;
|
||||
|
||||
err = ksmbd_init_smb_server(work);
|
||||
if (err) {
|
||||
ksmbd_free_work_struct(work);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ksmbd_conn_enqueue_request(work);
|
||||
atomic_inc(&conn->r_count);
|
||||
/* update activity on connection */
|
||||
|
@ -388,6 +388,10 @@ static struct smb_version_ops smb1_server_ops = {
|
||||
.set_rsp_status = set_smb1_rsp_status,
|
||||
};
|
||||
|
||||
static struct smb_version_values smb1_server_values = {
|
||||
.max_credits = SMB2_MAX_CREDITS,
|
||||
};
|
||||
|
||||
static int smb1_negotiate(struct ksmbd_work *work)
|
||||
{
|
||||
return ksmbd_smb_negotiate_common(work, SMB_COM_NEGOTIATE);
|
||||
@ -399,18 +403,18 @@ static struct smb_version_cmds smb1_server_cmds[1] = {
|
||||
|
||||
static int init_smb1_server(struct ksmbd_conn *conn)
|
||||
{
|
||||
conn->vals = &smb1_server_values;
|
||||
conn->ops = &smb1_server_ops;
|
||||
conn->cmds = smb1_server_cmds;
|
||||
conn->max_cmds = ARRAY_SIZE(smb1_server_cmds);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ksmbd_init_smb_server(struct ksmbd_work *work)
|
||||
int ksmbd_init_smb_server(struct ksmbd_conn *conn)
|
||||
{
|
||||
struct ksmbd_conn *conn = work->conn;
|
||||
__le32 proto;
|
||||
|
||||
proto = *(__le32 *)((struct smb_hdr *)work->request_buf)->Protocol;
|
||||
proto = *(__le32 *)((struct smb_hdr *)conn->request_buf)->Protocol;
|
||||
if (conn->need_neg == false) {
|
||||
if (proto == SMB1_PROTO_NUMBER)
|
||||
return -EINVAL;
|
||||
|
@ -427,7 +427,7 @@ bool ksmbd_smb_request(struct ksmbd_conn *conn);
|
||||
|
||||
int ksmbd_lookup_dialect_by_id(__le16 *cli_dialects, __le16 dialects_count);
|
||||
|
||||
int ksmbd_init_smb_server(struct ksmbd_work *work);
|
||||
int ksmbd_init_smb_server(struct ksmbd_conn *conn);
|
||||
|
||||
struct ksmbd_kstat;
|
||||
int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work,
|
||||
|
Loading…
Reference in New Issue
Block a user