[PATCH OLK-5.10] [Backport] smb/client: handle overlapping allocated ranges in fallocate
From: Huiwen He <hehuiwen@kylinos.cn> mainline inclusion from mainline-v7.2-rc4 commit b09ae45d85dc816987a71db9eebc54b0ae288e94 category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/17070 CVE: CVE-2026-68388 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i... -------------------------------- smb3_simple_fallocate_range() can skip holes when an allocated range returned by the server starts before the current fallocate offset. The skipped hole is not zero-filled, but fallocate still returns success. A later write to that hole may therefore fail with ENOSPC. The function queries allocated ranges so that it can preserve existing contents and write zeroes only into holes. However, the server may return a range that starts before the current fallocate offset. For example, assume the fallocate request is [100, 400) and the only allocated range returned by the server is [0, 200): Request: [100, 400) Server range: [ 0, 200) allocated Correct: [100, 200) allocated data, skip [200, 400) hole, zero-fill Current: [100, 300) skipped [300, 400) zero-filled afterwards The current code adds the full server range length, 200, to the current offset 100 and moves to 300. As a result, the hole in [200, 300) is skipped without being zero-filled. Fix this by advancing only over the part of the allocated range that overlaps the current fallocate offset. Ignore ranges that end before the current offset and reject ranges whose end offset overflows. This also prevents a malformed range length from causing an out-of-bounds zero-buffer read. Fixes: 966a3cb7c7db ("cifs: improve fallocate emulation") Signed-off-by: Huiwen He <hehuiwen@kylinos.cn> Reviewed-by: ChenXiaoSong <chenxiaosong@kylinos.cn> Signed-off-by: Steve French <stfrench@microsoft.com> Signed-off-by: Lu Chentao <luchentao1@huawei.com> --- fs/cifs/smb2ops.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index f46c99b61c04..dd72160a4bb4 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c @@ -3561,10 +3561,11 @@ static int smb3_simple_fallocate_range(unsigned int xid, loff_t off, loff_t len) { struct file_allocated_range_buffer in_data, *out_data = NULL, *tmp_data; u32 out_data_len; char *buf = NULL; + u64 range_start, range_len, range_end; loff_t l; int rc; in_data.file_offset = cpu_to_le64(off); in_data.length = cpu_to_le64(len); @@ -3597,17 +3598,25 @@ static int smb3_simple_fallocate_range(unsigned int xid, if (out_data_len < sizeof(struct file_allocated_range_buffer)) { rc = -EINVAL; goto out; } - if (off < le64_to_cpu(tmp_data->file_offset)) { + range_start = le64_to_cpu(tmp_data->file_offset); + range_len = le64_to_cpu(tmp_data->length); + if (check_add_overflow(range_start, range_len, &range_end) || + range_end > S64_MAX) { + rc = -EINVAL; + goto out; + } + + if (off < range_start) { /* * We are at a hole. Write until the end of the region * or until the next allocated data, * whichever comes next. */ - l = le64_to_cpu(tmp_data->file_offset) - off; + l = range_start - off; if (len < l) l = len; rc = smb3_simple_fallocate_write_range(xid, tcon, cfile, off, l, buf); if (rc) @@ -3620,15 +3629,17 @@ static int smb3_simple_fallocate_range(unsigned int xid, /* * We are at a section of allocated data, just skip forward * until the end of the data or the end of the region * we are supposed to fallocate, whichever comes first. */ - l = le64_to_cpu(tmp_data->length); - if (len < l) - l = len; - off += l; - len -= l; + if (off < range_end) { + l = range_end - off; + if (len < l) + l = len; + off += l; + len -= l; + } tmp_data = &tmp_data[1]; out_data_len -= sizeof(struct file_allocated_range_buffer); } -- 2.52.0
From: Yichong Chen <chenyichong@uniontech.com> mainline inclusion from mainline-v7.2-rc5 commit f6f5ee2aa33b350c671721b965251c42cebb962e category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/17157 CVE: CVE-2026-68343 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i... -------------------------------- parse_dfs_referrals() validates that the response contains the fixed referral entry array and, on for-next, the per-referral string offsets. However, the response also contains a PathConsumed value that is later used for DFS path parsing. If a malformed response provides a PathConsumed value larger than the search name, later DFS parsing can advance beyond the end of the path. Validate PathConsumed against the search name length before storing it in the parsed referral. Fixes: 4ecce920e13a ("CIFS: move DFS response parsing out of SMB1 code") Reviewed-by: Paulo Alcantara (Red Hat) <pc@manguebit.org> Signed-off-by: Yichong Chen <chenyichong@uniontech.com> Signed-off-by: Steve French <stfrench@microsoft.com> Conflicts: fs/cifs/misc.c [fs/cifs/misc.c: resolved via git 3-way merge of upstream f6f5ee2aa33b (clone base/theirs vs local); no overlap with local divergence] Signed-off-by: Lu Chentao <luchentao1@huawei.com> --- fs/cifs/misc.c | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 802d792306a3..e8e8a862bfdb 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -691,10 +691,12 @@ parse_dfs_referrals(struct get_dfs_referral_rsp *rsp, u32 rsp_size, const char *searchName, bool is_unicode) { int i, rc = 0; char *data_end; struct dfs_referral_level_3 *ref; + unsigned int path_consumed; + size_t search_name_len; *num_of_nodes = le16_to_cpu(rsp->NumberOfReferrals); if (*num_of_nodes < 1) { cifs_dbg(VFS, "num_referrals: must be at least > 0, but we get num_referrals = %d\n", @@ -721,33 +723,47 @@ parse_dfs_referrals(struct get_dfs_referral_rsp *rsp, u32 rsp_size, GFP_KERNEL); if (*target_nodes == NULL) { rc = -ENOMEM; goto parse_DFS_referrals_exit; } + search_name_len = strlen(searchName); /* collect necessary data from referrals */ for (i = 0; i < *num_of_nodes; i++) { char *temp; int max_len; struct dfs_info3_param *node = (*target_nodes)+i; node->flags = le32_to_cpu(rsp->DFSFlags); + path_consumed = le16_to_cpu(rsp->PathConsumed); if (is_unicode) { - __le16 *tmp = kmalloc(strlen(searchName)*2 + 2, - GFP_KERNEL); - if (tmp == NULL) { + size_t search_name_utf16_len = search_name_len * 2 + 2; + __le16 *tmp; + + if (path_consumed > search_name_utf16_len) { + rc = -EINVAL; + goto parse_DFS_referrals_exit; + } + + tmp = kmalloc(search_name_utf16_len, GFP_KERNEL); + if (!tmp) { rc = -ENOMEM; goto parse_DFS_referrals_exit; } - cifsConvertToUTF16((__le16 *) tmp, searchName, + cifsConvertToUTF16((__le16 *)tmp, searchName, PATH_MAX, nls_codepage, remap); - node->path_consumed = cifs_utf16_bytes(tmp, - le16_to_cpu(rsp->PathConsumed), - nls_codepage); + node->path_consumed = cifs_utf16_bytes(tmp, path_consumed, + nls_codepage); kfree(tmp); - } else - node->path_consumed = le16_to_cpu(rsp->PathConsumed); + } else { + if (path_consumed > search_name_len) { + rc = -EINVAL; + goto parse_DFS_referrals_exit; + } + + node->path_consumed = path_consumed; + } node->server_type = le16_to_cpu(ref->ServerType); node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags); /* copy DfsPath */ -- 2.52.0
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://atomgit.com/openeuler/kernel/merge_requests/26697 邮件列表地址:https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/2ZB... 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/26697 Mailing list address: https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/2ZB...
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://atomgit.com/openeuler/kernel/merge_requests/26698 邮件列表地址:https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/SYU... 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/26698 Mailing list address: https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/SYU...
participants (2)
-
Lu Chentao -
patchwork bot