Commit 97fb35e413f256ded07b88c73b3d932ec31ea84e
Committed by
James Morris
1 parent
5b636857fe
Exists in
master
and in
38 other branches
TOMOYO: Enable conditional ACL.
Enable conditional ACL by passing object's pointers. Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Signed-off-by: James Morris <jmorris@namei.org>
Showing 5 changed files with 80 additions and 33 deletions Side-by-side Diff
security/tomoyo/common.h
... | ... | @@ -836,7 +836,8 @@ |
836 | 836 | struct path *path2); |
837 | 837 | int tomoyo_path_number_perm(const u8 operation, struct path *path, |
838 | 838 | unsigned long number); |
839 | -int tomoyo_path_perm(const u8 operation, struct path *path); | |
839 | +int tomoyo_path_perm(const u8 operation, struct path *path, | |
840 | + const char *target); | |
840 | 841 | int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation, |
841 | 842 | const struct tomoyo_path_info *filename); |
842 | 843 | int tomoyo_poll_control(struct file *file, poll_table *wait); |
security/tomoyo/domain.c
... | ... | @@ -575,23 +575,27 @@ |
575 | 575 | */ |
576 | 576 | int tomoyo_find_next_domain(struct linux_binprm *bprm) |
577 | 577 | { |
578 | - struct tomoyo_request_info r; | |
579 | - char *tmp = kzalloc(TOMOYO_EXEC_TMPSIZE, GFP_NOFS); | |
580 | 578 | struct tomoyo_domain_info *old_domain = tomoyo_domain(); |
581 | 579 | struct tomoyo_domain_info *domain = NULL; |
582 | 580 | const char *original_name = bprm->filename; |
583 | - u8 mode; | |
584 | - bool is_enforce; | |
585 | 581 | int retval = -ENOMEM; |
586 | 582 | bool need_kfree = false; |
587 | 583 | bool reject_on_transition_failure = false; |
588 | 584 | struct tomoyo_path_info rn = { }; /* real name */ |
589 | - | |
590 | - mode = tomoyo_init_request_info(&r, NULL, TOMOYO_MAC_FILE_EXECUTE); | |
591 | - is_enforce = (mode == TOMOYO_CONFIG_ENFORCING); | |
592 | - if (!tmp) | |
593 | - goto out; | |
594 | - | |
585 | + struct tomoyo_execve *ee = kzalloc(sizeof(*ee), GFP_NOFS); | |
586 | + if (!ee) | |
587 | + return -ENOMEM; | |
588 | + ee->tmp = kzalloc(TOMOYO_EXEC_TMPSIZE, GFP_NOFS); | |
589 | + if (!ee->tmp) { | |
590 | + kfree(ee); | |
591 | + return -ENOMEM; | |
592 | + } | |
593 | + /* ee->dump->data is allocated by tomoyo_dump_page(). */ | |
594 | + tomoyo_init_request_info(&ee->r, NULL, TOMOYO_MAC_FILE_EXECUTE); | |
595 | + ee->r.ee = ee; | |
596 | + ee->bprm = bprm; | |
597 | + ee->r.obj = &ee->obj; | |
598 | + ee->obj.path1 = bprm->file->f_path; | |
595 | 599 | retry: |
596 | 600 | if (need_kfree) { |
597 | 601 | kfree(rn.name); |
... | ... | @@ -625,7 +629,7 @@ |
625 | 629 | } |
626 | 630 | |
627 | 631 | /* Check execute permission. */ |
628 | - retval = tomoyo_path_permission(&r, TOMOYO_TYPE_EXECUTE, &rn); | |
632 | + retval = tomoyo_path_permission(&ee->r, TOMOYO_TYPE_EXECUTE, &rn); | |
629 | 633 | if (retval == TOMOYO_RETRY_REQUEST) |
630 | 634 | goto retry; |
631 | 635 | if (retval < 0) |
632 | 636 | |
... | ... | @@ -636,12 +640,12 @@ |
636 | 640 | * wildcard) rather than the pathname passed to execve() |
637 | 641 | * (which never contains wildcard). |
638 | 642 | */ |
639 | - if (r.param.path.matched_path) { | |
643 | + if (ee->r.param.path.matched_path) { | |
640 | 644 | if (need_kfree) |
641 | 645 | kfree(rn.name); |
642 | 646 | need_kfree = false; |
643 | 647 | /* This is OK because it is read only. */ |
644 | - rn = *r.param.path.matched_path; | |
648 | + rn = *ee->r.param.path.matched_path; | |
645 | 649 | } |
646 | 650 | |
647 | 651 | /* Calculate domain to transit to. */ |
... | ... | @@ -649,7 +653,7 @@ |
649 | 653 | &rn)) { |
650 | 654 | case TOMOYO_TRANSITION_CONTROL_RESET: |
651 | 655 | /* Transit to the root of specified namespace. */ |
652 | - snprintf(tmp, TOMOYO_EXEC_TMPSIZE - 1, "<%s>", rn.name); | |
656 | + snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "<%s>", rn.name); | |
653 | 657 | /* |
654 | 658 | * Make do_execve() fail if domain transition across namespaces |
655 | 659 | * has failed. |
... | ... | @@ -658,7 +662,7 @@ |
658 | 662 | break; |
659 | 663 | case TOMOYO_TRANSITION_CONTROL_INITIALIZE: |
660 | 664 | /* Transit to the child of current namespace's root. */ |
661 | - snprintf(tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s", | |
665 | + snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s", | |
662 | 666 | old_domain->ns->name, rn.name); |
663 | 667 | break; |
664 | 668 | case TOMOYO_TRANSITION_CONTROL_KEEP: |
665 | 669 | |
666 | 670 | |
667 | 671 | |
668 | 672 | |
669 | 673 | |
... | ... | @@ -677,29 +681,30 @@ |
677 | 681 | domain = old_domain; |
678 | 682 | } else { |
679 | 683 | /* Normal domain transition. */ |
680 | - snprintf(tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s", | |
684 | + snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s", | |
681 | 685 | old_domain->domainname->name, rn.name); |
682 | 686 | } |
683 | 687 | break; |
684 | 688 | } |
685 | 689 | if (!domain) |
686 | - domain = tomoyo_assign_domain(tmp, true); | |
690 | + domain = tomoyo_assign_domain(ee->tmp, true); | |
687 | 691 | if (domain) |
688 | 692 | retval = 0; |
689 | 693 | else if (reject_on_transition_failure) { |
690 | - printk(KERN_WARNING "ERROR: Domain '%s' not ready.\n", tmp); | |
694 | + printk(KERN_WARNING "ERROR: Domain '%s' not ready.\n", | |
695 | + ee->tmp); | |
691 | 696 | retval = -ENOMEM; |
692 | - } else if (r.mode == TOMOYO_CONFIG_ENFORCING) | |
697 | + } else if (ee->r.mode == TOMOYO_CONFIG_ENFORCING) | |
693 | 698 | retval = -ENOMEM; |
694 | 699 | else { |
695 | 700 | retval = 0; |
696 | 701 | if (!old_domain->flags[TOMOYO_DIF_TRANSITION_FAILED]) { |
697 | 702 | old_domain->flags[TOMOYO_DIF_TRANSITION_FAILED] = true; |
698 | - r.granted = false; | |
699 | - tomoyo_write_log(&r, "%s", tomoyo_dif | |
703 | + ee->r.granted = false; | |
704 | + tomoyo_write_log(&ee->r, "%s", tomoyo_dif | |
700 | 705 | [TOMOYO_DIF_TRANSITION_FAILED]); |
701 | 706 | printk(KERN_WARNING |
702 | - "ERROR: Domain '%s' not defined.\n", tmp); | |
707 | + "ERROR: Domain '%s' not defined.\n", ee->tmp); | |
703 | 708 | } |
704 | 709 | } |
705 | 710 | out: |
... | ... | @@ -710,7 +715,9 @@ |
710 | 715 | bprm->cred->security = domain; |
711 | 716 | if (need_kfree) |
712 | 717 | kfree(rn.name); |
713 | - kfree(tmp); | |
718 | + kfree(ee->tmp); | |
719 | + kfree(ee->dump.data); | |
720 | + kfree(ee); | |
714 | 721 | return retval; |
715 | 722 | } |
716 | 723 |
security/tomoyo/file.c
... | ... | @@ -667,6 +667,9 @@ |
667 | 667 | unsigned long number) |
668 | 668 | { |
669 | 669 | struct tomoyo_request_info r; |
670 | + struct tomoyo_obj_info obj = { | |
671 | + .path1 = *path, | |
672 | + }; | |
670 | 673 | int error = -ENOMEM; |
671 | 674 | struct tomoyo_path_info buf; |
672 | 675 | int idx; |
... | ... | @@ -677,6 +680,7 @@ |
677 | 680 | idx = tomoyo_read_lock(); |
678 | 681 | if (!tomoyo_get_realpath(&buf, path)) |
679 | 682 | goto out; |
683 | + r.obj = &obj; | |
680 | 684 | if (type == TOMOYO_TYPE_MKDIR) |
681 | 685 | tomoyo_add_slash(&buf); |
682 | 686 | r.param_type = TOMOYO_TYPE_PATH_NUMBER_ACL; |
... | ... | @@ -711,6 +715,9 @@ |
711 | 715 | int error = 0; |
712 | 716 | struct tomoyo_path_info buf; |
713 | 717 | struct tomoyo_request_info r; |
718 | + struct tomoyo_obj_info obj = { | |
719 | + .path1 = *path, | |
720 | + }; | |
714 | 721 | int idx; |
715 | 722 | |
716 | 723 | buf.name = NULL; |
... | ... | @@ -723,6 +730,7 @@ |
723 | 730 | error = -ENOMEM; |
724 | 731 | goto out; |
725 | 732 | } |
733 | + r.obj = &obj; | |
726 | 734 | if (acc_mode & MAY_READ) |
727 | 735 | error = tomoyo_path_permission(&r, TOMOYO_TYPE_READ, |
728 | 736 | &buf); |
729 | 737 | |
730 | 738 | |
731 | 739 | |
... | ... | @@ -745,15 +753,21 @@ |
745 | 753 | * |
746 | 754 | * @operation: Type of operation. |
747 | 755 | * @path: Pointer to "struct path". |
756 | + * @target: Symlink's target if @operation is TOMOYO_TYPE_SYMLINK, | |
757 | + * NULL otherwise. | |
748 | 758 | * |
749 | 759 | * Returns 0 on success, negative value otherwise. |
750 | 760 | */ |
751 | -int tomoyo_path_perm(const u8 operation, struct path *path) | |
761 | +int tomoyo_path_perm(const u8 operation, struct path *path, const char *target) | |
752 | 762 | { |
753 | 763 | struct tomoyo_request_info r; |
764 | + struct tomoyo_obj_info obj = { | |
765 | + .path1 = *path, | |
766 | + }; | |
754 | 767 | int error; |
755 | 768 | struct tomoyo_path_info buf; |
756 | 769 | bool is_enforce; |
770 | + struct tomoyo_path_info symlink_target; | |
757 | 771 | int idx; |
758 | 772 | |
759 | 773 | if (tomoyo_init_request_info(&r, NULL, tomoyo_p2mac[operation]) |
760 | 774 | |
761 | 775 | |
... | ... | @@ -765,13 +779,23 @@ |
765 | 779 | idx = tomoyo_read_lock(); |
766 | 780 | if (!tomoyo_get_realpath(&buf, path)) |
767 | 781 | goto out; |
782 | + r.obj = &obj; | |
768 | 783 | switch (operation) { |
769 | 784 | case TOMOYO_TYPE_RMDIR: |
770 | 785 | case TOMOYO_TYPE_CHROOT: |
771 | 786 | tomoyo_add_slash(&buf); |
772 | 787 | break; |
788 | + case TOMOYO_TYPE_SYMLINK: | |
789 | + symlink_target.name = tomoyo_encode(target); | |
790 | + if (!symlink_target.name) | |
791 | + goto out; | |
792 | + tomoyo_fill_path_info(&symlink_target); | |
793 | + obj.symlink_target = &symlink_target; | |
794 | + break; | |
773 | 795 | } |
774 | 796 | error = tomoyo_path_permission(&r, operation, &buf); |
797 | + if (operation == TOMOYO_TYPE_SYMLINK) | |
798 | + kfree(symlink_target.name); | |
775 | 799 | out: |
776 | 800 | kfree(buf.name); |
777 | 801 | tomoyo_read_unlock(idx); |
... | ... | @@ -794,6 +818,9 @@ |
794 | 818 | const unsigned int mode, unsigned int dev) |
795 | 819 | { |
796 | 820 | struct tomoyo_request_info r; |
821 | + struct tomoyo_obj_info obj = { | |
822 | + .path1 = *path, | |
823 | + }; | |
797 | 824 | int error = -ENOMEM; |
798 | 825 | struct tomoyo_path_info buf; |
799 | 826 | int idx; |
... | ... | @@ -804,6 +831,7 @@ |
804 | 831 | idx = tomoyo_read_lock(); |
805 | 832 | error = -ENOMEM; |
806 | 833 | if (tomoyo_get_realpath(&buf, path)) { |
834 | + r.obj = &obj; | |
807 | 835 | dev = new_decode_dev(dev); |
808 | 836 | r.param_type = TOMOYO_TYPE_MKDEV_ACL; |
809 | 837 | r.param.mkdev.filename = &buf; |
... | ... | @@ -837,6 +865,10 @@ |
837 | 865 | struct tomoyo_path_info buf1; |
838 | 866 | struct tomoyo_path_info buf2; |
839 | 867 | struct tomoyo_request_info r; |
868 | + struct tomoyo_obj_info obj = { | |
869 | + .path1 = *path1, | |
870 | + .path2 = *path2, | |
871 | + }; | |
840 | 872 | int idx; |
841 | 873 | |
842 | 874 | if (tomoyo_init_request_info(&r, NULL, tomoyo_pp2mac[operation]) |
... | ... | @@ -861,6 +893,7 @@ |
861 | 893 | tomoyo_add_slash(&buf2); |
862 | 894 | break; |
863 | 895 | } |
896 | + r.obj = &obj; | |
864 | 897 | r.param_type = TOMOYO_TYPE_PATH2_ACL; |
865 | 898 | r.param.path2.operation = operation; |
866 | 899 | r.param.path2.filename1 = &buf1; |
security/tomoyo/mount.c
... | ... | @@ -75,6 +75,7 @@ |
75 | 75 | struct path *dir, const char *type, |
76 | 76 | unsigned long flags) |
77 | 77 | { |
78 | + struct tomoyo_obj_info obj = { }; | |
78 | 79 | struct path path; |
79 | 80 | struct file_system_type *fstype = NULL; |
80 | 81 | const char *requested_type = NULL; |
... | ... | @@ -85,6 +86,7 @@ |
85 | 86 | struct tomoyo_path_info rdir; |
86 | 87 | int need_dev = 0; |
87 | 88 | int error = -ENOMEM; |
89 | + r->obj = &obj; | |
88 | 90 | |
89 | 91 | /* Get fstype. */ |
90 | 92 | requested_type = tomoyo_encode(type); |
... | ... | @@ -94,6 +96,7 @@ |
94 | 96 | tomoyo_fill_path_info(&rtype); |
95 | 97 | |
96 | 98 | /* Get mount point. */ |
99 | + obj.path2 = *dir; | |
97 | 100 | requested_dir_name = tomoyo_realpath_from_path(dir); |
98 | 101 | if (!requested_dir_name) { |
99 | 102 | error = -ENOMEM; |
100 | 103 | |
... | ... | @@ -129,8 +132,8 @@ |
129 | 132 | error = -ENOENT; |
130 | 133 | goto out; |
131 | 134 | } |
135 | + obj.path1 = path; | |
132 | 136 | requested_dev_name = tomoyo_realpath_from_path(&path); |
133 | - path_put(&path); | |
134 | 137 | if (!requested_dev_name) { |
135 | 138 | error = -ENOENT; |
136 | 139 | goto out; |
... | ... | @@ -163,6 +166,9 @@ |
163 | 166 | if (fstype) |
164 | 167 | put_filesystem(fstype); |
165 | 168 | kfree(requested_type); |
169 | + /* Drop refcount obtained by kern_path(). */ | |
170 | + if (obj.path1.dentry) | |
171 | + path_put(&obj.path1); | |
166 | 172 | return error; |
167 | 173 | } |
168 | 174 |
security/tomoyo/tomoyo.c
... | ... | @@ -98,18 +98,18 @@ |
98 | 98 | static int tomoyo_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) |
99 | 99 | { |
100 | 100 | struct path path = { mnt, dentry }; |
101 | - return tomoyo_path_perm(TOMOYO_TYPE_GETATTR, &path); | |
101 | + return tomoyo_path_perm(TOMOYO_TYPE_GETATTR, &path, NULL); | |
102 | 102 | } |
103 | 103 | |
104 | 104 | static int tomoyo_path_truncate(struct path *path) |
105 | 105 | { |
106 | - return tomoyo_path_perm(TOMOYO_TYPE_TRUNCATE, path); | |
106 | + return tomoyo_path_perm(TOMOYO_TYPE_TRUNCATE, path, NULL); | |
107 | 107 | } |
108 | 108 | |
109 | 109 | static int tomoyo_path_unlink(struct path *parent, struct dentry *dentry) |
110 | 110 | { |
111 | 111 | struct path path = { parent->mnt, dentry }; |
112 | - return tomoyo_path_perm(TOMOYO_TYPE_UNLINK, &path); | |
112 | + return tomoyo_path_perm(TOMOYO_TYPE_UNLINK, &path, NULL); | |
113 | 113 | } |
114 | 114 | |
115 | 115 | static int tomoyo_path_mkdir(struct path *parent, struct dentry *dentry, |
116 | 116 | |
... | ... | @@ -123,14 +123,14 @@ |
123 | 123 | static int tomoyo_path_rmdir(struct path *parent, struct dentry *dentry) |
124 | 124 | { |
125 | 125 | struct path path = { parent->mnt, dentry }; |
126 | - return tomoyo_path_perm(TOMOYO_TYPE_RMDIR, &path); | |
126 | + return tomoyo_path_perm(TOMOYO_TYPE_RMDIR, &path, NULL); | |
127 | 127 | } |
128 | 128 | |
129 | 129 | static int tomoyo_path_symlink(struct path *parent, struct dentry *dentry, |
130 | 130 | const char *old_name) |
131 | 131 | { |
132 | 132 | struct path path = { parent->mnt, dentry }; |
133 | - return tomoyo_path_perm(TOMOYO_TYPE_SYMLINK, &path); | |
133 | + return tomoyo_path_perm(TOMOYO_TYPE_SYMLINK, &path, old_name); | |
134 | 134 | } |
135 | 135 | |
136 | 136 | static int tomoyo_path_mknod(struct path *parent, struct dentry *dentry, |
... | ... | @@ -225,7 +225,7 @@ |
225 | 225 | |
226 | 226 | static int tomoyo_path_chroot(struct path *path) |
227 | 227 | { |
228 | - return tomoyo_path_perm(TOMOYO_TYPE_CHROOT, path); | |
228 | + return tomoyo_path_perm(TOMOYO_TYPE_CHROOT, path, NULL); | |
229 | 229 | } |
230 | 230 | |
231 | 231 | static int tomoyo_sb_mount(char *dev_name, struct path *path, |
... | ... | @@ -237,7 +237,7 @@ |
237 | 237 | static int tomoyo_sb_umount(struct vfsmount *mnt, int flags) |
238 | 238 | { |
239 | 239 | struct path path = { mnt, mnt->mnt_root }; |
240 | - return tomoyo_path_perm(TOMOYO_TYPE_UMOUNT, &path); | |
240 | + return tomoyo_path_perm(TOMOYO_TYPE_UMOUNT, &path, NULL); | |
241 | 241 | } |
242 | 242 | |
243 | 243 | static int tomoyo_sb_pivotroot(struct path *old_path, struct path *new_path) |