Index: sys/modules/zfs/Makefile =================================================================== --- sys/modules/zfs/Makefile (revision 192766) +++ sys/modules/zfs/Makefile (working copy) @@ -16,6 +16,7 @@ SRCS+= nvpair.c SRCS+= u8_textprep.c .PATH: ${.CURDIR}/../../cddl/compat/opensolaris/kern +SRCS+= opensolaris_acl.c SRCS+= opensolaris_kmem.c SRCS+= opensolaris_kobj.c SRCS+= opensolaris_kstat.c Index: sys/cddl/contrib/opensolaris/common/acl/acl_common.c =================================================================== --- sys/cddl/contrib/opensolaris/common/acl/acl_common.c (revision 192766) +++ sys/cddl/contrib/opensolaris/common/acl/acl_common.c (working copy) @@ -424,7 +424,7 @@ cacl_free(void *ptr, size_t size) #endif } -#ifndef __FreeBSD__ +#if !defined(_KERNEL) acl_t * acl_alloc(enum acl_type type) { @@ -470,7 +470,6 @@ acl_free(acl_t *aclp) cacl_free(aclp, sizeof (acl_t)); } -#endif static uint32_t access_mask_set(int haswriteperm, int hasreadperm, int isowner, int isallow) @@ -1727,3 +1726,4 @@ out: return (error); #endif } +#endif /* _KERNEL */ Index: sys/cddl/contrib/opensolaris/common/acl/acl_common.h =================================================================== --- sys/cddl/contrib/opensolaris/common/acl/acl_common.h (revision 192766) +++ sys/cddl/contrib/opensolaris/common/acl/acl_common.h (working copy) @@ -46,6 +46,7 @@ extern int ace_trivial(ace_t *acep, int aclcnt); extern int ace_trivial_common(void *, int, uint64_t (*walk)(void *, uint64_t, int aclcnt, uint16_t *, uint16_t *, uint32_t *mask)); +#if !defined(_KERNEL) extern acl_t *acl_alloc(acl_type_t); extern void acl_free(acl_t *aclp); extern int acl_translate(acl_t *aclp, int target_flavor, @@ -53,6 +54,7 @@ extern int acl_translate(acl_t *aclp, int target_f void ksort(caddr_t v, int n, int s, int (*f)()); int cmp2acls(void *a, void *b); +#endif /* _KERNEL */ #ifdef __cplusplus } Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c =================================================================== --- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c (revision 192766) +++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c (working copy) @@ -45,7 +45,6 @@ #include #include #include -#include #include #include #include @@ -67,6 +66,7 @@ #include #include #include +#include /* * Programming rules. @@ -3846,7 +3846,6 @@ zfs_pathconf(vnode_t *vp, int cmd, ulong_t *valp, } } -#ifdef TODO /*ARGSUSED*/ static int zfs_getsecattr(vnode_t *vp, vsecattr_t *vsecp, int flag, cred_t *cr, @@ -3864,9 +3863,7 @@ zfs_getsecattr(vnode_t *vp, vsecattr_t *vsecp, int return (error); } -#endif /* TODO */ -#ifdef TODO /*ARGSUSED*/ static int zfs_setsecattr(vnode_t *vp, vsecattr_t *vsecp, int flag, cred_t *cr, @@ -3883,7 +3880,6 @@ zfs_setsecattr(vnode_t *vp, vsecattr_t *vsecp, int ZFS_EXIT(zfsvfs); return (error); } -#endif /* TODO */ static int zfs_freebsd_open(ap) @@ -4777,6 +4773,90 @@ vop_listextattr { return (error); } +int +zfs_freebsd_getacl(ap) + struct vop_getacl_args /* { + struct vnode *vp; + acl_type_t type; + struct acl *aclp; + struct ucred *cred; + struct thread *td; + } */ *ap; +{ + int error; + vsecattr_t vsecattr; + + if (ap->a_type != ACL_TYPE_NFS4) + return (EOPNOTSUPP); + + vsecattr.vsa_mask = VSA_ACE | VSA_ACECNT; + if (error = zfs_getsecattr(ap->a_vp, &vsecattr, 0, ap->a_cred, NULL)) + return (error); + + error = acl_from_aces(ap->a_aclp, vsecattr.vsa_aclentp, vsecattr.vsa_aclcnt); + if (vsecattr.vsa_aclentp != NULL) + kmem_free(vsecattr.vsa_aclentp, vsecattr.vsa_aclentsz); + + return (error); +} + +int +zfs_freebsd_setacl(ap) + struct vop_setacl_args /* { + struct vnode *vp; + acl_type_t type; + struct acl *aclp; + struct ucred *cred; + struct thread *td; + } */ *ap; +{ + int error; + vsecattr_t vsecattr; + int aclbsize; /* size of acl list in bytes */ + aclent_t *aaclp; + + if (ap->a_type != ACL_TYPE_NFS4) + return (EOPNOTSUPP); + + if (ap->a_aclp->acl_cnt < 1 || ap->a_aclp->acl_cnt > MAX_ACL_ENTRIES) + return (EINVAL); + + /* + * With NFS4 ACLs, chmod(2) may need to add additional entries, + * splitting every entry into two and appending "canonical six" + * entries at the end. Don't allow for setting an ACL that would + * cause chmod(2) to run out of ACL entries. + */ + if (ap->a_aclp->acl_cnt * 2 + 6 > ACL_MAX_ENTRIES) + return (ENOSPC); + + vsecattr.vsa_mask = VSA_ACE; + aclbsize = ap->a_aclp->acl_cnt * sizeof(ace_t); + vsecattr.vsa_aclentp = kmem_alloc(aclbsize, KM_SLEEP); + aaclp = vsecattr.vsa_aclentp; + vsecattr.vsa_aclentsz = aclbsize; + + aces_from_acl(vsecattr.vsa_aclentp, &vsecattr.vsa_aclcnt, ap->a_aclp); + error = zfs_setsecattr(ap->a_vp, &vsecattr, 0, ap->a_cred, NULL); + kmem_free(aaclp, aclbsize); + + return (error); +} + +int +zfs_freebsd_aclcheck(ap) + struct vop_aclcheck_args /* { + struct vnode *vp; + acl_type_t type; + struct acl *aclp; + struct ucred *cred; + struct thread *td; + } */ *ap; +{ + + return (EOPNOTSUPP); +} + struct vop_vector zfs_vnodeops; struct vop_vector zfs_fifoops; @@ -4816,6 +4896,11 @@ struct vop_vector zfs_vnodeops = { .vop_deleteextattr = zfs_deleteextattr, .vop_setextattr = zfs_setextattr, .vop_listextattr = zfs_listextattr, +#ifdef notyet + .vop_getacl = zfs_freebsd_getacl, + .vop_setacl = zfs_freebsd_setacl, + .vop_aclcheck = zfs_freebsd_aclcheck, +#endif }; struct vop_vector zfs_fifoops = { @@ -4829,4 +4914,9 @@ struct vop_vector zfs_fifoops = { .vop_setattr = zfs_freebsd_setattr, .vop_write = VOP_PANIC, .vop_fid = zfs_freebsd_fid, +#ifdef notyet + .vop_getacl = zfs_freebsd_getacl, + .vop_setacl = zfs_freebsd_setacl, + .vop_aclcheck = zfs_freebsd_aclcheck, +#endif }; Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_acl.c =================================================================== --- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_acl.c (revision 192766) +++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_acl.c (working copy) @@ -1909,7 +1909,6 @@ zfs_perm_init(znode_t *zp, znode_t *parent, int fl zfs_acl_free(aclp); } -#ifdef TODO /* * Retrieve a files ACL */ @@ -2005,7 +2004,6 @@ zfs_getacl(znode_t *zp, vsecattr_t *vsecp, boolean return (0); } -#endif /* TODO */ int zfs_vsec_2_aclp(zfsvfs_t *zfsvfs, vtype_t obj_type, @@ -2062,7 +2060,6 @@ zfs_vsec_2_aclp(zfsvfs_t *zfsvfs, vtype_t obj_type return (0); } -#ifdef TODO /* * Set a files ACL */ @@ -2170,7 +2167,6 @@ done: return (error); } -#endif /* TODO */ /* * working_mode returns the permissions that were not granted Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_acl.h =================================================================== --- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_acl.h (revision 192766) +++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_acl.h (working copy) @@ -188,10 +188,8 @@ struct zfs_fuid_info; #ifdef _KERNEL void zfs_perm_init(struct znode *, struct znode *, int, vattr_t *, dmu_tx_t *, cred_t *, zfs_acl_t *, zfs_fuid_info_t **); -#ifdef TODO int zfs_getacl(struct znode *, vsecattr_t *, boolean_t, cred_t *); int zfs_setacl(struct znode *, vsecattr_t *, boolean_t, cred_t *); -#endif void zfs_acl_rele(void *); void zfs_oldace_byteswap(ace_t *, int); void zfs_ace_byteswap(void *, size_t, boolean_t); Index: sys/cddl/contrib/opensolaris/uts/common/sys/acl_impl.h =================================================================== --- sys/cddl/contrib/opensolaris/uts/common/sys/acl_impl.h (revision 192766) +++ sys/cddl/contrib/opensolaris/uts/common/sys/acl_impl.h (working copy) @@ -44,10 +44,10 @@ extern "C" { typedef enum acl_type { ACLENT_T = 0, ACE_T = 1 -} acl_type_t; +} zfs_acl_type_t; struct acl_info { - acl_type_t acl_type; /* style of acl */ + zfs_acl_type_t acl_type; /* style of acl */ int acl_cnt; /* number of acl entries */ int acl_entry_size; /* sizeof acl entry */ int acl_flags; /* special flags about acl */ Index: sys/cddl/contrib/opensolaris/uts/common/sys/acl.h =================================================================== --- sys/cddl/contrib/opensolaris/uts/common/sys/acl.h (revision 192766) +++ sys/cddl/contrib/opensolaris/uts/common/sys/acl.h (working copy) @@ -31,12 +31,22 @@ #include #include +#if defined(_KERNEL) +/* + * When compiling OpenSolaris kernel code, this file is getting + * included instead of FreeBSD one. Pull the original sys/acl.h as well. + */ +#undef _SYS_ACL_H +#include_next +#define _SYS_ACL_H +#endif /* _KERNEL */ + #ifdef __cplusplus extern "C" { #endif #define MAX_ACL_ENTRIES (1024) /* max entries of each type */ -typedef struct acl { +typedef struct { int a_type; /* the type of ACL entry */ uid_t a_id; /* the entry in -uid or gid */ o_mode_t a_perm; /* the permission field */ @@ -49,7 +59,9 @@ typedef struct ace { uint16_t a_type; /* allow or deny */ } ace_t; +#if !defined(_KERNEL) typedef struct acl_info acl_t; +#endif /* * The following are Defined types for an aclent_t. Index: sys/cddl/compat/opensolaris/kern/opensolaris_acl.c =================================================================== --- sys/cddl/compat/opensolaris/kern/opensolaris_acl.c (revision 0) +++ sys/cddl/compat/opensolaris/kern/opensolaris_acl.c (revision 0) @@ -0,0 +1,217 @@ +/*- + * Copyright (c) 2008, 2009 Edward Tomasz Napierała + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * ALTHOUGH THIS SOFTWARE IS MADE OF WIN AND SCIENCE, IT IS PROVIDED BY THE + * AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include + +struct zfs2bsd { + uint32_t zb_zfs; + int zb_bsd; +}; + +struct zfs2bsd perms[] = {{ACE_READ_DATA, ACL_READ_DATA}, + {ACE_WRITE_DATA, ACL_WRITE_DATA}, + {ACE_EXECUTE, ACL_EXECUTE}, + {ACE_APPEND_DATA, ACL_APPEND_DATA}, + {ACE_DELETE_CHILD, ACL_DELETE_CHILD}, + {ACE_DELETE, ACL_DELETE}, + {ACE_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES}, + {ACE_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES}, + {ACE_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS}, + {ACE_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS}, + {ACE_READ_ACL, ACL_READ_ACL}, + {ACE_WRITE_ACL, ACL_WRITE_ACL}, + {ACE_WRITE_OWNER, ACL_WRITE_OWNER}, + {ACE_SYNCHRONIZE, ACL_SYNCHRONIZE}, + {0, 0}}; + +struct zfs2bsd flags[] = {{ACE_FILE_INHERIT_ACE, + ACL_ENTRY_FILE_INHERIT}, + {ACE_DIRECTORY_INHERIT_ACE, + ACL_ENTRY_DIRECTORY_INHERIT}, + {ACE_NO_PROPAGATE_INHERIT_ACE, + ACL_ENTRY_NO_PROPAGATE_INHERIT}, + {ACE_INHERIT_ONLY_ACE, + ACL_ENTRY_INHERIT_ONLY}, + {ACE_SUCCESSFUL_ACCESS_ACE_FLAG, + ACL_ENTRY_SUCCESSFUL_ACCESS}, + {ACE_FAILED_ACCESS_ACE_FLAG, + ACL_ENTRY_FAILED_ACCESS}, + {0, 0}}; + +static int +_bsd_from_zfs(uint32_t zfs, const struct zfs2bsd *table) +{ + const struct zfs2bsd *tmp; + int bsd = 0; + + for (tmp = table; tmp->zb_zfs != 0; tmp++) { + if (zfs & tmp->zb_zfs) + bsd |= tmp->zb_bsd; + } + + return (bsd); +} + +static uint32_t +_zfs_from_bsd(int bsd, const struct zfs2bsd *table) +{ + const struct zfs2bsd *tmp; + uint32_t zfs = 0; + + for (tmp = table; tmp->zb_bsd != 0; tmp++) { + if (bsd & tmp->zb_bsd) + zfs |= tmp->zb_zfs; + } + + return (zfs); +} + +int +acl_from_aces(struct acl *aclp, const ace_t *aces, int nentries) +{ + int i; + struct acl_entry *entry; + const ace_t *ace; + + bzero(aclp, sizeof(*aclp)); + + if (nentries > ACL_MAX_ENTRIES) { + /* + * I believe it may happen only when moving a pool + * from SunOS to FreeBSD. + */ + printf("acl_from_aces: ZFS ACL too big to fit " + "into 'struct acl'; returning EINVAL.\n"); + return (EINVAL); + } + + KASSERT(nentries >= 1, ("empty ZFS ACL")); + + aclp->acl_cnt = nentries; + aclp->acl_maxcnt = ACL_MAX_ENTRIES; + + for (i = 0; i < nentries; i++) { + entry = &(aclp->acl_entry[i]); + ace = &(aces[i]); + + if (ace->a_flags & ACE_OWNER) + entry->ae_tag = ACL_USER_OBJ; + else if (ace->a_flags & ACE_GROUP) + entry->ae_tag = ACL_GROUP_OBJ; + else if (ace->a_flags & ACE_EVERYONE) + entry->ae_tag = ACL_EVERYONE; + else if (ace->a_flags & ACE_IDENTIFIER_GROUP) + entry->ae_tag = ACL_GROUP; + else + entry->ae_tag = ACL_USER; + + if (entry->ae_tag == ACL_USER || entry->ae_tag == ACL_GROUP) + entry->ae_id = ace->a_who; + else + entry->ae_id = ACL_UNDEFINED_ID; + + entry->ae_perm = _bsd_from_zfs(ace->a_access_mask, perms); + entry->ae_flags = _bsd_from_zfs(ace->a_flags, flags); + + switch (ace->a_type) { + case ACE_ACCESS_ALLOWED_ACE_TYPE: + entry->ae_entry_type = ACL_ENTRY_TYPE_ALLOW; + break; + case ACE_ACCESS_DENIED_ACE_TYPE: + entry->ae_entry_type = ACL_ENTRY_TYPE_DENY; + break; + case ACE_SYSTEM_AUDIT_ACE_TYPE: + entry->ae_entry_type = ACL_ENTRY_TYPE_AUDIT; + break; + case ACE_SYSTEM_ALARM_ACE_TYPE: + entry->ae_entry_type = ACL_ENTRY_TYPE_ALARM; + break; + default: + panic("acl_from_aces: a_type is 0x%x", ace->a_type); + } + } + + return (0); +} + +void +aces_from_acl(ace_t *aces, int *nentries, const struct acl *aclp) +{ + int i; + const struct acl_entry *entry; + ace_t *ace; + + bzero(aces, sizeof(*aces) * aclp->acl_cnt); + + *nentries = aclp->acl_cnt; + + for (i = 0; i < aclp->acl_cnt; i++) { + entry = &(aclp->acl_entry[i]); + ace = &(aces[i]); + + ace->a_who = entry->ae_id; + + if (entry->ae_tag == ACL_USER_OBJ) + ace->a_flags = ACE_OWNER; + else if (entry->ae_tag == ACL_GROUP_OBJ) + ace->a_flags = (ACE_GROUP | ACE_IDENTIFIER_GROUP); + else if (entry->ae_tag == ACL_GROUP) + ace->a_flags = ACE_IDENTIFIER_GROUP; + else if (entry->ae_tag == ACL_EVERYONE) + ace->a_flags = ACE_EVERYONE; + else /* ACL_USER */ + ace->a_flags = 0; + + ace->a_access_mask = _zfs_from_bsd(entry->ae_perm, perms); + ace->a_flags |= _zfs_from_bsd(entry->ae_flags, flags); + + switch (entry->ae_entry_type) { + case ACL_ENTRY_TYPE_ALLOW: + ace->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; + break; + case ACL_ENTRY_TYPE_DENY: + ace->a_type = ACE_ACCESS_DENIED_ACE_TYPE; + break; + case ACL_ENTRY_TYPE_ALARM: + ace->a_type = ACE_SYSTEM_ALARM_ACE_TYPE; + break; + case ACL_ENTRY_TYPE_AUDIT: + ace->a_type = ACE_SYSTEM_AUDIT_ACE_TYPE; + break; + default: + panic("aces_from_acl: ae_entry_type is 0x%x", entry->ae_entry_type); + } + } +} Index: sys/cddl/compat/opensolaris/sys/acl.h =================================================================== --- sys/cddl/compat/opensolaris/sys/acl.h (revision 0) +++ sys/cddl/compat/opensolaris/sys/acl.h (revision 0) @@ -0,0 +1,39 @@ +/*- + * Copyright (c) 2008, 2009 Edward Tomasz Napierała + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * ALTHOUGH THIS SOFTWARE IS MADE OF WIN AND SCIENCE, IT IS PROVIDED BY THE + * AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef OPENSOLARIS_SYS_ACL_H +#define OPENSOLARIS_SYS_ACL_H + +#include_next + +struct acl; + +void aces_from_acl(ace_t *aces, int *nentries, const struct acl *aclp); +int acl_from_aces(struct acl *aclp, const ace_t *aces, int nentries); + +#endif /* OPENSOLARIS_SYS_ACL_H */