From: Deepak Gupta <debug@rivosinc.com>
To: linux-riscv@lists.infradead.org, linux-kernel@vger.kernel.org,
llvm@lists.linux.dev
Cc: paul.walmsley@sifive.com, palmer@dabbelt.com,
aou@eecs.berkeley.edu, nathan@kernel.org,
ndesaulniers@google.com, morbo@google.com,
justinstitt@google.com, andy.chiu@sifive.com, debug@rivosinc.com,
hankuan.chen@sifive.com, guoren@kernel.org,
greentime.hu@sifive.com, samitolvanen@google.com,
cleger@rivosinc.com, apatel@ventanamicro.com,
ajones@ventanamicro.com, conor.dooley@microchip.com,
mchitale@ventanamicro.com, dbarboza@ventanamicro.com,
waylingii@gmail.com, sameo@rivosinc.com, alexghiti@rivosinc.com,
akpm@linux-foundation.org, shikemeng@huaweicloud.com,
rppt@kernel.org, charlie@rivosinc.com, xiao.w.wang@intel.com,
willy@infradead.org, jszhang@kernel.org, leobras@redhat.com,
songshuaishuai@tinylab.org, haxel@fzi.de,
samuel.holland@sifive.com, namcaov@gmail.com, bjorn@rivosinc.com,
cuiyunhui@bytedance.com, wangkefeng.wang@huawei.com,
falcon@tinylab.org, viro@zeniv.linux.org.uk, bhe@redhat.com,
chenjiahao16@huawei.com, hca@linux.ibm.com, arnd@arndb.de,
kent.overstreet@linux.dev, boqun.feng@gmail.com, oleg@redhat.com,
paulmck@kernel.org, broonie@kernel.org,
rick.p.edgecombe@intel.com
Subject: [RFC PATCH 09/12] scs: kernel shadow stack with hardware assistance
Date: Mon, 8 Apr 2024 23:10:40 -0700 [thread overview]
Message-ID: <20240409061043.3269676-10-debug@rivosinc.com> (raw)
In-Reply-To: <20240409061043.3269676-1-debug@rivosinc.com>
If shadow stack have memory protections from underlying cpu, use those
protections. RISCV uses PAGE_KERNEL_SHADOWSTACK to vmalloc such shadow
stack pages. Shadow stack pages on RISCV grows downwards like regular
stack. Clang based software shadow call stack grows low to high address.
Thus this patch addresses some of those needs due to opposite direction
of shadow stack. Furthermore, RISCV hw shadow stack can't be memset
because memset uses normal stores. Lastly to store magic word at base of
shadow stack, arch specific shadow stack store has to be performed.
Signed-off-by: Deepak Gupta <debug@rivosinc.com>
---
include/linux/scs.h | 48 +++++++++++++++++++++++++++++++++------------
kernel/scs.c | 28 ++++++++++++++++++++++----
2 files changed, 59 insertions(+), 17 deletions(-)
diff --git a/include/linux/scs.h b/include/linux/scs.h
index 4ab5bdc898cf..3a31433532d1 100644
--- a/include/linux/scs.h
+++ b/include/linux/scs.h
@@ -12,6 +12,7 @@
#include <linux/poison.h>
#include <linux/sched.h>
#include <linux/sizes.h>
+#include <asm/scs.h>
#ifdef CONFIG_SHADOW_CALL_STACK
@@ -31,6 +32,29 @@ void scs_init(void);
int scs_prepare(struct task_struct *tsk, int node);
void scs_release(struct task_struct *tsk);
+#ifdef CONFIG_DYNAMIC_SCS
+/* dynamic_scs_enabled set to true if RISCV dynamic SCS */
+#ifdef CONFIG_RISCV
+DECLARE_STATIC_KEY_TRUE(dynamic_scs_enabled);
+#else
+DECLARE_STATIC_KEY_FALSE(dynamic_scs_enabled);
+#endif
+#endif
+
+static inline bool scs_is_dynamic(void)
+{
+ if (!IS_ENABLED(CONFIG_DYNAMIC_SCS))
+ return false;
+ return static_branch_likely(&dynamic_scs_enabled);
+}
+
+static inline bool scs_is_enabled(void)
+{
+ if (!IS_ENABLED(CONFIG_DYNAMIC_SCS))
+ return true;
+ return scs_is_dynamic();
+}
+
static inline void scs_task_reset(struct task_struct *tsk)
{
/*
@@ -42,6 +66,9 @@ static inline void scs_task_reset(struct task_struct *tsk)
static inline unsigned long *__scs_magic(void *s)
{
+ if (scs_is_dynamic())
+ return (unsigned long *)(s);
+
return (unsigned long *)(s + SCS_SIZE) - 1;
}
@@ -50,23 +77,18 @@ static inline bool task_scs_end_corrupted(struct task_struct *tsk)
unsigned long *magic = __scs_magic(task_scs(tsk));
unsigned long sz = task_scs_sp(tsk) - task_scs(tsk);
- return sz >= SCS_SIZE - 1 || READ_ONCE_NOCHECK(*magic) != SCS_END_MAGIC;
-}
-
-DECLARE_STATIC_KEY_FALSE(dynamic_scs_enabled);
+ if (scs_is_dynamic())
+ sz = (task_scs(tsk) + SCS_SIZE) - task_scs_sp(tsk);
-static inline bool scs_is_dynamic(void)
-{
- if (!IS_ENABLED(CONFIG_DYNAMIC_SCS))
- return false;
- return static_branch_likely(&dynamic_scs_enabled);
+ return sz >= SCS_SIZE - 1 || READ_ONCE_NOCHECK(*magic) != SCS_END_MAGIC;
}
-static inline bool scs_is_enabled(void)
+static inline void __scs_store_magic(unsigned long *s, unsigned long magic_val)
{
- if (!IS_ENABLED(CONFIG_DYNAMIC_SCS))
- return true;
- return scs_is_dynamic();
+ if (scs_is_dynamic())
+ arch_scs_store(s, magic_val);
+ else
+ *__scs_magic(s) = SCS_END_MAGIC;
}
#else /* CONFIG_SHADOW_CALL_STACK */
diff --git a/kernel/scs.c b/kernel/scs.c
index d7809affe740..e447483fa9f4 100644
--- a/kernel/scs.c
+++ b/kernel/scs.c
@@ -13,8 +13,13 @@
#include <linux/vmstat.h>
#ifdef CONFIG_DYNAMIC_SCS
+/* dynamic_scs_enabled set to true if RISCV dynamic SCS */
+#ifdef CONFIG_RISCV
+DEFINE_STATIC_KEY_TRUE(dynamic_scs_enabled);
+#else
DEFINE_STATIC_KEY_FALSE(dynamic_scs_enabled);
#endif
+#endif
static void __scs_account(void *s, int account)
{
@@ -32,19 +37,29 @@ static void *__scs_alloc(int node)
{
int i;
void *s;
+ pgprot_t prot = PAGE_KERNEL;
+
+ if (scs_is_dynamic())
+ prot = PAGE_KERNEL_SHADOWSTACK;
for (i = 0; i < NR_CACHED_SCS; i++) {
s = this_cpu_xchg(scs_cache[i], NULL);
if (s) {
s = kasan_unpoison_vmalloc(s, SCS_SIZE,
KASAN_VMALLOC_PROT_NORMAL);
- memset(s, 0, SCS_SIZE);
+/*
+ * If either of them undefined, its safe to memset. Else memset is not
+ * possible. memset constitutes stores and stores to shadow stack memory
+ * are disallowed and will fault.
+ */
+ if (!scs_is_dynamic())
+ memset(s, 0, SCS_SIZE);
goto out;
}
}
s = __vmalloc_node_range(SCS_SIZE, 1, VMALLOC_START, VMALLOC_END,
- GFP_SCS, PAGE_KERNEL, 0, node,
+ GFP_SCS, prot, 0, node,
__builtin_return_address(0));
out:
@@ -59,7 +74,7 @@ void *scs_alloc(int node)
if (!s)
return NULL;
- *__scs_magic(s) = SCS_END_MAGIC;
+ __scs_store_magic(__scs_magic(s), SCS_END_MAGIC);
/*
* Poison the allocation to catch unintentional accesses to
@@ -122,7 +137,12 @@ int scs_prepare(struct task_struct *tsk, int node)
if (!s)
return -ENOMEM;
- task_scs(tsk) = task_scs_sp(tsk) = s;
+ task_scs(tsk) = s;
+ if (scs_is_dynamic())
+ task_scs_sp(tsk) = s + SCS_SIZE;
+ else
+ task_scs_sp(tsk) = s;
+
return 0;
}
--
2.43.2
next prev parent reply other threads:[~2024-04-09 6:12 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-04-09 6:10 [RFC PATCH v1] riscv kernel control flow integrity Deepak Gupta
2024-04-09 6:10 ` [RFC PATCH 01/12] riscv: zicfiss / zicfilp extension csr and bit definitions Deepak Gupta
2024-04-09 6:10 ` [RFC PATCH 02/12] riscv: add landing pad for asm routines Deepak Gupta
2024-04-11 17:15 ` Sami Tolvanen
2024-04-11 17:53 ` Deepak Gupta
2024-04-11 18:33 ` Sami Tolvanen
2024-04-09 6:10 ` [RFC PATCH 03/12] riscv: after saving expected landing pad (elp), clear elp state Deepak Gupta
2024-04-09 6:10 ` [RFC PATCH 04/12] riscv: update asm call sites with label setup Deepak Gupta
2024-04-09 6:10 ` [RFC PATCH 05/12] riscv: fix certain indirect jumps for kernel cfi Deepak Gupta
2024-04-09 6:10 ` [RFC PATCH 06/12] scs: place init shadow stack in .shadowstack section Deepak Gupta
2024-04-09 6:10 ` [RFC PATCH 07/12] riscv/mm: prepare shadow stack for init task for kernel cfi Deepak Gupta
2024-05-12 20:12 ` Alexandre Ghiti
2024-05-13 18:59 ` Deepak Gupta
2024-04-09 6:10 ` [RFC PATCH 08/12] riscv: dynamic (zicfiss) shadow call stack support Deepak Gupta
2024-04-11 17:05 ` Sami Tolvanen
2024-04-11 17:30 ` Deepak Gupta
2024-04-11 17:47 ` Sami Tolvanen
2024-04-09 6:10 ` Deepak Gupta [this message]
2024-04-09 6:10 ` [RFC PATCH 10/12] riscv/traps: Introduce software check exception Deepak Gupta
2024-04-09 6:10 ` [RFC PATCH 11/12] riscv: Kconfig & Makefile for riscv kernel control flow integrity Deepak Gupta
2024-04-09 6:10 ` [RFC PATCH 12/12] riscv: enable kernel shadow stack and landing pad enforcement Deepak Gupta
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240409061043.3269676-10-debug@rivosinc.com \
--to=debug@rivosinc.com \
--cc=ajones@ventanamicro.com \
--cc=akpm@linux-foundation.org \
--cc=alexghiti@rivosinc.com \
--cc=andy.chiu@sifive.com \
--cc=aou@eecs.berkeley.edu \
--cc=apatel@ventanamicro.com \
--cc=arnd@arndb.de \
--cc=bhe@redhat.com \
--cc=bjorn@rivosinc.com \
--cc=boqun.feng@gmail.com \
--cc=broonie@kernel.org \
--cc=charlie@rivosinc.com \
--cc=chenjiahao16@huawei.com \
--cc=cleger@rivosinc.com \
--cc=conor.dooley@microchip.com \
--cc=cuiyunhui@bytedance.com \
--cc=dbarboza@ventanamicro.com \
--cc=falcon@tinylab.org \
--cc=greentime.hu@sifive.com \
--cc=guoren@kernel.org \
--cc=hankuan.chen@sifive.com \
--cc=haxel@fzi.de \
--cc=hca@linux.ibm.com \
--cc=jszhang@kernel.org \
--cc=justinstitt@google.com \
--cc=kent.overstreet@linux.dev \
--cc=leobras@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-riscv@lists.infradead.org \
--cc=llvm@lists.linux.dev \
--cc=mchitale@ventanamicro.com \
--cc=morbo@google.com \
--cc=namcaov@gmail.com \
--cc=nathan@kernel.org \
--cc=ndesaulniers@google.com \
--cc=oleg@redhat.com \
--cc=palmer@dabbelt.com \
--cc=paul.walmsley@sifive.com \
--cc=paulmck@kernel.org \
--cc=rick.p.edgecombe@intel.com \
--cc=rppt@kernel.org \
--cc=sameo@rivosinc.com \
--cc=samitolvanen@google.com \
--cc=samuel.holland@sifive.com \
--cc=shikemeng@huaweicloud.com \
--cc=songshuaishuai@tinylab.org \
--cc=viro@zeniv.linux.org.uk \
--cc=wangkefeng.wang@huawei.com \
--cc=waylingii@gmail.com \
--cc=willy@infradead.org \
--cc=xiao.w.wang@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox