diff options
| author | Zihan Xi <zihanx@nebusec.ai> | 2026-09-16 15:29:25 +0000 |
|---|---|---|
| committer | Paulo Alcantara <pc@manguebit.org> | 2026-09-21 21:40:17 -0300 |
| commit | fa2e9900dd2a3f5a1e7ef5a8c5e8d435feedbfcc (patch) | |
| tree | f65eed844ce32ccefe840661e3e54b225696e783 /fs | |
| parent | 67f4c1c6a1b51e203d986779299824d1c2c590a6 (diff) | |
| download | linux-fa2e9900dd2a3f5a1e7ef5a8c5e8d435feedbfcc.tar.gz linux-fa2e9900dd2a3f5a1e7ef5a8c5e8d435feedbfcc.zip | |
smb: client: validate POSIX create context length
parse_posix_ctxt() reads the fixed nlink, reparse_tag, and mode fields
before checking that the POSIX create context contains them. A short
context can pass the generic checks and still make these fixed-width
reads run past its declared data.
The current in-tree smb2_open_file() path passes a NULL posix pointer,
so this handler is not reached on the ordinary open path. Still require
the POSIX data to cover all three fields before reading them because the
helper performs those unguarded reads. Keep the existing soft-failure
behavior so malformed optional metadata does not fail the open.
Fixes: 69dda3059e7a ("cifs: add SMB2_open() arg to return POSIX data")
Cc: stable@vger.kernel.org
Reported-by: Vega <vega@nebusec.ai>
Assisted-by: LLM
Co-developed-by: Luxing Yin <root@tr0jan.top>
Signed-off-by: Luxing Yin <root@tr0jan.top>
Signed-off-by: Zihan Xi <zihanx@nebusec.ai>
Tested-by: Frank Sorenson <sorenson@redhat.com>
Signed-off-by: Paulo Alcantara <pc@manguebit.org>
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/smb/client/smb2pdu.c | 7 |
1 files changed, 5 insertions, 2 deletions
diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c index 4046500dbe93..538d708b0404 100644 --- a/fs/smb/client/smb2pdu.c +++ b/fs/smb/client/smb2pdu.c @@ -2396,12 +2396,15 @@ static void parse_posix_ctxt(struct create_context *cc, struct smb2_file_all_info *info, struct create_posix_rsp *posix) { - int sid_len; u8 *beg = (u8 *)cc + le16_to_cpu(cc->DataOffset); - u8 *end = beg + le32_to_cpu(cc->DataLength); + u32 dlen = le32_to_cpu(cc->DataLength); + u8 *end = beg + dlen; + int sid_len; u8 *sid; memset(posix, 0, sizeof(*posix)); + if (dlen < 3 * sizeof(__le32)) + return; posix->nlink = get_unaligned_le32(beg); posix->reparse_tag = get_unaligned_le32(beg + 4); |
