.. | .. |
---|
81 | 81 | return -ENOMEM; |
---|
82 | 82 | } |
---|
83 | 83 | |
---|
| 84 | +static void dev_exceptions_move(struct list_head *dest, struct list_head *orig) |
---|
| 85 | +{ |
---|
| 86 | + struct dev_exception_item *ex, *tmp; |
---|
| 87 | + |
---|
| 88 | + lockdep_assert_held(&devcgroup_mutex); |
---|
| 89 | + |
---|
| 90 | + list_for_each_entry_safe(ex, tmp, orig, list) { |
---|
| 91 | + list_move_tail(&ex->list, dest); |
---|
| 92 | + } |
---|
| 93 | +} |
---|
| 94 | + |
---|
84 | 95 | /* |
---|
85 | 96 | * called under devcgroup_mutex |
---|
86 | 97 | */ |
---|
.. | .. |
---|
603 | 614 | int count, rc = 0; |
---|
604 | 615 | struct dev_exception_item ex; |
---|
605 | 616 | struct dev_cgroup *parent = css_to_devcgroup(devcgroup->css.parent); |
---|
| 617 | + struct dev_cgroup tmp_devcgrp; |
---|
606 | 618 | |
---|
607 | 619 | if (!capable(CAP_SYS_ADMIN)) |
---|
608 | 620 | return -EPERM; |
---|
609 | 621 | |
---|
610 | 622 | memset(&ex, 0, sizeof(ex)); |
---|
| 623 | + memset(&tmp_devcgrp, 0, sizeof(tmp_devcgrp)); |
---|
611 | 624 | b = buffer; |
---|
612 | 625 | |
---|
613 | 626 | switch (*b) { |
---|
.. | .. |
---|
619 | 632 | |
---|
620 | 633 | if (!may_allow_all(parent)) |
---|
621 | 634 | return -EPERM; |
---|
622 | | - dev_exception_clean(devcgroup); |
---|
623 | | - devcgroup->behavior = DEVCG_DEFAULT_ALLOW; |
---|
624 | | - if (!parent) |
---|
| 635 | + if (!parent) { |
---|
| 636 | + devcgroup->behavior = DEVCG_DEFAULT_ALLOW; |
---|
| 637 | + dev_exception_clean(devcgroup); |
---|
625 | 638 | break; |
---|
| 639 | + } |
---|
626 | 640 | |
---|
627 | | - rc = dev_exceptions_copy(&devcgroup->exceptions, |
---|
628 | | - &parent->exceptions); |
---|
| 641 | + INIT_LIST_HEAD(&tmp_devcgrp.exceptions); |
---|
| 642 | + rc = dev_exceptions_copy(&tmp_devcgrp.exceptions, |
---|
| 643 | + &devcgroup->exceptions); |
---|
629 | 644 | if (rc) |
---|
630 | 645 | return rc; |
---|
| 646 | + dev_exception_clean(devcgroup); |
---|
| 647 | + rc = dev_exceptions_copy(&devcgroup->exceptions, |
---|
| 648 | + &parent->exceptions); |
---|
| 649 | + if (rc) { |
---|
| 650 | + dev_exceptions_move(&devcgroup->exceptions, |
---|
| 651 | + &tmp_devcgrp.exceptions); |
---|
| 652 | + return rc; |
---|
| 653 | + } |
---|
| 654 | + devcgroup->behavior = DEVCG_DEFAULT_ALLOW; |
---|
| 655 | + dev_exception_clean(&tmp_devcgrp); |
---|
631 | 656 | break; |
---|
632 | 657 | case DEVCG_DENY: |
---|
633 | 658 | if (css_has_online_children(&devcgroup->css)) |
---|