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

TOMOYO Linux Cross Reference
Linux/security/device_cgroup.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/device_cgroup.c (Version linux-6.11.5) and /security/device_cgroup.c (Version linux-2.4.37.11)


  1 // SPDX-License-Identifier: GPL-2.0                 1 
  2 /*                                                
  3  * device_cgroup.c - device cgroup subsystem      
  4  *                                                
  5  * Copyright 2007 IBM Corp                        
  6  */                                               
  7                                                   
  8 #include <linux/bpf-cgroup.h>                     
  9 #include <linux/device_cgroup.h>                  
 10 #include <linux/cgroup.h>                         
 11 #include <linux/ctype.h>                          
 12 #include <linux/list.h>                           
 13 #include <linux/uaccess.h>                        
 14 #include <linux/seq_file.h>                       
 15 #include <linux/slab.h>                           
 16 #include <linux/rcupdate.h>                       
 17 #include <linux/mutex.h>                          
 18                                                   
 19 #ifdef CONFIG_CGROUP_DEVICE                       
 20                                                   
 21 static DEFINE_MUTEX(devcgroup_mutex);             
 22                                                   
 23 enum devcg_behavior {                             
 24         DEVCG_DEFAULT_NONE,                       
 25         DEVCG_DEFAULT_ALLOW,                      
 26         DEVCG_DEFAULT_DENY,                       
 27 };                                                
 28                                                   
 29 /*                                                
 30  * exception list locking rules:                  
 31  * hold devcgroup_mutex for update/read.          
 32  * hold rcu_read_lock() for read.                 
 33  */                                               
 34                                                   
 35 struct dev_exception_item {                       
 36         u32 major, minor;                         
 37         short type;                               
 38         short access;                             
 39         struct list_head list;                    
 40         struct rcu_head rcu;                      
 41 };                                                
 42                                                   
 43 struct dev_cgroup {                               
 44         struct cgroup_subsys_state css;           
 45         struct list_head exceptions;              
 46         enum devcg_behavior behavior;             
 47 };                                                
 48                                                   
 49 static inline struct dev_cgroup *css_to_devcgr    
 50 {                                                 
 51         return s ? container_of(s, struct dev_    
 52 }                                                 
 53                                                   
 54 static inline struct dev_cgroup *task_devcgrou    
 55 {                                                 
 56         return css_to_devcgroup(task_css(task,    
 57 }                                                 
 58                                                   
 59 /*                                                
 60  * called under devcgroup_mutex                   
 61  */                                               
 62 static int dev_exceptions_copy(struct list_hea    
 63 {                                                 
 64         struct dev_exception_item *ex, *tmp, *    
 65                                                   
 66         lockdep_assert_held(&devcgroup_mutex);    
 67                                                   
 68         list_for_each_entry(ex, orig, list) {     
 69                 new = kmemdup(ex, sizeof(*ex),    
 70                 if (!new)                         
 71                         goto free_and_exit;       
 72                 list_add_tail(&new->list, dest    
 73         }                                         
 74                                                   
 75         return 0;                                 
 76                                                   
 77 free_and_exit:                                    
 78         list_for_each_entry_safe(ex, tmp, dest    
 79                 list_del(&ex->list);              
 80                 kfree(ex);                        
 81         }                                         
 82         return -ENOMEM;                           
 83 }                                                 
 84                                                   
 85 static void dev_exceptions_move(struct list_he    
 86 {                                                 
 87         struct dev_exception_item *ex, *tmp;      
 88                                                   
 89         lockdep_assert_held(&devcgroup_mutex);    
 90                                                   
 91         list_for_each_entry_safe(ex, tmp, orig    
 92                 list_move_tail(&ex->list, dest    
 93         }                                         
 94 }                                                 
 95                                                   
 96 /*                                                
 97  * called under devcgroup_mutex                   
 98  */                                               
 99 static int dev_exception_add(struct dev_cgroup    
100                              struct dev_except    
101 {                                                 
102         struct dev_exception_item *excopy, *wa    
103                                                   
104         lockdep_assert_held(&devcgroup_mutex);    
105                                                   
106         excopy = kmemdup(ex, sizeof(*ex), GFP_    
107         if (!excopy)                              
108                 return -ENOMEM;                   
109                                                   
110         list_for_each_entry(walk, &dev_cgroup-    
111                 if (walk->type != ex->type)       
112                         continue;                 
113                 if (walk->major != ex->major)     
114                         continue;                 
115                 if (walk->minor != ex->minor)     
116                         continue;                 
117                                                   
118                 walk->access |= ex->access;       
119                 kfree(excopy);                    
120                 excopy = NULL;                    
121         }                                         
122                                                   
123         if (excopy != NULL)                       
124                 list_add_tail_rcu(&excopy->lis    
125         return 0;                                 
126 }                                                 
127                                                   
128 /*                                                
129  * called under devcgroup_mutex                   
130  */                                               
131 static void dev_exception_rm(struct dev_cgroup    
132                              struct dev_except    
133 {                                                 
134         struct dev_exception_item *walk, *tmp;    
135                                                   
136         lockdep_assert_held(&devcgroup_mutex);    
137                                                   
138         list_for_each_entry_safe(walk, tmp, &d    
139                 if (walk->type != ex->type)       
140                         continue;                 
141                 if (walk->major != ex->major)     
142                         continue;                 
143                 if (walk->minor != ex->minor)     
144                         continue;                 
145                                                   
146                 walk->access &= ~ex->access;      
147                 if (!walk->access) {              
148                         list_del_rcu(&walk->li    
149                         kfree_rcu(walk, rcu);     
150                 }                                 
151         }                                         
152 }                                                 
153                                                   
154 static void __dev_exception_clean(struct dev_c    
155 {                                                 
156         struct dev_exception_item *ex, *tmp;      
157                                                   
158         list_for_each_entry_safe(ex, tmp, &dev    
159                 list_del_rcu(&ex->list);          
160                 kfree_rcu(ex, rcu);               
161         }                                         
162 }                                                 
163                                                   
164 /**                                               
165  * dev_exception_clean - frees all entries of     
166  * @dev_cgroup: dev_cgroup with the exception     
167  *                                                
168  * called under devcgroup_mutex                   
169  */                                               
170 static void dev_exception_clean(struct dev_cgr    
171 {                                                 
172         lockdep_assert_held(&devcgroup_mutex);    
173                                                   
174         __dev_exception_clean(dev_cgroup);        
175 }                                                 
176                                                   
177 static inline bool is_devcg_online(const struc    
178 {                                                 
179         return (devcg->behavior != DEVCG_DEFAU    
180 }                                                 
181                                                   
182 /**                                               
183  * devcgroup_online - initializes devcgroup's     
184  *                    parent's                    
185  * @css: css getting online                       
186  * returns 0 in case of success, error code ot    
187  */                                               
188 static int devcgroup_online(struct cgroup_subs    
189 {                                                 
190         struct dev_cgroup *dev_cgroup = css_to    
191         struct dev_cgroup *parent_dev_cgroup =    
192         int ret = 0;                              
193                                                   
194         mutex_lock(&devcgroup_mutex);             
195                                                   
196         if (parent_dev_cgroup == NULL)            
197                 dev_cgroup->behavior = DEVCG_D    
198         else {                                    
199                 ret = dev_exceptions_copy(&dev    
200                                           &par    
201                 if (!ret)                         
202                         dev_cgroup->behavior =    
203         }                                         
204         mutex_unlock(&devcgroup_mutex);           
205                                                   
206         return ret;                               
207 }                                                 
208                                                   
209 static void devcgroup_offline(struct cgroup_su    
210 {                                                 
211         struct dev_cgroup *dev_cgroup = css_to    
212                                                   
213         mutex_lock(&devcgroup_mutex);             
214         dev_cgroup->behavior = DEVCG_DEFAULT_N    
215         mutex_unlock(&devcgroup_mutex);           
216 }                                                 
217                                                   
218 /*                                                
219  * called from kernel/cgroup/cgroup.c with cgr    
220  */                                               
221 static struct cgroup_subsys_state *               
222 devcgroup_css_alloc(struct cgroup_subsys_state    
223 {                                                 
224         struct dev_cgroup *dev_cgroup;            
225                                                   
226         dev_cgroup = kzalloc(sizeof(*dev_cgrou    
227         if (!dev_cgroup)                          
228                 return ERR_PTR(-ENOMEM);          
229         INIT_LIST_HEAD(&dev_cgroup->exceptions    
230         dev_cgroup->behavior = DEVCG_DEFAULT_N    
231                                                   
232         return &dev_cgroup->css;                  
233 }                                                 
234                                                   
235 static void devcgroup_css_free(struct cgroup_s    
236 {                                                 
237         struct dev_cgroup *dev_cgroup = css_to    
238                                                   
239         __dev_exception_clean(dev_cgroup);        
240         kfree(dev_cgroup);                        
241 }                                                 
242                                                   
243 #define DEVCG_ALLOW 1                             
244 #define DEVCG_DENY 2                              
245 #define DEVCG_LIST 3                              
246                                                   
247 #define MAJMINLEN 13                              
248 #define ACCLEN 4                                  
249                                                   
250 static void set_access(char *acc, short access    
251 {                                                 
252         int idx = 0;                              
253         memset(acc, 0, ACCLEN);                   
254         if (access & DEVCG_ACC_READ)              
255                 acc[idx++] = 'r';                 
256         if (access & DEVCG_ACC_WRITE)             
257                 acc[idx++] = 'w';                 
258         if (access & DEVCG_ACC_MKNOD)             
259                 acc[idx++] = 'm';                 
260 }                                                 
261                                                   
262 static char type_to_char(short type)              
263 {                                                 
264         if (type == DEVCG_DEV_ALL)                
265                 return 'a';                       
266         if (type == DEVCG_DEV_CHAR)               
267                 return 'c';                       
268         if (type == DEVCG_DEV_BLOCK)              
269                 return 'b';                       
270         return 'X';                               
271 }                                                 
272                                                   
273 static void set_majmin(char *str, unsigned m)     
274 {                                                 
275         if (m == ~0)                              
276                 strcpy(str, "*");                 
277         else                                      
278                 sprintf(str, "%u", m);            
279 }                                                 
280                                                   
281 static int devcgroup_seq_show(struct seq_file     
282 {                                                 
283         struct dev_cgroup *devcgroup = css_to_    
284         struct dev_exception_item *ex;            
285         char maj[MAJMINLEN], min[MAJMINLEN], a    
286                                                   
287         rcu_read_lock();                          
288         /*                                        
289          * To preserve the compatibility:         
290          * - Only show the "all devices" when     
291          * - List the exceptions in case the d    
292          * This way, the file remains as a "wh    
293          */                                       
294         if (devcgroup->behavior == DEVCG_DEFAU    
295                 set_access(acc, DEVCG_ACC_MASK    
296                 set_majmin(maj, ~0);              
297                 set_majmin(min, ~0);              
298                 seq_printf(m, "%c %s:%s %s\n",    
299                            maj, min, acc);        
300         } else {                                  
301                 list_for_each_entry_rcu(ex, &d    
302                         set_access(acc, ex->ac    
303                         set_majmin(maj, ex->ma    
304                         set_majmin(min, ex->mi    
305                         seq_printf(m, "%c %s:%    
306                                    maj, min, a    
307                 }                                 
308         }                                         
309         rcu_read_unlock();                        
310                                                   
311         return 0;                                 
312 }                                                 
313                                                   
314 /**                                               
315  * match_exception      - iterates the excepti    
316  * @exceptions: list of exceptions                
317  * @type: device type (DEVCG_DEV_BLOCK or DEVC    
318  * @major: device file major number, ~0 to mat    
319  * @minor: device file minor number, ~0 to mat    
320  * @access: permission mask (DEVCG_ACC_READ, D    
321  *                                                
322  * It is considered a complete match if an exc    
323  * contain the entire range of provided parame    
324  *                                                
325  * Return: true in case it matches an exceptio    
326  */                                               
327 static bool match_exception(struct list_head *    
328                             u32 major, u32 min    
329 {                                                 
330         struct dev_exception_item *ex;            
331                                                   
332         list_for_each_entry_rcu(ex, exceptions    
333                 if ((type & DEVCG_DEV_BLOCK) &    
334                         continue;                 
335                 if ((type & DEVCG_DEV_CHAR) &&    
336                         continue;                 
337                 if (ex->major != ~0 && ex->maj    
338                         continue;                 
339                 if (ex->minor != ~0 && ex->min    
340                         continue;                 
341                 /* provided access cannot have    
342                 if (access & (~ex->access))       
343                         continue;                 
344                 return true;                      
345         }                                         
346         return false;                             
347 }                                                 
348                                                   
349 /**                                               
350  * match_exception_partial - iterates the exce    
351  * @exceptions: list of exceptions                
352  * @type: device type (DEVCG_DEV_BLOCK or DEVC    
353  * @major: device file major number, ~0 to mat    
354  * @minor: device file minor number, ~0 to mat    
355  * @access: permission mask (DEVCG_ACC_READ, D    
356  *                                                
357  * It is considered a partial match if an exce    
358  * contain *any* of the devices specified by p    
359  * used to make sure no extra access is being     
360  * any of the exception list.                     
361  *                                                
362  * Return: true in case the provided range mat    
363  */                                               
364 static bool match_exception_partial(struct lis    
365                                     u32 major,    
366 {                                                 
367         struct dev_exception_item *ex;            
368                                                   
369         list_for_each_entry_rcu(ex, exceptions    
370                                 lockdep_is_hel    
371                 if ((type & DEVCG_DEV_BLOCK) &    
372                         continue;                 
373                 if ((type & DEVCG_DEV_CHAR) &&    
374                         continue;                 
375                 /*                                
376                  * We must be sure that both t    
377                  * range aren't masking all de    
378                  */                               
379                 if (ex->major != ~0 && major !    
380                         continue;                 
381                 if (ex->minor != ~0 && minor !    
382                         continue;                 
383                 /*                                
384                  * In order to make sure the p    
385                  * an exception, all its acces    
386                  * exception's access bits        
387                  */                               
388                 if (!(access & ex->access))       
389                         continue;                 
390                 return true;                      
391         }                                         
392         return false;                             
393 }                                                 
394                                                   
395 /**                                               
396  * verify_new_ex - verifies if a new exception    
397  * @dev_cgroup: dev cgroup to be tested agains    
398  * @refex: new exception                          
399  * @behavior: behavior of the exception's dev_    
400  *                                                
401  * This is used to make sure a child cgroup wo    
402  * than its parent                                
403  */                                               
404 static bool verify_new_ex(struct dev_cgroup *d    
405                           struct dev_exception    
406                           enum devcg_behavior     
407 {                                                 
408         bool match = false;                       
409                                                   
410         RCU_LOCKDEP_WARN(!rcu_read_lock_held()    
411                          !lockdep_is_held(&dev    
412                          "device_cgroup:verify    
413                                                   
414         if (dev_cgroup->behavior == DEVCG_DEFA    
415                 if (behavior == DEVCG_DEFAULT_    
416                         /*                        
417                          * new exception in th    
418                          * adding extra restri    
419                          */                       
420                         return true;              
421                 } else {                          
422                         /*                        
423                          * new exception in th    
424                          * that can be accesse    
425                          * parent's exceptions    
426                          */                       
427                         match = match_exceptio    
428                                                   
429                                                   
430                                                   
431                                                   
432                                                   
433                         if (match)                
434                                 return false;     
435                         return true;              
436                 }                                 
437         } else {                                  
438                 /*                                
439                  * Only behavior == DEVCG_DEFA    
440                  * the new exception will add     
441                  * be contained completely in     
442                  * allowed                        
443                  */                               
444                 match = match_exception(&dev_c    
445                                         refex-    
446                                         refex-    
447                                                   
448                 if (match)                        
449                         /* parent has an excep    
450                         return true;              
451                 else                              
452                         return false;             
453         }                                         
454         return false;                             
455 }                                                 
456                                                   
457 /*                                                
458  * parent_has_perm:                               
459  * when adding a new allow rule to a device ex    
460  * must be allowed in the parent device           
461  */                                               
462 static int parent_has_perm(struct dev_cgroup *    
463                                   struct dev_e    
464 {                                                 
465         struct dev_cgroup *parent = css_to_dev    
466                                                   
467         if (!parent)                              
468                 return 1;                         
469         return verify_new_ex(parent, ex, child    
470 }                                                 
471                                                   
472 /**                                               
473  * parent_allows_removal - verify if it's ok t    
474  * @childcg: child cgroup from where the excep    
475  * @ex: exception being removed                   
476  *                                                
477  * When removing an exception in cgroups with     
478  * be checked if removing it will give the chi    
479  * parent.                                        
480  *                                                
481  * Return: true if it's ok to remove exception    
482  */                                               
483 static bool parent_allows_removal(struct dev_c    
484                                   struct dev_e    
485 {                                                 
486         struct dev_cgroup *parent = css_to_dev    
487                                                   
488         if (!parent)                              
489                 return true;                      
490                                                   
491         /* It's always allowed to remove acces    
492         if (childcg->behavior == DEVCG_DEFAULT    
493                 return true;                      
494                                                   
495         /*                                        
496          * Make sure you're not removing part     
497          * the parent cgroup                      
498          */                                       
499         return !match_exception_partial(&paren    
500                                         ex->ma    
501 }                                                 
502                                                   
503 /**                                               
504  * may_allow_all - checks if it's possible to     
505  *                 allow based on parent's rul    
506  * @parent: device cgroup's parent                
507  * returns: != 0 in case it's allowed, 0 other    
508  */                                               
509 static inline int may_allow_all(struct dev_cgr    
510 {                                                 
511         if (!parent)                              
512                 return 1;                         
513         return parent->behavior == DEVCG_DEFAU    
514 }                                                 
515                                                   
516 /**                                               
517  * revalidate_active_exceptions - walks throug    
518  *                                revalidates     
519  *                                behavior and    
520  *                                are no longe    
521  *                                Called with     
522  * @devcg: cgroup which exceptions will be che    
523  *                                                
524  * This is one of the three key functions for     
525  * This function is responsible for re-evaluat    
526  * exceptions due to a parent's exception chan    
527  * Refer to Documentation/admin-guide/cgroup-v    
528  */                                               
529 static void revalidate_active_exceptions(struc    
530 {                                                 
531         struct dev_exception_item *ex;            
532         struct list_head *this, *tmp;             
533                                                   
534         list_for_each_safe(this, tmp, &devcg->    
535                 ex = container_of(this, struct    
536                 if (!parent_has_perm(devcg, ex    
537                         dev_exception_rm(devcg    
538         }                                         
539 }                                                 
540                                                   
541 /**                                               
542  * propagate_exception - propagates a new exce    
543  * @devcg_root: device cgroup that added a new    
544  * @ex: new exception to be propagated            
545  *                                                
546  * returns: 0 in case of success, != 0 in case    
547  */                                               
548 static int propagate_exception(struct dev_cgro    
549                                struct dev_exce    
550 {                                                 
551         struct cgroup_subsys_state *pos;          
552         int rc = 0;                               
553                                                   
554         rcu_read_lock();                          
555                                                   
556         css_for_each_descendant_pre(pos, &devc    
557                 struct dev_cgroup *devcg = css    
558                                                   
559                 /*                                
560                  * Because devcgroup_mutex is     
561                  * online or offline during th    
562                  * methods), and online ones a    
563                  * read lock without bumping r    
564                  */                               
565                 if (pos == &devcg_root->css ||    
566                         continue;                 
567                                                   
568                 rcu_read_unlock();                
569                                                   
570                 /*                                
571                  * in case both root's behavio    
572                  * restriction means adding to    
573                  */                               
574                 if (devcg_root->behavior == DE    
575                     devcg->behavior == DEVCG_D    
576                         rc = dev_exception_add    
577                         if (rc)                   
578                                 return rc;        
579                 } else {                          
580                         /*                        
581                          * in the other possib    
582                          * root's behavior: al    
583                          * root's behavior: de    
584                          * the exception will     
585                          */                       
586                         dev_exception_rm(devcg    
587                 }                                 
588                 revalidate_active_exceptions(d    
589                                                   
590                 rcu_read_lock();                  
591         }                                         
592                                                   
593         rcu_read_unlock();                        
594         return rc;                                
595 }                                                 
596                                                   
597 /*                                                
598  * Modify the exception list using allow/deny     
599  * CAP_SYS_ADMIN is needed for this.  It's at     
600  * so we can give a container CAP_MKNOD to let    
601  * modify the exception list.                     
602  * It seems likely we'll want to add a CAP_CON    
603  * us to also grant CAP_SYS_ADMIN to container    
604  * device exception list controls, but for now    
605  *                                                
606  * Taking rules away is always allowed (given     
607  * new access is only allowed if you're in the    
608  * parent cgroup has the access you're asking     
609  */                                               
610 static int devcgroup_update_access(struct dev_    
611                                    int filetyp    
612 {                                                 
613         const char *b;                            
614         char temp[12];          /* 11 + 1 char    
615         int count, rc = 0;                        
616         struct dev_exception_item ex;             
617         struct dev_cgroup *parent = css_to_dev    
618         struct dev_cgroup tmp_devcgrp;            
619                                                   
620         if (!capable(CAP_SYS_ADMIN))              
621                 return -EPERM;                    
622                                                   
623         memset(&ex, 0, sizeof(ex));               
624         memset(&tmp_devcgrp, 0, sizeof(tmp_dev    
625         b = buffer;                               
626                                                   
627         switch (*b) {                             
628         case 'a':                                 
629                 switch (filetype) {               
630                 case DEVCG_ALLOW:                 
631                         if (css_has_online_chi    
632                                 return -EINVAL    
633                                                   
634                         if (!may_allow_all(par    
635                                 return -EPERM;    
636                         if (!parent) {            
637                                 devcgroup->beh    
638                                 dev_exception_    
639                                 break;            
640                         }                         
641                                                   
642                         INIT_LIST_HEAD(&tmp_de    
643                         rc = dev_exceptions_co    
644                                                   
645                         if (rc)                   
646                                 return rc;        
647                         dev_exception_clean(de    
648                         rc = dev_exceptions_co    
649                                                   
650                         if (rc) {                 
651                                 dev_exceptions    
652                                                   
653                                 return rc;        
654                         }                         
655                         devcgroup->behavior =     
656                         dev_exception_clean(&t    
657                         break;                    
658                 case DEVCG_DENY:                  
659                         if (css_has_online_chi    
660                                 return -EINVAL    
661                                                   
662                         dev_exception_clean(de    
663                         devcgroup->behavior =     
664                         break;                    
665                 default:                          
666                         return -EINVAL;           
667                 }                                 
668                 return 0;                         
669         case 'b':                                 
670                 ex.type = DEVCG_DEV_BLOCK;        
671                 break;                            
672         case 'c':                                 
673                 ex.type = DEVCG_DEV_CHAR;         
674                 break;                            
675         default:                                  
676                 return -EINVAL;                   
677         }                                         
678         b++;                                      
679         if (!isspace(*b))                         
680                 return -EINVAL;                   
681         b++;                                      
682         if (*b == '*') {                          
683                 ex.major = ~0;                    
684                 b++;                              
685         } else if (isdigit(*b)) {                 
686                 memset(temp, 0, sizeof(temp));    
687                 for (count = 0; count < sizeof    
688                         temp[count] = *b;         
689                         b++;                      
690                         if (!isdigit(*b))         
691                                 break;            
692                 }                                 
693                 rc = kstrtou32(temp, 10, &ex.m    
694                 if (rc)                           
695                         return -EINVAL;           
696         } else {                                  
697                 return -EINVAL;                   
698         }                                         
699         if (*b != ':')                            
700                 return -EINVAL;                   
701         b++;                                      
702                                                   
703         /* read minor */                          
704         if (*b == '*') {                          
705                 ex.minor = ~0;                    
706                 b++;                              
707         } else if (isdigit(*b)) {                 
708                 memset(temp, 0, sizeof(temp));    
709                 for (count = 0; count < sizeof    
710                         temp[count] = *b;         
711                         b++;                      
712                         if (!isdigit(*b))         
713                                 break;            
714                 }                                 
715                 rc = kstrtou32(temp, 10, &ex.m    
716                 if (rc)                           
717                         return -EINVAL;           
718         } else {                                  
719                 return -EINVAL;                   
720         }                                         
721         if (!isspace(*b))                         
722                 return -EINVAL;                   
723         for (b++, count = 0; count < 3; count+    
724                 switch (*b) {                     
725                 case 'r':                         
726                         ex.access |= DEVCG_ACC    
727                         break;                    
728                 case 'w':                         
729                         ex.access |= DEVCG_ACC    
730                         break;                    
731                 case 'm':                         
732                         ex.access |= DEVCG_ACC    
733                         break;                    
734                 case '\n':                        
735                 case '\0':                        
736                         count = 3;                
737                         break;                    
738                 default:                          
739                         return -EINVAL;           
740                 }                                 
741         }                                         
742                                                   
743         switch (filetype) {                       
744         case DEVCG_ALLOW:                         
745                 /*                                
746                  * If the default policy is to    
747                  * an matching exception inste    
748                  * don't want to break compati    
749                  */                               
750                 if (devcgroup->behavior == DEV    
751                         /* Check if the parent    
752                         if (!parent_allows_rem    
753                                 return -EPERM;    
754                         dev_exception_rm(devcg    
755                         break;                    
756                 }                                 
757                                                   
758                 if (!parent_has_perm(devcgroup    
759                         return -EPERM;            
760                 rc = dev_exception_add(devcgro    
761                 break;                            
762         case DEVCG_DENY:                          
763                 /*                                
764                  * If the default policy is to    
765                  * an matching exception inste    
766                  * don't want to break compati    
767                  */                               
768                 if (devcgroup->behavior == DEV    
769                         dev_exception_rm(devcg    
770                 else                              
771                         rc = dev_exception_add    
772                                                   
773                 if (rc)                           
774                         break;                    
775                 /* we only propagate new restr    
776                 rc = propagate_exception(devcg    
777                 break;                            
778         default:                                  
779                 rc = -EINVAL;                     
780         }                                         
781         return rc;                                
782 }                                                 
783                                                   
784 static ssize_t devcgroup_access_write(struct k    
785                                       char *bu    
786 {                                                 
787         int retval;                               
788                                                   
789         mutex_lock(&devcgroup_mutex);             
790         retval = devcgroup_update_access(css_t    
791                                          of_cf    
792         mutex_unlock(&devcgroup_mutex);           
793         return retval ?: nbytes;                  
794 }                                                 
795                                                   
796 static struct cftype dev_cgroup_files[] = {       
797         {                                         
798                 .name = "allow",                  
799                 .write = devcgroup_access_writ    
800                 .private = DEVCG_ALLOW,           
801         },                                        
802         {                                         
803                 .name = "deny",                   
804                 .write = devcgroup_access_writ    
805                 .private = DEVCG_DENY,            
806         },                                        
807         {                                         
808                 .name = "list",                   
809                 .seq_show = devcgroup_seq_show    
810                 .private = DEVCG_LIST,            
811         },                                        
812         { }     /* terminate */                   
813 };                                                
814                                                   
815 struct cgroup_subsys devices_cgrp_subsys = {      
816         .css_alloc = devcgroup_css_alloc,         
817         .css_free = devcgroup_css_free,           
818         .css_online = devcgroup_online,           
819         .css_offline = devcgroup_offline,         
820         .legacy_cftypes = dev_cgroup_files,       
821 };                                                
822                                                   
823 /**                                               
824  * devcgroup_legacy_check_permission - checks     
825  * @type: device type                             
826  * @major: device major number                    
827  * @minor: device minor number                    
828  * @access: combination of DEVCG_ACC_WRITE, DE    
829  *                                                
830  * returns 0 on success, -EPERM case the opera    
831  */                                               
832 static int devcgroup_legacy_check_permission(s    
833                                         short     
834 {                                                 
835         struct dev_cgroup *dev_cgroup;            
836         bool rc;                                  
837                                                   
838         rcu_read_lock();                          
839         dev_cgroup = task_devcgroup(current);     
840         if (dev_cgroup->behavior == DEVCG_DEFA    
841                 /* Can't match any of the exce    
842                 rc = !match_exception_partial(    
843                                                   
844         else                                      
845                 /* Need to match completely on    
846                 rc = match_exception(&dev_cgro    
847                                      minor, ac    
848         rcu_read_unlock();                        
849                                                   
850         if (!rc)                                  
851                 return -EPERM;                    
852                                                   
853         return 0;                                 
854 }                                                 
855                                                   
856 #endif /* CONFIG_CGROUP_DEVICE */                 
857                                                   
858 #if defined(CONFIG_CGROUP_DEVICE) || defined(C    
859                                                   
860 int devcgroup_check_permission(short type, u32    
861 {                                                 
862         int rc = BPF_CGROUP_RUN_PROG_DEVICE_CG    
863                                                   
864         if (rc)                                   
865                 return rc;                        
866                                                   
867         #ifdef CONFIG_CGROUP_DEVICE               
868         return devcgroup_legacy_check_permissi    
869                                                   
870         #else /* CONFIG_CGROUP_DEVICE */          
871         return 0;                                 
872                                                   
873         #endif /* CONFIG_CGROUP_DEVICE */         
874 }                                                 
875 EXPORT_SYMBOL(devcgroup_check_permission);        
876 #endif /* defined(CONFIG_CGROUP_DEVICE) || def    
877                                                   

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