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

From: Junrui Luo via B4 Relay

Date: Wed Aug 12 2026 - 01:49:22 EST


From: Junrui Luo <moonafterrain@xxxxxxxxxxx>

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 <danisjiang@xxxxxxxxx>
Assisted-by: Claude:claude-opus-5
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Junrui Luo <moonafterrain@xxxxxxxxxxx>
---
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