FAILED: patch "[PATCH] smb: client: fix missing lower-bound check on DFS referral" failed to apply to 5.10-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 5.10-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.10.y
git checkout FETCH_HEAD
git cherry-pick -x e83330c55edc0c3ac08aa6c95e49e4694c65523b
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026092230-mobilize-android-8f08@gregkh' --subject-prefix 'PATCH 5.10.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From e83330c55edc0c3ac08aa6c95e49e4694c65523b Mon Sep 17 00:00:00 2001
From: Frank Sorenson <[email protected]>
Date: Wed, 16 Sep 2026 16:33:55 -0500
Subject: [PATCH] smb: client: fix missing lower-bound check on DFS referral
string offsets
parse_dfs_referrals() checks that DfsPathOffset and NetworkAddressOffset do not exceed the buffer end, but fails to check that they don't point inside the referral header itself.
If a server provides an offset smaller thansizeof(struct dfs_referral_level_3), the derived string pointer overlaps with the struct fields, causing cifs_strndup_from_utf16() to interpret header data as UTF-16 strings.
Fix this by enforcing that string offsets are at least sizeof(*ref).
fs/smb/client/misc.c +10 -2
@@ -788,7 +788,11 @@ parse_dfs_referrals(struct get_dfs_referral_rsp *rsp, u32 rsp_size, node->ref_flag =le16_to_cpu (ref->ReferralEntryFlags);/* copy DfsPath */ -if (le16_to_cpu (ref->DfsPathOffset) > data_end - (char *)ref) { +if (le16_to_cpu (ref->DfsPathOffset) <sizeof (*ref) || +le16_to_cpu (ref->DfsPathOffset) > data_end - (char *)ref) { +cifs_dbg (VFS ,"%s: DfsPathOffset %u out of range [%zu, %td]\n" , + __func__,le16_to_cpu (ref->DfsPathOffset), +sizeof (*ref), data_end - (char *)ref); rc = -EINVAL ; goto parse_DFS_referrals_exit; }
@@ -802,7 +806,11 @@ parse_dfs_referrals(struct get_dfs_referral_rsp *rsp, u32 rsp_size, }/* copy link target UNC */ -if (le16_to_cpu (ref->NetworkAddressOffset) > data_end - (char *)ref) { +if (le16_to_cpu (ref->NetworkAddressOffset) <sizeof (*ref) || +le16_to_cpu (ref->NetworkAddressOffset) > data_end - (char *)ref) { +cifs_dbg (VFS ,"%s: NetworkAddressOffset %u out of range [%zu, %td]\n" , + __func__,le16_to_cpu (ref->NetworkAddressOffset), +sizeof (*ref), data_end - (char *)ref); rc = -EINVAL ; goto parse_DFS_referrals_exit; }
Sasha Levin
maintainerPATCH 1/2 cifs: validate DFS referral string offsets
From: Guangshuo Li <[email protected]>
[ Upstream commit 027a84ac6b50c12ef767c15abfc58aa865820e9e ]
parse_dfs_referrals() validates that the response header and referral array fit in the received buffer, but each referral also contains string offsets supplied by the server.
Those offsets are used to compute the DfsPath and NetworkAddress string pointers without checking whether they still point inside the response buffer. A malformed referral can therefore make the computed pointer exceed the end of the buffer. The resulting negative max_len is then passed to cifs_strndup_from_utf16(), and the non-Unicode path forwards it to kstrndup() as a size_t, allowing strnlen() to read out of bounds.
Validate each string offset before deriving the string pointer.
[5.15 backport: Apply both offset checks to fs/cifs/misc.c, where parse_dfs_referrals() lives in this tree. Preserve the existing parser and error cleanup; no new functions are introduced.]
[ sashal: Reduced backport -- upstream 027a84ac6b50c touches 1 file(s), this
backport carries 1. Not backported here:
fs/smb/client/misc.c
This note is generated from the file lists only; see the resolution record for the reasoning. ]
Stable-dep-of: e83330c55edc ("smb: client: fix missing lower-bound check on DFS referral string offsets")
--- fs/cifs/misc.c | 8 ++++++++ 1 file changed, 8 insertions(+)
fs/cifs/misc.c +8 -0
@@ -757,6 +757,10 @@ parse_dfs_referrals(struct get_dfs_referral_rsp *rsp, u32 rsp_size, node->ref_flag =le16_to_cpu (ref->ReferralEntryFlags);/* copy DfsPath */ +if (le16_to_cpu (ref->DfsPathOffset) > data_end - (char *)ref) { + rc = -EINVAL ; + goto parse_DFS_referrals_exit; + } temp = (char *)ref +le16_to_cpu (ref->DfsPathOffset); max_len = data_end - temp; node->path_name = cifs_strndup_from_utf16(temp, max_len,
@@ -767,6 +771,10 @@ parse_dfs_referrals(struct get_dfs_referral_rsp *rsp, u32 rsp_size, }/* copy link target UNC */ +if (le16_to_cpu (ref->NetworkAddressOffset) > data_end - (char *)ref) { + rc = -EINVAL ; + goto parse_DFS_referrals_exit; + } temp = (char *)ref +le16_to_cpu (ref->NetworkAddressOffset); max_len = data_end - temp; node->node_name = cifs_strndup_from_utf16(temp, max_len,
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 2/2 smb: client: fix missing lower-bound check on DFS referral string offsets
From: Frank Sorenson <[email protected]>
[ Upstream commit e83330c55edc0c3ac08aa6c95e49e4694c65523b ]
parse_dfs_referrals() checks that DfsPathOffset and NetworkAddressOffset do not exceed the buffer end, but fails to check that they don't point inside the referral header itself.
If a server provides an offset smaller thansizeof(struct dfs_referral_level_3), the derived string pointer overlaps with the struct fields, causing cifs_strndup_from_utf16() to interpret header data as UTF-16 strings.
Fix this by enforcing that string offsets are at least sizeof(*ref).
--- fs/cifs/misc.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
fs/cifs/misc.c +10 -2
@@ -757,7 +757,11 @@ parse_dfs_referrals(struct get_dfs_referral_rsp *rsp, u32 rsp_size, node->ref_flag =le16_to_cpu (ref->ReferralEntryFlags);/* copy DfsPath */ -if (le16_to_cpu (ref->DfsPathOffset) > data_end - (char *)ref) { +if (le16_to_cpu (ref->DfsPathOffset) <sizeof (*ref) || +le16_to_cpu (ref->DfsPathOffset) > data_end - (char *)ref) { +cifs_dbg (VFS ,"%s: DfsPathOffset %u out of range [%zu, %td]\n" , + __func__,le16_to_cpu (ref->DfsPathOffset), +sizeof (*ref), data_end - (char *)ref); rc = -EINVAL ; goto parse_DFS_referrals_exit; }
@@ -771,7 +775,11 @@ parse_dfs_referrals(struct get_dfs_referral_rsp *rsp, u32 rsp_size, }/* copy link target UNC */ -if (le16_to_cpu (ref->NetworkAddressOffset) > data_end - (char *)ref) { +if (le16_to_cpu (ref->NetworkAddressOffset) <sizeof (*ref) || +le16_to_cpu (ref->NetworkAddressOffset) > data_end - (char *)ref) { +cifs_dbg (VFS ,"%s: NetworkAddressOffset %u out of range [%zu, %td]\n" , + __func__,le16_to_cpu (ref->NetworkAddressOffset), +sizeof (*ref), data_end - (char *)ref); rc = -EINVAL ; goto parse_DFS_referrals_exit; }
Signature · 1 line
2.53.0