target-arm: Ignore attempts to set invalid modes in CPSR
Ignore attempts to set the CPSR mode field to an invalid value. This is UNPREDICTABLE, but we should not cpu_abort() for things a malicious guest (or a confused user on the gdbstub interface) can provoke. Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
1b9e01c110
commit
37064a8b6f
@ -463,6 +463,26 @@ void cpu_arm_close(CPUARMState *env)
|
|||||||
g_free(env);
|
g_free(env);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int bad_mode_switch(CPUState *env, int mode)
|
||||||
|
{
|
||||||
|
/* Return true if it is not valid for us to switch to
|
||||||
|
* this CPU mode (ie all the UNPREDICTABLE cases in
|
||||||
|
* the ARM ARM CPSRWriteByInstr pseudocode).
|
||||||
|
*/
|
||||||
|
switch (mode) {
|
||||||
|
case ARM_CPU_MODE_USR:
|
||||||
|
case ARM_CPU_MODE_SYS:
|
||||||
|
case ARM_CPU_MODE_SVC:
|
||||||
|
case ARM_CPU_MODE_ABT:
|
||||||
|
case ARM_CPU_MODE_UND:
|
||||||
|
case ARM_CPU_MODE_IRQ:
|
||||||
|
case ARM_CPU_MODE_FIQ:
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t cpsr_read(CPUARMState *env)
|
uint32_t cpsr_read(CPUARMState *env)
|
||||||
{
|
{
|
||||||
int ZF;
|
int ZF;
|
||||||
@ -499,7 +519,15 @@ void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((env->uncached_cpsr ^ val) & mask & CPSR_M) {
|
if ((env->uncached_cpsr ^ val) & mask & CPSR_M) {
|
||||||
switch_mode(env, val & CPSR_M);
|
if (bad_mode_switch(env, val & CPSR_M)) {
|
||||||
|
/* Attempt to switch to an invalid mode: this is UNPREDICTABLE.
|
||||||
|
* We choose to ignore the attempt and leave the CPSR M field
|
||||||
|
* untouched.
|
||||||
|
*/
|
||||||
|
mask &= ~CPSR_M;
|
||||||
|
} else {
|
||||||
|
switch_mode(env, val & CPSR_M);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mask &= ~CACHED_CPSR_BITS;
|
mask &= ~CACHED_CPSR_BITS;
|
||||||
env->uncached_cpsr = (env->uncached_cpsr & ~mask) | (val & mask);
|
env->uncached_cpsr = (env->uncached_cpsr & ~mask) | (val & mask);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user