6.6-stable review patch. If anyone has any objections, please let me know. ------------------ From: Frank Sorenson commit e83330c55edc0c3ac08aa6c95e49e4694c65523b upstream. 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: 4ecce920e13a ("CIFS: move DFS response parsing out of SMB1 code") Cc: stable@vger.kernel.org Signed-off-by: Frank Sorenson Reviewed-by: David Howells Signed-off-by: Paulo Alcantara Signed-off-by: Greg Kroah-Hartman --- fs/smb/client/misc.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) --- a/fs/smb/client/misc.c +++ b/fs/smb/client/misc.c @@ -1056,7 +1056,11 @@ parse_dfs_referrals(struct get_dfs_refer 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; } @@ -1070,7 +1074,11 @@ parse_dfs_referrals(struct get_dfs_refer } /* 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; }