Skip to content

Commit a16f70a

Browse files
Zisen Yegregkh
authored andcommitted
smb/client: fix out-of-bounds read in smb2_compound_op()
commit 8d09328 upstream. If a server sends a truncated response but a large OutputBufferLength, and terminates the EA list early, check_wsl_eas() returns success without validating that the entire OutputBufferLength fits within iov_len. Then smb2_compound_op() does: memcpy(idata->wsl.eas, data[0], size[0]); Where size[0] is OutputBufferLength. If iov_len is smaller than size[0], memcpy can read beyond the end of the rsp_iov allocation and leak adjacent kernel heap memory. Link: https://lore.kernel.org/linux-cifs/d998240c-aca9-420d-9dbd-f5ba24af19e0@chenxiaosong.com/ Fixes: ea41367 ("smb: client: introduce SMB2_OP_QUERY_WSL_EA") Cc: stable@vger.kernel.org Signed-off-by: Zisen Ye <zisenye@stu.xidian.edu.cn> Reviewed-by: ChenXiaoSong <chenxiaosong@kylinos.cn> Signed-off-by: Steve French <stfrench@microsoft.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent e5f9824 commit a16f70a

1 file changed

Lines changed: 8 additions & 4 deletions

File tree

fs/smb/client/smb2inode.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ static int check_wsl_eas(struct kvec *rsp_iov)
111111
u32 outlen, next;
112112
u16 vlen;
113113
u8 nlen;
114-
u8 *end;
114+
u8 *ea_end, *iov_end;
115115

116116
outlen = le32_to_cpu(rsp->OutputBufferLength);
117117
if (outlen < SMB2_WSL_MIN_QUERY_EA_RESP_SIZE ||
@@ -120,15 +120,19 @@ static int check_wsl_eas(struct kvec *rsp_iov)
120120

121121
ea = (void *)((u8 *)rsp_iov->iov_base +
122122
le16_to_cpu(rsp->OutputBufferOffset));
123-
end = (u8 *)rsp_iov->iov_base + rsp_iov->iov_len;
123+
ea_end = (u8 *)ea + outlen;
124+
iov_end = (u8 *)rsp_iov->iov_base + rsp_iov->iov_len;
125+
if (ea_end > iov_end)
126+
return -EINVAL;
127+
124128
for (;;) {
125-
if ((u8 *)ea > end - sizeof(*ea))
129+
if ((u8 *)ea > ea_end - sizeof(*ea))
126130
return -EINVAL;
127131

128132
nlen = ea->ea_name_length;
129133
vlen = le16_to_cpu(ea->ea_value_length);
130134
if (nlen != SMB2_WSL_XATTR_NAME_LEN ||
131-
(u8 *)ea->ea_data + nlen + 1 + vlen > end)
135+
(u8 *)ea->ea_data + nlen + 1 + vlen > ea_end)
132136
return -EINVAL;
133137

134138
switch (vlen) {

0 commit comments

Comments
 (0)