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 than
sizeof(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).

Fixes: 4ecce920e1 ("CIFS: move DFS response parsing out of SMB1 code")
Cc: stable@vger.kernel.org
Signed-off-by: Frank Sorenson <sorenson@redhat.com>
Reviewed-by: David Howells <dhowells@redhat.com>
Signed-off-by: Paulo Alcantara <pc@manguebit.org>
This commit is contained in:
Frank Sorenson 2026-09-16 16:33:55 -05:00 committed by Paulo Alcantara
parent f73726b83e
commit e83330c55e

View File

@ -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;
}