Re: [PATCH 1/2] smb: client: fix create context out-of-bounds reads

Steve French <[email protected]>
Newsgroups org.kernel.vger.linux-cifs
Message-ID <CAH2r5mvzR7npgJirx9e4GAKdbva9YAJBj6P71bSxJ3SbpF9dGw@mail.gmail.com>
This regresses all xfstests when I tried it.   Looks like a bug in the
patch so have not merged this one (although have merged
smb-client-harden-POSIX-SID-length-parsing pending more testing).
Let me know if you update it.

On Sun, Jun 28, 2026 at 4:20 AM Ren Wei <[email protected]> wrote:
>
> From: Zihan Xi <[email protected]>
>
> smb2_parse_contexts() validates generic create-context layout but does
> not ensure each handler's minimum size before parsing. A malicious
> server can supply a truncated QFid (Query On Disk ID) context with
> DataLength zero; parse_query_id_ctxt() then reads fixed offsets past
> the context boundary and triggers a slab out-of-bounds read.
>
> Bound each context by its Next field and reject lease, QFid, and POSIX
> contexts that are shorter than their parsers require.
>
> Fixes: 89a5bfa350fa ("smb3: optimize open to not send query file internal info")
> Cc: [email protected]
> Reported-by: Yuan Tan <[email protected]>
> Reported-by: Yifan Wu <[email protected]>
> Reported-by: Juefei Pu <[email protected]>
> Reported-by: Xin Liu <[email protected]>
> Assisted-by: Codex:gpt-5.4
> Signed-off-by: Zihan Xi <[email protected]>
> Signed-off-by: Ren Wei <[email protected]>
> ---
>  fs/smb/client/smb2pdu.c | 21 +++++++++++++++++++--
>  1 file changed, 19 insertions(+), 2 deletions(-)
>
> diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c
> index 3bd300347f16..840bc81718da 100644
> --- a/fs/smb/client/smb2pdu.c
> +++ b/fs/smb/client/smb2pdu.c
> @@ -2405,6 +2405,7 @@ int smb2_parse_contexts(struct TCP_Server_Info *server,
>         struct smb2_create_rsp *rsp = rsp_iov->iov_base;
>         struct create_context *cc;
>         size_t rem, off, len;
> +       size_t cc_len;
>         size_t doff, dlen;
>         size_t noff, nlen;
>         char *name;
> @@ -2427,9 +2428,18 @@ int smb2_parse_contexts(struct TCP_Server_Info *server,
>                 buf->IndexNumber = 0;
>
>         while (rem >= sizeof(*cc)) {
> +               off = le32_to_cpu(cc->Next);
> +               if (off) {
> +                       if ((off & 0x7) || off > rem)
> +                               return -EINVAL;
> +                       cc_len = off;
> +               } else {
> +                       cc_len = rem;
> +               }
> +
>                 doff = le16_to_cpu(cc->DataOffset);
>                 dlen = le32_to_cpu(cc->DataLength);
> -               if (check_add_overflow(doff, dlen, &len) || len > rem)
> +               if (check_add_overflow(doff, dlen, &len) || len > cc_len)
>                         return -EINVAL;
>
>                 noff = le16_to_cpu(cc->NameOffset);
> @@ -2441,16 +2451,23 @@ int smb2_parse_contexts(struct TCP_Server_Info *server,
>                 switch (nlen) {
>                 case 4:
>                         if (!strncmp(name, SMB2_CREATE_REQUEST_LEASE, 4)) {
> +                               if (cc_len < server->vals->create_lease_size)
> +                                       return -EINVAL;
>                                 *oplock = server->ops->parse_lease_buf(cc, epoch,
>                                                                        lease_key);
>                         } else if (buf &&
>                                    !strncmp(name, SMB2_CREATE_QUERY_ON_DISK_ID, 4)) {
> +                               if (cc_len < sizeof(struct create_disk_id_rsp))
> +                                       return -EINVAL;
>                                 parse_query_id_ctxt(cc, buf);
>                         }
>                         break;
>                 case 16:
> -                       if (posix && !memcmp(name, smb3_create_tag_posix, 16))
> +                       if (posix && !memcmp(name, smb3_create_tag_posix, 16)) {
> +                               if (dlen < 3 * sizeof(__le32) + MIN_SID_LEN + 2)
> +                                       return -EINVAL;
>                                 parse_posix_ctxt(cc, buf, posix);
> +                       }
>                         break;
>                 default:
>                         cifs_dbg(FYI, "%s: unhandled context (nlen=%zu dlen=%zu)\n",
> --
> 2.43.0
>
>


-- 
Thanks,

Steve
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.