lists.openwall.net | lists / announce owl-users owl-dev john-users john-dev passwdqc-users yescrypt popa3d-users / oss-security kernel-hardening musl sabotage tlsify passwords / crypt-dev xvendor / Bugtraq Full-Disclosure linux-kernel linux-netdev linux-ext4 linux-hardening linux-cve-announce PHC | |
Open Source and information security mailing list archives
| ||
|
Date: Mon, 29 Aug 2022 16:42:56 +0800 From: Mao Bibo <maobibo@...ngson.cn> To: Huacai Chen <chenhuacai@...nel.org> Cc: WANG Xuerui <kernel@...0n.name>, Jiaxun Yang <jiaxun.yang@...goat.com>, loongarch@...ts.linux.dev, linux-kernel@...r.kernel.org Subject: [PATCH] LoongArch: Add safer signal handler for TLS access LoongArch uses general purpose register R2 as thread pointer(TP) register, signal hanlder also uses TP register to access variables in TLS area, such as errno and variable in TLS. If GPR R2 is modified with wrong value, signal handler still uses the wrong TP register, so signal hanlder is insafe to access TLS variable. This patch adds one arch specific syscall set_thread_area, and restore previoud TP value before signal handler, so that signal handler is safe to access TLS variable. Signed-off-by: Mao Bibo <maobibo@...ngson.cn> --- arch/loongarch/include/asm/unistd.h | 1 + arch/loongarch/include/uapi/asm/unistd.h | 2 ++ arch/loongarch/kernel/process.c | 5 ++++- arch/loongarch/kernel/signal.c | 2 ++ arch/loongarch/kernel/syscall.c | 10 ++++++++++ 5 files changed, 19 insertions(+), 1 deletion(-) diff --git a/arch/loongarch/include/asm/unistd.h b/arch/loongarch/include/asm/unistd.h index cfddb0116a8c..1581624f0115 100644 --- a/arch/loongarch/include/asm/unistd.h +++ b/arch/loongarch/include/asm/unistd.h @@ -9,3 +9,4 @@ #include <uapi/asm/unistd.h> #define NR_syscalls (__NR_syscalls) +__SYSCALL(__NR_set_thread_area, sys_set_thread_area) diff --git a/arch/loongarch/include/uapi/asm/unistd.h b/arch/loongarch/include/uapi/asm/unistd.h index fcb668984f03..b47f26b5307b 100644 --- a/arch/loongarch/include/uapi/asm/unistd.h +++ b/arch/loongarch/include/uapi/asm/unistd.h @@ -3,3 +3,5 @@ #define __ARCH_WANT_SYS_CLONE3 #include <asm-generic/unistd.h> + +#define __NR_set_thread_area (__NR_arch_specific_syscall + 0) diff --git a/arch/loongarch/kernel/process.c b/arch/loongarch/kernel/process.c index 660492f064e7..9f512c91320e 100644 --- a/arch/loongarch/kernel/process.c +++ b/arch/loongarch/kernel/process.c @@ -88,6 +88,7 @@ void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long sp) clear_used_math(); regs->csr_era = pc; regs->regs[3] = sp; + task_thread_info(current)->tp_value = 0; } void exit_thread(struct task_struct *tsk) @@ -176,8 +177,10 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args) clear_tsk_thread_flag(p, TIF_LSX_CTX_LIVE); clear_tsk_thread_flag(p, TIF_LASX_CTX_LIVE); - if (clone_flags & CLONE_SETTLS) + if (clone_flags & CLONE_SETTLS) { childregs->regs[2] = tls; + task_thread_info(p)->tp_value = tls; + } return 0; } diff --git a/arch/loongarch/kernel/signal.c b/arch/loongarch/kernel/signal.c index 7f4889df4a17..2eca555fd4a6 100644 --- a/arch/loongarch/kernel/signal.c +++ b/arch/loongarch/kernel/signal.c @@ -487,6 +487,8 @@ static int setup_rt_frame(void *sig_return, struct ksignal *ksig, regs->regs[3] = (unsigned long) frame; regs->regs[1] = (unsigned long) sig_return; regs->csr_era = (unsigned long) ksig->ka.sa.sa_handler; + if (task_thread_info(current)->tp_value) + regs->regs[2] = task_thread_info(current)->tp_value; DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", current->comm, current->pid, diff --git a/arch/loongarch/kernel/syscall.c b/arch/loongarch/kernel/syscall.c index 3fc4211db989..b62560d8fe24 100644 --- a/arch/loongarch/kernel/syscall.c +++ b/arch/loongarch/kernel/syscall.c @@ -29,6 +29,16 @@ SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len, unsigned long, return ksys_mmap_pgoff(addr, len, prot, flags, fd, offset >> PAGE_SHIFT); } +SYSCALL_DEFINE1(set_thread_area, unsigned long, addr) +{ + struct thread_info *ti = task_thread_info(current); + struct pt_regs *regs = current_pt_regs(); + + regs->regs[2] = addr; + ti->tp_value = addr; + return 0; +} + void *sys_call_table[__NR_syscalls] = { [0 ... __NR_syscalls - 1] = sys_ni_syscall, #include <asm/unistd.h> -- 2.27.0
Powered by blists - more mailing lists