Date: Sun, 1 Jul 2012 14:55:36 +0000 (UTC) From: Martin Matuska <mm@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-vendor@freebsd.org Subject: svn commit: r237927 - in vendor/illumos/dist: common/acl common/atomic common/atomic/amd64 common/atomic/i386 common/atomic/sparc common/nvpair common/unicode common/zfs uts uts/common uts/common/c... Message-ID: <201207011455.q61EtapK008220@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: mm Date: Sun Jul 1 14:55:35 2012 New Revision: 237927 URL: http://svn.freebsd.org/changeset/base/237927 Log: Add kernel part (uts) with ZFS to vendor/illumos illumos-gate revision 13742:b6bbdd77139c Added: vendor/illumos/dist/common/acl/ vendor/illumos/dist/common/acl/acl_common.c vendor/illumos/dist/common/acl/acl_common.h vendor/illumos/dist/common/atomic/ vendor/illumos/dist/common/atomic/amd64/ vendor/illumos/dist/common/atomic/amd64/atomic.s vendor/illumos/dist/common/atomic/i386/ vendor/illumos/dist/common/atomic/i386/atomic.s vendor/illumos/dist/common/atomic/sparc/ vendor/illumos/dist/common/atomic/sparc/atomic.s vendor/illumos/dist/common/nvpair/ vendor/illumos/dist/common/nvpair/fnvpair.c vendor/illumos/dist/common/nvpair/nvpair.c vendor/illumos/dist/common/nvpair/nvpair_alloc_fixed.c vendor/illumos/dist/common/unicode/ vendor/illumos/dist/common/unicode/u8_textprep.c vendor/illumos/dist/common/zfs/ vendor/illumos/dist/common/zfs/zfeature_common.c vendor/illumos/dist/common/zfs/zfeature_common.h vendor/illumos/dist/common/zfs/zfs_comutil.c vendor/illumos/dist/common/zfs/zfs_comutil.h vendor/illumos/dist/common/zfs/zfs_deleg.c vendor/illumos/dist/common/zfs/zfs_deleg.h vendor/illumos/dist/common/zfs/zfs_fletcher.c vendor/illumos/dist/common/zfs/zfs_fletcher.h vendor/illumos/dist/common/zfs/zfs_namecheck.c vendor/illumos/dist/common/zfs/zfs_namecheck.h vendor/illumos/dist/common/zfs/zfs_prop.c vendor/illumos/dist/common/zfs/zfs_prop.h vendor/illumos/dist/common/zfs/zpool_prop.c vendor/illumos/dist/common/zfs/zprop_common.c vendor/illumos/dist/uts/ vendor/illumos/dist/uts/common/ vendor/illumos/dist/uts/common/Makefile.files vendor/illumos/dist/uts/common/ctf/ vendor/illumos/dist/uts/common/ctf/ctf_mod.c vendor/illumos/dist/uts/common/ctf/ctf_subr.c vendor/illumos/dist/uts/common/dtrace/ vendor/illumos/dist/uts/common/dtrace/dcpc.c vendor/illumos/dist/uts/common/dtrace/dtrace.c vendor/illumos/dist/uts/common/dtrace/fasttrap.c vendor/illumos/dist/uts/common/dtrace/lockstat.c vendor/illumos/dist/uts/common/dtrace/profile.c vendor/illumos/dist/uts/common/dtrace/sdt_subr.c vendor/illumos/dist/uts/common/dtrace/systrace.c vendor/illumos/dist/uts/common/fs/ vendor/illumos/dist/uts/common/fs/gfs.c vendor/illumos/dist/uts/common/fs/vnode.c vendor/illumos/dist/uts/common/fs/zfs/ vendor/illumos/dist/uts/common/fs/zfs/arc.c vendor/illumos/dist/uts/common/fs/zfs/bplist.c vendor/illumos/dist/uts/common/fs/zfs/bpobj.c vendor/illumos/dist/uts/common/fs/zfs/bptree.c vendor/illumos/dist/uts/common/fs/zfs/dbuf.c vendor/illumos/dist/uts/common/fs/zfs/ddt.c vendor/illumos/dist/uts/common/fs/zfs/ddt_zap.c vendor/illumos/dist/uts/common/fs/zfs/dmu.c vendor/illumos/dist/uts/common/fs/zfs/dmu_diff.c vendor/illumos/dist/uts/common/fs/zfs/dmu_object.c vendor/illumos/dist/uts/common/fs/zfs/dmu_objset.c vendor/illumos/dist/uts/common/fs/zfs/dmu_send.c vendor/illumos/dist/uts/common/fs/zfs/dmu_traverse.c vendor/illumos/dist/uts/common/fs/zfs/dmu_tx.c vendor/illumos/dist/uts/common/fs/zfs/dmu_zfetch.c vendor/illumos/dist/uts/common/fs/zfs/dnode.c vendor/illumos/dist/uts/common/fs/zfs/dnode_sync.c vendor/illumos/dist/uts/common/fs/zfs/dsl_dataset.c vendor/illumos/dist/uts/common/fs/zfs/dsl_deadlist.c vendor/illumos/dist/uts/common/fs/zfs/dsl_deleg.c vendor/illumos/dist/uts/common/fs/zfs/dsl_dir.c vendor/illumos/dist/uts/common/fs/zfs/dsl_pool.c vendor/illumos/dist/uts/common/fs/zfs/dsl_prop.c vendor/illumos/dist/uts/common/fs/zfs/dsl_scan.c vendor/illumos/dist/uts/common/fs/zfs/dsl_synctask.c vendor/illumos/dist/uts/common/fs/zfs/gzip.c vendor/illumos/dist/uts/common/fs/zfs/lzjb.c vendor/illumos/dist/uts/common/fs/zfs/metaslab.c vendor/illumos/dist/uts/common/fs/zfs/refcount.c vendor/illumos/dist/uts/common/fs/zfs/rrwlock.c vendor/illumos/dist/uts/common/fs/zfs/sa.c vendor/illumos/dist/uts/common/fs/zfs/sha256.c vendor/illumos/dist/uts/common/fs/zfs/spa.c vendor/illumos/dist/uts/common/fs/zfs/spa_config.c vendor/illumos/dist/uts/common/fs/zfs/spa_errlog.c vendor/illumos/dist/uts/common/fs/zfs/spa_history.c vendor/illumos/dist/uts/common/fs/zfs/spa_misc.c vendor/illumos/dist/uts/common/fs/zfs/space_map.c vendor/illumos/dist/uts/common/fs/zfs/sys/ vendor/illumos/dist/uts/common/fs/zfs/sys/arc.h vendor/illumos/dist/uts/common/fs/zfs/sys/bplist.h vendor/illumos/dist/uts/common/fs/zfs/sys/bpobj.h vendor/illumos/dist/uts/common/fs/zfs/sys/bptree.h vendor/illumos/dist/uts/common/fs/zfs/sys/dbuf.h vendor/illumos/dist/uts/common/fs/zfs/sys/ddt.h vendor/illumos/dist/uts/common/fs/zfs/sys/dmu.h vendor/illumos/dist/uts/common/fs/zfs/sys/dmu_impl.h vendor/illumos/dist/uts/common/fs/zfs/sys/dmu_objset.h vendor/illumos/dist/uts/common/fs/zfs/sys/dmu_traverse.h vendor/illumos/dist/uts/common/fs/zfs/sys/dmu_tx.h vendor/illumos/dist/uts/common/fs/zfs/sys/dmu_zfetch.h vendor/illumos/dist/uts/common/fs/zfs/sys/dnode.h vendor/illumos/dist/uts/common/fs/zfs/sys/dsl_dataset.h vendor/illumos/dist/uts/common/fs/zfs/sys/dsl_deadlist.h vendor/illumos/dist/uts/common/fs/zfs/sys/dsl_deleg.h vendor/illumos/dist/uts/common/fs/zfs/sys/dsl_dir.h vendor/illumos/dist/uts/common/fs/zfs/sys/dsl_pool.h vendor/illumos/dist/uts/common/fs/zfs/sys/dsl_prop.h vendor/illumos/dist/uts/common/fs/zfs/sys/dsl_scan.h vendor/illumos/dist/uts/common/fs/zfs/sys/dsl_synctask.h vendor/illumos/dist/uts/common/fs/zfs/sys/metaslab.h vendor/illumos/dist/uts/common/fs/zfs/sys/metaslab_impl.h vendor/illumos/dist/uts/common/fs/zfs/sys/refcount.h vendor/illumos/dist/uts/common/fs/zfs/sys/rrwlock.h vendor/illumos/dist/uts/common/fs/zfs/sys/sa.h vendor/illumos/dist/uts/common/fs/zfs/sys/sa_impl.h vendor/illumos/dist/uts/common/fs/zfs/sys/spa.h vendor/illumos/dist/uts/common/fs/zfs/sys/spa_boot.h vendor/illumos/dist/uts/common/fs/zfs/sys/spa_impl.h vendor/illumos/dist/uts/common/fs/zfs/sys/space_map.h vendor/illumos/dist/uts/common/fs/zfs/sys/txg.h vendor/illumos/dist/uts/common/fs/zfs/sys/txg_impl.h vendor/illumos/dist/uts/common/fs/zfs/sys/uberblock.h vendor/illumos/dist/uts/common/fs/zfs/sys/uberblock_impl.h vendor/illumos/dist/uts/common/fs/zfs/sys/unique.h vendor/illumos/dist/uts/common/fs/zfs/sys/vdev.h vendor/illumos/dist/uts/common/fs/zfs/sys/vdev_disk.h vendor/illumos/dist/uts/common/fs/zfs/sys/vdev_file.h vendor/illumos/dist/uts/common/fs/zfs/sys/vdev_impl.h vendor/illumos/dist/uts/common/fs/zfs/sys/zap.h vendor/illumos/dist/uts/common/fs/zfs/sys/zap_impl.h vendor/illumos/dist/uts/common/fs/zfs/sys/zap_leaf.h vendor/illumos/dist/uts/common/fs/zfs/sys/zfeature.h vendor/illumos/dist/uts/common/fs/zfs/sys/zfs_acl.h vendor/illumos/dist/uts/common/fs/zfs/sys/zfs_context.h vendor/illumos/dist/uts/common/fs/zfs/sys/zfs_ctldir.h vendor/illumos/dist/uts/common/fs/zfs/sys/zfs_debug.h vendor/illumos/dist/uts/common/fs/zfs/sys/zfs_dir.h vendor/illumos/dist/uts/common/fs/zfs/sys/zfs_fuid.h vendor/illumos/dist/uts/common/fs/zfs/sys/zfs_ioctl.h vendor/illumos/dist/uts/common/fs/zfs/sys/zfs_onexit.h vendor/illumos/dist/uts/common/fs/zfs/sys/zfs_rlock.h vendor/illumos/dist/uts/common/fs/zfs/sys/zfs_sa.h vendor/illumos/dist/uts/common/fs/zfs/sys/zfs_stat.h vendor/illumos/dist/uts/common/fs/zfs/sys/zfs_vfsops.h vendor/illumos/dist/uts/common/fs/zfs/sys/zfs_znode.h vendor/illumos/dist/uts/common/fs/zfs/sys/zil.h vendor/illumos/dist/uts/common/fs/zfs/sys/zil_impl.h vendor/illumos/dist/uts/common/fs/zfs/sys/zio.h vendor/illumos/dist/uts/common/fs/zfs/sys/zio_checksum.h vendor/illumos/dist/uts/common/fs/zfs/sys/zio_compress.h vendor/illumos/dist/uts/common/fs/zfs/sys/zio_impl.h vendor/illumos/dist/uts/common/fs/zfs/sys/zrlock.h vendor/illumos/dist/uts/common/fs/zfs/sys/zvol.h vendor/illumos/dist/uts/common/fs/zfs/txg.c vendor/illumos/dist/uts/common/fs/zfs/uberblock.c vendor/illumos/dist/uts/common/fs/zfs/unique.c vendor/illumos/dist/uts/common/fs/zfs/vdev.c vendor/illumos/dist/uts/common/fs/zfs/vdev_cache.c vendor/illumos/dist/uts/common/fs/zfs/vdev_disk.c vendor/illumos/dist/uts/common/fs/zfs/vdev_file.c vendor/illumos/dist/uts/common/fs/zfs/vdev_label.c vendor/illumos/dist/uts/common/fs/zfs/vdev_mirror.c vendor/illumos/dist/uts/common/fs/zfs/vdev_missing.c vendor/illumos/dist/uts/common/fs/zfs/vdev_queue.c vendor/illumos/dist/uts/common/fs/zfs/vdev_raidz.c vendor/illumos/dist/uts/common/fs/zfs/vdev_root.c vendor/illumos/dist/uts/common/fs/zfs/zap.c vendor/illumos/dist/uts/common/fs/zfs/zap_leaf.c vendor/illumos/dist/uts/common/fs/zfs/zap_micro.c vendor/illumos/dist/uts/common/fs/zfs/zfeature.c vendor/illumos/dist/uts/common/fs/zfs/zfs.conf vendor/illumos/dist/uts/common/fs/zfs/zfs_acl.c vendor/illumos/dist/uts/common/fs/zfs/zfs_byteswap.c vendor/illumos/dist/uts/common/fs/zfs/zfs_ctldir.c vendor/illumos/dist/uts/common/fs/zfs/zfs_debug.c vendor/illumos/dist/uts/common/fs/zfs/zfs_dir.c vendor/illumos/dist/uts/common/fs/zfs/zfs_fm.c vendor/illumos/dist/uts/common/fs/zfs/zfs_fuid.c vendor/illumos/dist/uts/common/fs/zfs/zfs_ioctl.c vendor/illumos/dist/uts/common/fs/zfs/zfs_log.c vendor/illumos/dist/uts/common/fs/zfs/zfs_onexit.c vendor/illumos/dist/uts/common/fs/zfs/zfs_replay.c vendor/illumos/dist/uts/common/fs/zfs/zfs_rlock.c vendor/illumos/dist/uts/common/fs/zfs/zfs_sa.c vendor/illumos/dist/uts/common/fs/zfs/zfs_vfsops.c vendor/illumos/dist/uts/common/fs/zfs/zfs_vnops.c vendor/illumos/dist/uts/common/fs/zfs/zfs_znode.c vendor/illumos/dist/uts/common/fs/zfs/zil.c vendor/illumos/dist/uts/common/fs/zfs/zio.c vendor/illumos/dist/uts/common/fs/zfs/zio_checksum.c vendor/illumos/dist/uts/common/fs/zfs/zio_compress.c vendor/illumos/dist/uts/common/fs/zfs/zio_inject.c vendor/illumos/dist/uts/common/fs/zfs/zle.c vendor/illumos/dist/uts/common/fs/zfs/zrlock.c vendor/illumos/dist/uts/common/fs/zfs/zvol.c vendor/illumos/dist/uts/common/os/ vendor/illumos/dist/uts/common/os/callb.c vendor/illumos/dist/uts/common/os/fm.c vendor/illumos/dist/uts/common/os/nvpair_alloc_system.c vendor/illumos/dist/uts/common/sys/ vendor/illumos/dist/uts/common/sys/acl.h vendor/illumos/dist/uts/common/sys/acl_impl.h vendor/illumos/dist/uts/common/sys/avl.h vendor/illumos/dist/uts/common/sys/avl_impl.h vendor/illumos/dist/uts/common/sys/bitmap.h vendor/illumos/dist/uts/common/sys/callb.h vendor/illumos/dist/uts/common/sys/ccompile.h vendor/illumos/dist/uts/common/sys/cmn_err.h vendor/illumos/dist/uts/common/sys/compress.h vendor/illumos/dist/uts/common/sys/cpupart.h vendor/illumos/dist/uts/common/sys/cpuvar.h vendor/illumos/dist/uts/common/sys/cred.h vendor/illumos/dist/uts/common/sys/ctf.h vendor/illumos/dist/uts/common/sys/ctf_api.h vendor/illumos/dist/uts/common/sys/debug.h vendor/illumos/dist/uts/common/sys/dtrace.h vendor/illumos/dist/uts/common/sys/dtrace_impl.h vendor/illumos/dist/uts/common/sys/errorq.h vendor/illumos/dist/uts/common/sys/extdirent.h vendor/illumos/dist/uts/common/sys/fasttrap.h vendor/illumos/dist/uts/common/sys/fasttrap_impl.h vendor/illumos/dist/uts/common/sys/feature_tests.h vendor/illumos/dist/uts/common/sys/fm/ vendor/illumos/dist/uts/common/sys/fm/fs/ vendor/illumos/dist/uts/common/sys/fm/fs/zfs.h vendor/illumos/dist/uts/common/sys/fm/protocol.h vendor/illumos/dist/uts/common/sys/fm/util.h vendor/illumos/dist/uts/common/sys/fs/ vendor/illumos/dist/uts/common/sys/fs/zfs.h vendor/illumos/dist/uts/common/sys/fs/zut.h vendor/illumos/dist/uts/common/sys/gfs.h vendor/illumos/dist/uts/common/sys/idmap.h vendor/illumos/dist/uts/common/sys/isa_defs.h vendor/illumos/dist/uts/common/sys/list.h vendor/illumos/dist/uts/common/sys/list_impl.h vendor/illumos/dist/uts/common/sys/note.h vendor/illumos/dist/uts/common/sys/nvpair.h vendor/illumos/dist/uts/common/sys/nvpair_impl.h vendor/illumos/dist/uts/common/sys/processor.h vendor/illumos/dist/uts/common/sys/procset.h vendor/illumos/dist/uts/common/sys/synch.h vendor/illumos/dist/uts/common/sys/sysevent/ vendor/illumos/dist/uts/common/sys/sysevent.h vendor/illumos/dist/uts/common/sys/sysevent/dev.h vendor/illumos/dist/uts/common/sys/sysevent/eventdefs.h vendor/illumos/dist/uts/common/sys/sysmacros.h vendor/illumos/dist/uts/common/sys/taskq.h vendor/illumos/dist/uts/common/sys/u8_textprep.h vendor/illumos/dist/uts/common/sys/u8_textprep_data.h vendor/illumos/dist/uts/common/sys/vnode.h vendor/illumos/dist/uts/common/sys/zmod.h vendor/illumos/dist/uts/common/zmod/ vendor/illumos/dist/uts/common/zmod/adler32.c vendor/illumos/dist/uts/common/zmod/crc32.h vendor/illumos/dist/uts/common/zmod/deflate.c vendor/illumos/dist/uts/common/zmod/deflate.h vendor/illumos/dist/uts/common/zmod/inffast.c vendor/illumos/dist/uts/common/zmod/inffast.h vendor/illumos/dist/uts/common/zmod/inffixed.h vendor/illumos/dist/uts/common/zmod/inflate.c vendor/illumos/dist/uts/common/zmod/inflate.h vendor/illumos/dist/uts/common/zmod/inftrees.c vendor/illumos/dist/uts/common/zmod/inftrees.h vendor/illumos/dist/uts/common/zmod/trees.c vendor/illumos/dist/uts/common/zmod/zconf.h vendor/illumos/dist/uts/common/zmod/zlib.h vendor/illumos/dist/uts/common/zmod/zmod.c vendor/illumos/dist/uts/common/zmod/zmod_subr.c vendor/illumos/dist/uts/common/zmod/zutil.c vendor/illumos/dist/uts/common/zmod/zutil.h vendor/illumos/dist/uts/intel/ vendor/illumos/dist/uts/intel/dtrace/ vendor/illumos/dist/uts/intel/dtrace/fasttrap_isa.c vendor/illumos/dist/uts/intel/sys/ vendor/illumos/dist/uts/intel/sys/fasttrap_isa.h vendor/illumos/dist/uts/sparc/ vendor/illumos/dist/uts/sparc/dtrace/ vendor/illumos/dist/uts/sparc/dtrace/fasttrap_isa.c vendor/illumos/dist/uts/sparc/sys/ vendor/illumos/dist/uts/sparc/sys/fasttrap_isa.h Added: vendor/illumos/dist/common/acl/acl_common.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ vendor/illumos/dist/common/acl/acl_common.c Sun Jul 1 14:55:35 2012 (r237927) @@ -0,0 +1,1760 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2011 Nexenta Systems, Inc. All rights reserved. + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/avl.h> +#if defined(_KERNEL) +#include <sys/systm.h> +#include <sys/sysmacros.h> +#include <acl/acl_common.h> +#else +#include <errno.h> +#include <stdlib.h> +#include <stddef.h> +#include <strings.h> +#include <unistd.h> +#include <assert.h> +#include <grp.h> +#include <pwd.h> +#include <acl_common.h> +#define ASSERT assert +#endif + +#define ACE_POSIX_SUPPORTED_BITS (ACE_READ_DATA | \ + ACE_WRITE_DATA | ACE_APPEND_DATA | ACE_EXECUTE | \ + ACE_READ_ATTRIBUTES | ACE_READ_ACL | ACE_WRITE_ACL) + + +#define ACL_SYNCHRONIZE_SET_DENY 0x0000001 +#define ACL_SYNCHRONIZE_SET_ALLOW 0x0000002 +#define ACL_SYNCHRONIZE_ERR_DENY 0x0000004 +#define ACL_SYNCHRONIZE_ERR_ALLOW 0x0000008 + +#define ACL_WRITE_OWNER_SET_DENY 0x0000010 +#define ACL_WRITE_OWNER_SET_ALLOW 0x0000020 +#define ACL_WRITE_OWNER_ERR_DENY 0x0000040 +#define ACL_WRITE_OWNER_ERR_ALLOW 0x0000080 + +#define ACL_DELETE_SET_DENY 0x0000100 +#define ACL_DELETE_SET_ALLOW 0x0000200 +#define ACL_DELETE_ERR_DENY 0x0000400 +#define ACL_DELETE_ERR_ALLOW 0x0000800 + +#define ACL_WRITE_ATTRS_OWNER_SET_DENY 0x0001000 +#define ACL_WRITE_ATTRS_OWNER_SET_ALLOW 0x0002000 +#define ACL_WRITE_ATTRS_OWNER_ERR_DENY 0x0004000 +#define ACL_WRITE_ATTRS_OWNER_ERR_ALLOW 0x0008000 + +#define ACL_WRITE_ATTRS_WRITER_SET_DENY 0x0010000 +#define ACL_WRITE_ATTRS_WRITER_SET_ALLOW 0x0020000 +#define ACL_WRITE_ATTRS_WRITER_ERR_DENY 0x0040000 +#define ACL_WRITE_ATTRS_WRITER_ERR_ALLOW 0x0080000 + +#define ACL_WRITE_NAMED_WRITER_SET_DENY 0x0100000 +#define ACL_WRITE_NAMED_WRITER_SET_ALLOW 0x0200000 +#define ACL_WRITE_NAMED_WRITER_ERR_DENY 0x0400000 +#define ACL_WRITE_NAMED_WRITER_ERR_ALLOW 0x0800000 + +#define ACL_READ_NAMED_READER_SET_DENY 0x1000000 +#define ACL_READ_NAMED_READER_SET_ALLOW 0x2000000 +#define ACL_READ_NAMED_READER_ERR_DENY 0x4000000 +#define ACL_READ_NAMED_READER_ERR_ALLOW 0x8000000 + + +#define ACE_VALID_MASK_BITS (\ + ACE_READ_DATA | \ + ACE_LIST_DIRECTORY | \ + ACE_WRITE_DATA | \ + ACE_ADD_FILE | \ + ACE_APPEND_DATA | \ + ACE_ADD_SUBDIRECTORY | \ + ACE_READ_NAMED_ATTRS | \ + ACE_WRITE_NAMED_ATTRS | \ + ACE_EXECUTE | \ + ACE_DELETE_CHILD | \ + ACE_READ_ATTRIBUTES | \ + ACE_WRITE_ATTRIBUTES | \ + ACE_DELETE | \ + ACE_READ_ACL | \ + ACE_WRITE_ACL | \ + ACE_WRITE_OWNER | \ + ACE_SYNCHRONIZE) + +#define ACE_MASK_UNDEFINED 0x80000000 + +#define ACE_VALID_FLAG_BITS (ACE_FILE_INHERIT_ACE | \ + ACE_DIRECTORY_INHERIT_ACE | \ + ACE_NO_PROPAGATE_INHERIT_ACE | ACE_INHERIT_ONLY_ACE | \ + ACE_SUCCESSFUL_ACCESS_ACE_FLAG | ACE_FAILED_ACCESS_ACE_FLAG | \ + ACE_IDENTIFIER_GROUP | ACE_OWNER | ACE_GROUP | ACE_EVERYONE) + +/* + * ACL conversion helpers + */ + +typedef enum { + ace_unused, + ace_user_obj, + ace_user, + ace_group, /* includes GROUP and GROUP_OBJ */ + ace_other_obj +} ace_to_aent_state_t; + +typedef struct acevals { + uid_t key; + avl_node_t avl; + uint32_t mask; + uint32_t allowed; + uint32_t denied; + int aent_type; +} acevals_t; + +typedef struct ace_list { + acevals_t user_obj; + avl_tree_t user; + int numusers; + acevals_t group_obj; + avl_tree_t group; + int numgroups; + acevals_t other_obj; + uint32_t acl_mask; + int hasmask; + int dfacl_flag; + ace_to_aent_state_t state; + int seen; /* bitmask of all aclent_t a_type values seen */ +} ace_list_t; + +/* + * Generic shellsort, from K&R (1st ed, p 58.), somewhat modified. + * v = Ptr to array/vector of objs + * n = # objs in the array + * s = size of each obj (must be multiples of a word size) + * f = ptr to function to compare two objs + * returns (-1 = less than, 0 = equal, 1 = greater than + */ +void +ksort(caddr_t v, int n, int s, int (*f)()) +{ + int g, i, j, ii; + unsigned int *p1, *p2; + unsigned int tmp; + + /* No work to do */ + if (v == NULL || n <= 1) + return; + + /* Sanity check on arguments */ + ASSERT(((uintptr_t)v & 0x3) == 0 && (s & 0x3) == 0); + ASSERT(s > 0); + for (g = n / 2; g > 0; g /= 2) { + for (i = g; i < n; i++) { + for (j = i - g; j >= 0 && + (*f)(v + j * s, v + (j + g) * s) == 1; + j -= g) { + p1 = (void *)(v + j * s); + p2 = (void *)(v + (j + g) * s); + for (ii = 0; ii < s / 4; ii++) { + tmp = *p1; + *p1++ = *p2; + *p2++ = tmp; + } + } + } + } +} + +/* + * Compare two acls, all fields. Returns: + * -1 (less than) + * 0 (equal) + * +1 (greater than) + */ +int +cmp2acls(void *a, void *b) +{ + aclent_t *x = (aclent_t *)a; + aclent_t *y = (aclent_t *)b; + + /* Compare types */ + if (x->a_type < y->a_type) + return (-1); + if (x->a_type > y->a_type) + return (1); + /* Equal types; compare id's */ + if (x->a_id < y->a_id) + return (-1); + if (x->a_id > y->a_id) + return (1); + /* Equal ids; compare perms */ + if (x->a_perm < y->a_perm) + return (-1); + if (x->a_perm > y->a_perm) + return (1); + /* Totally equal */ + return (0); +} + +/*ARGSUSED*/ +static void * +cacl_realloc(void *ptr, size_t size, size_t new_size) +{ +#if defined(_KERNEL) + void *tmp; + + tmp = kmem_alloc(new_size, KM_SLEEP); + (void) memcpy(tmp, ptr, (size < new_size) ? size : new_size); + kmem_free(ptr, size); + return (tmp); +#else + return (realloc(ptr, new_size)); +#endif +} + +static int +cacl_malloc(void **ptr, size_t size) +{ +#if defined(_KERNEL) + *ptr = kmem_zalloc(size, KM_SLEEP); + return (0); +#else + *ptr = calloc(1, size); + if (*ptr == NULL) + return (errno); + + return (0); +#endif +} + +/*ARGSUSED*/ +static void +cacl_free(void *ptr, size_t size) +{ +#if defined(_KERNEL) + kmem_free(ptr, size); +#else + free(ptr); +#endif +} + +acl_t * +acl_alloc(enum acl_type type) +{ + acl_t *aclp; + + if (cacl_malloc((void **)&aclp, sizeof (acl_t)) != 0) + return (NULL); + + aclp->acl_aclp = NULL; + aclp->acl_cnt = 0; + + switch (type) { + case ACE_T: + aclp->acl_type = ACE_T; + aclp->acl_entry_size = sizeof (ace_t); + break; + case ACLENT_T: + aclp->acl_type = ACLENT_T; + aclp->acl_entry_size = sizeof (aclent_t); + break; + default: + acl_free(aclp); + aclp = NULL; + } + return (aclp); +} + +/* + * Free acl_t structure + */ +void +acl_free(acl_t *aclp) +{ + int acl_size; + + if (aclp == NULL) + return; + + if (aclp->acl_aclp) { + acl_size = aclp->acl_cnt * aclp->acl_entry_size; + cacl_free(aclp->acl_aclp, acl_size); + } + + cacl_free(aclp, sizeof (acl_t)); +} + +static uint32_t +access_mask_set(int haswriteperm, int hasreadperm, int isowner, int isallow) +{ + uint32_t access_mask = 0; + int acl_produce; + int synchronize_set = 0, write_owner_set = 0; + int delete_set = 0, write_attrs_set = 0; + int read_named_set = 0, write_named_set = 0; + + acl_produce = (ACL_SYNCHRONIZE_SET_ALLOW | + ACL_WRITE_ATTRS_OWNER_SET_ALLOW | + ACL_WRITE_ATTRS_WRITER_SET_DENY); + + if (isallow) { + synchronize_set = ACL_SYNCHRONIZE_SET_ALLOW; + write_owner_set = ACL_WRITE_OWNER_SET_ALLOW; + delete_set = ACL_DELETE_SET_ALLOW; + if (hasreadperm) + read_named_set = ACL_READ_NAMED_READER_SET_ALLOW; + if (haswriteperm) + write_named_set = ACL_WRITE_NAMED_WRITER_SET_ALLOW; + if (isowner) + write_attrs_set = ACL_WRITE_ATTRS_OWNER_SET_ALLOW; + else if (haswriteperm) + write_attrs_set = ACL_WRITE_ATTRS_WRITER_SET_ALLOW; + } else { + + synchronize_set = ACL_SYNCHRONIZE_SET_DENY; + write_owner_set = ACL_WRITE_OWNER_SET_DENY; + delete_set = ACL_DELETE_SET_DENY; + if (hasreadperm) + read_named_set = ACL_READ_NAMED_READER_SET_DENY; + if (haswriteperm) + write_named_set = ACL_WRITE_NAMED_WRITER_SET_DENY; + if (isowner) + write_attrs_set = ACL_WRITE_ATTRS_OWNER_SET_DENY; + else if (haswriteperm) + write_attrs_set = ACL_WRITE_ATTRS_WRITER_SET_DENY; + else + /* + * If the entity is not the owner and does not + * have write permissions ACE_WRITE_ATTRIBUTES will + * always go in the DENY ACE. + */ + access_mask |= ACE_WRITE_ATTRIBUTES; + } + + if (acl_produce & synchronize_set) + access_mask |= ACE_SYNCHRONIZE; + if (acl_produce & write_owner_set) + access_mask |= ACE_WRITE_OWNER; + if (acl_produce & delete_set) + access_mask |= ACE_DELETE; + if (acl_produce & write_attrs_set) + access_mask |= ACE_WRITE_ATTRIBUTES; + if (acl_produce & read_named_set) + access_mask |= ACE_READ_NAMED_ATTRS; + if (acl_produce & write_named_set) + access_mask |= ACE_WRITE_NAMED_ATTRS; + + return (access_mask); +} + +/* + * Given an mode_t, convert it into an access_mask as used + * by nfsace, assuming aclent_t -> nfsace semantics. + */ +static uint32_t +mode_to_ace_access(mode_t mode, boolean_t isdir, int isowner, int isallow) +{ + uint32_t access = 0; + int haswriteperm = 0; + int hasreadperm = 0; + + if (isallow) { + haswriteperm = (mode & S_IWOTH); + hasreadperm = (mode & S_IROTH); + } else { + haswriteperm = !(mode & S_IWOTH); + hasreadperm = !(mode & S_IROTH); + } + + /* + * The following call takes care of correctly setting the following + * mask bits in the access_mask: + * ACE_SYNCHRONIZE, ACE_WRITE_OWNER, ACE_DELETE, + * ACE_WRITE_ATTRIBUTES, ACE_WRITE_NAMED_ATTRS, ACE_READ_NAMED_ATTRS + */ + access = access_mask_set(haswriteperm, hasreadperm, isowner, isallow); + + if (isallow) { + access |= ACE_READ_ACL | ACE_READ_ATTRIBUTES; + if (isowner) + access |= ACE_WRITE_ACL; + } else { + if (! isowner) + access |= ACE_WRITE_ACL; + } + + /* read */ + if (mode & S_IROTH) { + access |= ACE_READ_DATA; + } + /* write */ + if (mode & S_IWOTH) { + access |= ACE_WRITE_DATA | + ACE_APPEND_DATA; + if (isdir) + access |= ACE_DELETE_CHILD; + } + /* exec */ + if (mode & S_IXOTH) { + access |= ACE_EXECUTE; + } + + return (access); +} + +/* + * Given an nfsace (presumably an ALLOW entry), make a + * corresponding DENY entry at the address given. + */ +static void +ace_make_deny(ace_t *allow, ace_t *deny, int isdir, int isowner) +{ + (void) memcpy(deny, allow, sizeof (ace_t)); + + deny->a_who = allow->a_who; + + deny->a_type = ACE_ACCESS_DENIED_ACE_TYPE; + deny->a_access_mask ^= ACE_POSIX_SUPPORTED_BITS; + if (isdir) + deny->a_access_mask ^= ACE_DELETE_CHILD; + + deny->a_access_mask &= ~(ACE_SYNCHRONIZE | ACE_WRITE_OWNER | + ACE_DELETE | ACE_WRITE_ATTRIBUTES | ACE_READ_NAMED_ATTRS | + ACE_WRITE_NAMED_ATTRS); + deny->a_access_mask |= access_mask_set((allow->a_access_mask & + ACE_WRITE_DATA), (allow->a_access_mask & ACE_READ_DATA), isowner, + B_FALSE); +} +/* + * Make an initial pass over an array of aclent_t's. Gather + * information such as an ACL_MASK (if any), number of users, + * number of groups, and whether the array needs to be sorted. + */ +static int +ln_aent_preprocess(aclent_t *aclent, int n, + int *hasmask, mode_t *mask, + int *numuser, int *numgroup, int *needsort) +{ + int error = 0; + int i; + int curtype = 0; + + *hasmask = 0; + *mask = 07; + *needsort = 0; + *numuser = 0; + *numgroup = 0; + + for (i = 0; i < n; i++) { + if (aclent[i].a_type < curtype) + *needsort = 1; + else if (aclent[i].a_type > curtype) + curtype = aclent[i].a_type; + if (aclent[i].a_type & USER) + (*numuser)++; + if (aclent[i].a_type & (GROUP | GROUP_OBJ)) + (*numgroup)++; + if (aclent[i].a_type & CLASS_OBJ) { + if (*hasmask) { + error = EINVAL; + goto out; + } else { + *hasmask = 1; + *mask = aclent[i].a_perm; + } + } + } + + if ((! *hasmask) && (*numuser + *numgroup > 1)) { + error = EINVAL; + goto out; + } + +out: + return (error); +} + +/* + * Convert an array of aclent_t into an array of nfsace entries, + * following POSIX draft -> nfsv4 conversion semantics as outlined in + * the IETF draft. + */ +static int +ln_aent_to_ace(aclent_t *aclent, int n, ace_t **acepp, int *rescount, int isdir) +{ + int error = 0; + mode_t mask; + int numuser, numgroup, needsort; + int resultsize = 0; + int i, groupi = 0, skip; + ace_t *acep, *result = NULL; + int hasmask; + + error = ln_aent_preprocess(aclent, n, &hasmask, &mask, + &numuser, &numgroup, &needsort); + if (error != 0) + goto out; + + /* allow + deny for each aclent */ + resultsize = n * 2; + if (hasmask) { + /* + * stick extra deny on the group_obj and on each + * user|group for the mask (the group_obj was added + * into the count for numgroup) + */ + resultsize += numuser + numgroup; + /* ... and don't count the mask itself */ + resultsize -= 2; + } + + /* sort the source if necessary */ + if (needsort) + ksort((caddr_t)aclent, n, sizeof (aclent_t), cmp2acls); + + if (cacl_malloc((void **)&result, resultsize * sizeof (ace_t)) != 0) + goto out; + + acep = result; + + for (i = 0; i < n; i++) { + /* + * don't process CLASS_OBJ (mask); mask was grabbed in + * ln_aent_preprocess() + */ + if (aclent[i].a_type & CLASS_OBJ) + continue; + + /* If we need an ACL_MASK emulator, prepend it now */ + if ((hasmask) && + (aclent[i].a_type & (USER | GROUP | GROUP_OBJ))) { + acep->a_type = ACE_ACCESS_DENIED_ACE_TYPE; + acep->a_flags = 0; + if (aclent[i].a_type & GROUP_OBJ) { + acep->a_who = (uid_t)-1; + acep->a_flags |= + (ACE_IDENTIFIER_GROUP|ACE_GROUP); + } else if (aclent[i].a_type & USER) { + acep->a_who = aclent[i].a_id; + } else { + acep->a_who = aclent[i].a_id; + acep->a_flags |= ACE_IDENTIFIER_GROUP; + } + if (aclent[i].a_type & ACL_DEFAULT) { + acep->a_flags |= ACE_INHERIT_ONLY_ACE | + ACE_FILE_INHERIT_ACE | + ACE_DIRECTORY_INHERIT_ACE; + } + /* + * Set the access mask for the prepended deny + * ace. To do this, we invert the mask (found + * in ln_aent_preprocess()) then convert it to an + * DENY ace access_mask. + */ + acep->a_access_mask = mode_to_ace_access((mask ^ 07), + isdir, 0, 0); + acep += 1; + } + + /* handle a_perm -> access_mask */ + acep->a_access_mask = mode_to_ace_access(aclent[i].a_perm, + isdir, aclent[i].a_type & USER_OBJ, 1); + + /* emulate a default aclent */ + if (aclent[i].a_type & ACL_DEFAULT) { + acep->a_flags |= ACE_INHERIT_ONLY_ACE | + ACE_FILE_INHERIT_ACE | + ACE_DIRECTORY_INHERIT_ACE; + } + + /* + * handle a_perm and a_id + * + * this must be done last, since it involves the + * corresponding deny aces, which are handled + * differently for each different a_type. + */ + if (aclent[i].a_type & USER_OBJ) { + acep->a_who = (uid_t)-1; + acep->a_flags |= ACE_OWNER; + ace_make_deny(acep, acep + 1, isdir, B_TRUE); + acep += 2; + } else if (aclent[i].a_type & USER) { + acep->a_who = aclent[i].a_id; + ace_make_deny(acep, acep + 1, isdir, B_FALSE); + acep += 2; + } else if (aclent[i].a_type & (GROUP_OBJ | GROUP)) { + if (aclent[i].a_type & GROUP_OBJ) { + acep->a_who = (uid_t)-1; + acep->a_flags |= ACE_GROUP; + } else { + acep->a_who = aclent[i].a_id; + } + acep->a_flags |= ACE_IDENTIFIER_GROUP; + /* + * Set the corresponding deny for the group ace. + * + * The deny aces go after all of the groups, unlike + * everything else, where they immediately follow + * the allow ace. + * + * We calculate "skip", the number of slots to + * skip ahead for the deny ace, here. + * + * The pattern is: + * MD1 A1 MD2 A2 MD3 A3 D1 D2 D3 + * thus, skip is + * (2 * numgroup) - 1 - groupi + * (2 * numgroup) to account for MD + A + * - 1 to account for the fact that we're on the + * access (A), not the mask (MD) + * - groupi to account for the fact that we have + * passed up groupi number of MD's. + */ + skip = (2 * numgroup) - 1 - groupi; + ace_make_deny(acep, acep + skip, isdir, B_FALSE); + /* + * If we just did the last group, skip acep past + * all of the denies; else, just move ahead one. + */ + if (++groupi >= numgroup) + acep += numgroup + 1; + else + acep += 1; + } else if (aclent[i].a_type & OTHER_OBJ) { + acep->a_who = (uid_t)-1; + acep->a_flags |= ACE_EVERYONE; + ace_make_deny(acep, acep + 1, isdir, B_FALSE); + acep += 2; + } else { + error = EINVAL; + goto out; + } + } + + *acepp = result; + *rescount = resultsize; + +out: + if (error != 0) { + if ((result != NULL) && (resultsize > 0)) { + cacl_free(result, resultsize * sizeof (ace_t)); + } + } + + return (error); +} + +static int +convert_aent_to_ace(aclent_t *aclentp, int aclcnt, boolean_t isdir, + ace_t **retacep, int *retacecnt) +{ + ace_t *acep; + ace_t *dfacep; + int acecnt = 0; + int dfacecnt = 0; + int dfaclstart = 0; + int dfaclcnt = 0; + aclent_t *aclp; + int i; + int error; + int acesz, dfacesz; + + ksort((caddr_t)aclentp, aclcnt, sizeof (aclent_t), cmp2acls); + + for (i = 0, aclp = aclentp; i < aclcnt; aclp++, i++) { + if (aclp->a_type & ACL_DEFAULT) + break; + } + + if (i < aclcnt) { + dfaclstart = i; + dfaclcnt = aclcnt - i; + } + + if (dfaclcnt && !isdir) { + return (EINVAL); + } + + error = ln_aent_to_ace(aclentp, i, &acep, &acecnt, isdir); + if (error) + return (error); + + if (dfaclcnt) { + error = ln_aent_to_ace(&aclentp[dfaclstart], dfaclcnt, + &dfacep, &dfacecnt, isdir); + if (error) { + if (acep) { + cacl_free(acep, acecnt * sizeof (ace_t)); + } + return (error); + } + } + + if (dfacecnt != 0) { + acesz = sizeof (ace_t) * acecnt; + dfacesz = sizeof (ace_t) * dfacecnt; + acep = cacl_realloc(acep, acesz, acesz + dfacesz); + if (acep == NULL) + return (ENOMEM); + if (dfaclcnt) { + (void) memcpy(acep + acecnt, dfacep, dfacesz); + } + } + if (dfaclcnt) + cacl_free(dfacep, dfacecnt * sizeof (ace_t)); + + *retacecnt = acecnt + dfacecnt; + *retacep = acep; + return (0); +} + +static int +ace_mask_to_mode(uint32_t mask, o_mode_t *modep, boolean_t isdir) +{ + int error = 0; + o_mode_t mode = 0; + uint32_t bits, wantbits; + + /* read */ + if (mask & ACE_READ_DATA) + mode |= S_IROTH; + + /* write */ + wantbits = (ACE_WRITE_DATA | ACE_APPEND_DATA); + if (isdir) + wantbits |= ACE_DELETE_CHILD; + bits = mask & wantbits; + if (bits != 0) { + if (bits != wantbits) { + error = ENOTSUP; + goto out; + } + mode |= S_IWOTH; + } + + /* exec */ + if (mask & ACE_EXECUTE) { + mode |= S_IXOTH; + } + + *modep = mode; + +out: + return (error); +} + +static void +acevals_init(acevals_t *vals, uid_t key) +{ + bzero(vals, sizeof (*vals)); + vals->allowed = ACE_MASK_UNDEFINED; + vals->denied = ACE_MASK_UNDEFINED; + vals->mask = ACE_MASK_UNDEFINED; + vals->key = key; +} + +static void +ace_list_init(ace_list_t *al, int dfacl_flag) +{ + acevals_init(&al->user_obj, NULL); + acevals_init(&al->group_obj, NULL); + acevals_init(&al->other_obj, NULL); + al->numusers = 0; + al->numgroups = 0; + al->acl_mask = 0; + al->hasmask = 0; + al->state = ace_unused; + al->seen = 0; + al->dfacl_flag = dfacl_flag; +} + +/* + * Find or create an acevals holder for a given id and avl tree. + * + * Note that only one thread will ever touch these avl trees, so + * there is no need for locking. + */ +static acevals_t * +acevals_find(ace_t *ace, avl_tree_t *avl, int *num) +{ + acevals_t key, *rc; + avl_index_t where; + + key.key = ace->a_who; + rc = avl_find(avl, &key, &where); + if (rc != NULL) + return (rc); + + /* this memory is freed by ln_ace_to_aent()->ace_list_free() */ + if (cacl_malloc((void **)&rc, sizeof (acevals_t)) != 0) + return (NULL); + + acevals_init(rc, ace->a_who); + avl_insert(avl, rc, where); + (*num)++; + + return (rc); +} + +static int +access_mask_check(ace_t *acep, int mask_bit, int isowner) +{ + int set_deny, err_deny; + int set_allow, err_allow; + int acl_consume; + int haswriteperm, hasreadperm; + + if (acep->a_type == ACE_ACCESS_DENIED_ACE_TYPE) { + haswriteperm = (acep->a_access_mask & ACE_WRITE_DATA) ? 0 : 1; + hasreadperm = (acep->a_access_mask & ACE_READ_DATA) ? 0 : 1; + } else { + haswriteperm = (acep->a_access_mask & ACE_WRITE_DATA) ? 1 : 0; + hasreadperm = (acep->a_access_mask & ACE_READ_DATA) ? 1 : 0; + } + + acl_consume = (ACL_SYNCHRONIZE_ERR_DENY | + ACL_DELETE_ERR_DENY | + ACL_WRITE_OWNER_ERR_DENY | + ACL_WRITE_OWNER_ERR_ALLOW | + ACL_WRITE_ATTRS_OWNER_SET_ALLOW | + ACL_WRITE_ATTRS_OWNER_ERR_DENY | + ACL_WRITE_ATTRS_WRITER_SET_DENY | + ACL_WRITE_ATTRS_WRITER_ERR_ALLOW | + ACL_WRITE_NAMED_WRITER_ERR_DENY | + ACL_READ_NAMED_READER_ERR_DENY); + + if (mask_bit == ACE_SYNCHRONIZE) { + set_deny = ACL_SYNCHRONIZE_SET_DENY; + err_deny = ACL_SYNCHRONIZE_ERR_DENY; + set_allow = ACL_SYNCHRONIZE_SET_ALLOW; + err_allow = ACL_SYNCHRONIZE_ERR_ALLOW; + } else if (mask_bit == ACE_WRITE_OWNER) { + set_deny = ACL_WRITE_OWNER_SET_DENY; + err_deny = ACL_WRITE_OWNER_ERR_DENY; + set_allow = ACL_WRITE_OWNER_SET_ALLOW; + err_allow = ACL_WRITE_OWNER_ERR_ALLOW; + } else if (mask_bit == ACE_DELETE) { + set_deny = ACL_DELETE_SET_DENY; + err_deny = ACL_DELETE_ERR_DENY; + set_allow = ACL_DELETE_SET_ALLOW; + err_allow = ACL_DELETE_ERR_ALLOW; + } else if (mask_bit == ACE_WRITE_ATTRIBUTES) { + if (isowner) { + set_deny = ACL_WRITE_ATTRS_OWNER_SET_DENY; + err_deny = ACL_WRITE_ATTRS_OWNER_ERR_DENY; + set_allow = ACL_WRITE_ATTRS_OWNER_SET_ALLOW; + err_allow = ACL_WRITE_ATTRS_OWNER_ERR_ALLOW; + } else if (haswriteperm) { + set_deny = ACL_WRITE_ATTRS_WRITER_SET_DENY; + err_deny = ACL_WRITE_ATTRS_WRITER_ERR_DENY; + set_allow = ACL_WRITE_ATTRS_WRITER_SET_ALLOW; + err_allow = ACL_WRITE_ATTRS_WRITER_ERR_ALLOW; + } else { + if ((acep->a_access_mask & mask_bit) && + (acep->a_type & ACE_ACCESS_ALLOWED_ACE_TYPE)) { + return (ENOTSUP); + } + return (0); + } + } else if (mask_bit == ACE_READ_NAMED_ATTRS) { + if (!hasreadperm) + return (0); + + set_deny = ACL_READ_NAMED_READER_SET_DENY; + err_deny = ACL_READ_NAMED_READER_ERR_DENY; + set_allow = ACL_READ_NAMED_READER_SET_ALLOW; + err_allow = ACL_READ_NAMED_READER_ERR_ALLOW; + } else if (mask_bit == ACE_WRITE_NAMED_ATTRS) { + if (!haswriteperm) + return (0); + + set_deny = ACL_WRITE_NAMED_WRITER_SET_DENY; + err_deny = ACL_WRITE_NAMED_WRITER_ERR_DENY; + set_allow = ACL_WRITE_NAMED_WRITER_SET_ALLOW; + err_allow = ACL_WRITE_NAMED_WRITER_ERR_ALLOW; + } else { + return (EINVAL); + } + + if (acep->a_type == ACE_ACCESS_DENIED_ACE_TYPE) { + if (acl_consume & set_deny) { + if (!(acep->a_access_mask & mask_bit)) { + return (ENOTSUP); + } + } else if (acl_consume & err_deny) { + if (acep->a_access_mask & mask_bit) { + return (ENOTSUP); + } + } + } else { + /* ACE_ACCESS_ALLOWED_ACE_TYPE */ + if (acl_consume & set_allow) { + if (!(acep->a_access_mask & mask_bit)) { + return (ENOTSUP); + } + } else if (acl_consume & err_allow) { + if (acep->a_access_mask & mask_bit) { + return (ENOTSUP); + } + } + } + return (0); +} + +static int +ace_to_aent_legal(ace_t *acep) +{ + int error = 0; + int isowner; + + /* only ALLOW or DENY */ + if ((acep->a_type != ACE_ACCESS_ALLOWED_ACE_TYPE) && + (acep->a_type != ACE_ACCESS_DENIED_ACE_TYPE)) { + error = ENOTSUP; + goto out; + } + + /* check for invalid flags */ + if (acep->a_flags & ~(ACE_VALID_FLAG_BITS)) { + error = EINVAL; + goto out; + } + + /* some flags are illegal */ + if (acep->a_flags & (ACE_SUCCESSFUL_ACCESS_ACE_FLAG | + ACE_FAILED_ACCESS_ACE_FLAG | + ACE_NO_PROPAGATE_INHERIT_ACE)) { + error = ENOTSUP; + goto out; + } + + /* check for invalid masks */ + if (acep->a_access_mask & ~(ACE_VALID_MASK_BITS)) { + error = EINVAL; + goto out; + } + + if ((acep->a_flags & ACE_OWNER)) { + isowner = 1; + } else { + isowner = 0; + } + + error = access_mask_check(acep, ACE_SYNCHRONIZE, isowner); + if (error) + goto out; + + error = access_mask_check(acep, ACE_WRITE_OWNER, isowner); + if (error) + goto out; + + error = access_mask_check(acep, ACE_DELETE, isowner); + if (error) + goto out; + + error = access_mask_check(acep, ACE_WRITE_ATTRIBUTES, isowner); + if (error) + goto out; + + error = access_mask_check(acep, ACE_READ_NAMED_ATTRS, isowner); + if (error) + goto out; + + error = access_mask_check(acep, ACE_WRITE_NAMED_ATTRS, isowner); + if (error) + goto out; + + /* more detailed checking of masks */ + if (acep->a_type == ACE_ACCESS_ALLOWED_ACE_TYPE) { + if (! (acep->a_access_mask & ACE_READ_ATTRIBUTES)) { + error = ENOTSUP; + goto out; + } + if ((acep->a_access_mask & ACE_WRITE_DATA) && + (! (acep->a_access_mask & ACE_APPEND_DATA))) { + error = ENOTSUP; *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201207011455.q61EtapK008220>