From patchwork Thu Sep 12 23:16:42 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Deepak Gupta X-Patchwork-Id: 13802846 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 2F499EEE271 for ; Thu, 12 Sep 2024 23:18:51 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id AD4116B00B9; Thu, 12 Sep 2024 19:18:50 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id A82036B00BA; Thu, 12 Sep 2024 19:18:50 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 887FC6B00BB; Thu, 12 Sep 2024 19:18:50 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0011.hostedemail.com [216.40.44.11]) by kanga.kvack.org (Postfix) with ESMTP id 691916B00B9 for ; Thu, 12 Sep 2024 19:18:50 -0400 (EDT) Received: from smtpin03.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay04.hostedemail.com (Postfix) with ESMTP id 20FB91A0D45 for ; Thu, 12 Sep 2024 23:18:50 +0000 (UTC) X-FDA: 82557653220.03.9C11F3F Received: from mail-pg1-f176.google.com (mail-pg1-f176.google.com [209.85.215.176]) by imf10.hostedemail.com (Postfix) with ESMTP id 3778CC0002 for ; Thu, 12 Sep 2024 23:18:47 +0000 (UTC) Authentication-Results: imf10.hostedemail.com; dkim=pass header.d=rivosinc-com.20230601.gappssmtp.com header.s=20230601 header.b=cE+rVR06; spf=pass (imf10.hostedemail.com: domain of debug@rivosinc.com designates 209.85.215.176 as permitted sender) smtp.mailfrom=debug@rivosinc.com; dmarc=none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1726183075; 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=QuNLZoEwAoxFOzNtpFEIpmCklLXVvlyHizGcnsawnko=; b=aoEjgMJ9PyfHZMzA6d0wFJf8LTDiUWH6jYCyS1Tt9GO9W2n4R4Sdv5mQmH5dXbnx2QHSrR YgU0AxX0UVfb88j+nV+wAf76yAu0S0kSXKcZAF7ZzJl5NLvFxZNDW6I0aJQ/cdgMYpEV8d BsbPSTwyF75ED7L2F90VCgPuWF2sf+w= ARC-Authentication-Results: i=1; imf10.hostedemail.com; dkim=pass header.d=rivosinc-com.20230601.gappssmtp.com header.s=20230601 header.b=cE+rVR06; spf=pass (imf10.hostedemail.com: domain of debug@rivosinc.com designates 209.85.215.176 as permitted sender) smtp.mailfrom=debug@rivosinc.com; dmarc=none ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1726183075; a=rsa-sha256; cv=none; b=DX71E8XceJ+o8HjrhhlmRxnfR9Z0gaPnNhzIrdbCCccAsIrH6LdNSZ2ipUI3PXWP1dFNtr 9I34emWbDnOBW+DTUJshdPPirDbQumZ2NB5KZHS4UzvCX+zY65+blLN0SSLHAxZpl/0Ihu k719lY+2/4Xi6OeTP63mp38m9a0K71I= Received: by mail-pg1-f176.google.com with SMTP id 41be03b00d2f7-7db2e3fa438so231057a12.1 for ; Thu, 12 Sep 2024 16:18:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=rivosinc-com.20230601.gappssmtp.com; s=20230601; t=1726183127; x=1726787927; 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=QuNLZoEwAoxFOzNtpFEIpmCklLXVvlyHizGcnsawnko=; b=cE+rVR06xQYD87RkDxKvMZb+FvrlT2FAMyDMnAkw9fOxk786klpMOChRfhR3L0z1Ua kx2fzKDWUCgzt9hnONVomYnGBhARuUscySz/FhDTtketNPCbvMP+bGt6JHnwl3DqcKDT XKpp2XTRk/M011HpChohX4oBfYFHUy22w88rBh85YqMhL+jE2l8cQu9LUMriC4ADkSGE RqhctF2Tmjy90JW9rr6MgF/lZyTpGzqNPZyz+xNr/IucFnLMCGB9rE98f8aum5052/70 10jYZk3ZeAJOELcaTI1sRMDC+9wZ2hLM+QH01KK8HzTknkWR1YtDOd5/KpyAiKbfhlIY 2GMA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1726183127; x=1726787927; 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=QuNLZoEwAoxFOzNtpFEIpmCklLXVvlyHizGcnsawnko=; b=ZFU4Y6sEw/Lt9ZKJBCzl/GSUCwXghnv/wv1brp4MyPY75KhTnaxmjD0rDwGBmohFc6 6naS1xFRHYoquBLC7HDe2CS7hZf1ZSpzsQprB48Yo4fxbzFSPkD3JOFLs/V7zW0Coavc isokZOXR83TBA6p8vzU/BbJGOebTdJsr3nAPd0VJDwu/jO21+sLa0J/nhqmOQQMaiZW+ 3z5HLiRZ/Vx8E5ct4rfGH1R56jEwJoO9Ai6F6uWlxdqlfrtJf0JdgH+UbRxGjOt8GBPW z3ilFPZgSZ7Izk/nTLo05u71ciRyQIWzITJYpkV93Spsw0EMPXavB4doOUVd5QAptEeF eidA== X-Forwarded-Encrypted: i=1; AJvYcCV6k9oKfUuuVU87LmfLFMh++J/DQ+TeHx72cUItLKB6Cuf0oxhQvDr19j2Mm1CqP3CNnl6zbOJt3A==@kvack.org X-Gm-Message-State: AOJu0YwB5MhW5ZoDdhc9cximhsTscUW69/V+IKz6LX8OA/6GOBDquO7t JA/QtBv1xVYICIOgsEszleT3Jy/mgqSuAtVpbUWkWq3+tZWv2Wc7p0T7YH4qKY8= X-Google-Smtp-Source: AGHT+IFe2b+wfH4HddVQdWnBa2Cv1PojGiau8/JID+xbbETXDST/X3AAL06qD2zWAK34gSRESgSPDg== X-Received: by 2002:a17:90a:4b82:b0:2c9:8105:483 with SMTP id 98e67ed59e1d1-2db9ffca8a1mr4592061a91.14.1726183126845; Thu, 12 Sep 2024 16:18:46 -0700 (PDT) Received: from debug.ba.rivosinc.com ([64.71.180.162]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-2db6c1ac69asm3157591a91.0.2024.09.12.16.18.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 12 Sep 2024 16:18:46 -0700 (PDT) From: Deepak Gupta To: paul.walmsley@sifive.com, palmer@sifive.com, conor@kernel.org, linux-doc@vger.kernel.org, linux-riscv@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, linux-arch@vger.kernel.org, linux-kselftest@vger.kernel.org Cc: corbet@lwn.net, palmer@dabbelt.com, aou@eecs.berkeley.edu, robh@kernel.org, krzk+dt@kernel.org, oleg@redhat.com, tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, dave.hansen@linux.intel.com, x86@kernel.org, hpa@zytor.com, peterz@infradead.org, akpm@linux-foundation.org, arnd@arndb.de, ebiederm@xmission.com, kees@kernel.org, Liam.Howlett@oracle.com, vbabka@suse.cz, lorenzo.stoakes@oracle.com, shuah@kernel.org, brauner@kernel.org, samuel.holland@sifive.com, debug@rivosinc.com, andy.chiu@sifive.com, jerry.shih@sifive.com, greentime.hu@sifive.com, charlie@rivosinc.com, evan@rivosinc.com, cleger@rivosinc.com, xiao.w.wang@intel.com, ajones@ventanamicro.com, anup@brainfault.org, mchitale@ventanamicro.com, atishp@rivosinc.com, sameo@rivosinc.com, bjorn@rivosinc.com, alexghiti@rivosinc.com, david@redhat.com, libang.li@antgroup.com, jszhang@kernel.org, leobras@redhat.com, guoren@kernel.org, samitolvanen@google.com, songshuaishuai@tinylab.org, costa.shul@redhat.com, bhe@redhat.com, zong.li@sifive.com, puranjay@kernel.org, namcaov@gmail.com, antonb@tenstorrent.com, sorear@fastmail.com, quic_bjorande@quicinc.com, ancientmodern4@gmail.com, ben.dooks@codethink.co.uk, quic_zhonhan@quicinc.com, cuiyunhui@bytedance.com, yang.lee@linux.alibaba.com, ke.zhao@shingroup.cn, sunilvl@ventanamicro.com, tanzhasanwork@gmail.com, schwab@suse.de, dawei.li@shingroup.cn, rppt@kernel.org, willy@infradead.org, usama.anjum@collabora.com, osalvador@suse.de, ryan.roberts@arm.com, andrii@kernel.org, alx@kernel.org, catalin.marinas@arm.com, broonie@kernel.org, revest@chromium.org, bgray@linux.ibm.com, deller@gmx.de, zev@bewilderbeest.net Subject: [PATCH v4 23/30] riscv signal: save and restore of shadow stack for signal Date: Thu, 12 Sep 2024 16:16:42 -0700 Message-ID: <20240912231650.3740732-24-debug@rivosinc.com> X-Mailer: git-send-email 2.45.0 In-Reply-To: <20240912231650.3740732-1-debug@rivosinc.com> References: <20240912231650.3740732-1-debug@rivosinc.com> MIME-Version: 1.0 X-Rspamd-Server: rspam03 X-Rspam-User: X-Rspamd-Queue-Id: 3778CC0002 X-Stat-Signature: f3gddrb7cuz1cyhbzo5dyyddfu9fowps X-HE-Tag: 1726183127-363915 X-HE-Meta: U2FsdGVkX1+l4Agzh4w6fxTuBUx3lBQKuCDY7sDjJQi2ciRu2PSRP53dSizKFhiAGV/s6Zga8I53gJESrBvjAbTkQnp8SBgEaFCDvFx9eSUsFDRcSc5zzwSieGc0KQfLCsfNLMSXk9jaN8/crL+BLiaAI+2p8Tj3v8sgwhUtp+iAoCIKj/ZA4k2nPr/G6D9H61f+K3wbPfcwwwPpXblO+9LH5948GRGfSUQpNg6yiVAvg45VMMHzQ1Uvezrsj5yYG2RjtjZZK2H25QqPlLUlzuSgkTPHe7JabBXe38YC5le2utbgjkpbTdUHHK7pPCJIC+3VJkym/WfG+VQrvBHnMSnwknZL9Acwkhsmb9h75Y643dqaDZnUQ8yAB/GaT1NrF/RKPpSF9f+MEQLiFpT4hfnKvMZwqHQeXgk3hGwU6JLny6jQrEjiknoLYGU+YmeNwkQt3e8wwK2Kk1aiA4uW9nnTvRfZQSgcY403Q9np9FwX3ADl4Sdascock20aLiI3mgf5pBIvCaLeQXF4pMXe3gYWeNoNwVKgvyQnoHo8T5d8euOj+mz7B1U+IsiSgEJiuEu3CgPlJRStSMK5PbVVJgkjQVyGLwAobd6HngRkGMGN1hky54lBe6+Nv0GEHs2l70zC0A7ls4VSATxSUoz60NChgYg7DGOCQBMC6GmMGss9zsGkMfoX2lTHwGR3p69V4haFL27I1rpoq8NI96OLQmQXb3GrYL158FezvlEUp2R/9Bd32GxbPOEbZTzKDQCvwzdJFA9doQqykNkb7UYWKN65peZV5ftk5ysmEVoWHywPUEogUknd2lAkpzVt2fqNB7MUncHFBvtrXPGP0TQclbCs/mM2d3uJAYlAztEEOj0I980tczSo7ttxMK0YSj50m5YKRyvWOJSD+7U0HVrvN2sWM22jqSpnvTzP7birTNlX7OKXY4DozV8Akk76JwzDf1nO9gR9FNqCoxKKPJF Hp4b5GPX mCVu4/2P+DxYZjGkJucZlhCeElH5x4Jqh4/v2Hf/+MND3WiHmgDtAY54aGmZmA9lOe4obJekV/CUopBUxIh3R9Wjw8d9lkZ9EfgcyEfa28ZJ+fwC9xdSZGyVcCNCAUDfu7Qt6CaoYwwPMuGLmouGxcHXg+0dszFdAg36+GSUKeqeJYueHN+x2t3h7ZEQUGob4lBklV3vXPREr+bkqlJ80AqwKQmmeFpugPuyTOhbtcRvlSQgFo7m4ql9v3elePrDpfitZPsubEubMJRJlrgT715npvTqjg3Wyi4YDayC6JwxHB4F7BhQVEHNtcHAyMIFpR+FzjyINxpvwPqj/0yJfiVLSJxCk0sish8KtYS6QN2IsXfXJgx+AKAkMTKgx1i0AZyqLRnh/nC0mFd8S2Cy7/Li+9O2cVmLA4+RzDzx7mPQbyuOoS2bd9orCC/ZkWQrv3TsAolQa1iiaz+itUXpERWNiF+GUSumjOp2MZtCxvxC4KZU5zuPUepCHiqSXWhdfILX7 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: Save shadow stack pointer in sigcontext structure while delivering signal. Restore shadow stack pointer from sigcontext on sigreturn. As part of save operation, kernel uses `ssamoswap` to save snapshot of current shadow stack on shadow stack itself (can be called as a save token). During restore on sigreturn, kernel retrieves token from top of shadow stack and validates it. This allows that user mode can't arbitrary pivot to any shadow stack address without having a token and thus provide strong security assurance between signaly delivery and sigreturn window. Signed-off-by: Deepak Gupta Suggested-by: Andy Chiu --- arch/riscv/include/asm/usercfi.h | 19 ++++++++++ arch/riscv/kernel/signal.c | 62 +++++++++++++++++++++++++++++++- arch/riscv/kernel/usercfi.c | 57 +++++++++++++++++++++++++++++ 3 files changed, 137 insertions(+), 1 deletion(-) diff --git a/arch/riscv/include/asm/usercfi.h b/arch/riscv/include/asm/usercfi.h index 20a9102cce51..d5050a5df26c 100644 --- a/arch/riscv/include/asm/usercfi.h +++ b/arch/riscv/include/asm/usercfi.h @@ -8,6 +8,7 @@ #ifndef __ASSEMBLY__ #include #include +#include struct task_struct; struct kernel_clone_args; @@ -35,6 +36,9 @@ bool is_shstk_locked(struct task_struct *task); bool is_shstk_allocated(struct task_struct *task); void set_shstk_lock(struct task_struct *task); void set_shstk_status(struct task_struct *task, bool enable); +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); bool is_indir_lp_enabled(struct task_struct *task); bool is_indir_lp_locked(struct task_struct *task); void set_indir_lp_status(struct task_struct *task, bool enable); @@ -96,6 +100,21 @@ static inline void set_shstk_status(struct task_struct *task, bool enable) } +static inline int restore_user_shstk(struct task_struct *tsk, unsigned long shstk_ptr) +{ + return -EINVAL; +} + +static inline int save_user_shstk(struct task_struct *tsk, unsigned long *saved_shstk_ptr) +{ + return -EINVAL; +} + +static inline unsigned long get_active_shstk(struct task_struct *task) +{ + return 0; +} + static inline bool is_indir_lp_enabled(struct task_struct *task) { return false; diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c index dcd282419456..7d5c1825650f 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; @@ -153,6 +154,16 @@ static long restore_sigcontext(struct pt_regs *regs, void __user *sc_ext_ptr = &sc->sc_extdesc.hdr; __u32 rsvd; long err; + unsigned long ss_ptr = 0; + struct __sc_riscv_cfi_state __user *sc_cfi = NULL; + + sc_cfi = (struct __sc_riscv_cfi_state *) + ((unsigned long) sc_ext_ptr + sizeof(struct __riscv_ctx_hdr)); + + if (has_vector() && riscv_v_vstate_query(regs)) + sc_cfi = (struct __sc_riscv_cfi_state *) + ((unsigned long) sc_cfi + riscv_v_sc_size); + /* sc_regs is structured the same as the start of pt_regs */ err = __copy_from_user(regs, &sc->sc_regs, sizeof(sc->sc_regs)); if (unlikely(err)) @@ -172,6 +183,24 @@ static long restore_sigcontext(struct pt_regs *regs, if (unlikely(rsvd)) return -EINVAL; + /* + * 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 (is_shstk_enabled(current)) { + err |= __copy_from_user(&ss_ptr, &sc_cfi->ss_ptr, sizeof(unsigned long)); + err |= restore_user_shstk(current, ss_ptr); + } + while (!err) { __u32 magic, size; struct __riscv_ctx_hdr __user *head = sc_ext_ptr; @@ -215,6 +244,10 @@ static size_t get_rt_frame_size(bool cal_all) if (cal_all || riscv_v_vstate_query(task_pt_regs(current))) total_context_size += riscv_v_sc_size; } + + if (is_shstk_enabled(current)) + total_context_size += sizeof(struct __sc_riscv_cfi_state); + /* * Preserved a __riscv_ctx_hdr for END signal context header if an * extension uses __riscv_extra_ext_header @@ -276,18 +309,40 @@ static long setup_sigcontext(struct rt_sigframe __user *frame, { struct sigcontext __user *sc = &frame->uc.uc_mcontext; struct __riscv_ctx_hdr __user *sc_ext_ptr = &sc->sc_extdesc.hdr; + unsigned long ss_ptr = 0; + struct __sc_riscv_cfi_state __user *sc_cfi = NULL; long err; + sc_cfi = (struct __sc_riscv_cfi_state *) (sc_ext_ptr + 1); + /* sc_regs is structured the same as the start of pt_regs */ err = __copy_to_user(&sc->sc_regs, regs, sizeof(sc->sc_regs)); /* Save the floating-point state. */ if (has_fpu()) err |= save_fp_state(regs, &sc->sc_fpregs); /* Save the vector state. */ - if (has_vector() && riscv_v_vstate_query(regs)) + if (has_vector() && riscv_v_vstate_query(regs)) { err |= save_v_state(regs, (void __user **)&sc_ext_ptr); + sc_cfi = (struct __sc_riscv_cfi_state *) ((unsigned long) sc_cfi + riscv_v_sc_size); + } /* Write zero to fp-reserved space and check it on restore_sigcontext */ err |= __put_user(0, &sc->sc_extdesc.reserved); + /* + * 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, &sc_cfi->ss_ptr); + } /* And put END __riscv_ctx_hdr at the end. */ err |= __put_user(END_MAGIC, &sc_ext_ptr->magic); err |= __put_user(END_HDR_SIZE, &sc_ext_ptr->size); @@ -345,6 +400,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 8da509afdbe9..40c32258b6ec 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; @@ -164,6 +169,58 @@ 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); + + if (!ret) { + *saved_shstk_ptr = token_loc; + set_active_shstk(tsk, 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) { + pr_info_ratelimited( + "%s[%d]: bad restore token in %s: pc=%p sp=%p, token=%p, shstk_ptr=%p\n", + tsk->comm, task_pid_nr(tsk), __func__, + (void *)(task_pt_regs(tsk)->epc), (void *)(task_pt_regs(tsk)->sp), + (void *)token, (void *)shstk_ptr); + 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)