[PATCH 2/5] powerpc/spufs: fix out-of-bounds read in spufs_wbox_info_read()

Junrui Luo via B4 Relay <[email protected]>
Newsgroups org.ozlabs.lists.linuxppc-dev,org.kernel.feeds.b4-sent,org.kernel.vger.linux-kernel,org.kernel.vger.stable
Message-ID <[email protected]>
From: Junrui Luo <[email protected]>

Reading a context's wbox_info file can copy up to 48 bytes past the end
of an on-stack buffer to userspace.

spufs_wbox_info_cnt() already returns a byte count: it multiplies the
number of queued SPU inbound mailbox entries by sizeof(u32), yielding one
of 0, 4, 8, 12 or 16. spufs_wbox_info_dump() uses it that way and passes
the result to spufs_dump_emit() unscaled.

spufs_wbox_info_read() instead multiplies it by sizeof(u32) a second time
and hands the product to simple_read_from_buffer() as the length of the
available data. The buffer being described is u32
data[ARRAY_SIZE(ctx->csa.spu_mailbox_data)], i.e. 16 bytes, but the value
passed reaches 64. simple_read_from_buffer() clamps the transfer against
that length rather than against the buffer, so once the mailbox holds two
or more entries, a read reaching past offset 16 - either by requesting
more than 16 bytes or by seeking there first - copies adjacent kernel
stack to userspace.

The mailbox occupancy is under unprivileged control. Writing to the
context's wbox file drives spu_backing_wbox_write(), which lowers the
free-slot count in mb_stat_R from four down to zero, and wbox_info is
mode 0444 in spufs_dir_contents[], so the owner of the context can then
read it back.

This dates to the introduction of spufs_wbox_info_cnt(). Before that
commit the local count held an entry count, for which the sizeof(u32)
scaling at the call site was correct.

Pass the byte count through unscaled, as spufs_wbox_info_dump() does.

Fixes: 88413a6bfbbe ("powerpc/spufs: fix copy_to_user while atomic")
Reported-by: Yuhao Jiang <[email protected]>
Assisted-by: Claude:claude-opus-5
Cc: [email protected]
Signed-off-by: Junrui Luo <[email protected]>
---
 arch/powerpc/platforms/cell/spufs/file.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index de7494748fec..07b1755ddc3d 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -2028,8 +2028,7 @@ static ssize_t spufs_wbox_info_read(struct file *file, char __user *buf,
 	spin_unlock(&ctx->csa.register_lock);
 	spu_release_saved(ctx);
 
-	return simple_read_from_buffer(buf, len, pos, &data,
-				count * sizeof(u32));
+	return simple_read_from_buffer(buf, len, pos, &data, count);
 }
 
 static const struct file_operations spufs_wbox_info_fops = {

-- 
2.51.2
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.