This patch set fix three ksmbd cve issue.
Dawei Li (1): ksmbd: Remove duplicated codes
Namjae Jeon (3): ksmbd: validate mech token in session setup ksmbd: validate session id and tree id in compound request ksmbd: fix UAF issue in ksmbd_tcp_new_connection()
Yang Yingliang (1): ksmbd: switch to use kmemdup_nul() helper
luosili (1): ksmbd: fix uaf in smb20_oplock_break_ack
fs/ksmbd/asn1.c | 32 +++++++++++++++++--------------- fs/ksmbd/connection.c | 6 ------ fs/ksmbd/connection.h | 2 +- fs/ksmbd/smb2pdu.c | 38 +++++++++++++++++++++++++------------- fs/ksmbd/transport_rdma.c | 11 ++++++----- fs/ksmbd/transport_tcp.c | 13 +++++++------ 6 files changed, 56 insertions(+), 46 deletions(-)
From: Dawei Li set_pte_at@outlook.com
stable inclusion from stable-v5.15.81 commit a35ebf65899344cf1d4cbc8c8c773b4185bf8388 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/I93E71 CVE: CVE-2024-26594
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=l...
--------------------------------
[ Upstream commit 7010357004096e54c884813e702d71147dc081f8 ]
ksmbd_neg_token_init_mech_token() and ksmbd_neg_token_targ_resp_token() share same implementation, unify them.
Signed-off-by: Dawei Li set_pte_at@outlook.com Acked-by: Namjae Jeon linkinjeon@kernel.org Signed-off-by: Steve French stfrench@microsoft.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
Conflict: fs/ksmbd/asn1.c
Signed-off-by: Long Li leo.lilong@huawei.com --- fs/ksmbd/asn1.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-)
diff --git a/fs/ksmbd/asn1.c b/fs/ksmbd/asn1.c index b014f4638610..2276624e47ef 100644 --- a/fs/ksmbd/asn1.c +++ b/fs/ksmbd/asn1.c @@ -312,9 +312,9 @@ int ksmbd_neg_token_init_mech_type(void *context, size_t hdrlen, return -EBADMSG; }
-int ksmbd_neg_token_init_mech_token(void *context, size_t hdrlen, - unsigned char tag, const void *value, - size_t vlen) +static int ksmbd_neg_token_alloc(void *context, size_t hdrlen, + unsigned char tag, const void *value, + size_t vlen) { struct ksmbd_conn *conn = context;
@@ -327,17 +327,16 @@ int ksmbd_neg_token_init_mech_token(void *context, size_t hdrlen, return 0; }
-int ksmbd_neg_token_targ_resp_token(void *context, size_t hdrlen, +int ksmbd_neg_token_init_mech_token(void *context, size_t hdrlen, unsigned char tag, const void *value, size_t vlen) { - struct ksmbd_conn *conn = context; - - conn->mechToken = kmalloc(vlen + 1, GFP_KERNEL); - if (!conn->mechToken) - return -ENOMEM; + return ksmbd_neg_token_alloc(context, hdrlen, tag, value, vlen); +}
- memcpy(conn->mechToken, value, vlen); - conn->mechToken[vlen] = '\0'; - return 0; +int ksmbd_neg_token_targ_resp_token(void *context, size_t hdrlen, + unsigned char tag, const void *value, + size_t vlen) +{ + return ksmbd_neg_token_alloc(context, hdrlen, tag, value, vlen); }
From: Yang Yingliang yangyingliang@huawei.com
stable inclusion from stable-v5.15.81 commit d7ad0ac5a8f66c3527da2e85392e75095481768a category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/I93E71 CVE: CVE-2024-26594
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=l...
--------------------------------
[ Upstream commit 084ba46fc41c21ba827fd92e61f78def7a6e52ea ]
Use kmemdup_nul() helper instead of open-coding to simplify the code.
Acked-by: Namjae Jeon linkinjeon@kernel.org Signed-off-by: Yang Yingliang yangyingliang@huawei.com Signed-off-by: Steve French stfrench@microsoft.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Long Li leo.lilong@huawei.com --- fs/ksmbd/asn1.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/fs/ksmbd/asn1.c b/fs/ksmbd/asn1.c index 2276624e47ef..a82739dc92b3 100644 --- a/fs/ksmbd/asn1.c +++ b/fs/ksmbd/asn1.c @@ -318,12 +318,10 @@ static int ksmbd_neg_token_alloc(void *context, size_t hdrlen, { struct ksmbd_conn *conn = context;
- conn->mechToken = kmalloc(vlen + 1, GFP_KERNEL); + conn->mechToken = kmemdup_nul(value, vlen, GFP_KERNEL); if (!conn->mechToken) return -ENOMEM;
- memcpy(conn->mechToken, value, vlen); - conn->mechToken[vlen] = '\0'; return 0; }
From: Namjae Jeon linkinjeon@kernel.org
stable inclusion from stable-v5.15.81 commit dd1de9268745f0eac83a430db7afc32cbd62e84b category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/I93E71 CVE: CVE-2024-26594
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=l...
--------------------------------
[ Upstream commit 92e470163d96df8db6c4fa0f484e4a229edb903d ]
If client send invalid mech token in session setup request, ksmbd validate and make the error if it is invalid.
Cc: stable@vger.kernel.org Reported-by: zdi-disclosures@trendmicro.com # ZDI-CAN-22890 Signed-off-by: Namjae Jeon linkinjeon@kernel.org Signed-off-by: Steve French stfrench@microsoft.com Signed-off-by: Sasha Levin sashal@kernel.org Signed-off-by: Long Li leo.lilong@huawei.com --- fs/ksmbd/asn1.c | 5 +++++ fs/ksmbd/connection.h | 1 + fs/ksmbd/smb2pdu.c | 22 +++++++++++++++++----- 3 files changed, 23 insertions(+), 5 deletions(-)
diff --git a/fs/ksmbd/asn1.c b/fs/ksmbd/asn1.c index a82739dc92b3..8391963ff2a8 100644 --- a/fs/ksmbd/asn1.c +++ b/fs/ksmbd/asn1.c @@ -318,10 +318,15 @@ static int ksmbd_neg_token_alloc(void *context, size_t hdrlen, { struct ksmbd_conn *conn = context;
+ if (!vlen) + return -EINVAL; + conn->mechToken = kmemdup_nul(value, vlen, GFP_KERNEL); if (!conn->mechToken) return -ENOMEM;
+ conn->mechTokenLen = (unsigned int)vlen; + return 0; }
diff --git a/fs/ksmbd/connection.h b/fs/ksmbd/connection.h index 2e3d96e63953..75a1849ba828 100644 --- a/fs/ksmbd/connection.h +++ b/fs/ksmbd/connection.h @@ -85,6 +85,7 @@ struct ksmbd_conn { __u16 dialect;
char *mechToken; + unsigned int mechTokenLen;
struct ksmbd_conn_ops *conn_ops;
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c index b21ac851345f..7234ff23af80 100644 --- a/fs/ksmbd/smb2pdu.c +++ b/fs/ksmbd/smb2pdu.c @@ -1421,7 +1421,10 @@ static struct ksmbd_user *session_user(struct ksmbd_conn *conn, char *name; unsigned int name_off, name_len, secbuf_len;
- secbuf_len = le16_to_cpu(req->SecurityBufferLength); + if (conn->use_spnego && conn->mechToken) + secbuf_len = conn->mechTokenLen; + else + secbuf_len = le16_to_cpu(req->SecurityBufferLength); if (secbuf_len < sizeof(struct authenticate_message)) { ksmbd_debug(SMB, "blob len %d too small\n", secbuf_len); return NULL; @@ -1513,7 +1516,10 @@ static int ntlm_authenticate(struct ksmbd_work *work, struct authenticate_message *authblob;
authblob = user_authblob(conn, req); - sz = le16_to_cpu(req->SecurityBufferLength); + if (conn->use_spnego && conn->mechToken) + sz = conn->mechTokenLen; + else + sz = le16_to_cpu(req->SecurityBufferLength); rc = ksmbd_decode_ntlmssp_auth_blob(authblob, sz, conn, sess); if (rc) { set_user_flag(sess->user, KSMBD_USER_FLAG_BAD_PASSWORD); @@ -1786,8 +1792,7 @@ int smb2_sess_setup(struct ksmbd_work *work)
negblob_off = le16_to_cpu(req->SecurityBufferOffset); negblob_len = le16_to_cpu(req->SecurityBufferLength); - if (negblob_off < offsetof(struct smb2_sess_setup_req, Buffer) || - negblob_len < offsetof(struct negotiate_message, NegotiateFlags)) { + if (negblob_off < offsetof(struct smb2_sess_setup_req, Buffer)) { rc = -EINVAL; goto out_err; } @@ -1796,8 +1801,15 @@ int smb2_sess_setup(struct ksmbd_work *work) negblob_off);
if (decode_negotiation_token(conn, negblob, negblob_len) == 0) { - if (conn->mechToken) + if (conn->mechToken) { negblob = (struct negotiate_message *)conn->mechToken; + negblob_len = conn->mechTokenLen; + } + } + + if (negblob_len < offsetof(struct negotiate_message, NegotiateFlags)) { + rc = -EINVAL; + goto out_err; }
if (server_conf.auth_mechs & conn->auth_mechs) {
From: Namjae Jeon linkinjeon@kernel.org
stable inclusion from stable-v5.15.81 commit 017d85c94f02090a87f4a473dbe0d6ee0da72693 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/I92OR4 CVE: CVE-2023-52442
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=l...
--------------------------------
[ Upstream commit 3df0411e132ee74a87aa13142dfd2b190275332e ]
`smb2_get_msg()` in smb2_get_ksmbd_tcon() and smb2_check_user_session() will always return the first request smb2 header in a compound request. if `SMB2_TREE_CONNECT_HE` is the first command in compound request, will return 0, i.e. The tree id check is skipped. This patch use ksmbd_req_buf_next() to get current command in compound.
Reported-by: zdi-disclosures@trendmicro.com # ZDI-CAN-21506 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 Signed-off-by: Long Li leo.lilong@huawei.com --- fs/ksmbd/smb2pdu.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c index 7234ff23af80..7d4283e3d4b1 100644 --- a/fs/ksmbd/smb2pdu.c +++ b/fs/ksmbd/smb2pdu.c @@ -86,9 +86,9 @@ struct channel *lookup_chann_list(struct ksmbd_session *sess, struct ksmbd_conn */ int smb2_get_ksmbd_tcon(struct ksmbd_work *work) { - struct smb2_hdr *req_hdr = smb2_get_msg(work->request_buf); + struct smb2_hdr *req_hdr = ksmbd_req_buf_next(work); unsigned int cmd = le16_to_cpu(req_hdr->Command); - int tree_id; + unsigned int tree_id;
if (cmd == SMB2_TREE_CONNECT_HE || cmd == SMB2_CANCEL_HE || @@ -113,7 +113,7 @@ int smb2_get_ksmbd_tcon(struct ksmbd_work *work) pr_err("The first operation in the compound does not have tcon\n"); return -EINVAL; } - if (work->tcon->id != tree_id) { + if (tree_id != UINT_MAX && work->tcon->id != tree_id) { pr_err("tree id(%u) is different with id(%u) in first operation\n", tree_id, work->tcon->id); return -EINVAL; @@ -570,9 +570,9 @@ int smb2_allocate_rsp_buf(struct ksmbd_work *work) */ int smb2_check_user_session(struct ksmbd_work *work) { - struct smb2_hdr *req_hdr = smb2_get_msg(work->request_buf); + struct smb2_hdr *req_hdr = ksmbd_req_buf_next(work); struct ksmbd_conn *conn = work->conn; - unsigned int cmd = conn->ops->get_cmd_val(work); + unsigned int cmd = le16_to_cpu(req_hdr->Command); unsigned long long sess_id;
/* @@ -598,7 +598,7 @@ int smb2_check_user_session(struct ksmbd_work *work) pr_err("The first operation in the compound does not have sess\n"); return -EINVAL; } - if (work->sess->id != sess_id) { + if (sess_id != ULLONG_MAX && work->sess->id != sess_id) { pr_err("session id(%llu) is different with the first operation(%lld)\n", sess_id, work->sess->id); return -EINVAL;
From: luosili rootlab@huawei.com
stable inclusion from stable-v5.15.81 commit 694e13732e830cbbfedb562e57f28644927c33fd category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/I94P2I CVE: CVE-2023-52479
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=l...
--------------------------------
commit c69813471a1ec081a0b9bf0c6bd7e8afd818afce upstream.
drop reference after use opinfo.
Signed-off-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
Conflict: fs/ksmbd/transport_tcp.c
Signed-off-by: Long Li leo.lilong@huawei.com --- fs/ksmbd/smb2pdu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c index 7d4283e3d4b1..2f025205c843 100644 --- a/fs/ksmbd/smb2pdu.c +++ b/fs/ksmbd/smb2pdu.c @@ -8046,10 +8046,10 @@ static void smb20_oplock_break_ack(struct ksmbd_work *work) goto err_out; }
- opinfo_put(opinfo); - ksmbd_fd_put(work, fp); opinfo->op_state = OPLOCK_STATE_NONE; wake_up_interruptible_all(&opinfo->oplock_q); + opinfo_put(opinfo); + ksmbd_fd_put(work, fp);
rsp->StructureSize = cpu_to_le16(24); rsp->OplockLevel = rsp_oplevel;
From: Namjae Jeon linkinjeon@kernel.org
stable inclusion from stable-v5.15.81 commit 999daf367b924fdf14e9d83e034ee0f86bc17ec6 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/I932W8 CVE: CVE-2024-26592
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=l...
--------------------------------
[ Upstream commit 38d20c62903d669693a1869aa68c4dd5674e2544 ]
The race is between the handling of a new TCP connection and its disconnection. It leads to UAF on `struct tcp_transport` in ksmbd_tcp_new_connection() function.
Cc: stable@vger.kernel.org Reported-by: zdi-disclosures@trendmicro.com # ZDI-CAN-22991 Signed-off-by: Namjae Jeon linkinjeon@kernel.org Signed-off-by: Steve French stfrench@microsoft.com Signed-off-by: Sasha Levin sashal@kernel.org
Conflict: fs/ksmbd/transport_tcp.c
Signed-off-by: Long Li leo.lilong@huawei.com --- fs/ksmbd/connection.c | 6 ------ fs/ksmbd/connection.h | 1 - fs/ksmbd/transport_rdma.c | 11 ++++++----- fs/ksmbd/transport_tcp.c | 13 +++++++------ 4 files changed, 13 insertions(+), 18 deletions(-)
diff --git a/fs/ksmbd/connection.c b/fs/ksmbd/connection.c index f0818e764230..d48d177cba6b 100644 --- a/fs/ksmbd/connection.c +++ b/fs/ksmbd/connection.c @@ -434,13 +434,7 @@ static void stop_sessions(void) again: down_read(&conn_list_lock); list_for_each_entry(conn, &conn_list, conns_list) { - struct task_struct *task; - t = conn->transport; - task = t->handler; - if (task) - ksmbd_debug(CONN, "Stop session handler %s/%d\n", - task->comm, task_pid_nr(task)); ksmbd_conn_set_exiting(conn); if (t->ops->shutdown) { up_read(&conn_list_lock); diff --git a/fs/ksmbd/connection.h b/fs/ksmbd/connection.h index 75a1849ba828..9708ba99d8a5 100644 --- a/fs/ksmbd/connection.h +++ b/fs/ksmbd/connection.h @@ -128,7 +128,6 @@ struct ksmbd_transport_ops { struct ksmbd_transport { struct ksmbd_conn *conn; struct ksmbd_transport_ops *ops; - struct task_struct *handler; };
#define KSMBD_TCP_RECV_TIMEOUT (7 * HZ) diff --git a/fs/ksmbd/transport_rdma.c b/fs/ksmbd/transport_rdma.c index d3b60b833a81..2a8640ce1107 100644 --- a/fs/ksmbd/transport_rdma.c +++ b/fs/ksmbd/transport_rdma.c @@ -1976,6 +1976,7 @@ static bool rdma_frwr_is_supported(struct ib_device_attr *attrs) static int smb_direct_handle_connect_request(struct rdma_cm_id *new_cm_id) { struct smb_direct_transport *t; + struct task_struct *handler; int ret;
if (!rdma_frwr_is_supported(&new_cm_id->device->attrs)) { @@ -1993,11 +1994,11 @@ static int smb_direct_handle_connect_request(struct rdma_cm_id *new_cm_id) if (ret) goto out_err;
- KSMBD_TRANS(t)->handler = kthread_run(ksmbd_conn_handler_loop, - KSMBD_TRANS(t)->conn, "ksmbd:r%u", - smb_direct_port); - if (IS_ERR(KSMBD_TRANS(t)->handler)) { - ret = PTR_ERR(KSMBD_TRANS(t)->handler); + handler = kthread_run(ksmbd_conn_handler_loop, + KSMBD_TRANS(t)->conn, "ksmbd:r%u", + smb_direct_port); + if (IS_ERR(handler)) { + ret = PTR_ERR(handler); pr_err("Can't start thread\n"); goto out_err; } diff --git a/fs/ksmbd/transport_tcp.c b/fs/ksmbd/transport_tcp.c index d34812d140eb..79b40f26587c 100644 --- a/fs/ksmbd/transport_tcp.c +++ b/fs/ksmbd/transport_tcp.c @@ -183,6 +183,7 @@ static int ksmbd_tcp_new_connection(struct socket *client_sk) struct sockaddr *csin; int rc = 0; struct tcp_transport *t; + struct task_struct *handler;
t = alloc_transport(client_sk); if (!t) @@ -195,13 +196,13 @@ static int ksmbd_tcp_new_connection(struct socket *client_sk) goto out_error; }
- KSMBD_TRANS(t)->handler = kthread_run(ksmbd_conn_handler_loop, - KSMBD_TRANS(t)->conn, - "ksmbd:%u", - ksmbd_tcp_get_port(csin)); - if (IS_ERR(KSMBD_TRANS(t)->handler)) { + handler = kthread_run(ksmbd_conn_handler_loop, + KSMBD_TRANS(t)->conn, + "ksmbd:%u", + ksmbd_tcp_get_port(csin)); + if (IS_ERR(handler)) { pr_err("cannot start conn thread\n"); - rc = PTR_ERR(KSMBD_TRANS(t)->handler); + rc = PTR_ERR(handler); free_transport(t); } return rc;
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://gitee.com/openeuler/kernel/pulls/5378 邮件列表地址:https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/W...
FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://gitee.com/openeuler/kernel/pulls/5378 Mailing list address: https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/W...