From: Junrui Luo <[email protected]>
spu_process_callback() masks the low bits of the NPC register and uses
the result as an offset into the SPU local store: `ls_pointer = in_be32(ls
+ npc)`. The following guard validates ls_pointer against LS_SIZE, but npc
itself is never bounds-checked.
Fix by rejecting npc greater than LS_SIZE - sizeof(ls_pointer) before the
read, mirroring the adjacent ls_pointer guard and returning the same
-EFAULT.
Fixes: 2dd14934c913 ("[PATCH] spufs: allow SPU code to do syscalls")
Reported-by: Yuhao Jiang <[email protected]>
Cc: [email protected]
Signed-off-by: Junrui Luo <[email protected]>
---
arch/powerpc/platforms/cell/spufs/run.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/powerpc/platforms/cell/spufs/run.c
b/arch/powerpc/platforms/cell/spufs/run.c
index ce52b87496d2..87497316d128 100644
--- a/arch/powerpc/platforms/cell/spufs/run.c
+++ b/arch/powerpc/platforms/cell/spufs/run.c
@@ -317,6 +317,8 @@ static int spu_process_callback(struct spu_context *ctx)
/* get syscall block from local store */
npc = ctx->ops->npc_read(ctx) & ~3;
ls = (void __iomem *)ctx->ops->get_ls(ctx);
+ if (npc > (LS_SIZE - sizeof(ls_pointer)))
+ return -EFAULT;
ls_pointer = in_be32(ls + npc);
if (ls_pointer > (LS_SIZE - sizeof(s)))
return -EFAULT;
--
2.51.2