[PATCH OLK-6.6] [Backport] nvmet-auth: validate reply message payload bounds against transfer length
From: Tianchu Chen <flynnnchen@tencent.com> stable inclusion from stable-v6.6.145 commit 80cd28b56ab62d3e7ed0a7bf05282e6d3ee5b2a0 category: bugfix bugzilla: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=... -------------------------------- [ Upstream commit 3a413ece2504c70aa34a20be4dafec04e8c741f9 ] nvmet_auth_reply() accesses the variable-length rval[] array using attacker-controlled hl (hash length) and dhvlen (DH value length) fields without verifying they fit within the allocated buffer of tl bytes. A malicious NVMe-oF initiator can craft a DHCHAP_REPLY message with a small transfer length but large hl/dhvlen values, causing out-of-bounds heap reads when the target processes the DH public key (rval + 2*hl) or performs the host response memcmp. With DH authentication configured, the OOB pointer is passed directly to sg_init_one() and read by crypto_kpp_compute_shared_secret(), reaching up to 526 bytes past the buffer. This is exploitable pre-authentication. Add bounds validation ensuring sizeof(*data) + 2*hl + dhvlen <= tl before any access to the variable-length fields. Discovered by Atuin - Automated Vulnerability Discovery Engine. Fixes: db1312dd9548 ("nvmet: implement basic In-Band Authentication") Cc: stable@vger.kernel.org Reviewed-by: Hannes Reinecke <hare@kernel.org> Signed-off-by: Tianchu Chen <flynnnchen@tencent.com> Signed-off-by: Keith Busch <kbusch@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Conflicts: drivers/nvme/target/fabrics-cmd-auth.c [drivers/nvme/target/fabrics-cmd-auth.c: Added u32 tl parameter to nvmet_auth_reply and inserted bounds checks before accessing variable-length fields; call site updated accordingly.] Signed-off-by: Lu Chentao <luchentao1@huawei.com> --- drivers/nvme/target/fabrics-cmd-auth.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/nvme/target/fabrics-cmd-auth.c b/drivers/nvme/target/fabrics-cmd-auth.c index c103eba96350..65a01343e553 100644 --- a/drivers/nvme/target/fabrics-cmd-auth.c +++ b/drivers/nvme/target/fabrics-cmd-auth.c @@ -107,17 +107,26 @@ static u16 nvmet_auth_negotiate(struct nvmet_req *req, void *d) __func__, ctrl->cntlid, req->sq->qid, nvme_auth_dhgroup_name(ctrl->dh_gid), ctrl->dh_gid); return 0; } -static u16 nvmet_auth_reply(struct nvmet_req *req, void *d) +static u16 nvmet_auth_reply(struct nvmet_req *req, void *d, u32 tl) { struct nvmet_ctrl *ctrl = req->sq->ctrl; struct nvmf_auth_dhchap_reply_data *data = d; - u16 dhvlen = le16_to_cpu(data->dhvlen); + u16 dhvlen; u8 *response; + if (tl < sizeof(*data)) + return NVME_AUTH_DHCHAP_FAILURE_INCORRECT_PAYLOAD; + + dhvlen = le16_to_cpu(data->dhvlen); + + /* Validate that hl and dhvlen fit within the transfer length */ + if (sizeof(*data) + 2 * (size_t)data->hl + dhvlen > tl) + return NVME_AUTH_DHCHAP_FAILURE_INCORRECT_PAYLOAD; + pr_debug("%s: ctrl %d qid %d: data hl %d cvalid %d dhvlen %u\n", __func__, ctrl->cntlid, req->sq->qid, data->hl, data->cvalid, dhvlen); if (dhvlen) { @@ -282,11 +291,11 @@ void nvmet_execute_auth_send(struct nvmet_req *req) goto done_kfree; } switch (data->auth_id) { case NVME_AUTH_DHCHAP_MESSAGE_REPLY: - status = nvmet_auth_reply(req, d); + status = nvmet_auth_reply(req, d, tl); if (status == 0) req->sq->dhchap_step = NVME_AUTH_DHCHAP_MESSAGE_SUCCESS1; else { req->sq->dhchap_step = -- 2.52.0
From: Bryam Vargas <hexlabsecurity@proton.me> mainline inclusion from mainline-v7.2-rc1 commit 53cd102a7a56079b11b897835bd9b94c14e6322c category: bugfix bugzilla: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i... -------------------------------- nvmet_execute_disc_get_log_page() validates only the dword alignment of the host-supplied Log Page Offset (lpo). The 64-bit offset is then added to a small kzalloc'd buffer that holds the discovery log page and the result is passed straight to nvmet_copy_to_sgl(), which memcpy()s data_len bytes out to the host with no source-side bound check: u64 offset = nvmet_get_log_page_offset(req->cmd); /* 64-bit host */ size_t data_len = nvmet_get_log_page_len(req->cmd); /* 32-bit host */ ... if (offset & 0x3) { ... } /* only check */ ... alloc_len = sizeof(*hdr) + entry_size * discovery_log_entries(req); buffer = kzalloc(alloc_len, GFP_KERNEL); ... status = nvmet_copy_to_sgl(req, 0, buffer + offset, data_len); The Discovery controller is unauthenticated -- nvmet_host_allowed() returns true unconditionally for the discovery subsystem -- so the call is reachable pre-authentication by any TCP/RDMA/FC peer that can reach the nvmet target. With a discovery log page of ~1 KiB, an attacker requesting up to 4 KiB starting at offset == alloc_len reads the next slab page out and gets its content returned over the fabric (an empirical run on a default nvmet-tcp loopback target leaked 81 canonical kernel pointers in one Get Log Page response). Pointing the offset at unmapped kernel memory faults the in-kernel memcpy and crashes (or panics, on panic_on_oops=1) the target host instead. The attacker-controlled source-side offset pattern "nvmet_copy_to_sgl(req, 0, buffer + ATTACKER_OFFSET, ...)" is unique to nvmet_execute_disc_get_log_page in the entire nvmet codebase: every other Get Log Page handler in admin-cmd.c either ignores lpo (and silently starts every response at offset 0) or tracks a local destination offset with a fixed source pointer. Validate the host-supplied offset against the log page size, cap the copy length to what is actually available, and zero-fill any remainder of the host transfer buffer. The zero-fill matches the existing short-response pattern in nvmet_execute_get_log_changed_ns() (admin-cmd.c) and prevents leaking transport SGL contents when the host asks for more bytes than the log page contains. Fixes: a07b4970f464 ("nvmet: add a generic NVMe target") Cc: stable@vger.kernel.org Reviewed-by: Chaitanya Kulkarni <kch@nvidia.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me> Signed-off-by: Keith Busch <kbusch@kernel.org> Conflicts: drivers/nvme/target/discovery.c [drivers/nvme/target/discovery.c: Replaced NVME_STATUS_DNR with NVME_SC_DNR; added copy_len variable and offset validation; used nvmet_zero_sgl for zero-fill remainder.] Signed-off-by: Lu Chentao <luchentao1@huawei.com> --- drivers/nvme/target/discovery.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/drivers/nvme/target/discovery.c b/drivers/nvme/target/discovery.c index 668d257fa986..d5f0abbbe406 100644 --- a/drivers/nvme/target/discovery.c +++ b/drivers/nvme/target/discovery.c @@ -164,10 +164,11 @@ static void nvmet_execute_disc_get_log_page(struct nvmet_req *req) struct nvmet_ctrl *ctrl = req->sq->ctrl; struct nvmf_disc_rsp_page_hdr *hdr; u64 offset = nvmet_get_log_page_offset(req->cmd); size_t data_len = nvmet_get_log_page_len(req->cmd); size_t alloc_len; + size_t copy_len; struct nvmet_subsys_link *p; struct nvmet_port *r; u32 numrec = 0; u16 status = 0; void *buffer; @@ -237,11 +238,31 @@ static void nvmet_execute_disc_get_log_page(struct nvmet_req *req) nvmet_clear_aen_bit(req, NVME_AEN_BIT_DISC_CHANGE); up_read(&nvmet_config_sem); - status = nvmet_copy_to_sgl(req, 0, buffer + offset, data_len); + /* + * Validate the host-supplied log page offset before copying out. + * Without this check, the host controls a 64-bit byte offset into + * a small kzalloc'd buffer: a value past the log page lets the + * subsequent memcpy read adjacent kernel heap, and a value aimed + * at unmapped kernel memory faults the in-kernel copy and crashes + * the target host. The Discovery controller is unauthenticated, + * so the bug is reachable from any reachable fabric peer. + */ + if (offset > alloc_len) { + req->error_loc = + offsetof(struct nvme_get_log_page_command, lpo); + status = NVME_SC_INVALID_FIELD | NVME_SC_DNR; + goto out_free_buffer; + } + + copy_len = min_t(size_t, data_len, alloc_len - offset); + status = nvmet_copy_to_sgl(req, 0, buffer + offset, copy_len); + if (!status && copy_len < data_len) + status = nvmet_zero_sgl(req, copy_len, data_len - copy_len); +out_free_buffer: kfree(buffer); out: nvmet_req_complete(req, status); } -- 2.52.0
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://atomgit.com/openeuler/kernel/merge_requests/25587 邮件列表地址:https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/E2V... 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://atomgit.com/openeuler/kernel/merge_requests/25587 Mailing list address: https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/E2V...
From: Haoxiang Li <haoxiang_li2024@163.com> stable inclusion from stable-v6.6.145 commit 9136a08dc29328edd9867f2545e73906ac9df93b category: bugfix bugzilla: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=... -------------------------------- commit 1c6267a1d5cf4c73b656f8181b310cbbb3e4767b upstream. receive_encrypted_standard() allocates next_buffer before checking whether the number of compound PDUs already reached MAX_COMPOUND. If the limit check fails, the function returns immediately and the newly allocated next_buffer is not assigned to server->smallbuf/server->bigbuf, making it leaked. Move the MAX_COMPOUND check before allocating next_buffer. Fixes: b24df3e30cbf ("cifs: update receive_encrypted_standard to handle compounded responses") Cc: stable@vger.kernel.org Signed-off-by: Haoxiang Li <haoxiang_li2024@163.com> Signed-off-by: Steve French <stfrench@microsoft.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Lu Chentao <luchentao1@huawei.com> --- fs/smb/client/smb2ops.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c index d4b708f0425e..06cd9890afa9 100644 --- a/fs/smb/client/smb2ops.c +++ b/fs/smb/client/smb2ops.c @@ -4938,10 +4938,16 @@ receive_encrypted_standard(struct TCP_Server_Info *server, next_is_large = server->large_buf; one_more: shdr = (struct smb2_hdr *)buf; next_cmd = le32_to_cpu(shdr->NextCommand); + + if (*num_mids >= MAX_COMPOUND) { + cifs_server_dbg(VFS, "too many PDUs in compound\n"); + return -1; + } + if (next_cmd) { if (WARN_ON_ONCE(next_cmd > pdu_length)) return -1; if (next_is_large) next_buffer = (char *)cifs_buf_get(); @@ -4961,14 +4967,10 @@ receive_encrypted_standard(struct TCP_Server_Info *server, cifs_dbg(FYI, "mid found\n"); mid_entry->decrypted = true; mid_entry->resp_buf_size = server->pdu_size; } - if (*num_mids >= MAX_COMPOUND) { - cifs_server_dbg(VFS, "too many PDUs in compound\n"); - return -1; - } bufs[*num_mids] = buf; mids[(*num_mids)++] = mid_entry; if (mid_entry && mid_entry->handle) ret = mid_entry->handle(server, mid_entry); -- 2.52.0
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://atomgit.com/openeuler/kernel/merge_requests/25586 邮件列表地址:https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/ITG... 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://atomgit.com/openeuler/kernel/merge_requests/25586 Mailing list address: https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/ITG...
From: Zihan Xi <xizh2024@lzu.edu.cn> stable inclusion from stable-v6.6.145 commit 0de5b8e76847f5de26f364a82c6602c4881c30da category: bugfix bugzilla: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=... -------------------------------- commit 7ad2bcf2441430bb2e918fb3ef9a90d775a6e422 upstream. posix_info_sid_size() reads sid[1] to obtain the subauthority count, but its existing boundary check still accepts buffers with only one remaining byte. Require two bytes before reading sid[1] so all client paths that reuse the helper reject truncated POSIX SIDs safely. Fixes: 349e13ad30b4 ("cifs: add smb2 POSIX info level") Cc: stable@vger.kernel.org Reported-by: Yuan Tan <yuantan098@gmail.com> Reported-by: Yifan Wu <yifanwucs@gmail.com> Reported-by: Juefei Pu <tomapufckgml@gmail.com> Reported-by: Xin Liu <bird@lzu.edu.cn> Assisted-by: Codex:gpt-5.4 Signed-off-by: Zihan Xi <xizh2024@lzu.edu.cn> Signed-off-by: Ren Wei <n05ec@lzu.edu.cn> Signed-off-by: Steve French <stfrench@microsoft.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Lu Chentao <luchentao1@huawei.com> --- fs/smb/client/smb2pdu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c index 6c12f696122f..68b78b6bb597 100644 --- a/fs/smb/client/smb2pdu.c +++ b/fs/smb/client/smb2pdu.c @@ -5136,11 +5136,11 @@ SMB2_write(const unsigned int xid, struct cifs_io_parms *io_parms, int posix_info_sid_size(const void *beg, const void *end) { size_t subauth; int total; - if (beg + 1 > end) + if (beg + 2 > end) return -1; subauth = *(u8 *)(beg+1); if (subauth < 1 || subauth > 15) return -1; -- 2.52.0
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://atomgit.com/openeuler/kernel/merge_requests/25588 邮件列表地址:https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/6S7... 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://atomgit.com/openeuler/kernel/merge_requests/25588 Mailing list address: https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/6S7...
From: Norbert Manthey <nmanthey@amazon.de> stable inclusion from stable-v6.6.145 commit 08c600b7e1818539ba5efee4cdb06215c245ca78 category: bugfix bugzilla: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=... -------------------------------- commit e3d9c7160d483fc8f9e225aafad8ecbbc43f3151 upstream. When modefromsid is active, parse_dacl() applies the server-provided sub_auth[2] value from the NFS mode SID to cf_mode without masking to 07777. Apply the correct masking, same as in the read path. Fixes: e2f8fbfb8d09c ("cifs: get mode bits from special sid on stat") Signed-off-by: Norbert Manthey <nmanthey@amazon.de> Assisted-by: Kiro:claude-opus-4.6 Cc: stable@vger.kernel.org Signed-off-by: Steve French <stfrench@microsoft.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Lu Chentao <luchentao1@huawei.com> --- fs/smb/client/cifsacl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/smb/client/cifsacl.c b/fs/smb/client/cifsacl.c index 3d5ef404b886..93bd4fd91648 100644 --- a/fs/smb/client/cifsacl.c +++ b/fs/smb/client/cifsacl.c @@ -888,11 +888,11 @@ static void parse_dacl(struct smb_acl *pdacl, char *end_of_acl, * 07777 = S_ISUID | S_ISGID | S_ISVTX | * S_IRWXU | S_IRWXG | S_IRWXO */ fattr->cf_mode &= ~07777; fattr->cf_mode |= - le32_to_cpu(ppace[i]->sid.sub_auth[2]); + le32_to_cpu(ppace[i]->sid.sub_auth[2]) & 07777; break; } else { if (compare_sids(&(ppace[i]->sid), pownersid) == 0) { access_flags_to_mode(ppace[i]->access_req, ppace[i]->type, -- 2.52.0
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://atomgit.com/openeuler/kernel/merge_requests/25589 邮件列表地址:https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/2VD... 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://atomgit.com/openeuler/kernel/merge_requests/25589 Mailing list address: https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/2VD...
From: Bryam Vargas <hexlabsecurity@proton.me> stable inclusion from stable-v6.6.145 commit 7285276aa50d2839afb5957ffd491ad282dc8f72 category: bugfix bugzilla: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=... -------------------------------- commit 3ec997bd5508e9b25210b5bbec89031629cdb093 upstream. udf_load_sparable_map() accepts a sparing table when sizeof(*st) + le16_to_cpu(st->reallocationTableLen) > sb->s_blocksize is false, i.e. it treats reallocationTableLen as a number of BYTES that must fit in the block. But the table is walked as an array of 8-byte sparingEntry elements: for (i = 0; i < le16_to_cpu(st->reallocationTableLen); i++) { struct sparingEntry *entry = &st->mapEntry[i]; ... entry->origLocation ... } in udf_get_pblock_spar15() and udf_relocate_blocks(). A reallocationTableLen of N therefore passes the check whenever sizeof(*st) + N <= blocksize, yet the consumers index sizeof(*st) + N * sizeof(struct sparingEntry) bytes -- up to ~8x the block. On a crafted UDF image this is an out-of-bounds read in udf_get_pblock_spar15(); udf_relocate_blocks() additionally feeds the same length to udf_update_tag(), whose crc_itu_t() reads far past the block, and its memmove() through st->mapEntry[] is an out-of-bounds write. Validate reallocationTableLen as the entry count it is, with struct_size(). Fixes: 1df2ae31c724 ("udf: Fortify loading of sparing table") Cc: stable@vger.kernel.org Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me> Link: https://patch.msgid.link/20260612-b4-disp-91780c4e-v1-1-f15112ff6882@proton.... Signed-off-by: Jan Kara <jack@suse.cz> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Lu Chentao <luchentao1@huawei.com> --- fs/udf/super.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/udf/super.c b/fs/udf/super.c index 7f63d8f197e4..3d631e2a3668 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -1385,11 +1385,12 @@ static int udf_load_sparable_map(struct super_block *sb, st = (struct sparingTable *)bh->b_data; if (ident != 0 || strncmp(st->sparingIdent.ident, UDF_ID_SPARING, strlen(UDF_ID_SPARING)) || - sizeof(*st) + le16_to_cpu(st->reallocationTableLen) > + struct_size(st, mapEntry, + le16_to_cpu(st->reallocationTableLen)) > sb->s_blocksize) { brelse(bh); continue; } -- 2.52.0
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://atomgit.com/openeuler/kernel/merge_requests/25590 邮件列表地址:https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/QRQ... 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://atomgit.com/openeuler/kernel/merge_requests/25590 Mailing list address: https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/QRQ...
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://atomgit.com/openeuler/kernel/merge_requests/25585 邮件列表地址:https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/BGM... 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://atomgit.com/openeuler/kernel/merge_requests/25585 Mailing list address: https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/BGM...
participants (2)
-
Lu Chentao -
patchwork bot