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) | |