Fix a sparse warning in the arm64 signal code dealing with the user
shadow stack register, GCSPR_EL0. -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEE5RElWfyWxS+3PLO2a9axLQDIXvEFAmdlufgACgkQa9axLQDI XvHS9Q//WmBcPgp99ZgmHwV4x9VZz4lBiZphBp2+WYNmYFjkEcNDggs8nWs+JwgR Y1isI5fLEuNYCqjoejtT5iPY3i9YAtiOtq8J7xnlZ35r3Ycur28f4C28ZxQnpHGH xaFO7deNTGhUkLvHaxIDxAyu8iHcJL+Q4XwuuTozedHPGwCHb5uyYHZB1fvYTrB0 x4yxJDBehsN9x/xQPNYlaaXpYG3i0as/1DQod7kKIDckxnGOOk1s1sTPPMTsOMAv W9xvUPUmzoRvn7nH1ErT7X3O8LzbACy6RDg1iGzdMINTuLDDM9n55i2tl0TToqqq 9h5IQ7ZSsPPixrPGarSZMhKnRKLHd0psFwfzhaWdPSGn4MHQInhkIP4vK05ycpxc E3AzbQMTb8ABVwW57XeJYnJJ28wY2QvQp0mm96xjSHfhYwafx4heTAM/4jzw5ZwC JsIbQsy603Ir7JhSV3rNozAUPI8GdQzXBYZ5PtW0AIbyJHAWP2R+/Q5kGK2IJd7a T5fzCLNSd0u7soY/4J856HYsDYw0SC0f6ua9BbaIC99vOlG9PhO/MJIkr+FsPeQq O3zH/xg/LGWQYudAoXYJhY6YuQ18mpdMw++/cNci2wWdhApf2sQLrhkO1Kz1numd WDDO13hyQZQMeulTeTrkS0teQmhuVeGvgb3vxLJzYi4OIEr8Iv4= =sJbw -----END PGP SIGNATURE----- Merge tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux Pull arm64 fix from Catalin Marinas: "Fix a sparse warning in the arm64 signal code dealing with the user shadow stack register, GCSPR_EL0" * tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux: arm64/signal: Silence sparse warning storing GCSPR_EL0
This commit is contained in:
commit
499551201b
|
|
@ -36,15 +36,8 @@
|
||||||
#include <asm/traps.h>
|
#include <asm/traps.h>
|
||||||
#include <asm/vdso.h>
|
#include <asm/vdso.h>
|
||||||
|
|
||||||
#ifdef CONFIG_ARM64_GCS
|
|
||||||
#define GCS_SIGNAL_CAP(addr) (((unsigned long)addr) & GCS_CAP_ADDR_MASK)
|
#define GCS_SIGNAL_CAP(addr) (((unsigned long)addr) & GCS_CAP_ADDR_MASK)
|
||||||
|
|
||||||
static bool gcs_signal_cap_valid(u64 addr, u64 val)
|
|
||||||
{
|
|
||||||
return val == GCS_SIGNAL_CAP(addr);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Do a signal return; undo the signal stack. These are aligned to 128-bit.
|
* Do a signal return; undo the signal stack. These are aligned to 128-bit.
|
||||||
*/
|
*/
|
||||||
|
|
@ -1062,8 +1055,7 @@ static int restore_sigframe(struct pt_regs *regs,
|
||||||
#ifdef CONFIG_ARM64_GCS
|
#ifdef CONFIG_ARM64_GCS
|
||||||
static int gcs_restore_signal(void)
|
static int gcs_restore_signal(void)
|
||||||
{
|
{
|
||||||
unsigned long __user *gcspr_el0;
|
u64 gcspr_el0, cap;
|
||||||
u64 cap;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!system_supports_gcs())
|
if (!system_supports_gcs())
|
||||||
|
|
@ -1072,7 +1064,7 @@ static int gcs_restore_signal(void)
|
||||||
if (!(current->thread.gcs_el0_mode & PR_SHADOW_STACK_ENABLE))
|
if (!(current->thread.gcs_el0_mode & PR_SHADOW_STACK_ENABLE))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
gcspr_el0 = (unsigned long __user *)read_sysreg_s(SYS_GCSPR_EL0);
|
gcspr_el0 = read_sysreg_s(SYS_GCSPR_EL0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ensure that any changes to the GCS done via GCS operations
|
* Ensure that any changes to the GCS done via GCS operations
|
||||||
|
|
@ -1087,22 +1079,23 @@ static int gcs_restore_signal(void)
|
||||||
* then faults will be generated on GCS operations - the main
|
* then faults will be generated on GCS operations - the main
|
||||||
* concern is to protect GCS pages.
|
* concern is to protect GCS pages.
|
||||||
*/
|
*/
|
||||||
ret = copy_from_user(&cap, gcspr_el0, sizeof(cap));
|
ret = copy_from_user(&cap, (unsigned long __user *)gcspr_el0,
|
||||||
|
sizeof(cap));
|
||||||
if (ret)
|
if (ret)
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check that the cap is the actual GCS before replacing it.
|
* Check that the cap is the actual GCS before replacing it.
|
||||||
*/
|
*/
|
||||||
if (!gcs_signal_cap_valid((u64)gcspr_el0, cap))
|
if (cap != GCS_SIGNAL_CAP(gcspr_el0))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
/* Invalidate the token to prevent reuse */
|
/* Invalidate the token to prevent reuse */
|
||||||
put_user_gcs(0, (__user void*)gcspr_el0, &ret);
|
put_user_gcs(0, (unsigned long __user *)gcspr_el0, &ret);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
write_sysreg_s(gcspr_el0 + 1, SYS_GCSPR_EL0);
|
write_sysreg_s(gcspr_el0 + 8, SYS_GCSPR_EL0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -1421,7 +1414,7 @@ static int get_sigframe(struct rt_sigframe_user_layout *user,
|
||||||
|
|
||||||
static int gcs_signal_entry(__sigrestore_t sigtramp, struct ksignal *ksig)
|
static int gcs_signal_entry(__sigrestore_t sigtramp, struct ksignal *ksig)
|
||||||
{
|
{
|
||||||
unsigned long __user *gcspr_el0;
|
u64 gcspr_el0;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (!system_supports_gcs())
|
if (!system_supports_gcs())
|
||||||
|
|
@ -1434,18 +1427,20 @@ static int gcs_signal_entry(__sigrestore_t sigtramp, struct ksignal *ksig)
|
||||||
* We are entering a signal handler, current register state is
|
* We are entering a signal handler, current register state is
|
||||||
* active.
|
* active.
|
||||||
*/
|
*/
|
||||||
gcspr_el0 = (unsigned long __user *)read_sysreg_s(SYS_GCSPR_EL0);
|
gcspr_el0 = read_sysreg_s(SYS_GCSPR_EL0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Push a cap and the GCS entry for the trampoline onto the GCS.
|
* Push a cap and the GCS entry for the trampoline onto the GCS.
|
||||||
*/
|
*/
|
||||||
put_user_gcs((unsigned long)sigtramp, gcspr_el0 - 2, &ret);
|
put_user_gcs((unsigned long)sigtramp,
|
||||||
put_user_gcs(GCS_SIGNAL_CAP(gcspr_el0 - 1), gcspr_el0 - 1, &ret);
|
(unsigned long __user *)(gcspr_el0 - 16), &ret);
|
||||||
|
put_user_gcs(GCS_SIGNAL_CAP(gcspr_el0 - 8),
|
||||||
|
(unsigned long __user *)(gcspr_el0 - 8), &ret);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
gcspr_el0 -= 2;
|
gcspr_el0 -= 16;
|
||||||
write_sysreg_s((unsigned long)gcspr_el0, SYS_GCSPR_EL0);
|
write_sysreg_s(gcspr_el0, SYS_GCSPR_EL0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue