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 Assisted-by: LLM Co-developed-by: Luxing Yin Signed-off-by: Luxing Yin Signed-off-by: Zihan Xi --- changes in v5: - Rerolled the series after fixing a NULL dereference reported by the kernel test robot Smatch analysis in patch 5: https://lore.kernel.org/r/202609241449.HlHmnZFZ-lkp@intel.com/ - v4 Link: https://lore.kernel.org/all/cover.1789478666.git.zihanx@nebusec.ai/ changes in v4: - Keep the handler-level minimum check and preserve soft failure for malformed optional POSIX metadata. - v3 Link: https://lore.kernel.org/all/cover.1788516372.git.zihanx@nebusec.ai/ changes in v3: - Split the POSIX handler check into a separate patch and corrected the parser Fixes history. - v2 Link: https://lore.kernel.org/all/cover.1787486936.git.zihanx@nebusec.ai/ changes in v2: - Add the POSIX handler check for the three fixed fields. - v1 Link: https://lore.kernel.org/all/eb1bc35611f91bd10a4772400b37fac26f660956.1782579150.git.xizh2024@lzu.edu.cn/ --- fs/smb/client/smb2pdu.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c index 7a6627400ba30..1b2ca3b2c2f87 100644 --- a/fs/smb/client/smb2pdu.c +++ b/fs/smb/client/smb2pdu.c @@ -2395,12 +2395,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); -- 2.43.0