From nobody Tue Apr 7 10:40:51 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5A0C8ECAAD4 for ; Mon, 29 Aug 2022 08:43:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229675AbiH2InH (ORCPT ); Mon, 29 Aug 2022 04:43:07 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54608 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229521AbiH2InE (ORCPT ); Mon, 29 Aug 2022 04:43:04 -0400 Received: from loongson.cn (mail.loongson.cn [114.242.206.163]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 2373158B5C for ; Mon, 29 Aug 2022 01:43:02 -0700 (PDT) Received: from localhost.localdomain (unknown [10.2.9.158]) by localhost.localdomain (Coremail) with SMTP id AQAAf8DxvmsQfAxjg8cLAA--.40214S2; Mon, 29 Aug 2022 16:42:56 +0800 (CST) From: Mao Bibo To: Huacai Chen Cc: WANG Xuerui , Jiaxun Yang , loongarch@lists.linux.dev, linux-kernel@vger.kernel.org Subject: [PATCH] LoongArch: Add safer signal handler for TLS access Date: Mon, 29 Aug 2022 16:42:56 +0800 Message-Id: <20220829084256.3453391-1-maobibo@loongson.cn> X-Mailer: git-send-email 2.27.0 MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: AQAAf8DxvmsQfAxjg8cLAA--.40214S2 X-Coremail-Antispam: 1UD129KBjvJXoWxCryxKFW5Xw1fZryfGr4xCrg_yoWrXrWDpF 9rAw1DJrWUWr1kZryqva4DurykJ3s7Cw429ayaka4fAa1Iq3WrXr1vqFyDZF1Yya1kGFW0 qasYg3sxta1jqaUanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUkjb7Iv0xC_Kw4lb4IE77IF4wAFF20E14v26r1j6r4UM7CY07I2 0VC2zVCF04k26cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28lY4IEw2IIxxk0rw A2F7IY1VAKz4vEj48ve4kI8wA2z4x0Y4vE2Ix0cI8IcVAFwI0_Xr0_Ar1l84ACjcxK6xII jxv20xvEc7CjxVAFwI0_Gr1j6F4UJwA2z4x0Y4vEx4A2jsIE14v26F4UJVW0owA2z4x0Y4 vEx4A2jsIEc7CjxVAFwI0_GcCE3s1le2I262IYc4CY6c8Ij28IcVAaY2xG8wAqx4xG64xv F2IEw4CE5I8CrVC2j2WlYx0E2Ix0cI8IcVAFwI0_JrI_JrylYx0Ex4A2jsIE14v26r1j6r 4UMcvjeVCFs4IE7xkEbVWUJVW8JwACjcxG0xvY0x0EwIxGrwCY02Avz4vE-syl42xK82IY c2Ij64vIr41l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAqx4xG67AKxVWUJVWUGwC20s 026x8GjcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26r126r1DMIIYrxkI7VAKI48JMIIF 0xvE2Ix0cI8IcVAFwI0_Jr0_JF4lIxAIcVC0I7IYx2IY6xkF7I0E14v26r1j6r4UMIIF0x vE42xK8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67AKxVWUJVW8JwCI42IY6I8E87Iv 6xkF7I0E14v26r1j6r4UYxBIdaVFxhVjvjDU0xZFpf9x07beJ5wUUUUU= X-CM-SenderInfo: xpdruxter6z05rqj20fqof0/ Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" 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 --- 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/a= sm/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 =20 #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/incl= ude/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 =20 #include + +#define __NR_set_thread_area (__NR_arch_specific_syscall + 0) diff --git a/arch/loongarch/kernel/process.c b/arch/loongarch/kernel/proces= s.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 =3D pc; regs->regs[3] =3D sp; + task_thread_info(current)->tp_value =3D 0; } =20 void exit_thread(struct task_struct *tsk) @@ -176,8 +177,10 @@ int copy_thread(struct task_struct *p, const struct ke= rnel_clone_args *args) clear_tsk_thread_flag(p, TIF_LSX_CTX_LIVE); clear_tsk_thread_flag(p, TIF_LASX_CTX_LIVE); =20 - if (clone_flags & CLONE_SETTLS) + if (clone_flags & CLONE_SETTLS) { childregs->regs[2] =3D tls; + task_thread_info(p)->tp_value =3D tls; + } =20 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 ksig= nal *ksig, regs->regs[3] =3D (unsigned long) frame; regs->regs[1] =3D (unsigned long) sig_return; regs->csr_era =3D (unsigned long) ksig->ka.sa.sa_handler; + if (task_thread_info(current)->tp_value) + regs->regs[2] =3D task_thread_info(current)->tp_value; =20 DEBUGP("SIG deliver (%s:%d): sp=3D0x%p pc=3D0x%lx ra=3D0x%lx\n", current->comm, current->pid, diff --git a/arch/loongarch/kernel/syscall.c b/arch/loongarch/kernel/syscal= l.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); } =20 +SYSCALL_DEFINE1(set_thread_area, unsigned long, addr) +{ + struct thread_info *ti =3D task_thread_info(current); + struct pt_regs *regs =3D current_pt_regs(); + + regs->regs[2] =3D addr; + ti->tp_value =3D addr; + return 0; +} + void *sys_call_table[__NR_syscalls] =3D { [0 ... __NR_syscalls - 1] =3D sys_ni_syscall, #include --=20 2.27.0