From patchwork Thu Jan 25 06:21:48 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Deepak Gupta X-Patchwork-Id: 13530093 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 kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 98970C47DDF for ; Thu, 25 Jan 2024 06:30:28 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id DDBE08D000E; Thu, 25 Jan 2024 01:30:24 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id D67B48D000C; Thu, 25 Jan 2024 01:30:24 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id B19CC8D000E; Thu, 25 Jan 2024 01:30:24 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0017.hostedemail.com [216.40.44.17]) by kanga.kvack.org (Postfix) with ESMTP id 96B3A8D000C for ; Thu, 25 Jan 2024 01:30:24 -0500 (EST) Received: from smtpin29.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay03.hostedemail.com (Postfix) with ESMTP id 760B0A0791 for ; Thu, 25 Jan 2024 06:30:24 +0000 (UTC) X-FDA: 81716859168.29.300E924 Received: from mail-oi1-f170.google.com (mail-oi1-f170.google.com [209.85.167.170]) by imf30.hostedemail.com (Postfix) with ESMTP id AA43680017 for ; Thu, 25 Jan 2024 06:30:22 +0000 (UTC) Authentication-Results: imf30.hostedemail.com; dkim=pass header.d=rivosinc-com.20230601.gappssmtp.com header.s=20230601 header.b=oNAOmu18; dmarc=none; spf=pass (imf30.hostedemail.com: domain of debug@rivosinc.com designates 209.85.167.170 as permitted sender) smtp.mailfrom=debug@rivosinc.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1706164222; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=Rd0guRwVXbpygS5QcHTElt8jUaWNDA8n6eGW6ag7sBw=; b=thBpcYdy35cdGEJmoR0Hr013lX2RMGHyJfCh/2zCWK9yAUfJQhKTyOg1uSAM7MCWQ/ikMI 6WlTmkaCRyZM+JxeAQETiQuKg68wqOTgVykjl8V2omTqRWNljUmLlIBvfdDkxnCQK0lGJD 9zlpGudAfhMoHJefZGppueptrOPJMGw= ARC-Authentication-Results: i=1; imf30.hostedemail.com; dkim=pass header.d=rivosinc-com.20230601.gappssmtp.com header.s=20230601 header.b=oNAOmu18; dmarc=none; spf=pass (imf30.hostedemail.com: domain of debug@rivosinc.com designates 209.85.167.170 as permitted sender) smtp.mailfrom=debug@rivosinc.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1706164222; a=rsa-sha256; cv=none; b=LIWybjx+P+x4lGqkadb1uNDc1JwKVxOoaUQFzWspMXPWYI3KCKNzPQjfo3U2PsbhJ3/ks7 7Pj2DEYXYtrQToh+njGfzkrEU2AnZi/c+TINOvjqGkTBldlGuseG4OyD1rR5f/r3SvUgzY rEoC6vvBDnODo5HHtfpHPuZZIuH6xfE= Received: by mail-oi1-f170.google.com with SMTP id 5614622812f47-3bd67e9d6ceso3979978b6e.3 for ; Wed, 24 Jan 2024 22:30:22 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=rivosinc-com.20230601.gappssmtp.com; s=20230601; t=1706164222; x=1706769022; darn=kvack.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Rd0guRwVXbpygS5QcHTElt8jUaWNDA8n6eGW6ag7sBw=; b=oNAOmu18RaD/97YYuZwt9WMENEcSJIX8vPmc17bbRThpD8xRUtF0F/Hc2UbWr9v1dM CDLXnE1uyW28UtP9eglTcGi+pyPKUi3n5apFGnXG9MgZT6M8aC+zCghSmkAbtg4EElol PG9LlyZ0dGfv8LlIRthE3DRTXCgp59nl5WCkTJwZabpQ/28VjQWSIxQ9YE8fKQdhnc7a ALHUDfqq73l/NkOy2BG4ra09Afkt/AjR4aNrbXeHTZ1CNZAAja6ekprD1DkwfQebBumQ 61q8WaqLqiDEu+vS8n6gNVZGeEpSRhBUikLLNhSJnzdU7ApzP2ZPmKn1JxrWjD/i2jek C7Vw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1706164222; x=1706769022; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Rd0guRwVXbpygS5QcHTElt8jUaWNDA8n6eGW6ag7sBw=; b=hnM6B5r4i6YUQY3zMbuqM5uvbIGH8IEbDe9vS64l753mB3b4+/I5i81kZGecKVrSBE QwVN8lC9osxAxiNLVRnTNSBkUNWP/d8g5YXRnng0KpqlqQGI2zHd777dbpYlzSgpBC36 915J0DjjuM1J/mfW14QvcFFExKJiTbeZ4pETcMNwUlJW+7qon4QJrZ8mkEcHr86vYY0U dQp31v0KVPvbM66VC1OBZvL75n/T/RZBhB4syD/3N7Ge4/hXhhNtN9D2yzqBATt4IWhh 4dCNhL54rZSWskqm2HLasrosqkfkPwnB2r53Splzh+DR300p8l8Tdvh87bYtaQtU8iZ/ GU7w== X-Gm-Message-State: AOJu0YwXLnPKjQs+pgbLqlAYykbciJLxLIXIqvQcx0u+gENIhlUzpywS PRHWcxdHUtOjAR0Olj7xZ+ekAY0XSfkJrFQkxQ6x1wEFCu5FioGkYstYX9kfzxM= X-Google-Smtp-Source: AGHT+IEtSqWNKgoD+4o7h4VeWcDOxTfmpZBfxFewovyKCCIR9bqFDHsIO0YxZXMfxploC95qwEYn2g== X-Received: by 2002:a05:6808:319b:b0:3bd:c4e3:455e with SMTP id cd27-20020a056808319b00b003bdc4e3455emr586022oib.61.1706164221729; Wed, 24 Jan 2024 22:30:21 -0800 (PST) Received: from debug.ba.rivosinc.com ([64.71.180.162]) by smtp.gmail.com with ESMTPSA id t19-20020a056a00139300b006dd870b51b8sm3201139pfg.126.2024.01.24.22.30.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 24 Jan 2024 22:30:21 -0800 (PST) From: debug@rivosinc.com To: rick.p.edgecombe@intel.com, broonie@kernel.org, Szabolcs.Nagy@arm.com, kito.cheng@sifive.com, keescook@chromium.org, ajones@ventanamicro.com, paul.walmsley@sifive.com, palmer@dabbelt.com, conor.dooley@microchip.com, cleger@rivosinc.com, atishp@atishpatra.org, alex@ghiti.fr, bjorn@rivosinc.com, alexghiti@rivosinc.com Cc: corbet@lwn.net, aou@eecs.berkeley.edu, oleg@redhat.com, akpm@linux-foundation.org, arnd@arndb.de, ebiederm@xmission.com, shuah@kernel.org, brauner@kernel.org, debug@rivosinc.com, guoren@kernel.org, samitolvanen@google.com, evan@rivosinc.com, xiao.w.wang@intel.com, apatel@ventanamicro.com, mchitale@ventanamicro.com, waylingii@gmail.com, greentime.hu@sifive.com, heiko@sntech.de, jszhang@kernel.org, shikemeng@huaweicloud.com, david@redhat.com, charlie@rivosinc.com, panqinglin2020@iscas.ac.cn, willy@infradead.org, vincent.chen@sifive.com, andy.chiu@sifive.com, gerg@kernel.org, jeeheng.sia@starfivetech.com, mason.huo@starfivetech.com, ancientmodern4@gmail.com, mathis.salmen@matsal.de, cuiyunhui@bytedance.com, bhe@redhat.com, chenjiahao16@huawei.com, ruscur@russell.cc, bgray@linux.ibm.com, alx@kernel.org, baruch@tkos.co.il, zhangqing@loongson.cn, catalin.marinas@arm.com, revest@chromium.org, josh@joshtriplett.org, joey.gouly@arm.com, shr@devkernel.io, omosnace@redhat.com, ojeda@kernel.org, jhubbard@nvidia.com, linux-doc@vger.kernel.org, linux-riscv@lists.infradead.org, linux-kernel@vger.kernel.org, linux-mm@kvack.org, linux-arch@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [RFC PATCH v1 23/28] riscv signal: Save and restore of shadow stack for signal Date: Wed, 24 Jan 2024 22:21:48 -0800 Message-ID: <20240125062739.1339782-24-debug@rivosinc.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240125062739.1339782-1-debug@rivosinc.com> References: <20240125062739.1339782-1-debug@rivosinc.com> MIME-Version: 1.0 X-Rspamd-Queue-Id: AA43680017 X-Rspam-User: X-Rspamd-Server: rspam05 X-Stat-Signature: 79u6gbo54zg3kfu57ei14epfoanexqkd X-HE-Tag: 1706164222-273718 X-HE-Meta: U2FsdGVkX18sBqcksrqA75scoCYxGX+cmL55u/67yuTOxACU4ufA6Dd1rD98J5a92sl/VIEah5gXTVEh7qeTQ4P8oI5N8fIaw0DGHvrvhC6KyIPS+v8RnI+KVZc3Bg6GrN3DQe4XXXCHCoeiPFufigmMIK87d9y2xYZp5Usu3fiyriO0ZG0FAnAz7cdgrLkr3Dd/KYwjjcIO2ihg/6UYmJU7UjThKvNk/wNg6Ei/qoNgf3F1TzhYLmLGVhq/SczGAKNvHClr5ROcVN5XgGP8wO/PBOJCiXSM+/0TrK+u7x0mSkISoz/mL8x2yz6voexl5eprkYqaeVlzjQUUeTypBiGDZcTueM/g+1kGCNXjWM3TkQu/HDLB353yIEdsCycqu7PJ7wr6MGsA3d9JBKYkUlG+NJJHd8+mdxXQ+hh338swBguCfrQULlsoRbl2fScGulOrLToZHryKDMQQs77AB7MY4AH2s69HWdbwy7MfEInUbS137zYmpirIoMejFe3tXcAWXhMgVxeEa335BANmp75PuWjbtGf0qN20H5ebiYYxHJBPIZiXo3Brb3J1t01LSmFg7ylU/jGx0NKIBaM+sZHKX5+VEg07a95MAAqHF95pOATRTBgvj4/g3dQlELIf8kkKRMO/+iBaxVZ0W9LfCOYWNS7VF3bORQwUzyFYjjEUCZdFLWKPAr2mQm3hx+RWEFtPwqn49ugCsTXcy8kOo4zzaHNUJ9x1lrttC7LknhzJ/wo0mNe21nej921fvv5bYd+K2hUGqN3wnLGFNko+xGeFbF+8x0rZbw4aKb1POQXV4NL5FBuINUw6KXqwJlTPgxkcCt5iJvdrYV2BtKsKaYQsfbp5cCUO61G75iz7RCxluYSaOGTYV8OSG09Z/Sc+LmBg+/REFqzvGi04Ge3ScsU6KQ6hXC+o/R+MnICrPS0c5t0tW64mbjKJYiYXKsGxpIcm/T5hBL1xzBd2WMq 7e8o8liT waxJEzb4dGc15ROXpISDDllvsgp9RjoEuAXb6b1U2ef8ptSIpNxyuishia/nJs596Io6pEXIJAvomiQM9VmysduaLQttOAAeoQwwM0A3n36QDDRjI1ahkALAr9896hiNgMpDpsXfsOddjyeIXusiyWt2/v3/cQulWvqJ2y1FGk8PJSiQ5/sIEnSUHOe8pybXOtZ9YRKZwCx2i9ASqvtzarHbn6jlhwOubgvkyqce5p1VpdT17nzRwYyV2vS/zy1iE12IZg3Fi1wRVRVBoGVCAr6c/XxePUfTOeabqkjRgCuxcs9PVRdzPcz1nxS8ANtKa65twC5IxqHGdqXhRlTK5nmnGIbvQThOZjK26O5OB8lRlwtbvDC4vxQ5/R7uGHRhhymoCfWC2RwpCg7g65c9DvHDE1lO/lA99RVDwuAnjmIiMkLqkCs1ePciRXRTzuBPiXbTu X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: From: Deepak Gupta Save shadow stack pointer in sigcontext structure while delivering signal. Restore shadow stack pointer from sigcontext on sigreturn. Signed-off-by: Deepak Gupta --- arch/riscv/include/asm/usercfi.h | 18 ++++++++++++ arch/riscv/kernel/signal.c | 45 ++++++++++++++++++++++++++++++ arch/riscv/kernel/usercfi.c | 47 ++++++++++++++++++++++++++++++++ 3 files changed, 110 insertions(+) diff --git a/arch/riscv/include/asm/usercfi.h b/arch/riscv/include/asm/usercfi.h index 4bd10dcd48aa..28c67866ff6f 100644 --- a/arch/riscv/include/asm/usercfi.h +++ b/arch/riscv/include/asm/usercfi.h @@ -33,6 +33,9 @@ bool is_shstk_enabled(struct task_struct *task); bool is_shstk_locked(struct task_struct *task); bool is_indir_lp_enabled(struct task_struct *task); bool is_indir_lp_locked(struct task_struct *task); +unsigned long get_active_shstk(struct task_struct *task); +int restore_user_shstk(struct task_struct *tsk, unsigned long shstk_ptr); +int save_user_shstk(struct task_struct *tsk, unsigned long *saved_shstk_ptr); #define PR_SHADOW_STACK_SUPPORTED_STATUS_MASK (PR_SHADOW_STACK_ENABLE) @@ -70,6 +73,16 @@ static inline bool is_shstk_locked(struct task_struct *task) return false; } +int restore_user_shstk(struct task_struct *tsk, unsigned long shstk_ptr) +{ + return -EINVAL; +} + +int save_user_shstk(struct task_struct *tsk, unsigned long *saved_shstk_ptr) +{ + return -EINVAL; +} + static inline bool is_indir_lp_enabled(struct task_struct *task) { return false; @@ -81,6 +94,11 @@ static inline bool is_indir_lp_locked(struct task_struct *task) return false; } +static inline unsigned long get_active_shstk(struct task_struct *task) +{ + return 0; +} + #endif /* CONFIG_RISCV_USER_CFI */ #endif /* __ASSEMBLY__ */ diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c index 88b6220b2608..d1092f0a6363 100644 --- a/arch/riscv/kernel/signal.c +++ b/arch/riscv/kernel/signal.c @@ -22,6 +22,7 @@ #include #include #include +#include unsigned long signal_minsigstksz __ro_after_init; @@ -229,6 +230,7 @@ SYSCALL_DEFINE0(rt_sigreturn) struct pt_regs *regs = current_pt_regs(); struct rt_sigframe __user *frame; struct task_struct *task; + unsigned long ss_ptr = 0; sigset_t set; size_t frame_size = get_rt_frame_size(false); @@ -251,6 +253,26 @@ SYSCALL_DEFINE0(rt_sigreturn) if (restore_altstack(&frame->uc.uc_stack)) goto badframe; + /* + * Restore shadow stack as a form of token stored on shadow stack itself as a safe + * way to restore. + * A token on shadow gives following properties + * - Safe save and restore for shadow stack switching. Any save of shadow stack + * must have had saved a token on shadow stack. Similarly any restore of shadow + * stack must check the token before restore. Since writing to shadow stack with + * address of shadow stack itself is not easily allowed. A restore without a save + * is quite difficult for an attacker to perform. + * - A natural break. A token in shadow stack provides a natural break in shadow stack + * So a single linear range can be bucketed into different shadow stack segments. + * sspopchk will detect the condition and fault to kernel as sw check exception. + */ + if (__copy_from_user(&ss_ptr, &frame->uc.uc_mcontext.sc_cfi_state.ss_ptr, + sizeof(unsigned long))) + goto badframe; + + if (is_shstk_enabled(current) && restore_user_shstk(current, ss_ptr)) + goto badframe; + regs->cause = -1UL; return regs->a0; @@ -320,6 +342,7 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct rt_sigframe __user *frame; long err = 0; unsigned long __maybe_unused addr; + unsigned long ss_ptr = 0; size_t frame_size = get_rt_frame_size(false); frame = get_sigframe(ksig, regs, frame_size); @@ -331,6 +354,23 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, /* Create the ucontext. */ err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(NULL, &frame->uc.uc_link); + /* + * Save a pointer to shadow stack itself on shadow stack as a form of token. + * A token on shadow gives following properties + * - Safe save and restore for shadow stack switching. Any save of shadow stack + * must have had saved a token on shadow stack. Similarly any restore of shadow + * stack must check the token before restore. Since writing to shadow stack with + * address of shadow stack itself is not easily allowed. A restore without a save + * is quite difficult for an attacker to perform. + * - A natural break. A token in shadow stack provides a natural break in shadow stack + * So a single linear range can be bucketed into different shadow stack segments. Any + * sspopchk will detect the condition and fault to kernel as sw check exception. + */ + if (is_shstk_enabled(current)) { + err |= save_user_shstk(current, &ss_ptr); + err |= __put_user(ss_ptr, &frame->uc.uc_mcontext.sc_cfi_state.ss_ptr); + } + err |= __save_altstack(&frame->uc.uc_stack, regs->sp); err |= setup_sigcontext(frame, regs); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); @@ -341,6 +381,11 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, #ifdef CONFIG_MMU regs->ra = (unsigned long)VDSO_SYMBOL( current->mm->context.vdso, rt_sigreturn); + + /* if bcfi is enabled x1 (ra) and x5 (t0) must match. not sure if we need this? */ + if (is_shstk_enabled(current)) + regs->t0 = regs->ra; + #else /* * For the nommu case we don't have a VDSO. Instead we push two diff --git a/arch/riscv/kernel/usercfi.c b/arch/riscv/kernel/usercfi.c index af8cc8f4616c..f5eb0124571b 100644 --- a/arch/riscv/kernel/usercfi.c +++ b/arch/riscv/kernel/usercfi.c @@ -52,6 +52,11 @@ void set_active_shstk(struct task_struct *task, unsigned long shstk_addr) task->thread_info.user_cfi_state.user_shdw_stk = shstk_addr; } +unsigned long get_active_shstk(struct task_struct *task) +{ + return task->thread_info.user_cfi_state.user_shdw_stk; +} + void set_shstk_status(struct task_struct *task, bool enable) { task->thread_info.user_cfi_state.ubcfi_en = enable ? 1 : 0; @@ -165,6 +170,48 @@ static int create_rstor_token(unsigned long ssp, unsigned long *token_addr) return 0; } +/* + * Save user shadow stack pointer on shadow stack itself and return pointer to saved location + * returns -EFAULT if operation was unsuccessful + */ +int save_user_shstk(struct task_struct *tsk, unsigned long *saved_shstk_ptr) +{ + unsigned long ss_ptr = 0; + unsigned long token_loc = 0; + int ret = 0; + + if (saved_shstk_ptr == NULL) + return -EINVAL; + + ss_ptr = get_active_shstk(tsk); + ret = create_rstor_token(ss_ptr, &token_loc); + + *saved_shstk_ptr = token_loc; + return ret; +} + +/* + * Restores user shadow stack pointer from token on shadow stack for task `tsk` + * returns -EFAULT if operation was unsuccessful + */ +int restore_user_shstk(struct task_struct *tsk, unsigned long shstk_ptr) +{ + unsigned long token = 0; + + token = amo_user_shstk((unsigned long __user *)shstk_ptr, 0); + + if (token == -1) + return -EFAULT; + + /* invalid token, return EINVAL */ + if ((token - shstk_ptr) != SHSTK_ENTRY_SIZE) + return -EINVAL; + + /* all checks passed, set active shstk and return success */ + set_active_shstk(tsk, token); + return 0; +} + static unsigned long allocate_shadow_stack(unsigned long addr, unsigned long size, unsigned long token_offset, bool set_tok)