diff mbox series

firmware: qcom: scm: Fix crash in qcom_scm_call_atomic1()

Message ID 20180409214016.21219-1-niklas.cassel@linaro.org
State Accepted
Commit 5ec3444c8346c922316f4effafa8afc17defda0e
Headers show
Series firmware: qcom: scm: Fix crash in qcom_scm_call_atomic1() | expand

Commit Message

Niklas Cassel April 9, 2018, 9:40 p.m. UTC
qcom_scm_call_atomic1() can crash with a NULL pointer dereference at
qcom_scm_call_atomic1+0x30/0x48.

disassembly of qcom_scm_call_atomic1():
...
<0xc08d73b0 <+12>: ldr r3, [r12]
... (no instruction explicitly modifies r12)
0xc08d73cc <+40>: smc 0
... (no instruction explicitly modifies r12)
0xc08d73d4 <+48>: ldr r3, [r12] <- crashing instruction
...

Since the first ldr is successful, and since r12 isn't explicitly
modified by any instruction between the first and the second ldr,
it must have been modified by the smc call, which is ok,
since r12 is caller save according to the AAPCS.

Add r12 to the clobber list so that the compiler knows that the
callee potentially overwrites the value in r12.
Clobber descriptions may not in any way overlap with an input or
output operand.

Signed-off-by: Niklas Cassel <niklas.cassel@linaro.org>

---
 drivers/firmware/qcom_scm-32.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

-- 
2.14.3

--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Comments

Bjorn Andersson April 10, 2018, 6:58 p.m. UTC | #1
On Mon 09 Apr 14:40 PDT 2018, Niklas Cassel wrote:

> qcom_scm_call_atomic1() can crash with a NULL pointer dereference at

> qcom_scm_call_atomic1+0x30/0x48.

> 

> disassembly of qcom_scm_call_atomic1():

> ...

> <0xc08d73b0 <+12>: ldr r3, [r12]

> ... (no instruction explicitly modifies r12)

> 0xc08d73cc <+40>: smc 0

> ... (no instruction explicitly modifies r12)

> 0xc08d73d4 <+48>: ldr r3, [r12] <- crashing instruction

> ...

> 

> Since the first ldr is successful, and since r12 isn't explicitly

> modified by any instruction between the first and the second ldr,

> it must have been modified by the smc call, which is ok,

> since r12 is caller save according to the AAPCS.

> 

> Add r12 to the clobber list so that the compiler knows that the

> callee potentially overwrites the value in r12.

> Clobber descriptions may not in any way overlap with an input or

> output operand.

> 


Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org>


Regards,
Bjorn

> Signed-off-by: Niklas Cassel <niklas.cassel@linaro.org>

> ---

>  drivers/firmware/qcom_scm-32.c | 8 ++++----

>  1 file changed, 4 insertions(+), 4 deletions(-)

> 

> diff --git a/drivers/firmware/qcom_scm-32.c b/drivers/firmware/qcom_scm-32.c

> index dfbd894d5bb7..4e24e591ae74 100644

> --- a/drivers/firmware/qcom_scm-32.c

> +++ b/drivers/firmware/qcom_scm-32.c

> @@ -147,7 +147,7 @@ static u32 smc(u32 cmd_addr)

>  			"smc	#0	@ switch to secure world\n"

>  			: "=r" (r0)

>  			: "r" (r0), "r" (r1), "r" (r2)

> -			: "r3");

> +			: "r3", "r12");

>  	} while (r0 == QCOM_SCM_INTERRUPTED);

>  

>  	return r0;

> @@ -263,7 +263,7 @@ static s32 qcom_scm_call_atomic1(u32 svc, u32 cmd, u32 arg1)

>  			"smc    #0      @ switch to secure world\n"

>  			: "=r" (r0)

>  			: "r" (r0), "r" (r1), "r" (r2)

> -			: "r3");

> +			: "r3", "r12");

>  	return r0;

>  }

>  

> @@ -298,7 +298,7 @@ static s32 qcom_scm_call_atomic2(u32 svc, u32 cmd, u32 arg1, u32 arg2)

>  			"smc    #0      @ switch to secure world\n"

>  			: "=r" (r0)

>  			: "r" (r0), "r" (r1), "r" (r2), "r" (r3)

> -			);

> +			: "r12");

>  	return r0;

>  }

>  

> @@ -328,7 +328,7 @@ u32 qcom_scm_get_version(void)

>  			"smc	#0	@ switch to secure world\n"

>  			: "=r" (r0), "=r" (r1)

>  			: "r" (r0), "r" (r1)

> -			: "r2", "r3");

> +			: "r2", "r3", "r12");

>  	} while (r0 == QCOM_SCM_INTERRUPTED);

>  

>  	version = r1;

> -- 

> 2.14.3

> 

--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Stephen Boyd April 11, 2018, 1:55 a.m. UTC | #2
Quoting Niklas Cassel (2018-04-09 14:40:15)
> qcom_scm_call_atomic1() can crash with a NULL pointer dereference at

> qcom_scm_call_atomic1+0x30/0x48.

> 

> disassembly of qcom_scm_call_atomic1():

> ...

> <0xc08d73b0 <+12>: ldr r3, [r12]

> ... (no instruction explicitly modifies r12)

> 0xc08d73cc <+40>: smc 0

> ... (no instruction explicitly modifies r12)

> 0xc08d73d4 <+48>: ldr r3, [r12] <- crashing instruction

> ...

> 

> Since the first ldr is successful, and since r12 isn't explicitly

> modified by any instruction between the first and the second ldr,

> it must have been modified by the smc call, which is ok,

> since r12 is caller save according to the AAPCS.

> 

> Add r12 to the clobber list so that the compiler knows that the

> callee potentially overwrites the value in r12.

> Clobber descriptions may not in any way overlap with an input or

> output operand.

> 

> Signed-off-by: Niklas Cassel <niklas.cassel@linaro.org>

> ---


Reviewed-by: Stephen Boyd <sboyd@kernel.org>


--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox series

Patch

diff --git a/drivers/firmware/qcom_scm-32.c b/drivers/firmware/qcom_scm-32.c
index dfbd894d5bb7..4e24e591ae74 100644
--- a/drivers/firmware/qcom_scm-32.c
+++ b/drivers/firmware/qcom_scm-32.c
@@ -147,7 +147,7 @@  static u32 smc(u32 cmd_addr)
 			"smc	#0	@ switch to secure world\n"
 			: "=r" (r0)
 			: "r" (r0), "r" (r1), "r" (r2)
-			: "r3");
+			: "r3", "r12");
 	} while (r0 == QCOM_SCM_INTERRUPTED);
 
 	return r0;
@@ -263,7 +263,7 @@  static s32 qcom_scm_call_atomic1(u32 svc, u32 cmd, u32 arg1)
 			"smc    #0      @ switch to secure world\n"
 			: "=r" (r0)
 			: "r" (r0), "r" (r1), "r" (r2)
-			: "r3");
+			: "r3", "r12");
 	return r0;
 }
 
@@ -298,7 +298,7 @@  static s32 qcom_scm_call_atomic2(u32 svc, u32 cmd, u32 arg1, u32 arg2)
 			"smc    #0      @ switch to secure world\n"
 			: "=r" (r0)
 			: "r" (r0), "r" (r1), "r" (r2), "r" (r3)
-			);
+			: "r12");
 	return r0;
 }
 
@@ -328,7 +328,7 @@  u32 qcom_scm_get_version(void)
 			"smc	#0	@ switch to secure world\n"
 			: "=r" (r0), "=r" (r1)
 			: "r" (r0), "r" (r1)
-			: "r2", "r3");
+			: "r2", "r3", "r12");
 	} while (r0 == QCOM_SCM_INTERRUPTED);
 
 	version = r1;