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

TOMOYO Linux Cross Reference
Linux/security/safesetid/securityfs.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ 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.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /security/safesetid/securityfs.c (Version linux-6.11.5) and /security/safesetid/securityfs.c (Version linux-4.16.18)


  1 // SPDX-License-Identifier: GPL-2.0                 1 
  2 /*                                                
  3  * SafeSetID Linux Security Module                
  4  *                                                
  5  * Author: Micah Morton <mortonm@chromium.org>    
  6  *                                                
  7  * Copyright (C) 2018 The Chromium OS Authors.    
  8  *                                                
  9  * This program is free software; you can redi    
 10  * it under the terms of the GNU General Publi    
 11  * published by the Free Software Foundation.     
 12  *                                                
 13  */                                               
 14                                                   
 15 #define pr_fmt(fmt) "SafeSetID: " fmt             
 16                                                   
 17 #include <linux/security.h>                       
 18 #include <linux/cred.h>                           
 19                                                   
 20 #include "lsm.h"                                  
 21                                                   
 22 static DEFINE_MUTEX(uid_policy_update_lock);      
 23 static DEFINE_MUTEX(gid_policy_update_lock);      
 24                                                   
 25 /*                                                
 26  * In the case the input buffer contains one o    
 27  * variables pointed to by @parent and @child     
 28  * function will return an error.                 
 29  * Contents of @buf may be modified.              
 30  */                                               
 31 static int parse_policy_line(struct file *file    
 32         struct setid_rule *rule)                  
 33 {                                                 
 34         char *child_str;                          
 35         int ret;                                  
 36         u32 parsed_parent, parsed_child;          
 37                                                   
 38         /* Format of |buf| string should be <U    
 39         child_str = strchr(buf, ':');             
 40         if (child_str == NULL)                    
 41                 return -EINVAL;                   
 42         *child_str = '\0';                        
 43         child_str++;                              
 44                                                   
 45         ret = kstrtou32(buf, 0, &parsed_parent    
 46         if (ret)                                  
 47                 return ret;                       
 48                                                   
 49         ret = kstrtou32(child_str, 0, &parsed_    
 50         if (ret)                                  
 51                 return ret;                       
 52                                                   
 53         if (rule->type == UID){                   
 54                 rule->src_id.uid = make_kuid(f    
 55                 rule->dst_id.uid = make_kuid(f    
 56                 if (!uid_valid(rule->src_id.ui    
 57                         return -EINVAL;           
 58         } else if (rule->type == GID){            
 59                 rule->src_id.gid = make_kgid(f    
 60                 rule->dst_id.gid = make_kgid(f    
 61                 if (!gid_valid(rule->src_id.gi    
 62                         return -EINVAL;           
 63         } else {                                  
 64                 /* Error, rule->type is an inv    
 65                 return -EINVAL;                   
 66         }                                         
 67         return 0;                                 
 68 }                                                 
 69                                                   
 70 static void __release_ruleset(struct rcu_head     
 71 {                                                 
 72         struct setid_ruleset *pol =               
 73                 container_of(rcu, struct setid    
 74         int bucket;                               
 75         struct setid_rule *rule;                  
 76         struct hlist_node *tmp;                   
 77                                                   
 78         hash_for_each_safe(pol->rules, bucket,    
 79                 kfree(rule);                      
 80         kfree(pol->policy_str);                   
 81         kfree(pol);                               
 82 }                                                 
 83                                                   
 84 static void release_ruleset(struct setid_rules    
 85         call_rcu(&pol->rcu, __release_ruleset)    
 86 }                                                 
 87                                                   
 88 static void insert_rule(struct setid_ruleset *    
 89 {                                                 
 90         if (pol->type == UID)                     
 91                 hash_add(pol->rules, &rule->ne    
 92         else if (pol->type == GID)                
 93                 hash_add(pol->rules, &rule->ne    
 94         else /* Error, pol->type is neither UI    
 95                 return;                           
 96 }                                                 
 97                                                   
 98 static int verify_ruleset(struct setid_ruleset    
 99 {                                                 
100         int bucket;                               
101         struct setid_rule *rule, *nrule;          
102         int res = 0;                              
103                                                   
104         hash_for_each(pol->rules, bucket, rule    
105                 if (_setid_policy_lookup(pol,     
106                         if (pol->type == UID)     
107                                 pr_warn("insec    
108                                         __kuid    
109                                         __kuid    
110                         } else if (pol->type =    
111                                 pr_warn("insec    
112                                         __kgid    
113                                         __kgid    
114                         } else { /* pol->type     
115                                 res = -EINVAL;    
116                                 return res;       
117                         }                         
118                         res = -EINVAL;            
119                                                   
120                         /* fix it up */           
121                         nrule = kmalloc(sizeof    
122                         if (!nrule)               
123                                 return -ENOMEM    
124                         if (pol->type == UID){    
125                                 nrule->src_id.    
126                                 nrule->dst_id.    
127                                 nrule->type =     
128                         } else { /* pol->type     
129                                 nrule->src_id.    
130                                 nrule->dst_id.    
131                                 nrule->type =     
132                         }                         
133                         insert_rule(pol, nrule    
134                 }                                 
135         }                                         
136         return res;                               
137 }                                                 
138                                                   
139 static ssize_t handle_policy_update(struct fil    
140                                     const char    
141 {                                                 
142         struct setid_ruleset *pol;                
143         char *buf, *p, *end;                      
144         int err;                                  
145                                                   
146         pol = kmalloc(sizeof(struct setid_rule    
147         if (!pol)                                 
148                 return -ENOMEM;                   
149         pol->policy_str = NULL;                   
150         pol->type = policy_type;                  
151         hash_init(pol->rules);                    
152                                                   
153         p = buf = memdup_user_nul(ubuf, len);     
154         if (IS_ERR(buf)) {                        
155                 err = PTR_ERR(buf);               
156                 goto out_free_pol;                
157         }                                         
158         pol->policy_str = kstrdup(buf, GFP_KER    
159         if (pol->policy_str == NULL) {            
160                 err = -ENOMEM;                    
161                 goto out_free_buf;                
162         }                                         
163                                                   
164         /* policy lines, including the last on    
165         while (*p != '\0') {                      
166                 struct setid_rule *rule;          
167                                                   
168                 end = strchr(p, '\n');            
169                 if (end == NULL) {                
170                         err = -EINVAL;            
171                         goto out_free_buf;        
172                 }                                 
173                 *end = '\0';                      
174                                                   
175                 rule = kmalloc(sizeof(struct s    
176                 if (!rule) {                      
177                         err = -ENOMEM;            
178                         goto out_free_buf;        
179                 }                                 
180                                                   
181                 rule->type = policy_type;         
182                 err = parse_policy_line(file,     
183                 if (err)                          
184                         goto out_free_rule;       
185                                                   
186                 if (_setid_policy_lookup(pol,     
187                         pr_warn("bad policy: d    
188                         err = -EEXIST;            
189                         goto out_free_rule;       
190                 }                                 
191                                                   
192                 insert_rule(pol, rule);           
193                 p = end + 1;                      
194                 continue;                         
195                                                   
196 out_free_rule:                                    
197                 kfree(rule);                      
198                 goto out_free_buf;                
199         }                                         
200                                                   
201         err = verify_ruleset(pol);                
202         /* bogus policy falls through after fi    
203         if (err && err != -EINVAL)                
204                 goto out_free_buf;                
205                                                   
206         /*                                        
207          * Everything looks good, apply the po    
208          * What we really want here is an xchg    
209          * doesn't currently exist, just use a    
210          */                                       
211         if (policy_type == UID) {                 
212                 mutex_lock(&uid_policy_update_    
213                 pol = rcu_replace_pointer(safe    
214                                           lock    
215                 mutex_unlock(&uid_policy_updat    
216         } else if (policy_type == GID) {          
217                 mutex_lock(&gid_policy_update_    
218                 pol = rcu_replace_pointer(safe    
219                                           lock    
220                 mutex_unlock(&gid_policy_updat    
221         } else {                                  
222                 /* Error, policy type is neith    
223                 pr_warn("error: bad policy typ    
224         }                                         
225         err = len;                                
226                                                   
227 out_free_buf:                                     
228         kfree(buf);                               
229 out_free_pol:                                     
230         if (pol)                                  
231                 release_ruleset(pol);             
232         return err;                               
233 }                                                 
234                                                   
235 static ssize_t safesetid_uid_file_write(struct    
236                                     const char    
237                                     size_t len    
238                                     loff_t *pp    
239 {                                                 
240         if (!file_ns_capable(file, &init_user_    
241                 return -EPERM;                    
242                                                   
243         if (*ppos != 0)                           
244                 return -EINVAL;                   
245                                                   
246         return handle_policy_update(file, buf,    
247 }                                                 
248                                                   
249 static ssize_t safesetid_gid_file_write(struct    
250                                     const char    
251                                     size_t len    
252                                     loff_t *pp    
253 {                                                 
254         if (!file_ns_capable(file, &init_user_    
255                 return -EPERM;                    
256                                                   
257         if (*ppos != 0)                           
258                 return -EINVAL;                   
259                                                   
260         return handle_policy_update(file, buf,    
261 }                                                 
262                                                   
263 static ssize_t safesetid_file_read(struct file    
264                                    size_t len,    
265 {                                                 
266         ssize_t res = 0;                          
267         struct setid_ruleset *pol;                
268         const char *kbuf;                         
269                                                   
270         mutex_lock(policy_update_lock);           
271         pol = rcu_dereference_protected(rulese    
272         if (pol) {                                
273                 kbuf = pol->policy_str;           
274                 res = simple_read_from_buffer(    
275                                                   
276         }                                         
277         mutex_unlock(policy_update_lock);         
278                                                   
279         return res;                               
280 }                                                 
281                                                   
282 static ssize_t safesetid_uid_file_read(struct     
283                                    size_t len,    
284 {                                                 
285         return safesetid_file_read(file, buf,     
286                                    &uid_policy    
287 }                                                 
288                                                   
289 static ssize_t safesetid_gid_file_read(struct     
290                                    size_t len,    
291 {                                                 
292         return safesetid_file_read(file, buf,     
293                                    &gid_policy    
294 }                                                 
295                                                   
296                                                   
297                                                   
298 static const struct file_operations safesetid_    
299         .read = safesetid_uid_file_read,          
300         .write = safesetid_uid_file_write,        
301 };                                                
302                                                   
303 static const struct file_operations safesetid_    
304         .read = safesetid_gid_file_read,          
305         .write = safesetid_gid_file_write,        
306 };                                                
307                                                   
308 static int __init safesetid_init_securityfs(vo    
309 {                                                 
310         int ret;                                  
311         struct dentry *policy_dir;                
312         struct dentry *uid_policy_file;           
313         struct dentry *gid_policy_file;           
314                                                   
315         if (!safesetid_initialized)               
316                 return 0;                         
317                                                   
318         policy_dir = securityfs_create_dir("sa    
319         if (IS_ERR(policy_dir)) {                 
320                 ret = PTR_ERR(policy_dir);        
321                 goto error;                       
322         }                                         
323                                                   
324         uid_policy_file = securityfs_create_fi    
325                         policy_dir, NULL, &saf    
326         if (IS_ERR(uid_policy_file)) {            
327                 ret = PTR_ERR(uid_policy_file)    
328                 goto error;                       
329         }                                         
330                                                   
331         gid_policy_file = securityfs_create_fi    
332                         policy_dir, NULL, &saf    
333         if (IS_ERR(gid_policy_file)) {            
334                 ret = PTR_ERR(gid_policy_file)    
335                 goto error;                       
336         }                                         
337                                                   
338                                                   
339         return 0;                                 
340                                                   
341 error:                                            
342         securityfs_remove(policy_dir);            
343         return ret;                               
344 }                                                 
345 fs_initcall(safesetid_init_securityfs);           
346                                                   

~ [ 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