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