Add range checking from the rtas syscall, and other error checks
and warnings to kernel callers, so problems can be found and
fixed.

Signed-off-by: Nicholas Piggin <npig...@gmail.com>
---
 arch/powerpc/kernel/rtas.c | 23 +++++++++++++++++------
 1 file changed, 17 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index adf4892aeecd..7f8a3fd685f9 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -428,6 +428,23 @@ static int notrace va_raw_rtas_call(struct rtas_args 
*args, int token,
 {
        int i;
 
+       if (!irqs_disabled()) {
+               WARN_ON_ONCE(1);
+               return -1;
+       }
+
+       if (!rtas.entry || token == RTAS_UNKNOWN_SERVICE) {
+               WARN_ON_ONCE(1);
+               return -1;
+       }
+
+       if (nargs >= ARRAY_SIZE(args->args)
+           || nret > ARRAY_SIZE(args->args)
+           || nargs + nret > ARRAY_SIZE(args->args)) {
+               WARN_ON_ONCE(1);
+               return -1;
+       }
+
        args->token = cpu_to_be32(token);
        args->nargs = cpu_to_be32(nargs);
        args->nret  = cpu_to_be32(nret);
@@ -476,9 +493,6 @@ int rtas_call(int token, int nargs, int nret, int *outputs, 
...)
        char *buff_copy = NULL;
        int ret;
 
-       if (!rtas.entry || token == RTAS_UNKNOWN_SERVICE)
-               return -1;
-
        if ((mfmsr() & (MSR_IR|MSR_DR)) != (MSR_IR|MSR_DR)) {
                WARN_ON_ONCE(1);
                return -1;
@@ -955,9 +969,6 @@ int rtas_call_reentrant(int token, int nargs, int nret, int 
*outputs, ...)
        unsigned long flags;
        int ret;
 
-       if (!rtas.entry || token == RTAS_UNKNOWN_SERVICE)
-               return -1;
-
        local_irq_save(flags);
        preempt_disable();
 
-- 
2.23.0

Reply via email to