1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Deferred user space unwinding 4 */ 5 #include <linux/kernel.h> 6 #include <linux/sched.h> 7 #include <linux/sizes.h> 8 #include <linux/slab.h> 9 #include <linux/unwind_deferred.h> 10 11 /* Make the cache fit in a 4K page */ 12 #define UNWIND_MAX_ENTRIES \ 13 ((SZ_4K - sizeof(struct unwind_cache)) / sizeof(long)) 14 15 /** 16 * unwind_user_faultable - Produce a user stacktrace in faultable context 17 * @trace: The descriptor that will store the user stacktrace 18 * 19 * This must be called in a known faultable context (usually when entering 20 * or exiting user space). Depending on the available implementations 21 * the @trace will be loaded with the addresses of the user space stacktrace 22 * if it can be found. 23 * 24 * Return: 0 on success and negative on error 25 * On success @trace will contain the user space stacktrace 26 */ 27 int unwind_user_faultable(struct unwind_stacktrace *trace) 28 { 29 struct unwind_task_info *info = ¤t->unwind_info; 30 struct unwind_cache *cache; 31 32 /* Should always be called from faultable context */ 33 might_fault(); 34 35 if (current->flags & PF_EXITING) 36 return -EINVAL; 37 38 if (!info->cache) { 39 info->cache = kzalloc(struct_size(cache, entries, UNWIND_MAX_ENTRIES), 40 GFP_KERNEL); 41 if (!info->cache) 42 return -ENOMEM; 43 } 44 45 cache = info->cache; 46 trace->entries = cache->entries; 47 48 if (cache->nr_entries) { 49 /* 50 * The user stack has already been previously unwound in this 51 * entry context. Skip the unwind and use the cache. 52 */ 53 trace->nr = cache->nr_entries; 54 return 0; 55 } 56 57 trace->nr = 0; 58 unwind_user(trace, UNWIND_MAX_ENTRIES); 59 60 cache->nr_entries = trace->nr; 61 62 return 0; 63 } 64 65 void unwind_task_init(struct task_struct *task) 66 { 67 struct unwind_task_info *info = &task->unwind_info; 68 69 memset(info, 0, sizeof(*info)); 70 } 71 72 void unwind_task_free(struct task_struct *task) 73 { 74 struct unwind_task_info *info = &task->unwind_info; 75 76 kfree(info->cache); 77 } 78