Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

fs/proc: Show STACKLEAK metrics in the /proc file system

Introduce CONFIG_STACKLEAK_METRICS providing STACKLEAK information about
tasks via the /proc file system. In particular, /proc/<pid>/stack_depth
shows the maximum kernel stack consumption for the current and previous
syscalls. Although this information is not precise, it can be useful for
estimating the STACKLEAK performance impact for your workloads.

Suggested-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Alexander Popov <alex.popov@linux.com>
Tested-by: Laura Abbott <labbott@redhat.com>
Signed-off-by: Kees Cook <keescook@chromium.org>

authored by

Alexander Popov and committed by
Kees Cook
c8d12627 f90d1e0c

+38
+18
fs/proc/base.c
··· 2891 2891 } 2892 2892 #endif /* CONFIG_LIVEPATCH */ 2893 2893 2894 + #ifdef CONFIG_STACKLEAK_METRICS 2895 + static int proc_stack_depth(struct seq_file *m, struct pid_namespace *ns, 2896 + struct pid *pid, struct task_struct *task) 2897 + { 2898 + unsigned long prev_depth = THREAD_SIZE - 2899 + (task->prev_lowest_stack & (THREAD_SIZE - 1)); 2900 + unsigned long depth = THREAD_SIZE - 2901 + (task->lowest_stack & (THREAD_SIZE - 1)); 2902 + 2903 + seq_printf(m, "previous stack depth: %lu\nstack depth: %lu\n", 2904 + prev_depth, depth); 2905 + return 0; 2906 + } 2907 + #endif /* CONFIG_STACKLEAK_METRICS */ 2908 + 2894 2909 /* 2895 2910 * Thread groups 2896 2911 */ ··· 3006 2991 REG("timerslack_ns", S_IRUGO|S_IWUGO, proc_pid_set_timerslack_ns_operations), 3007 2992 #ifdef CONFIG_LIVEPATCH 3008 2993 ONE("patch_state", S_IRUSR, proc_pid_patch_state), 2994 + #endif 2995 + #ifdef CONFIG_STACKLEAK_METRICS 2996 + ONE("stack_depth", S_IRUGO, proc_stack_depth), 3009 2997 #endif 3010 2998 }; 3011 2999
+1
include/linux/sched.h
··· 1194 1194 1195 1195 #ifdef CONFIG_GCC_PLUGIN_STACKLEAK 1196 1196 unsigned long lowest_stack; 1197 + unsigned long prev_lowest_stack; 1197 1198 #endif 1198 1199 1199 1200 /*
+3
include/linux/stackleak.h
··· 18 18 static inline void stackleak_task_init(struct task_struct *t) 19 19 { 20 20 t->lowest_stack = (unsigned long)end_of_stack(t) + sizeof(unsigned long); 21 + # ifdef CONFIG_STACKLEAK_METRICS 22 + t->prev_lowest_stack = t->lowest_stack; 23 + # endif 21 24 } 22 25 #else /* !CONFIG_GCC_PLUGIN_STACKLEAK */ 23 26 static inline void stackleak_task_init(struct task_struct *t) { }
+4
kernel/stackleak.c
··· 41 41 if (kstack_ptr == boundary) 42 42 kstack_ptr += sizeof(unsigned long); 43 43 44 + #ifdef CONFIG_STACKLEAK_METRICS 45 + current->prev_lowest_stack = kstack_ptr; 46 + #endif 47 + 44 48 /* 45 49 * Now write the poison value to the kernel stack. Start from 46 50 * 'kstack_ptr' and move up till the new 'boundary'. We assume that
+12
scripts/gcc-plugins/Kconfig
··· 170 170 a stack frame size greater than or equal to this parameter. 171 171 If unsure, leave the default value 100. 172 172 173 + config STACKLEAK_METRICS 174 + bool "Show STACKLEAK metrics in the /proc file system" 175 + depends on GCC_PLUGIN_STACKLEAK 176 + depends on PROC_FS 177 + help 178 + If this is set, STACKLEAK metrics for every task are available in 179 + the /proc file system. In particular, /proc/<pid>/stack_depth 180 + shows the maximum kernel stack consumption for the current and 181 + previous syscalls. Although this information is not precise, it 182 + can be useful for estimating the STACKLEAK performance impact for 183 + your workloads. 184 + 173 185 endif