summaryrefslogtreecommitdiff
path: root/arch/s390
diff options
context:
space:
mode:
authorVasily Gorbik <gor@linux.ibm.com>2020-09-24 01:01:29 +0200
committerVasily Gorbik <gor@linux.ibm.com>2020-10-02 14:40:48 +0200
commit21a66717079c3d74e8573cd48743728e4a244507 (patch)
tree21020abd1377ff1b503bea8547a4a06dea7f9de5 /arch/s390
parent5627b9224b00334e4c91122ebbb8536a9a575969 (diff)
s390/kasan: make sure int handler always run with DAT on
Since commit 998f5bbe3dbd ("s390/kasan: fix early pgm check handler execution") early pgm check handler is executed with DAT on if Kasan is enabled. Still there is a window between setup_lowcore_dat_off() and setup_lowcore_dat_on() when int handlers could be executed with DAT off under Kasan. If this happens the kernel ends up in pgm check loop due to Kasan shadow memory access attempts. With Kasan enabled paging is initialized much earlier and DAT flag has to be on at all times instrumented code is executed. Make sure int handlers are set up to be called with DAT on right away in this case. Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
Diffstat (limited to 'arch/s390')
-rw-r--r--arch/s390/kernel/setup.c12
1 files changed, 8 insertions, 4 deletions
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 419a0604959f..dc4d461095cc 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -372,8 +372,12 @@ void __init arch_call_rest_init(void)
static void __init setup_lowcore_dat_off(void)
{
+ unsigned long int_psw_mask = PSW_KERNEL_BITS;
struct lowcore *lc;
+ if (IS_ENABLED(CONFIG_KASAN))
+ int_psw_mask |= PSW_MASK_DAT;
+
/*
* Setup lowcore for boot cpu
*/
@@ -385,15 +389,15 @@ static void __init setup_lowcore_dat_off(void)
lc->restart_psw.mask = PSW_KERNEL_BITS;
lc->restart_psw.addr = (unsigned long) restart_int_handler;
- lc->external_new_psw.mask = PSW_KERNEL_BITS | PSW_MASK_MCHECK;
+ lc->external_new_psw.mask = int_psw_mask | PSW_MASK_MCHECK;
lc->external_new_psw.addr = (unsigned long) ext_int_handler;
- lc->svc_new_psw.mask = PSW_KERNEL_BITS | PSW_MASK_MCHECK;
+ lc->svc_new_psw.mask = int_psw_mask | PSW_MASK_MCHECK;
lc->svc_new_psw.addr = (unsigned long) system_call;
- lc->program_new_psw.mask = PSW_KERNEL_BITS | PSW_MASK_MCHECK;
+ lc->program_new_psw.mask = int_psw_mask | PSW_MASK_MCHECK;
lc->program_new_psw.addr = (unsigned long) pgm_check_handler;
lc->mcck_new_psw.mask = PSW_KERNEL_BITS;
lc->mcck_new_psw.addr = (unsigned long) mcck_int_handler;
- lc->io_new_psw.mask = PSW_KERNEL_BITS | PSW_MASK_MCHECK;
+ lc->io_new_psw.mask = int_psw_mask | PSW_MASK_MCHECK;
lc->io_new_psw.addr = (unsigned long) io_int_handler;
lc->clock_comparator = clock_comparator_max;
lc->nodat_stack = ((unsigned long) &init_thread_union)