Deleted Added
full compact
subr_acl_posix1e.c (160145) subr_acl_posix1e.c (160146)
1/*-
1/*-
2 * Copyright (c) 1999-2003 Robert N. M. Watson
2 * Copyright (c) 1999-2006 Robert N. M. Watson
3 * All rights reserved.
4 *
5 * This software was developed by Robert Watson for the TrustedBSD Project.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright

--- 11 unchanged lines hidden (view full) ---

22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28/*
29 * Developed by the TrustedBSD Project.
3 * All rights reserved.
4 *
5 * This software was developed by Robert Watson for the TrustedBSD Project.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright

--- 11 unchanged lines hidden (view full) ---

22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28/*
29 * Developed by the TrustedBSD Project.
30 * Support for POSIX.1e access control lists.
30 *
31 * ACL support routines specific to POSIX.1e access control lists. These are
32 * utility routines for code common across file systems implementing POSIX.1e
33 * ACLs.
31 */
32
33#include <sys/cdefs.h>
34 */
35
36#include <sys/cdefs.h>
34__FBSDID("$FreeBSD: head/sys/kern/subr_acl_posix1e.c 150262 2005-09-17 22:01:14Z csjp $");
37__FBSDID("$FreeBSD: head/sys/kern/subr_acl_posix1e.c 160146 2006-07-06 23:37:39Z rwatson $");
35
38
36#include "opt_mac.h"
37
38#include <sys/param.h>
39#include <sys/systm.h>
39#include <sys/param.h>
40#include <sys/systm.h>
40#include <sys/sysproto.h>
41#include <sys/kernel.h>
42#include <sys/mac.h>
43#include <sys/malloc.h>
44#include <sys/mount.h>
45#include <sys/vnode.h>
41#include <sys/mount.h>
42#include <sys/vnode.h>
46#include <sys/lock.h>
47#include <sys/mutex.h>
48#include <sys/namei.h>
49#include <sys/file.h>
50#include <sys/filedesc.h>
51#include <sys/proc.h>
52#include <sys/sysent.h>
53#include <sys/errno.h>
54#include <sys/stat.h>
55#include <sys/acl.h>
56
43#include <sys/errno.h>
44#include <sys/stat.h>
45#include <sys/acl.h>
46
57#include <vm/uma.h>
58
59uma_zone_t acl_zone;
60static int vacl_set_acl(struct thread *td, struct vnode *vp,
61 acl_type_t type, struct acl *aclp);
62static int vacl_get_acl(struct thread *td, struct vnode *vp,
63 acl_type_t type, struct acl *aclp);
64static int vacl_aclcheck(struct thread *td, struct vnode *vp,
65 acl_type_t type, struct acl *aclp);
66
67/*
68 * Implement a version of vaccess() that understands POSIX.1e ACL semantics.
69 * Return 0 on success, else an errno value. Should be merged into
70 * vaccess() eventually.
71 */
72int
73vaccess_acl_posix1e(enum vtype type, uid_t file_uid, gid_t file_gid,
74 struct acl *acl, mode_t acc_mode, struct ucred *cred, int *privused)

--- 563 unchanged lines hidden (view full) ---

638 * it to appear in the resulting mode/ACL. First clear any
639 * possibly effected bits, then reconstruct.
640 */
641 mode &= ACL_PRESERVE_MASK;
642 mode |= (ACL_OVERRIDE_MASK & cmode & acl_posix1e_acl_to_mode(dacl));
643
644 return (mode);
645}
47/*
48 * Implement a version of vaccess() that understands POSIX.1e ACL semantics.
49 * Return 0 on success, else an errno value. Should be merged into
50 * vaccess() eventually.
51 */
52int
53vaccess_acl_posix1e(enum vtype type, uid_t file_uid, gid_t file_gid,
54 struct acl *acl, mode_t acc_mode, struct ucred *cred, int *privused)

--- 563 unchanged lines hidden (view full) ---

618 * it to appear in the resulting mode/ACL. First clear any
619 * possibly effected bits, then reconstruct.
620 */
621 mode &= ACL_PRESERVE_MASK;
622 mode |= (ACL_OVERRIDE_MASK & cmode & acl_posix1e_acl_to_mode(dacl));
623
624 return (mode);
625}
646
647/*
648 * These calls wrap the real vnode operations, and are called by the
649 * syscall code once the syscall has converted the path or file
650 * descriptor to a vnode (unlocked). The aclp pointer is assumed
651 * still to point to userland, so this should not be consumed within
652 * the kernel except by syscall code. Other code should directly
653 * invoke VOP_{SET,GET}ACL.
654 */
655
656/*
657 * Given a vnode, set its ACL.
658 */
659static int
660vacl_set_acl(struct thread *td, struct vnode *vp, acl_type_t type,
661 struct acl *aclp)
662{
663 struct acl inkernacl;
664 struct mount *mp;
665 int error;
666
667 error = copyin(aclp, &inkernacl, sizeof(struct acl));
668 if (error)
669 return(error);
670 error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
671 if (error != 0)
672 return (error);
673 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
674 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
675#ifdef MAC
676 error = mac_check_vnode_setacl(td->td_ucred, vp, type, &inkernacl);
677 if (error != 0)
678 goto out;
679#endif
680 error = VOP_SETACL(vp, type, &inkernacl, td->td_ucred, td);
681#ifdef MAC
682out:
683#endif
684 VOP_UNLOCK(vp, 0, td);
685 vn_finished_write(mp);
686 return(error);
687}
688
689/*
690 * Given a vnode, get its ACL.
691 */
692static int
693vacl_get_acl(struct thread *td, struct vnode *vp, acl_type_t type,
694 struct acl *aclp)
695{
696 struct acl inkernelacl;
697 int error;
698
699 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
700 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
701#ifdef MAC
702 error = mac_check_vnode_getacl(td->td_ucred, vp, type);
703 if (error != 0)
704 goto out;
705#endif
706 error = VOP_GETACL(vp, type, &inkernelacl, td->td_ucred, td);
707#ifdef MAC
708out:
709#endif
710 VOP_UNLOCK(vp, 0, td);
711 if (error == 0)
712 error = copyout(&inkernelacl, aclp, sizeof(struct acl));
713 return (error);
714}
715
716/*
717 * Given a vnode, delete its ACL.
718 */
719static int
720vacl_delete(struct thread *td, struct vnode *vp, acl_type_t type)
721{
722 struct mount *mp;
723 int error;
724
725 error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
726 if (error)
727 return (error);
728 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
729 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
730#ifdef MAC
731 error = mac_check_vnode_deleteacl(td->td_ucred, vp, type);
732 if (error)
733 goto out;
734#endif
735 error = VOP_SETACL(vp, type, 0, td->td_ucred, td);
736#ifdef MAC
737out:
738#endif
739 VOP_UNLOCK(vp, 0, td);
740 vn_finished_write(mp);
741 return (error);
742}
743
744/*
745 * Given a vnode, check whether an ACL is appropriate for it
746 */
747static int
748vacl_aclcheck(struct thread *td, struct vnode *vp, acl_type_t type,
749 struct acl *aclp)
750{
751 struct acl inkernelacl;
752 int error;
753
754 error = copyin(aclp, &inkernelacl, sizeof(struct acl));
755 if (error)
756 return(error);
757 error = VOP_ACLCHECK(vp, type, &inkernelacl, td->td_ucred, td);
758 return (error);
759}
760
761/*
762 * syscalls -- convert the path/fd to a vnode, and call vacl_whatever.
763 * Don't need to lock, as the vacl_ code will get/release any locks
764 * required.
765 */
766
767/*
768 * Given a file path, get an ACL for it
769 *
770 * MPSAFE
771 */
772int
773__acl_get_file(struct thread *td, struct __acl_get_file_args *uap)
774{
775 struct nameidata nd;
776 int vfslocked, error;
777
778 NDINIT(&nd, LOOKUP, MPSAFE|FOLLOW, UIO_USERSPACE, uap->path, td);
779 error = namei(&nd);
780 vfslocked = NDHASGIANT(&nd);
781 if (error == 0) {
782 error = vacl_get_acl(td, nd.ni_vp, uap->type, uap->aclp);
783 NDFREE(&nd, 0);
784 }
785 VFS_UNLOCK_GIANT(vfslocked);
786 return (error);
787}
788
789/*
790 * Given a file path, get an ACL for it; don't follow links.
791 *
792 * MPSAFE
793 */
794int
795__acl_get_link(struct thread *td, struct __acl_get_link_args *uap)
796{
797 struct nameidata nd;
798 int vfslocked, error;
799
800 NDINIT(&nd, LOOKUP, MPSAFE|NOFOLLOW, UIO_USERSPACE, uap->path, td);
801 error = namei(&nd);
802 vfslocked = NDHASGIANT(&nd);
803 if (error == 0) {
804 error = vacl_get_acl(td, nd.ni_vp, uap->type, uap->aclp);
805 NDFREE(&nd, 0);
806 }
807 VFS_UNLOCK_GIANT(vfslocked);
808 return (error);
809}
810
811/*
812 * Given a file path, set an ACL for it
813 *
814 * MPSAFE
815 */
816int
817__acl_set_file(struct thread *td, struct __acl_set_file_args *uap)
818{
819 struct nameidata nd;
820 int vfslocked, error;
821
822 NDINIT(&nd, LOOKUP, MPSAFE|FOLLOW, UIO_USERSPACE, uap->path, td);
823 error = namei(&nd);
824 vfslocked = NDHASGIANT(&nd);
825 if (error == 0) {
826 error = vacl_set_acl(td, nd.ni_vp, uap->type, uap->aclp);
827 NDFREE(&nd, 0);
828 }
829 VFS_UNLOCK_GIANT(vfslocked);
830 return (error);
831}
832
833/*
834 * Given a file path, set an ACL for it; don't follow links.
835 *
836 * MPSAFE
837 */
838int
839__acl_set_link(struct thread *td, struct __acl_set_link_args *uap)
840{
841 struct nameidata nd;
842 int vfslocked, error;
843
844 NDINIT(&nd, LOOKUP, MPSAFE|NOFOLLOW, UIO_USERSPACE, uap->path, td);
845 error = namei(&nd);
846 vfslocked = NDHASGIANT(&nd);
847 if (error == 0) {
848 error = vacl_set_acl(td, nd.ni_vp, uap->type, uap->aclp);
849 NDFREE(&nd, 0);
850 }
851 VFS_UNLOCK_GIANT(vfslocked);
852 return (error);
853}
854
855/*
856 * Given a file descriptor, get an ACL for it
857 *
858 * MPSAFE
859 */
860int
861__acl_get_fd(struct thread *td, struct __acl_get_fd_args *uap)
862{
863 struct file *fp;
864 int vfslocked, error;
865
866 error = getvnode(td->td_proc->p_fd, uap->filedes, &fp);
867 if (error == 0) {
868 vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
869 error = vacl_get_acl(td, fp->f_vnode, uap->type, uap->aclp);
870 fdrop(fp, td);
871 VFS_UNLOCK_GIANT(vfslocked);
872 }
873 return (error);
874}
875
876/*
877 * Given a file descriptor, set an ACL for it
878 *
879 * MPSAFE
880 */
881int
882__acl_set_fd(struct thread *td, struct __acl_set_fd_args *uap)
883{
884 struct file *fp;
885 int vfslocked, error;
886
887 error = getvnode(td->td_proc->p_fd, uap->filedes, &fp);
888 if (error == 0) {
889 vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
890 error = vacl_set_acl(td, fp->f_vnode, uap->type, uap->aclp);
891 fdrop(fp, td);
892 VFS_UNLOCK_GIANT(vfslocked);
893 }
894 return (error);
895}
896
897/*
898 * Given a file path, delete an ACL from it.
899 *
900 * MPSAFE
901 */
902int
903__acl_delete_file(struct thread *td, struct __acl_delete_file_args *uap)
904{
905 struct nameidata nd;
906 int vfslocked, error;
907
908 NDINIT(&nd, LOOKUP, MPSAFE|FOLLOW, UIO_USERSPACE, uap->path, td);
909 error = namei(&nd);
910 vfslocked = NDHASGIANT(&nd);
911 if (error == 0) {
912 error = vacl_delete(td, nd.ni_vp, uap->type);
913 NDFREE(&nd, 0);
914 }
915 VFS_UNLOCK_GIANT(vfslocked);
916 return (error);
917}
918
919/*
920 * Given a file path, delete an ACL from it; don't follow links.
921 *
922 * MPSAFE
923 */
924int
925__acl_delete_link(struct thread *td, struct __acl_delete_link_args *uap)
926{
927 struct nameidata nd;
928 int vfslocked, error;
929
930 NDINIT(&nd, LOOKUP, MPSAFE|NOFOLLOW, UIO_USERSPACE, uap->path, td);
931 error = namei(&nd);
932 vfslocked = NDHASGIANT(&nd);
933 if (error == 0) {
934 error = vacl_delete(td, nd.ni_vp, uap->type);
935 NDFREE(&nd, 0);
936 }
937 VFS_UNLOCK_GIANT(vfslocked);
938 return (error);
939}
940
941/*
942 * Given a file path, delete an ACL from it.
943 *
944 * MPSAFE
945 */
946int
947__acl_delete_fd(struct thread *td, struct __acl_delete_fd_args *uap)
948{
949 struct file *fp;
950 int vfslocked, error;
951
952 error = getvnode(td->td_proc->p_fd, uap->filedes, &fp);
953 if (error == 0) {
954 vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
955 error = vacl_delete(td, fp->f_vnode, uap->type);
956 fdrop(fp, td);
957 VFS_UNLOCK_GIANT(vfslocked);
958 }
959 return (error);
960}
961
962/*
963 * Given a file path, check an ACL for it
964 *
965 * MPSAFE
966 */
967int
968__acl_aclcheck_file(struct thread *td, struct __acl_aclcheck_file_args *uap)
969{
970 struct nameidata nd;
971 int vfslocked, error;
972
973 NDINIT(&nd, LOOKUP, MPSAFE|FOLLOW, UIO_USERSPACE, uap->path, td);
974 error = namei(&nd);
975 vfslocked = NDHASGIANT(&nd);
976 if (error == 0) {
977 error = vacl_aclcheck(td, nd.ni_vp, uap->type, uap->aclp);
978 NDFREE(&nd, 0);
979 }
980 VFS_UNLOCK_GIANT(vfslocked);
981 return (error);
982}
983
984/*
985 * Given a file path, check an ACL for it; don't follow links.
986 *
987 * MPSAFE
988 */
989int
990__acl_aclcheck_link(struct thread *td, struct __acl_aclcheck_link_args *uap)
991{
992 struct nameidata nd;
993 int vfslocked, error;
994
995 NDINIT(&nd, LOOKUP, MPSAFE|NOFOLLOW, UIO_USERSPACE, uap->path, td);
996 error = namei(&nd);
997 vfslocked = NDHASGIANT(&nd);
998 if (error == 0) {
999 error = vacl_aclcheck(td, nd.ni_vp, uap->type, uap->aclp);
1000 NDFREE(&nd, 0);
1001 }
1002 VFS_UNLOCK_GIANT(vfslocked);
1003 return (error);
1004}
1005
1006/*
1007 * Given a file descriptor, check an ACL for it
1008 *
1009 * MPSAFE
1010 */
1011int
1012__acl_aclcheck_fd(struct thread *td, struct __acl_aclcheck_fd_args *uap)
1013{
1014 struct file *fp;
1015 int vfslocked, error;
1016
1017 error = getvnode(td->td_proc->p_fd, uap->filedes, &fp);
1018 if (error == 0) {
1019 vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
1020 error = vacl_aclcheck(td, fp->f_vnode, uap->type, uap->aclp);
1021 fdrop(fp, td);
1022 VFS_UNLOCK_GIANT(vfslocked);
1023 }
1024 return (error);
1025}
1026
1027/* ARGUSED */
1028
1029static void
1030aclinit(void *dummy __unused)
1031{
1032
1033 acl_zone = uma_zcreate("ACL UMA zone", sizeof(struct acl),
1034 NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
1035}
1036SYSINIT(acls, SI_SUB_ACL, SI_ORDER_FIRST, aclinit, NULL)