x86: Expose thread features in /proc/$PID/status
authorRick Edgecombe <rick.p.edgecombe@intel.com>
Tue, 13 Jun 2023 00:11:02 +0000 (17:11 -0700)
committerDave Hansen <dave.hansen@linux.intel.com>
Wed, 2 Aug 2023 22:01:51 +0000 (15:01 -0700)
Applications and loaders can have logic to decide whether to enable
shadow stack. They usually don't report whether shadow stack has been
enabled or not, so there is no way to verify whether an application
actually is protected by shadow stack.

Add two lines in /proc/$PID/status to report enabled and locked features.

Since, this involves referring to arch specific defines in asm/prctl.h,
implement an arch breakout to emit the feature lines.

[Switched to CET, added to commit log]

Co-developed-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Signed-off-by: Rick Edgecombe <rick.p.edgecombe@intel.com>
Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
Reviewed-by: Borislav Petkov (AMD) <bp@alien8.de>
Reviewed-by: Kees Cook <keescook@chromium.org>
Acked-by: Mike Rapoport (IBM) <rppt@kernel.org>
Tested-by: Pengfei Xu <pengfei.xu@intel.com>
Tested-by: John Allen <john.allen@amd.com>
Tested-by: Kees Cook <keescook@chromium.org>
Link: https://lore.kernel.org/all/20230613001108.3040476-37-rick.p.edgecombe%40intel.com
arch/x86/kernel/cpu/proc.c
fs/proc/array.c
include/linux/proc_fs.h

index 099b6f0d96bdc1c369b493867bc703fa228ab892..31c0e68f6227292cc5b217d68646ff2e26f3889a 100644 (file)
@@ -4,6 +4,8 @@
 #include <linux/string.h>
 #include <linux/seq_file.h>
 #include <linux/cpufreq.h>
+#include <asm/prctl.h>
+#include <linux/proc_fs.h>
 
 #include "cpu.h"
 
@@ -175,3 +177,24 @@ const struct seq_operations cpuinfo_op = {
        .stop   = c_stop,
        .show   = show_cpuinfo,
 };
+
+#ifdef CONFIG_X86_USER_SHADOW_STACK
+static void dump_x86_features(struct seq_file *m, unsigned long features)
+{
+       if (features & ARCH_SHSTK_SHSTK)
+               seq_puts(m, "shstk ");
+       if (features & ARCH_SHSTK_WRSS)
+               seq_puts(m, "wrss ");
+}
+
+void arch_proc_pid_thread_features(struct seq_file *m, struct task_struct *task)
+{
+       seq_puts(m, "x86_Thread_features:\t");
+       dump_x86_features(m, task->thread.features);
+       seq_putc(m, '\n');
+
+       seq_puts(m, "x86_Thread_features_locked:\t");
+       dump_x86_features(m, task->thread.features_locked);
+       seq_putc(m, '\n');
+}
+#endif /* CONFIG_X86_USER_SHADOW_STACK */
index d35bbf35a8740182cd62d9a08322e0ac0c58e5c6..2c2efbe685d872201175a02377b818b1dbf31892 100644 (file)
@@ -431,6 +431,11 @@ static inline void task_untag_mask(struct seq_file *m, struct mm_struct *mm)
        seq_printf(m, "untag_mask:\t%#lx\n", mm_untag_mask(mm));
 }
 
+__weak void arch_proc_pid_thread_features(struct seq_file *m,
+                                         struct task_struct *task)
+{
+}
+
 int proc_pid_status(struct seq_file *m, struct pid_namespace *ns,
                        struct pid *pid, struct task_struct *task)
 {
@@ -455,6 +460,7 @@ int proc_pid_status(struct seq_file *m, struct pid_namespace *ns,
        task_cpus_allowed(m, task);
        cpuset_task_status_allowed(m, task);
        task_context_switch_counts(m, task);
+       arch_proc_pid_thread_features(m, task);
        return 0;
 }
 
index 253f2676d93a5f8c456c2e7822d1b497e2d363d9..de407e7c3b55fdbd9b5d3cbe93585b1e417a3e20 100644 (file)
@@ -159,6 +159,7 @@ int proc_pid_arch_status(struct seq_file *m, struct pid_namespace *ns,
 #endif /* CONFIG_PROC_PID_ARCH_STATUS */
 
 void arch_report_meminfo(struct seq_file *m);
+void arch_proc_pid_thread_features(struct seq_file *m, struct task_struct *task);
 
 #else /* CONFIG_PROC_FS */