| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
| From: Sami Tolvanen <samitolvanen@google.com> |
| Date: Thu, 6 Sep 2018 13:09:06 -0700 |
| Subject: FROMLIST: scs: add support for stack usage debugging |
| |
| Implements CONFIG_DEBUG_STACK_USAGE for shadow stacks. When enabled, |
| also prints out the highest shadow stack usage per process. |
| |
| Bug: 145210207 |
| Change-Id: I2b2fea68760ca8d94d6f887cfe5828883d233b88 |
| (am from https://lore.kernel.org/patchwork/patch/1149056/) |
| Reviewed-by: Kees Cook <keescook@chromium.org> |
| Signed-off-by: Sami Tolvanen <samitolvanen@google.com> |
| --- |
| kernel/scs.c | 39 +++++++++++++++++++++++++++++++++++++++ |
| 1 file changed, 39 insertions(+) |
| |
| diff --git a/kernel/scs.c b/kernel/scs.c |
| index 5245e992c692..ad74d13f2c0f 100644 |
| --- a/kernel/scs.c |
| +++ b/kernel/scs.c |
| @@ -184,6 +184,44 @@ int scs_prepare(struct task_struct *tsk, int node) |
| return 0; |
| } |
| |
| +#ifdef CONFIG_DEBUG_STACK_USAGE |
| +static inline unsigned long scs_used(struct task_struct *tsk) |
| +{ |
| + unsigned long *p = __scs_base(tsk); |
| + unsigned long *end = scs_magic(p); |
| + unsigned long s = (unsigned long)p; |
| + |
| + while (p < end && READ_ONCE_NOCHECK(*p)) |
| + p++; |
| + |
| + return (unsigned long)p - s; |
| +} |
| + |
| +static void scs_check_usage(struct task_struct *tsk) |
| +{ |
| + static DEFINE_SPINLOCK(lock); |
| + static unsigned long highest; |
| + unsigned long used = scs_used(tsk); |
| + |
| + if (used <= highest) |
| + return; |
| + |
| + spin_lock(&lock); |
| + |
| + if (used > highest) { |
| + pr_info("%s (%d): highest shadow stack usage: %lu bytes\n", |
| + tsk->comm, task_pid_nr(tsk), used); |
| + highest = used; |
| + } |
| + |
| + spin_unlock(&lock); |
| +} |
| +#else |
| +static inline void scs_check_usage(struct task_struct *tsk) |
| +{ |
| +} |
| +#endif |
| + |
| bool scs_corrupted(struct task_struct *tsk) |
| { |
| unsigned long *magic = scs_magic(__scs_base(tsk)); |
| @@ -200,6 +238,7 @@ void scs_release(struct task_struct *tsk) |
| return; |
| |
| WARN_ON(scs_corrupted(tsk)); |
| + scs_check_usage(tsk); |
| |
| scs_account(tsk, -1); |
| task_set_scs(tsk, NULL); |