diff mbox series

[14/14] powerpc/rtas: Consolidate and improve checking for rtas callers

Message ID 20220308135047.478297-15-npiggin@gmail.com (mailing list archive)
State Changes Requested
Headers show
Series powerpc/rtas: various cleanups and improvements | expand

Checks

Context Check Description
snowpatch_ozlabs/github-powerpc_ppctests success Successfully ran 8 jobs.
snowpatch_ozlabs/github-powerpc_selftests success Successfully ran 8 jobs.
snowpatch_ozlabs/github-powerpc_kernel_qemu success Successfully ran 24 jobs.
snowpatch_ozlabs/github-powerpc_clang success Successfully ran 7 jobs.
snowpatch_ozlabs/github-powerpc_sparse success Successfully ran 4 jobs.

Commit Message

Nicholas Piggin March 8, 2022, 1:50 p.m. UTC
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 <npiggin@gmail.com>
---
 arch/powerpc/kernel/rtas.c | 23 +++++++++++++++++------
 1 file changed, 17 insertions(+), 6 deletions(-)

Comments

Laurent Dufour March 15, 2022, 5:26 p.m. UTC | #1
On 08/03/2022, 14:50:47, Nicholas Piggin wrote:
> 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 <npiggin@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;
> +	}

These 3 tests are making the function returning -1, which is previously
only returned in the case the call cannot be achieved because of a hardware
error (as stated in rtas_call()).

Should a dedicated error code been returned here?


> +
>  	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();
>
diff mbox series

Patch

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();