Commit 97fb35e413f256ded07b88c73b3d932ec31ea84e

Authored by Tetsuo Handa
Committed by James Morris
1 parent 5b636857fe

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)