Skip to content

Commit b078f39

Browse files
dhkts1smfrench
authored andcommitted
ksmbd: zero the smb2_read alignment tail to avoid an infoleak
Commit 6b9a2e0 ("ksmbd: avoid zeroing the read buffer in smb2_read()") switched the SMB2 READ payload buffer from kvzalloc() to kvmalloc(), on the premise that only the nbytes actually read are ever transmitted, so the ALIGN(length, 8) tail need not be initialized. That premise does not hold for a compound response. ksmbd_vfs_read() fills only nbytes, leaving [nbytes, ALIGN(length, 8)) uninitialized. The aux payload is pinned as the last response iov with iov_len == nbytes, but when the READ is a member of a compound, init_chained_smb2_rsp() 8-byte-aligns the previous member by extending that same iov: new_len = ALIGN(len, 8); work->iov[work->iov_idx].iov_len += (new_len - len); inc_rfc1001_len(work->response_buf, new_len - len); so up to 7 uninitialized bytes of the kvmalloc()'d slab tail are sent to the client. When the read length is small the buffer is served from a general kmalloc slab, so those bytes can be stale kernel-heap contents, including pointer values -- an information leak usable to defeat KASLR. An authenticated client triggers it with a compound request containing a READ whose returned nbytes is not 8-aligned (for example [READ, CLOSE] with a 1-byte read). Zero only the alignment tail after the read, preserving the bulk no-zeroing optimization of 6b9a2e0. Fixes: 6b9a2e0 ("ksmbd: avoid zeroing the read buffer in smb2_read()") Cc: stable@vger.kernel.org Signed-off-by: Gil Portnoy <dddhkts1@gmail.com> Acked-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Steve French <stfrench@microsoft.com>
1 parent aa5d8f3 commit b078f39

1 file changed

Lines changed: 9 additions & 0 deletions

File tree

fs/smb/server/smb2pdu.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7446,6 +7446,15 @@ int smb2_read(struct ksmbd_work *work)
74467446
goto out;
74477447
}
74487448

7449+
/*
7450+
* ksmbd_vfs_read() fills only nbytes; the [nbytes, ALIGN(nbytes, 8))
7451+
* tail of the un-zeroed buffer is transmitted as compound-response
7452+
* alignment padding, leaking uninitialized kernel memory to the
7453+
* client. Zero just that tail.
7454+
*/
7455+
if (nbytes & 7)
7456+
memset(aux_payload_buf + nbytes, 0, ALIGN(nbytes, 8) - nbytes);
7457+
74497458
if ((nbytes == 0 && length != 0) || nbytes < mincount) {
74507459
kvfree(aux_payload_buf);
74517460
rsp->hdr.Status = STATUS_END_OF_FILE;

0 commit comments

Comments
 (0)