~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/kernel/scs.c

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /kernel/scs.c (Version linux-6.12-rc7) and /kernel/scs.c (Version linux-5.0.21)


  1 // SPDX-License-Identifier: GPL-2.0                 1 
  2 /*                                                
  3  * Shadow Call Stack support.                     
  4  *                                                
  5  * Copyright (C) 2019 Google LLC                  
  6  */                                               
  7                                                   
  8 #include <linux/cpuhotplug.h>                     
  9 #include <linux/kasan.h>                          
 10 #include <linux/mm.h>                             
 11 #include <linux/scs.h>                            
 12 #include <linux/vmalloc.h>                        
 13 #include <linux/vmstat.h>                         
 14                                                   
 15 #ifdef CONFIG_DYNAMIC_SCS                         
 16 DEFINE_STATIC_KEY_FALSE(dynamic_scs_enabled);     
 17 #endif                                            
 18                                                   
 19 static void __scs_account(void *s, int account    
 20 {                                                 
 21         struct page *scs_page = vmalloc_to_pag    
 22                                                   
 23         mod_node_page_state(page_pgdat(scs_pag    
 24                             account * (SCS_SIZ    
 25 }                                                 
 26                                                   
 27 /* Matches NR_CACHED_STACKS for VMAP_STACK */     
 28 #define NR_CACHED_SCS 2                           
 29 static DEFINE_PER_CPU(void *, scs_cache[NR_CAC    
 30                                                   
 31 static void *__scs_alloc(int node)                
 32 {                                                 
 33         int i;                                    
 34         void *s;                                  
 35                                                   
 36         for (i = 0; i < NR_CACHED_SCS; i++) {     
 37                 s = this_cpu_xchg(scs_cache[i]    
 38                 if (s) {                          
 39                         s = kasan_unpoison_vma    
 40                                                   
 41                         memset(s, 0, SCS_SIZE)    
 42                         goto out;                 
 43                 }                                 
 44         }                                         
 45                                                   
 46         s = __vmalloc_node_range(SCS_SIZE, 1,     
 47                                     GFP_SCS, P    
 48                                     __builtin_    
 49                                                   
 50 out:                                              
 51         return kasan_reset_tag(s);                
 52 }                                                 
 53                                                   
 54 void *scs_alloc(int node)                         
 55 {                                                 
 56         void *s;                                  
 57                                                   
 58         s = __scs_alloc(node);                    
 59         if (!s)                                   
 60                 return NULL;                      
 61                                                   
 62         *__scs_magic(s) = SCS_END_MAGIC;          
 63                                                   
 64         /*                                        
 65          * Poison the allocation to catch unin    
 66          * the shadow stack when KASAN is enab    
 67          */                                       
 68         kasan_poison_vmalloc(s, SCS_SIZE);        
 69         __scs_account(s, 1);                      
 70         return s;                                 
 71 }                                                 
 72                                                   
 73 void scs_free(void *s)                            
 74 {                                                 
 75         int i;                                    
 76                                                   
 77         __scs_account(s, -1);                     
 78                                                   
 79         /*                                        
 80          * We cannot sleep as this can be call    
 81          * so use this_cpu_cmpxchg to update t    
 82          * to free the stack.                     
 83          */                                       
 84                                                   
 85         for (i = 0; i < NR_CACHED_SCS; i++)       
 86                 if (this_cpu_cmpxchg(scs_cache    
 87                         return;                   
 88                                                   
 89         kasan_unpoison_vmalloc(s, SCS_SIZE, KA    
 90         vfree_atomic(s);                          
 91 }                                                 
 92                                                   
 93 static int scs_cleanup(unsigned int cpu)          
 94 {                                                 
 95         int i;                                    
 96         void **cache = per_cpu_ptr(scs_cache,     
 97                                                   
 98         for (i = 0; i < NR_CACHED_SCS; i++) {     
 99                 vfree(cache[i]);                  
100                 cache[i] = NULL;                  
101         }                                         
102                                                   
103         return 0;                                 
104 }                                                 
105                                                   
106 void __init scs_init(void)                        
107 {                                                 
108         if (!scs_is_enabled())                    
109                 return;                           
110         cpuhp_setup_state(CPUHP_BP_PREPARE_DYN    
111                           scs_cleanup);           
112 }                                                 
113                                                   
114 int scs_prepare(struct task_struct *tsk, int n    
115 {                                                 
116         void *s;                                  
117                                                   
118         if (!scs_is_enabled())                    
119                 return 0;                         
120                                                   
121         s = scs_alloc(node);                      
122         if (!s)                                   
123                 return -ENOMEM;                   
124                                                   
125         task_scs(tsk) = task_scs_sp(tsk) = s;     
126         return 0;                                 
127 }                                                 
128                                                   
129 static void scs_check_usage(struct task_struct    
130 {                                                 
131         static unsigned long highest;             
132                                                   
133         unsigned long *p, prev, curr = highest    
134                                                   
135         if (!IS_ENABLED(CONFIG_DEBUG_STACK_USA    
136                 return;                           
137                                                   
138         for (p = task_scs(tsk); p < __scs_magi    
139                 if (!READ_ONCE_NOCHECK(*p))       
140                         break;                    
141                 used += sizeof(*p);               
142         }                                         
143                                                   
144         while (used > curr) {                     
145                 prev = cmpxchg_relaxed(&highes    
146                                                   
147                 if (prev == curr) {               
148                         pr_info("%s (%d): high    
149                                 tsk->comm, tas    
150                         break;                    
151                 }                                 
152                                                   
153                 curr = prev;                      
154         }                                         
155 }                                                 
156                                                   
157 void scs_release(struct task_struct *tsk)         
158 {                                                 
159         void *s = task_scs(tsk);                  
160                                                   
161         if (!scs_is_enabled() || !s)              
162                 return;                           
163                                                   
164         WARN(task_scs_end_corrupted(tsk),         
165              "corrupted shadow stack detected     
166         scs_check_usage(tsk);                     
167         scs_free(s);                              
168 }                                                 
169                                                   

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php