aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/mm/extable.c
diff options
context:
space:
mode:
authorHeiko Carstens <hca@linux.ibm.com>2022-05-01 21:26:06 +0200
committerHeiko Carstens <hca@linux.ibm.com>2022-06-01 12:03:17 +0200
commit454ede3f1424c36bc124f8d7ed4b3ea654654be1 (patch)
tree6a362eef8004422f3df1ff17bbe3ec3387b6ef86 /arch/s390/mm/extable.c
parents390/uaccess: use symbolic names for inline assembler operands (diff)
downloadlinux-dev-454ede3f1424c36bc124f8d7ed4b3ea654654be1.tar.xz
linux-dev-454ede3f1424c36bc124f8d7ed4b3ea654654be1.zip
s390/uaccess: use exception handler to zero result on get_user() failure
Historically the uaccess code pre-initializes the result of get_user() (and now also __get_kernel_nofault()) to zero and uses the result as input parameter for inline assemblies. This is different to what most, if not all, other architectures are doing, which set the result to zero within the exception handler in case of a fault. Use the new extable mechanism and handle zeroing of the result within the exception handler in case of a fault. Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
Diffstat (limited to '')
-rw-r--r--arch/s390/mm/extable.c39
1 files changed, 35 insertions, 4 deletions
diff --git a/arch/s390/mm/extable.c b/arch/s390/mm/extable.c
index 8ac8ad2474a0..1e4d2187541a 100644
--- a/arch/s390/mm/extable.c
+++ b/arch/s390/mm/extable.c
@@ -1,6 +1,8 @@
// SPDX-License-Identifier: GPL-2.0
+#include <linux/bitfield.h>
#include <linux/extable.h>
+#include <linux/string.h>
#include <linux/errno.h>
#include <linux/panic.h>
#include <asm/asm-extable.h>
@@ -24,9 +26,34 @@ static bool ex_handler_fixup(const struct exception_table_entry *ex, struct pt_r
return true;
}
-static bool ex_handler_uaccess(const struct exception_table_entry *ex, struct pt_regs *regs)
+static bool ex_handler_ua_store(const struct exception_table_entry *ex, struct pt_regs *regs)
{
- regs->gprs[ex->data] = -EFAULT;
+ unsigned int reg_err = FIELD_GET(EX_DATA_REG_ERR, ex->data);
+
+ regs->gprs[reg_err] = -EFAULT;
+ regs->psw.addr = extable_fixup(ex);
+ return true;
+}
+
+static bool ex_handler_ua_load_mem(const struct exception_table_entry *ex, struct pt_regs *regs)
+{
+ unsigned int reg_addr = FIELD_GET(EX_DATA_REG_ADDR, ex->data);
+ unsigned int reg_err = FIELD_GET(EX_DATA_REG_ERR, ex->data);
+ size_t len = FIELD_GET(EX_DATA_LEN, ex->data);
+
+ regs->gprs[reg_err] = -EFAULT;
+ memset((void *)regs->gprs[reg_addr], 0, len);
+ regs->psw.addr = extable_fixup(ex);
+ return true;
+}
+
+static bool ex_handler_ua_load_reg(const struct exception_table_entry *ex, struct pt_regs *regs)
+{
+ unsigned int reg_zero = FIELD_GET(EX_DATA_REG_ADDR, ex->data);
+ unsigned int reg_err = FIELD_GET(EX_DATA_REG_ERR, ex->data);
+
+ regs->gprs[reg_err] = -EFAULT;
+ regs->gprs[reg_zero] = 0;
regs->psw.addr = extable_fixup(ex);
return true;
}
@@ -43,8 +70,12 @@ bool fixup_exception(struct pt_regs *regs)
return ex_handler_fixup(ex, regs);
case EX_TYPE_BPF:
return ex_handler_bpf(ex, regs);
- case EX_TYPE_UACCESS:
- return ex_handler_uaccess(ex, regs);
+ case EX_TYPE_UA_STORE:
+ return ex_handler_ua_store(ex, regs);
+ case EX_TYPE_UA_LOAD_MEM:
+ return ex_handler_ua_load_mem(ex, regs);
+ case EX_TYPE_UA_LOAD_REG:
+ return ex_handler_ua_load_reg(ex, regs);
}
panic("invalid exception table entry");
}