diff options
| author | Frank Sorenson <sorenson@redhat.com> | 2026-08-17 12:16:57 -0500 |
|---|---|---|
| committer | Paulo Alcantara <pc@manguebit.org> | 2026-08-24 17:08:53 -0300 |
| commit | 05f78e6cf34ea3a285053bd5999e08e8ac298bd5 (patch) | |
| tree | ad00bb50414b0efd5017f96aab0d844563310064 /fs | |
| parent | 62656b024efc21c3230eade1a847f25871c3d2bb (diff) | |
smb: client: fix use-before-check of ReparseDataLength in reparse_buf_ptr()
reparse_buf_ptr() reads buf->ReparseDataLength before checking that
count covers the full fixed header:
buf = (struct reparse_data_buffer *)((u8 *)io + off);
len = sizeof(*buf); /* 8 bytes */
rdlen = le16_to_cpu(buf->ReparseDataLength); /* offset 4, 2 bytes */
if (count < len || count < rdlen + len) /* check comes after */
struct reparse_data_buffer has ReparseDataLength at offset 4. If a
server returns OutputCount < 6, the read at offset 4-5 reaches past
the end of the received data. The off+count bounds against iov_len
were already validated, but that does not protect against count being
smaller than sizeof(*buf).
Split the check: verify count >= sizeof(*buf) before reading
ReparseDataLength, then verify count covers the data region.
Fixes: a158bb66b137 ("smb: client: optimise reparse point querying")
Cc: stable@vger.kernel.org
Signed-off-by: Frank Sorenson <sorenson@redhat.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Paulo Alcantara <pc@manguebit.org>
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/smb/client/smb2inode.c | 6 |
1 files changed, 4 insertions, 2 deletions
diff --git a/fs/smb/client/smb2inode.c b/fs/smb/client/smb2inode.c index bcaa44814b71..98ea5c6c34af 100644 --- a/fs/smb/client/smb2inode.c +++ b/fs/smb/client/smb2inode.c @@ -41,9 +41,11 @@ static struct reparse_data_buffer *reparse_buf_ptr(struct kvec *iov) buf = (struct reparse_data_buffer *)((u8 *)io + off); len = sizeof(*buf); - rdlen = le16_to_cpu(buf->ReparseDataLength); + if (count < len) + return ERR_PTR(smb_EIO2(smb_eio_trace_reparse_rdlen, count, 0)); - if (count < len || count < rdlen + len) + rdlen = le16_to_cpu(buf->ReparseDataLength); + if (count < rdlen + len) return ERR_PTR(smb_EIO2(smb_eio_trace_reparse_rdlen, count, rdlen)); return buf; } |
