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



Reply via email to