[Qemu-devel] [PATCH for-2.12 4/4] target/arm: Always set FAR to a known unknown value for debug exceptions

Peter Maydell posted 4 patches 7 years, 10 months ago
[Qemu-devel] [PATCH for-2.12 4/4] target/arm: Always set FAR to a known unknown value for debug exceptions
Posted by Peter Maydell 7 years, 10 months ago
For debug exceptions due to breakpoints or the BKPT instruction which
are taken to AArch32, the Fault Address Register is architecturally
UNKNOWN.  We were using that as license to simply not set
env->exception.vaddress, but this isn't correct, because it will
expose to the guest whatever old value was in that field when
arm_cpu_do_interrupt_aarch32() writes it to the guest IFSR.  That old
value might be a FAR for a previous guest EL2 or secure exception, in
which case we shouldn't show it to an EL1 or non-secure exception
handler. It might also be a non-deterministic value, which is bad
for record-and-replay.

Clear env->exception.vaddress before taking breakpoint debug
exceptions, to avoid this minor information leak.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
 target/arm/op_helper.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
index 8e1e521193..a266cc0116 100644
--- a/target/arm/op_helper.c
+++ b/target/arm/op_helper.c
@@ -490,6 +490,11 @@ void HELPER(exception_bkpt_insn)(CPUARMState *env, uint32_t syndrome)
 {
     /* FSR will only be used if the debug target EL is AArch32. */
     env->exception.fsr = arm_debug_exception_fsr(env);
+    /* FAR is UNKNOWN: clear vaddress to avoid potentially exposing
+     * values to the guest that it shouldn't be able to see at its
+     * exception/security level.
+     */
+    env->exception.vaddress = 0;
     raise_exception(env, EXCP_BKPT, syndrome, arm_debug_target_el(env));
 }
 
@@ -1353,7 +1358,11 @@ void arm_debug_excp_handler(CPUState *cs)
         }
 
         env->exception.fsr = arm_debug_exception_fsr(env);
-        /* FAR is UNKNOWN, so doesn't need setting */
+        /* FAR is UNKNOWN: clear vaddress to avoid potentially exposing
+         * values to the guest that it shouldn't be able to see at its
+         * exception/security level.
+         */
+        env->exception.vaddress = 0;
         raise_exception(env, EXCP_PREFETCH_ABORT,
                         syn_breakpoint(same_el),
                         arm_debug_target_el(env));
-- 
2.16.2


Re: [Qemu-devel] [PATCH for-2.12 4/4] target/arm: Always set FAR to a known unknown value for debug exceptions
Posted by Philippe Mathieu-Daudé 7 years, 10 months ago
On 03/20/2018 02:41 PM, Peter Maydell wrote:
> For debug exceptions due to breakpoints or the BKPT instruction which
> are taken to AArch32, the Fault Address Register is architecturally
> UNKNOWN.  We were using that as license to simply not set
> env->exception.vaddress, but this isn't correct, because it will
> expose to the guest whatever old value was in that field when
> arm_cpu_do_interrupt_aarch32() writes it to the guest IFSR.  That old
> value might be a FAR for a previous guest EL2 or secure exception, in
> which case we shouldn't show it to an EL1 or non-secure exception
> handler. It might also be a non-deterministic value, which is bad
> for record-and-replay.
> 
> Clear env->exception.vaddress before taking breakpoint debug
> exceptions, to avoid this minor information leak.

So this series is worth Cc'ing qemu-stable...?

> 
> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>

> ---
>  target/arm/op_helper.c | 11 ++++++++++-
>  1 file changed, 10 insertions(+), 1 deletion(-)
> 
> diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
> index 8e1e521193..a266cc0116 100644
> --- a/target/arm/op_helper.c
> +++ b/target/arm/op_helper.c
> @@ -490,6 +490,11 @@ void HELPER(exception_bkpt_insn)(CPUARMState *env, uint32_t syndrome)
>  {
>      /* FSR will only be used if the debug target EL is AArch32. */
>      env->exception.fsr = arm_debug_exception_fsr(env);
> +    /* FAR is UNKNOWN: clear vaddress to avoid potentially exposing
> +     * values to the guest that it shouldn't be able to see at its
> +     * exception/security level.
> +     */
> +    env->exception.vaddress = 0;
>      raise_exception(env, EXCP_BKPT, syndrome, arm_debug_target_el(env));
>  }
>  
> @@ -1353,7 +1358,11 @@ void arm_debug_excp_handler(CPUState *cs)
>          }
>  
>          env->exception.fsr = arm_debug_exception_fsr(env);
> -        /* FAR is UNKNOWN, so doesn't need setting */
> +        /* FAR is UNKNOWN: clear vaddress to avoid potentially exposing
> +         * values to the guest that it shouldn't be able to see at its
> +         * exception/security level.
> +         */
> +        env->exception.vaddress = 0;
>          raise_exception(env, EXCP_PREFETCH_ABORT,
>                          syn_breakpoint(same_el),
>                          arm_debug_target_el(env));
> 

Re: [Qemu-devel] [PATCH for-2.12 4/4] target/arm: Always set FAR to a known unknown value for debug exceptions
Posted by Peter Maydell 7 years, 10 months ago
On 21 March 2018 at 22:29, Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
> On 03/20/2018 02:41 PM, Peter Maydell wrote:
>> For debug exceptions due to breakpoints or the BKPT instruction which
>> are taken to AArch32, the Fault Address Register is architecturally
>> UNKNOWN.  We were using that as license to simply not set
>> env->exception.vaddress, but this isn't correct, because it will
>> expose to the guest whatever old value was in that field when
>> arm_cpu_do_interrupt_aarch32() writes it to the guest IFSR.  That old
>> value might be a FAR for a previous guest EL2 or secure exception, in
>> which case we shouldn't show it to an EL1 or non-secure exception
>> handler. It might also be a non-deterministic value, which is bad
>> for record-and-replay.
>>
>> Clear env->exception.vaddress before taking breakpoint debug
>> exceptions, to avoid this minor information leak.
>
> So this series is worth Cc'ing qemu-stable...?

I don't think so. This isn't a regression -- we've behaved this
way ever since we introduced LPAE support, five years or so ago.
In particular Linux doesn't care about it.

thanks
-- PMM