]> www.infradead.org Git - users/hch/misc.git/commitdiff
cifs: parse_dfs_referrals: prevent oob on malformed input
authorEugene Korenevsky <ekorenevsky@aliyun.com>
Mon, 13 Oct 2025 18:39:30 +0000 (21:39 +0300)
committerSteve French <stfrench@microsoft.com>
Thu, 16 Oct 2025 03:10:28 +0000 (22:10 -0500)
Malicious SMB server can send invalid reply to FSCTL_DFS_GET_REFERRALS

- reply smaller than sizeof(struct get_dfs_referral_rsp)
- reply with number of referrals smaller than NumberOfReferrals in the
header

Processing of such replies will cause oob.

Return -EINVAL error on such replies to prevent oob-s.

Signed-off-by: Eugene Korenevsky <ekorenevsky@aliyun.com>
Cc: stable@vger.kernel.org
Suggested-by: Nathan Chancellor <nathan@kernel.org>
Acked-by: Paulo Alcantara (Red Hat) <pc@manguebit.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/smb/client/misc.c

index dda6dece802ad2ae1008570ac09d8a2ec7a4625f..e10123d8cd7d93af4cca37ef55df2ac4679f7dfe 100644 (file)
@@ -916,6 +916,14 @@ parse_dfs_referrals(struct get_dfs_referral_rsp *rsp, u32 rsp_size,
        char *data_end;
        struct dfs_referral_level_3 *ref;
 
+       if (rsp_size < sizeof(*rsp)) {
+               cifs_dbg(VFS | ONCE,
+                        "%s: header is malformed (size is %u, must be %zu)\n",
+                        __func__, rsp_size, sizeof(*rsp));
+               rc = -EINVAL;
+               goto parse_DFS_referrals_exit;
+       }
+
        *num_of_nodes = le16_to_cpu(rsp->NumberOfReferrals);
 
        if (*num_of_nodes < 1) {
@@ -925,6 +933,15 @@ parse_dfs_referrals(struct get_dfs_referral_rsp *rsp, u32 rsp_size,
                goto parse_DFS_referrals_exit;
        }
 
+       if (sizeof(*rsp) + *num_of_nodes * sizeof(REFERRAL3) > rsp_size) {
+               cifs_dbg(VFS | ONCE,
+                        "%s: malformed buffer (size is %u, must be at least %zu)\n",
+                        __func__, rsp_size,
+                        sizeof(*rsp) + *num_of_nodes * sizeof(REFERRAL3));
+               rc = -EINVAL;
+               goto parse_DFS_referrals_exit;
+       }
+
        ref = (struct dfs_referral_level_3 *) &(rsp->referrals);
        if (ref->VersionNumber != cpu_to_le16(3)) {
                cifs_dbg(VFS, "Referrals of V%d version are not supported, should be V3\n",