FreeBSD/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_acl.c
/*
 * Create file system object initial permissions
 * including inheritable ACEs.
 * Also, create FUIDs for owner and group.
 */
Create file system object initial permissions
including inheritable ACEs.
Also, create FUIDs for owner and group.
Create file system object initial permissions including inheritable ACEs . Also create FUIDs for owner and group .
int
zfs_acl_ids_create(znode_t *dzp, int flag, vattr_t *vap, cred_t *cr,
    vsecattr_t *vsecp, zfs_acl_ids_t *acl_ids)
{
	int		error;
	zfsvfs_t	*zfsvfs = dzp->z_zfsvfs;
	zfs_acl_t	*paclp;
	gid_t		gid;
	boolean_t	trim = B_FALSE;
	boolean_t	inherited = B_FALSE;
	ASSERT_VOP_ELOCKED(ZTOV(dzp), __func__);
	bzero(acl_ids, sizeof (zfs_acl_ids_t));
	acl_ids->z_mode = MAKEIMODE(vap->va_type, vap->va_mode);
	if (vsecp)
		if ((error = zfs_vsec_2_aclp(zfsvfs, vap->va_type, vsecp, cr,
		    &acl_ids->z_fuidp, &acl_ids->z_aclp)) != 0)
			return (error);
	if ((flag & IS_ROOT_NODE) || zfsvfs->z_replay ||
	    ((flag & IS_XATTR) && (vap->va_type == VDIR))) {
		acl_ids->z_fuid = zfs_fuid_create(zfsvfs,
		    (uint64_t)vap->va_uid, cr,
		    ZFS_OWNER, &acl_ids->z_fuidp);
		acl_ids->z_fgid = zfs_fuid_create(zfsvfs,
		    (uint64_t)vap->va_gid, cr,
		    ZFS_GROUP, &acl_ids->z_fuidp);
		gid = vap->va_gid;
	} else {
		acl_ids->z_fuid = zfs_fuid_create_cred(zfsvfs, ZFS_OWNER,
		    cr, &acl_ids->z_fuidp);
		acl_ids->z_fgid = 0;
		if (vap->va_mask & AT_GID)  {
			acl_ids->z_fgid = zfs_fuid_create(zfsvfs,
			    (uint64_t)vap->va_gid,
			    cr, ZFS_GROUP, &acl_ids->z_fuidp);
			gid = vap->va_gid;
			if (acl_ids->z_fgid != dzp->z_gid &&
			    !groupmember(vap->va_gid, cr) &&
			    secpolicy_vnode_create_gid(cr) != 0)
				acl_ids->z_fgid = 0;
		}
		if (acl_ids->z_fgid == 0) {
			if (dzp->z_mode & S_ISGID) {
				char		*domain;
				uint32_t	rid;
				acl_ids->z_fgid = dzp->z_gid;
				gid = zfs_fuid_map_id(zfsvfs, acl_ids->z_fgid,
				    cr, ZFS_GROUP);
				if (zfsvfs->z_use_fuids &&
				    IS_EPHEMERAL(acl_ids->z_fgid)) {
					domain = zfs_fuid_idx_domain(
					    &zfsvfs->z_fuid_idx,
					    FUID_INDEX(acl_ids->z_fgid));
					rid = FUID_RID(acl_ids->z_fgid);
					zfs_fuid_node_add(&acl_ids->z_fuidp,
					    domain, rid,
					    FUID_INDEX(acl_ids->z_fgid),
					    acl_ids->z_fgid, ZFS_GROUP);
				}
			} else {
				acl_ids->z_fgid = zfs_fuid_create_cred(zfsvfs,
				    ZFS_GROUP, cr, &acl_ids->z_fuidp);
#ifdef __FreeBSD_kernel__
				gid = acl_ids->z_fgid = dzp->z_gid;
#else
				gid = crgetgid(cr);
#endif
			}
		}
	}
	if (!(flag & IS_ROOT_NODE) && (dzp->z_mode & S_ISGID) &&
	    (vap->va_type == VDIR)) {
		acl_ids->z_mode |= S_ISGID;
	} else {
		if ((acl_ids->z_mode & S_ISGID) &&
		    secpolicy_vnode_setids_setgids(ZTOV(dzp), cr, gid) != 0)
			acl_ids->z_mode &= ~S_ISGID;
	}
	if (acl_ids->z_aclp == NULL) {
		mutex_enter(&dzp->z_acl_lock);
		if (!(flag & IS_ROOT_NODE) &&
		    (dzp->z_pflags & ZFS_INHERIT_ACE) &&
		    !(dzp->z_pflags & ZFS_XATTR)) {
			VERIFY(0 == zfs_acl_node_read(dzp, &paclp, B_FALSE));
			acl_ids->z_aclp = zfs_acl_inherit(zfsvfs,
			    vap->va_type, paclp, acl_ids->z_mode);
			inherited = B_TRUE;
		} else {
			acl_ids->z_aclp =
			    zfs_acl_alloc(zfs_acl_version_zp(dzp));
			acl_ids->z_aclp->z_hints |= ZFS_ACL_TRIVIAL;
		}
		mutex_exit(&dzp->z_acl_lock);
		if (vap->va_type == VDIR)
			acl_ids->z_aclp->z_hints |= ZFS_ACL_AUTO_INHERIT;
		if (zfsvfs->z_acl_mode == ZFS_ACL_GROUPMASK &&
		    zfsvfs->z_acl_inherit != ZFS_ACL_PASSTHROUGH &&
		    zfsvfs->z_acl_inherit != ZFS_ACL_PASSTHROUGH_X)
			trim = B_TRUE;
		zfs_acl_chmod(vap->va_type, acl_ids->z_mode, B_FALSE, trim,
		    acl_ids->z_aclp);
	}
	if (inherited || vsecp) {
		acl_ids->z_mode = zfs_mode_compute(acl_ids->z_mode,
		    acl_ids->z_aclp, &acl_ids->z_aclp->z_hints,
		    acl_ids->z_fuid, acl_ids->z_fgid);
		if (ace_trivial_common(acl_ids->z_aclp, 0, zfs_ace_walk) == 0)
			acl_ids->z_aclp->z_hints |= ZFS_ACL_TRIVIAL;
	}
	return (0);
}
int zfs_acl_ids_create ( znode_t * dzp , int flag , vattr_t * vap , cred_t * cr , vsecattr_t * vsecp , zfs_acl_ids_t * acl_ids ) { int error ; zfsvfs_t * zfsvfs = dzp -> z_zfsvfs ; zfs_acl_t * paclp ; gid_t gid ; boolean_t trim = B_FALSE ; boolean_t inherited = B_FALSE ; ASSERT_VOP_ELOCKED ( ZTOV ( dzp ) , __func__ ) ; bzero ( acl_ids , sizeof ( zfs_acl_ids_t ) ) ; acl_ids -> z_mode = MAKEIMODE ( vap -> va_type , vap -> va_mode ) ; if ( vsecp ) if ( ( error = zfs_vsec_2_aclp ( zfsvfs , vap -> va_type , vsecp , cr , & acl_ids -> z_fuidp , & acl_ids -> z_aclp ) ) != 0 ) return ( error ) ; if ( ( flag & IS_ROOT_NODE ) || zfsvfs -> z_replay || ( ( flag & IS_XATTR ) && ( vap -> va_type == VDIR ) ) ) { acl_ids -> z_fuid = zfs_fuid_create ( zfsvfs , ( uint64_t ) vap -> va_uid , cr , ZFS_OWNER , & acl_ids -> z_fuidp ) ; acl_ids -> z_fgid = zfs_fuid_create ( zfsvfs , ( uint64_t ) vap -> va_gid , cr , ZFS_GROUP , & acl_ids -> z_fuidp ) ; gid = vap -> va_gid ; } else { acl_ids -> z_fuid = zfs_fuid_create_cred ( zfsvfs , ZFS_OWNER , cr , & acl_ids -> z_fuidp ) ; acl_ids -> z_fgid = 0 ; if ( vap -> va_mask & AT_GID ) { acl_ids -> z_fgid = zfs_fuid_create ( zfsvfs , ( uint64_t ) vap -> va_gid , cr , ZFS_GROUP , & acl_ids -> z_fuidp ) ; gid = vap -> va_gid ; if ( acl_ids -> z_fgid != dzp -> z_gid && ! groupmember ( vap -> va_gid , cr ) && secpolicy_vnode_create_gid ( cr ) != 0 ) acl_ids -> z_fgid = 0 ; } if ( acl_ids -> z_fgid == 0 ) { if ( dzp -> z_mode & S_ISGID ) { char * domain ; uint32_t rid ; acl_ids -> z_fgid = dzp -> z_gid ; gid = zfs_fuid_map_id ( zfsvfs , acl_ids -> z_fgid , cr , ZFS_GROUP ) ; if ( zfsvfs -> z_use_fuids && IS_EPHEMERAL ( acl_ids -> z_fgid ) ) { domain = zfs_fuid_idx_domain ( & zfsvfs -> z_fuid_idx , FUID_INDEX ( acl_ids -> z_fgid ) ) ; rid = FUID_RID ( acl_ids -> z_fgid ) ; zfs_fuid_node_add ( & acl_ids -> z_fuidp , domain , rid , FUID_INDEX ( acl_ids -> z_fgid ) , acl_ids -> z_fgid , ZFS_GROUP ) ; } } else { acl_ids -> z_fgid = zfs_fuid_create_cred ( zfsvfs , ZFS_GROUP , cr , & acl_ids -> z_fuidp ) ; #ifdef __FreeBSD_kernel__ gid = acl_ids -> z_fgid = dzp -> z_gid ; #else gid = crgetgid ( cr ) ; #endif } } } if ( ! ( flag & IS_ROOT_NODE ) && ( dzp -> z_mode & S_ISGID ) && ( vap -> va_type == VDIR ) ) { acl_ids -> z_mode |= S_ISGID ; } else { if ( ( acl_ids -> z_mode & S_ISGID ) && secpolicy_vnode_setids_setgids ( ZTOV ( dzp ) , cr , gid ) != 0 ) acl_ids -> z_mode &= ~ S_ISGID ; } if ( acl_ids -> z_aclp == NULL ) { mutex_enter ( & dzp -> z_acl_lock ) ; if ( ! ( flag & IS_ROOT_NODE ) && ( dzp -> z_pflags & ZFS_INHERIT_ACE ) && ! ( dzp -> z_pflags & ZFS_XATTR ) ) { VERIFY ( 0 == zfs_acl_node_read ( dzp , & paclp , B_FALSE ) ) ; acl_ids -> z_aclp = zfs_acl_inherit ( zfsvfs , vap -> va_type , paclp , acl_ids -> z_mode ) ; inherited = B_TRUE ; } else { acl_ids -> z_aclp = zfs_acl_alloc ( zfs_acl_version_zp ( dzp ) ) ; acl_ids -> z_aclp -> z_hints |= ZFS_ACL_TRIVIAL ; } mutex_exit ( & dzp -> z_acl_lock ) ; if ( vap -> va_type == VDIR ) acl_ids -> z_aclp -> z_hints |= ZFS_ACL_AUTO_INHERIT ; if ( zfsvfs -> z_acl_mode == ZFS_ACL_GROUPMASK && zfsvfs -> z_acl_inherit != ZFS_ACL_PASSTHROUGH && zfsvfs -> z_acl_inherit != ZFS_ACL_PASSTHROUGH_X ) trim = B_TRUE ; zfs_acl_chmod ( vap -> va_type , acl_ids -> z_mode , B_FALSE , trim , acl_ids -> z_aclp ) ; } if ( inherited || vsecp ) { acl_ids -> z_mode = zfs_mode_compute ( acl_ids -> z_mode , acl_ids -> z_aclp , & acl_ids -> z_aclp -> z_hints , acl_ids -> z_fuid , acl_ids -> z_fgid ) ; if ( ace_trivial_common ( acl_ids -> z_aclp , 0 , zfs_ace_walk ) == 0 ) acl_ids -> z_aclp -> z_hints |= ZFS_ACL_TRIVIAL ; } return ( 0 ) ; }
Create file system object initial permissions
 including inheritable ACEs.
Create file system object initial permissions including inheritable ACEs .
/*
	 * Determine uid and gid.
	 */ /*
	 * If we're creating a directory, and the parent directory has the
	 * set-GID bit set, set in on the new directory.
	 * Otherwise, if the user is neither privileged nor a member of the
	 * file's new group, clear the file's set-GID bit.
	 */