예제 #1
0
/*
 * XDR loopback unix auth parameters.
 * NOTE: this is an XDR_ENCODE only routine.
 */
bool_t
xdr_authloopback(XDR *xdrs)
{
	uid_t uid;
	gid_t gid;
	int len;
	caddr_t groups;
	char *name = uts_nodename();
	struct cred *cr;
	time_t now;

	if (xdrs->x_op != XDR_ENCODE)
		return (FALSE);

	cr = CRED();
	uid = crgetuid(cr);
	gid = crgetgid(cr);
	len = crgetngroups(cr);
	groups = (caddr_t)crgetgroups(cr);
	now = gethrestime_sec();
	if (xdr_uint32(xdrs, (uint32_t *)&now) &&
	    xdr_string(xdrs, &name, MAX_MACHINE_NAME) &&
	    xdr_uid_t(xdrs, &uid) &&
	    xdr_gid_t(xdrs, &gid) &&
	    xdr_array(xdrs, &groups, (uint_t *)&len, NGRPS_LOOPBACK,
	    sizeof (int), (xdrproc_t)xdr_int))
		return (TRUE);
	return (FALSE);
}
예제 #2
0
/*
 * Load all permissions user based on cred belongs to.
 */
static void
dsl_load_user_sets(objset_t *mos, uint64_t zapobj, avl_tree_t *avl,
    char checkflag, cred_t *cr)
{
	const	gid_t *gids;
	int	ngids, i;
	uint64_t id;

	id = crgetuid(cr);
	(void) dsl_load_sets(mos, zapobj,
	    ZFS_DELEG_USER_SETS, checkflag, &id, avl);

	id = crgetgid(cr);
	(void) dsl_load_sets(mos, zapobj,
	    ZFS_DELEG_GROUP_SETS, checkflag, &id, avl);

	(void) dsl_load_sets(mos, zapobj,
	    ZFS_DELEG_EVERYONE_SETS, checkflag, NULL, avl);

	ngids = crgetngroups(cr);
	gids = crgetgroups(cr);
	for (i = 0; i != ngids; i++) {
		id = gids[i];
		(void) dsl_load_sets(mos, zapobj,
		    ZFS_DELEG_GROUP_SETS, checkflag, &id, avl);
	}
}
예제 #3
0
파일: zfs_fuid.c 프로젝트: glycerine/zfs
uid_t
zfs_fuid_map_id(zfsvfs_t *zfsvfs, uint64_t fuid,
    cred_t *cr, zfs_fuid_type_t type)
{
#ifdef HAVE_ZPL
	uint32_t index = FUID_INDEX(fuid);
	const char *domain;
	uid_t id;

	if (index == 0)
		return (fuid);

	domain = zfs_fuid_find_by_idx(zfsvfs, index);
	ASSERT(domain != NULL);

	if (type == ZFS_OWNER || type == ZFS_ACE_USER) {
		(void) kidmap_getuidbysid(crgetzone(cr), domain,
		    FUID_RID(fuid), &id);
	} else {
		(void) kidmap_getgidbysid(crgetzone(cr), domain,
		    FUID_RID(fuid), &id);
	}
	return (id);
#endif
	if(type == ZFS_OWNER || type == ZFS_ACE_USER)
		return (crgetuid(cr));
	else
		return (crgetgid(cr));

}
예제 #4
0
/*
 * Create a file system FUID, based on information in the users cred
 */
uint64_t
zfs_fuid_create_cred(zfsvfs_t *zfsvfs, zfs_fuid_type_t type,
    dmu_tx_t *tx, cred_t *cr, zfs_fuid_info_t **fuidp)
{
	uint64_t	idx;
	ksid_t		*ksid;
	uint32_t	rid;
	char 		*kdomain;
	const char	*domain;
	uid_t		id;

	VERIFY(type == ZFS_OWNER || type == ZFS_GROUP);

	if (type == ZFS_OWNER)
		id = crgetuid(cr);
	else
		id = crgetgid(cr);

	if (!zfsvfs->z_use_fuids || !IS_EPHEMERAL(id))
		return ((uint64_t)id);

	ksid = crgetsid(cr, (type == ZFS_OWNER) ? KSID_OWNER : KSID_GROUP);

	VERIFY(ksid != NULL);
	rid = ksid_getrid(ksid);
	domain = ksid_getdomain(ksid);

	idx = zfs_fuid_find_by_domain(zfsvfs, domain, &kdomain, tx);

	zfs_fuid_node_add(fuidp, kdomain, rid, idx, id, type);

	return (FUID_ENCODE(idx, rid));
}
예제 #5
0
static int
splat_cred_test1(struct file *file, void *arg)
{
	char str[GROUP_STR_SIZE];
	uid_t uid, ruid, suid;
	gid_t gid, rgid, sgid, *groups;
	int ngroups, i, count = 0;

	uid  = crgetuid(CRED());
	ruid = crgetruid(CRED());
	suid = crgetsuid(CRED());

	gid  = crgetgid(CRED());
	rgid = crgetrgid(CRED());
	sgid = crgetsgid(CRED());

	crhold(CRED());
	ngroups = crgetngroups(CRED());
	groups  = crgetgroups(CRED());

	memset(str, 0, GROUP_STR_SIZE);
	for (i = 0; i < ngroups; i++) {
		count += sprintf(str + count, "%d ", groups[i]);

		if (count > (GROUP_STR_SIZE - GROUP_STR_REDZONE)) {
			splat_vprint(file, SPLAT_CRED_TEST1_NAME,
				     "Failed too many group entries for temp "
				     "buffer: %d, %s\n", ngroups, str);
			return -ENOSPC;
		}
	}

	crfree(CRED());

	splat_vprint(file, SPLAT_CRED_TEST1_NAME,
		     "uid: %d ruid: %d suid: %d "
		     "gid: %d rgid: %d sgid: %d\n",
		     uid, ruid, suid, gid, rgid, sgid);
	splat_vprint(file, SPLAT_CRED_TEST1_NAME,
		     "ngroups: %d groups: %s\n", ngroups, str);

	if (uid || ruid || suid || gid || rgid || sgid) {
		splat_vprint(file, SPLAT_CRED_TEST1_NAME,
			     "Failed expected all uids+gids to be %d\n", 0);
		return -EIDRM;
	}

	if (ngroups > NGROUPS_MAX) {
		splat_vprint(file, SPLAT_CRED_TEST1_NAME,
			     "Failed ngroups must not exceed NGROUPS_MAX: "
			     "%d > %d\n", ngroups, NGROUPS_MAX);
		return -EIDRM;
	}

	splat_vprint(file, SPLAT_CRED_TEST1_NAME,
		     "Success sane CRED(): %d\n", 0);

        return 0;
} /* splat_cred_test1() */
예제 #6
0
int
zfs_make_xattrdir(znode_t *zp, vattr_t *vap, vnode_t **xvpp, cred_t *cr)
{
	zfsvfs_t *zfsvfs = zp->z_zfsvfs;
	znode_t *xzp;
	dmu_tx_t *tx;
	int error;
	zfs_fuid_info_t *fuidp = NULL;

	*xvpp = NULL;

	/*
	 * In FreeBSD, access checking for creating an EA is being done
	 * in zfs_setextattr(),
	 */
#ifndef __FreeBSD__
	if (error = zfs_zaccess(zp, ACE_WRITE_NAMED_ATTRS, 0, B_FALSE, cr))
		return (error);
#endif

	tx = dmu_tx_create(zfsvfs->z_os);
	dmu_tx_hold_bonus(tx, zp->z_id);
	dmu_tx_hold_zap(tx, DMU_NEW_OBJECT, FALSE, NULL);
	if (IS_EPHEMERAL(crgetuid(cr)) || IS_EPHEMERAL(crgetgid(cr))) {
		if (zfsvfs->z_fuid_obj == 0) {
			dmu_tx_hold_bonus(tx, DMU_NEW_OBJECT);
			dmu_tx_hold_write(tx, DMU_NEW_OBJECT, 0,
			    FUID_SIZE_ESTIMATE(zfsvfs));
			dmu_tx_hold_zap(tx, MASTER_NODE_OBJ, FALSE, NULL);
		} else {
			dmu_tx_hold_bonus(tx, zfsvfs->z_fuid_obj);
			dmu_tx_hold_write(tx, zfsvfs->z_fuid_obj, 0,
			    FUID_SIZE_ESTIMATE(zfsvfs));
		}
	}
	error = dmu_tx_assign(tx, zfsvfs->z_assign);
	if (error) {
		if (error == ERESTART && zfsvfs->z_assign == TXG_NOWAIT)
			dmu_tx_wait(tx);
		dmu_tx_abort(tx);
		return (error);
	}
	zfs_mknode(zp, vap, tx, cr, IS_XATTR, &xzp, 0, NULL, &fuidp);
	ASSERT(xzp->z_phys->zp_parent == zp->z_id);
	dmu_buf_will_dirty(zp->z_dbuf, tx);
	zp->z_phys->zp_xattr = xzp->z_id;

	(void) zfs_log_create(zfsvfs->z_log, tx, TX_MKXATTR, zp,
	    xzp, "", NULL, fuidp, vap);
	if (fuidp)
		zfs_fuid_info_free(fuidp);
	dmu_tx_commit(tx);

	*xvpp = ZTOV(xzp);

	return (0);
}
예제 #7
0
파일: zfs_fuid.c 프로젝트: glycerine/zfs
/*
 * Create a file system FUID, based on information in the users cred
 *
 * If cred contains KSID_OWNER then it should be used to determine
 * the uid otherwise cred's uid will be used. By default cred's gid
 * is used unless it's an ephemeral ID in which case KSID_GROUP will
 * be used if it exists.
 */
uint64_t
zfs_fuid_create_cred(zfsvfs_t *zfsvfs, zfs_fuid_type_t type,
    cred_t *cr, zfs_fuid_info_t **fuidp)
{
	uint64_t	idx;
	ksid_t		*ksid;
	uint32_t	rid;
	char 		*kdomain;
	const char	*domain;
	uid_t		id;

	VERIFY(type == ZFS_OWNER || type == ZFS_GROUP);

	ksid = crgetsid(cr, (type == ZFS_OWNER) ? KSID_OWNER : KSID_GROUP);

	if (!zfsvfs->z_use_fuids || (ksid == NULL)) {
		id = (type == ZFS_OWNER) ? crgetuid(cr) : crgetgid(cr);

		if (IS_EPHEMERAL(id))
			return ((type == ZFS_OWNER) ? UID_NOBODY : GID_NOBODY);

		return ((uint64_t)id);
	}

	/*
	 * ksid is present and FUID is supported
	 */
	id = (type == ZFS_OWNER) ? ksid_getid(ksid) : crgetgid(cr);

	if (!IS_EPHEMERAL(id))
		return ((uint64_t)id);

	if (type == ZFS_GROUP)
		id = ksid_getid(ksid);

	rid = ksid_getrid(ksid);
	domain = ksid_getdomain(ksid);

	idx = zfs_fuid_find_by_domain(zfsvfs, domain, &kdomain, B_TRUE);

	zfs_fuid_node_add(fuidp, kdomain, rid, idx, id, type);

	return (FUID_ENCODE(idx, rid));
}
예제 #8
0
int
zfs_create_share_dir(zfs_sb_t *zsb, dmu_tx_t *tx)
{
#ifdef HAVE_SMB_SHARE
	zfs_acl_ids_t acl_ids;
	vattr_t vattr;
	znode_t *sharezp;
	vnode_t *vp;
	znode_t *zp;
	int error;

	vattr.va_mask = AT_MODE|AT_UID|AT_GID|AT_TYPE;
	vattr.va_mode = S_IFDIR | 0555;
	vattr.va_uid = crgetuid(kcred);
	vattr.va_gid = crgetgid(kcred);

	sharezp = kmem_cache_alloc(znode_cache, KM_SLEEP);
	sharezp->z_moved = 0;
	sharezp->z_unlinked = 0;
	sharezp->z_atime_dirty = 0;
	sharezp->z_zfsvfs = zfsvfs;
	sharezp->z_is_sa = zfsvfs->z_use_sa;

	vp = ZTOV(sharezp);
	vn_reinit(vp);
	vp->v_type = VDIR;

	VERIFY(0 == zfs_acl_ids_create(sharezp, IS_ROOT_NODE, &vattr,
	    kcred, NULL, &acl_ids));
	zfs_mknode(sharezp, &vattr, tx, kcred, IS_ROOT_NODE, &zp, &acl_ids);
	ASSERT3P(zp, ==, sharezp);
	ASSERT(!vn_in_dnlc(ZTOV(sharezp))); /* not valid to move */
	POINTER_INVALIDATE(&sharezp->z_zfsvfs);
	error = zap_add(zfsvfs->z_os, MASTER_NODE_OBJ,
	    ZFS_SHARES_DIR, 8, 1, &sharezp->z_id, tx);
	zfsvfs->z_shares_dir = sharezp->z_id;

	zfs_acl_ids_free(&acl_ids);
	// ZTOV(sharezp)->v_count = 0;
	sa_handle_destroy(sharezp->z_sa_hdl);
	kmem_cache_free(znode_cache, sharezp);

	return (error);
#else
	return (0);
#endif /* HAVE_SMB_SHARE */
}
예제 #9
0
파일: dsl_deleg.c 프로젝트: ph7/zfs
/*
 * check a specified user/group for a requested permission
 */
static int
dsl_check_user_access(objset_t *mos, uint64_t zapobj, const char *perm,
    int checkflag, cred_t *cr)
{
	//const	gid_t *gids;
    //	int	ngids;
	//int	i;
	uint64_t id;

	/* check for user */
	id = crgetuid(cr);
	if (dsl_check_access(mos, zapobj,
	    ZFS_DELEG_USER, checkflag, &id, perm) == 0)
		return (0);

	/* check for users primary group */
	id = crgetgid(cr);
	if (dsl_check_access(mos, zapobj,
	    ZFS_DELEG_GROUP, checkflag, &id, perm) == 0)
		return (0);

	/* check for everyone entry */
	id = -1;
	if (dsl_check_access(mos, zapobj,
	    ZFS_DELEG_EVERYONE, checkflag, &id, perm) == 0)
		return (0);

	/* check each supplemental group user is a member of */
/*XXX NOEL: get kauth equivs for the below, crgetngroups, crgetgroups*/
#ifndef __APPLE__

	ngids = crgetngroups(cr);
	gids = crgetgroups(cr);
	for (i = 0; i != ngids; i++) {
		id = gids[i];
		if (dsl_check_access(mos, zapobj,
		    ZFS_DELEG_GROUP, checkflag, &id, perm) == 0)
			return (0);
	}

	return (EPERM);
#endif
    return 0;
}
예제 #10
0
/*
 *
 * Cachefs used to know too much about how creds looked; since it's
 * committed to persistent storage, we can't change the layout so
 * it now has a "dl_cred_t" which (unsurprisingly) looks exactly like
 * an old credential.
 *
 * The dst argument needs to point to:
 *		struct dl_cred_t;
 *		<buffer space>			buffer for groups
 *
 * The source is a proper kernel cred_t.
 *
 */
static size_t
copy_cred(cred_t *src, dl_cred_t *dst)
{
	int n;
	const gid_t *sgrp = crgetgroups(src);

	n = MIN(NGROUPS_MAX_DEFAULT, crgetngroups(src));

	/* copy the fixed fields */
	dst->cr_uid = crgetuid(src);
	dst->cr_ruid = crgetruid(src);
	dst->cr_suid = crgetsuid(src);
	dst->cr_gid = crgetgid(src);
	dst->cr_rgid = crgetrgid(src);
	dst->cr_sgid = crgetsgid(src);
	dst->cr_groups[0] = sgrp[0];

	dst->cr_ngroups = n;
	bcopy(sgrp, (void *)(dst + 1), (n - 1) * sizeof (gid_t));
	return (sizeof (dl_cred_t) + (n - 1) * sizeof (gid_t));
}
예제 #11
0
/*
 * check a specified user/group for a requested permission
 */
static int
dsl_check_user_access(objset_t *mos, uint64_t zapobj, const char *perm,
    int checkflag, cred_t *cr)
{
	const	gid_t *gids;
	int	ngids;
	int	i;
	uint64_t id;

	/* check for user */
	id = crgetuid(cr);
	if (dsl_check_access(mos, zapobj,
	    ZFS_DELEG_USER, checkflag, &id, perm) == 0)
		return (0);

	/* check for users primary group */
	id = crgetgid(cr);
	if (dsl_check_access(mos, zapobj,
	    ZFS_DELEG_GROUP, checkflag, &id, perm) == 0)
		return (0);

	/* check for everyone entry */
	id = -1;
	if (dsl_check_access(mos, zapobj,
	    ZFS_DELEG_EVERYONE, checkflag, &id, perm) == 0)
		return (0);

	/* check each supplemental group user is a member of */
	ngids = crgetngroups(cr);
	gids = crgetgroups(cr);
	for (i = 0; i != ngids; i++) {
		id = gids[i];
		if (dsl_check_access(mos, zapobj,
		    ZFS_DELEG_GROUP, checkflag, &id, perm) == 0)
			return (0);
	}

	return (EPERM);
}
예제 #12
0
/*
 * Callup to the mountd to get access information in the kernel.
 */
static bool_t
nfsauth_retrieve(struct exportinfo *exi, char *req_netid, int flavor,
    struct netbuf *addr, int *access, cred_t *clnt_cred, uid_t *srv_uid,
    gid_t *srv_gid, uint_t *srv_gids_cnt, gid_t **srv_gids)
{
	varg_t			  varg = {0};
	nfsauth_res_t		  res = {0};
	XDR			  xdrs;
	size_t			  absz;
	caddr_t			  abuf;
	int			  last = 0;
	door_arg_t		  da;
	door_info_t		  di;
	door_handle_t		  dh;
	uint_t			  ntries = 0;

	/*
	 * No entry in the cache for this client/flavor
	 * so we need to call the nfsauth service in the
	 * mount daemon.
	 */

	varg.vers = V_PROTO;
	varg.arg_u.arg.cmd = NFSAUTH_ACCESS;
	varg.arg_u.arg.areq.req_client.n_len = addr->len;
	varg.arg_u.arg.areq.req_client.n_bytes = addr->buf;
	varg.arg_u.arg.areq.req_netid = req_netid;
	varg.arg_u.arg.areq.req_path = exi->exi_export.ex_path;
	varg.arg_u.arg.areq.req_flavor = flavor;
	varg.arg_u.arg.areq.req_clnt_uid = crgetuid(clnt_cred);
	varg.arg_u.arg.areq.req_clnt_gid = crgetgid(clnt_cred);
	varg.arg_u.arg.areq.req_clnt_gids.len = crgetngroups(clnt_cred);
	varg.arg_u.arg.areq.req_clnt_gids.val = (gid_t *)crgetgroups(clnt_cred);

	DTRACE_PROBE1(nfsserv__func__nfsauth__varg, varg_t *, &varg);

	/*
	 * Setup the XDR stream for encoding the arguments. Notice that
	 * in addition to the args having variable fields (req_netid and
	 * req_path), the argument data structure is itself versioned,
	 * so we need to make sure we can size the arguments buffer
	 * appropriately to encode all the args. If we can't get sizing
	 * info _or_ properly encode the arguments, there's really no
	 * point in continuting, so we fail the request.
	 */
	if ((absz = xdr_sizeof(xdr_varg, &varg)) == 0) {
		*access = NFSAUTH_DENIED;
		return (FALSE);
	}

	abuf = (caddr_t)kmem_alloc(absz, KM_SLEEP);
	xdrmem_create(&xdrs, abuf, absz, XDR_ENCODE);
	if (!xdr_varg(&xdrs, &varg)) {
		XDR_DESTROY(&xdrs);
		goto fail;
	}
	XDR_DESTROY(&xdrs);

	/*
	 * Prepare the door arguments
	 *
	 * We don't know the size of the message the daemon
	 * will pass back to us.  By setting rbuf to NULL,
	 * we force the door code to allocate a buf of the
	 * appropriate size.  We must set rsize > 0, however,
	 * else the door code acts as if no response was
	 * expected and doesn't pass the data to us.
	 */
	da.data_ptr = (char *)abuf;
	da.data_size = absz;
	da.desc_ptr = NULL;
	da.desc_num = 0;
	da.rbuf = NULL;
	da.rsize = 1;

retry:
	mutex_enter(&mountd_lock);
	dh = mountd_dh;
	if (dh != NULL)
		door_ki_hold(dh);
	mutex_exit(&mountd_lock);

	if (dh == NULL) {
		/*
		 * The rendezvous point has not been established yet!
		 * This could mean that either mountd(1m) has not yet
		 * been started or that _this_ routine nuked the door
		 * handle after receiving an EINTR for a REVOKED door.
		 *
		 * Returning NFSAUTH_DROP will cause the NFS client
		 * to retransmit the request, so let's try to be more
		 * rescillient and attempt for ntries before we bail.
		 */
		if (++ntries % NFSAUTH_DR_TRYCNT) {
			delay(hz);
			goto retry;
		}

		kmem_free(abuf, absz);

		sys_log("nfsauth: mountd has not established door");
		*access = NFSAUTH_DROP;
		return (FALSE);
	}

	ntries = 0;

	/*
	 * Now that we've got what we need, place the call.
	 */
	switch (door_ki_upcall_limited(dh, &da, NULL, SIZE_MAX, 0)) {
	case 0:				/* Success */
		door_ki_rele(dh);

		if (da.data_ptr == NULL && da.data_size == 0) {
			/*
			 * The door_return that contained the data
			 * failed! We're here because of the 2nd
			 * door_return (w/o data) such that we can
			 * get control of the thread (and exit
			 * gracefully).
			 */
			DTRACE_PROBE1(nfsserv__func__nfsauth__door__nil,
			    door_arg_t *, &da);
			goto fail;
		}

		break;

	case EAGAIN:
		/*
		 * Server out of resources; back off for a bit
		 */
		door_ki_rele(dh);
		delay(hz);
		goto retry;
		/* NOTREACHED */

	case EINTR:
		if (!door_ki_info(dh, &di)) {
			door_ki_rele(dh);

			if (di.di_attributes & DOOR_REVOKED) {
				/*
				 * The server barfed and revoked
				 * the (existing) door on us; we
				 * want to wait to give smf(5) a
				 * chance to restart mountd(1m)
				 * and establish a new door handle.
				 */
				mutex_enter(&mountd_lock);
				if (dh == mountd_dh) {
					door_ki_rele(mountd_dh);
					mountd_dh = NULL;
				}
				mutex_exit(&mountd_lock);
				delay(hz);
				goto retry;
			}
			/*
			 * If the door was _not_ revoked on us,
			 * then more than likely we took an INTR,
			 * so we need to fail the operation.
			 */
			goto fail;
		}
		/*
		 * The only failure that can occur from getting
		 * the door info is EINVAL, so we let the code
		 * below handle it.
		 */
		/* FALLTHROUGH */

	case EBADF:
	case EINVAL:
	default:
		/*
		 * If we have a stale door handle, give smf a last
		 * chance to start it by sleeping for a little bit.
		 * If we're still hosed, we'll fail the call.
		 *
		 * Since we're going to reacquire the door handle
		 * upon the retry, we opt to sleep for a bit and
		 * _not_ to clear mountd_dh. If mountd restarted
		 * and was able to set mountd_dh, we should see
		 * the new instance; if not, we won't get caught
		 * up in the retry/DELAY loop.
		 */
		door_ki_rele(dh);
		if (!last) {
			delay(hz);
			last++;
			goto retry;
		}
		sys_log("nfsauth: stale mountd door handle");
		goto fail;
	}
예제 #13
0
id_t
getmyid(idtype_t idtype)
{
	proc_t	*pp;
	uid_t uid;
	gid_t gid;
	pid_t sid;

	pp = ttoproc(curthread);

	switch (idtype) {
	case P_LWPID:
		return (curthread->t_tid);

	case P_PID:
		return (pp->p_pid);

	case P_PPID:
		return (pp->p_ppid);

	case P_PGID:
		return (pp->p_pgrp);

	case P_SID:
		mutex_enter(&pp->p_splock);
		sid = pp->p_sessp->s_sid;
		mutex_exit(&pp->p_splock);
		return (sid);

	case P_TASKID:
		return (pp->p_task->tk_tkid);

	case P_CID:
		return (curthread->t_cid);

	case P_UID:
		mutex_enter(&pp->p_crlock);
		uid = crgetuid(pp->p_cred);
		mutex_exit(&pp->p_crlock);
		return (uid);

	case P_GID:
		mutex_enter(&pp->p_crlock);
		gid = crgetgid(pp->p_cred);
		mutex_exit(&pp->p_crlock);
		return (gid);

	case P_PROJID:
		return (pp->p_task->tk_proj->kpj_id);

	case P_POOLID:
		return (pp->p_pool->pool_id);

	case P_ZONEID:
		return (pp->p_zone->zone_id);

	case P_CTID:
		return (PRCTID(pp));

	case P_ALL:
		/*
		 * The value doesn't matter for P_ALL.
		 */
		return (0);

	default:
		return (-1);
	}
}
예제 #14
0
/*
 * lwpinset returns 1 if the thread pointed to
 * by tp is in the process set specified by psp and is not in
 * the sys scheduling class - otherwise 0 is returned.
 *
 * This function expects to be called with a valid procset_t.
 * The set should be checked using checkprocset() before calling
 * this function.
 */
int
lwpinset(proc_t *pp, procset_t *psp, kthread_t *tp, int *done)
{
	int	loperand = 0;
	int	roperand = 0;
	int	lwplinset  = 0;
	int	lwprinset  = 0;

	ASSERT(ttoproc(tp) == pp);

	/*
	 * If process is in the sys class return (0).
	 */
	if (proctot(pp)->t_cid == 0) {
		return (0);
	}

	switch (psp->p_lidtype) {

	case P_LWPID:
		if (tp->t_tid == psp->p_lid)
			lwplinset ++;
		break;

	case P_PID:
		if (pp->p_pid == psp->p_lid)
			loperand++;
		break;

	case P_PPID:
		if (pp->p_ppid == psp->p_lid)
			loperand++;
		break;

	case P_PGID:
		if (pp->p_pgrp == psp->p_lid)
			loperand++;
		break;

	case P_SID:
		mutex_enter(&pp->p_splock);
		if (pp->p_sessp->s_sid == psp->p_lid)
			loperand++;
		mutex_exit(&pp->p_splock);
		break;

	case P_TASKID:
		if (pp->p_task->tk_tkid == psp->p_lid)
			loperand++;
		break;

	case P_CID:
		if (tp->t_cid == psp->p_lid)
			loperand++;
		break;

	case P_UID:
		mutex_enter(&pp->p_crlock);
		if (crgetuid(pp->p_cred) == psp->p_lid)
			loperand++;
		mutex_exit(&pp->p_crlock);
		break;

	case P_GID:
		mutex_enter(&pp->p_crlock);
		if (crgetgid(pp->p_cred) == psp->p_lid)
			loperand++;
		mutex_exit(&pp->p_crlock);
		break;

	case P_PROJID:
		if (pp->p_task->tk_proj->kpj_id == psp->p_lid)
			loperand++;
		break;

	case P_POOLID:
		if (pp->p_pool->pool_id == psp->p_lid)
			loperand++;
		break;

	case P_ZONEID:
		if (pp->p_zone->zone_id == psp->p_lid)
			loperand++;
		break;

	case P_CTID:
		if (PRCTID(pp) == psp->p_lid)
			loperand++;
		break;

	case P_ALL:
		loperand++;
		break;

	default:
#ifdef DEBUG
		cmn_err(CE_WARN, "lwpinset called with bad set");
		return (0);
#else
		return (0);
#endif
	}

	switch (psp->p_ridtype) {

	case P_LWPID:
		if (tp->t_tid == psp->p_rid)
			lwprinset ++;
		break;

	case P_PID:
		if (pp->p_pid == psp->p_rid)
			roperand++;
		break;

	case P_PPID:
		if (pp->p_ppid == psp->p_rid)
			roperand++;
		break;

	case P_PGID:
		if (pp->p_pgrp == psp->p_rid)
			roperand++;
		break;

	case P_SID:
		mutex_enter(&pp->p_splock);
		if (pp->p_sessp->s_sid == psp->p_rid)
			roperand++;
		mutex_exit(&pp->p_splock);
		break;

	case P_TASKID:
		if (pp->p_task->tk_tkid == psp->p_rid)
			roperand++;
		break;

	case P_CID:
		if (tp->t_cid == psp->p_rid)
			roperand++;
		break;

	case P_UID:
		mutex_enter(&pp->p_crlock);
		if (crgetuid(pp->p_cred) == psp->p_rid)
			roperand++;
		mutex_exit(&pp->p_crlock);
		break;

	case P_GID:
		mutex_enter(&pp->p_crlock);
		if (crgetgid(pp->p_cred) == psp->p_rid)
			roperand++;
		mutex_exit(&pp->p_crlock);
		break;

	case P_PROJID:
		if (pp->p_task->tk_proj->kpj_id == psp->p_rid)
			roperand++;
		break;

	case P_POOLID:
		if (pp->p_pool->pool_id == psp->p_rid)
			roperand++;
		break;

	case P_ZONEID:
		if (pp->p_zone->zone_id == psp->p_rid)
			roperand++;
		break;

	case P_CTID:
		if (PRCTID(pp) == psp->p_rid)
			roperand++;
		break;

	case P_ALL:
		roperand++;
		break;

	default:
#ifdef DEBUG
		cmn_err(CE_WARN, "lwpinset called with bad set");
		return (0);
#else
		return (0);
#endif
	}

	if (lwplinset && lwprinset)
		*done = 1;

	switch (psp->p_op) {

	case POP_DIFF:
		if ((loperand || lwplinset) && !(lwprinset || roperand))
			return (1);
		else
			return (0);

	case POP_AND:
		if ((loperand || lwplinset) && (roperand || lwprinset))
			return (1);
		else
			return (0);

	case POP_OR:
		if (loperand || roperand || lwplinset || lwprinset)
			return (1);
		else
			return (0);

	case POP_XOR:
		if (((loperand || lwplinset) &&
		    !(lwprinset || roperand)) ||
		    ((roperand || lwprinset) &&
		    !(lwplinset || loperand)))
			return (1);
		else
			return (0);

	default:
#ifdef DEBUG
		cmn_err(CE_WARN, "lwpinset called with bad set");
		return (0);
#else
		return (0);
#endif
	}
	/* NOTREACHED */
}
예제 #15
0
/*
 * procinset returns 1 if the process pointed to by pp is in the process
 * set specified by psp, otherwise 0 is returned. If either process set operand
 * has type P_CID and pp refers to a process that is exiting, by which we mean
 * that its p_tlist is NULL, then procinset will return 0. pp's p_lock must be
 * held across the call to this function. The caller should ensure that the
 * process does not belong to the SYS scheduling class.
 *
 * This function expects to be called with a valid procset_t.
 * The set should be checked using checkprocset() before calling
 * this function.
 */
int
procinset(proc_t *pp, procset_t *psp)
{
	int	loperand = 0;
	int	roperand = 0;
	int	lwplinproc = 0;
	int	lwprinproc = 0;
	kthread_t	*tp;

	ASSERT(MUTEX_HELD(&pp->p_lock));

	switch (psp->p_lidtype) {

	case P_LWPID:
		if (pp == ttoproc(curthread))
			if (getlwpptr(psp->p_lid) != NULL)
				lwplinproc++;
		break;

	case P_PID:
		if (pp->p_pid == psp->p_lid)
			loperand++;
		break;

	case P_PPID:
		if (pp->p_ppid == psp->p_lid)
			loperand++;
		break;

	case P_PGID:
		if (pp->p_pgrp == psp->p_lid)
			loperand++;
		break;

	case P_SID:
		mutex_enter(&pp->p_splock);
		if (pp->p_sessp->s_sid == psp->p_lid)
			loperand++;
		mutex_exit(&pp->p_splock);
		break;

	case P_CID:
		tp = proctot(pp);
		if (tp == NULL)
			return (0);
		if (tp->t_cid == psp->p_lid)
			loperand++;
		break;

	case P_TASKID:
		if (pp->p_task->tk_tkid == psp->p_lid)
			loperand++;
		break;

	case P_UID:
		mutex_enter(&pp->p_crlock);
		if (crgetuid(pp->p_cred) == psp->p_lid)
			loperand++;
		mutex_exit(&pp->p_crlock);
		break;

	case P_GID:
		mutex_enter(&pp->p_crlock);
		if (crgetgid(pp->p_cred) == psp->p_lid)
			loperand++;
		mutex_exit(&pp->p_crlock);
		break;

	case P_PROJID:
		if (pp->p_task->tk_proj->kpj_id == psp->p_lid)
			loperand++;
		break;

	case P_POOLID:
		if (pp->p_pool->pool_id == psp->p_lid)
			loperand++;
		break;

	case P_ZONEID:
		if (pp->p_zone->zone_id == psp->p_lid)
			loperand++;
		break;

	case P_CTID:
		if (PRCTID(pp) == psp->p_lid)
			loperand++;
		break;

	case P_ALL:
		loperand++;
		break;

	default:
#ifdef DEBUG
		cmn_err(CE_WARN, "procinset called with bad set");
		return (0);
#else
		return (0);
#endif
	}

	switch (psp->p_ridtype) {

	case P_LWPID:
		if (pp == ttoproc(curthread))
			if (getlwpptr(psp->p_rid) != NULL)
				lwprinproc++;
		break;

	case P_PID:
		if (pp->p_pid == psp->p_rid)
			roperand++;
		break;

	case P_PPID:
		if (pp->p_ppid == psp->p_rid)
			roperand++;
		break;

	case P_PGID:
		if (pp->p_pgrp == psp->p_rid)
			roperand++;
		break;

	case P_SID:
		mutex_enter(&pp->p_splock);
		if (pp->p_sessp->s_sid == psp->p_rid)
			roperand++;
		mutex_exit(&pp->p_splock);
		break;

	case P_TASKID:
		if (pp->p_task->tk_tkid == psp->p_rid)
			roperand++;
		break;

	case P_CID:
		tp = proctot(pp);
		if (tp == NULL)
			return (0);
		if (tp->t_cid == psp->p_rid)
			roperand++;
		break;

	case P_UID:
		mutex_enter(&pp->p_crlock);
		if (crgetuid(pp->p_cred) == psp->p_rid)
			roperand++;
		mutex_exit(&pp->p_crlock);
		break;

	case P_GID:
		mutex_enter(&pp->p_crlock);
		if (crgetgid(pp->p_cred) == psp->p_rid)
			roperand++;
		mutex_exit(&pp->p_crlock);
		break;

	case P_PROJID:
		if (pp->p_task->tk_proj->kpj_id == psp->p_rid)
			roperand++;
		break;

	case P_POOLID:
		if (pp->p_pool->pool_id == psp->p_rid)
			roperand++;
		break;

	case P_ZONEID:
		if (pp->p_zone->zone_id == psp->p_rid)
			roperand++;
		break;

	case P_CTID:
		if (PRCTID(pp) == psp->p_rid)
			roperand++;
		break;

	case P_ALL:
		roperand++;
		break;

	default:
#ifdef DEBUG
		cmn_err(CE_WARN, "procinset called with bad set");
		return (0);
#else
		return (0);
#endif
	}

	switch (psp->p_op) {

	case POP_DIFF:
		if (loperand && !lwprinproc && !roperand)
			return (1);
		else
			return (0);

	case POP_AND:
		if (loperand && roperand)
			return (1);
		else
			return (0);

	case POP_OR:
		if (loperand || roperand)
			return (1);
		else
			return (0);

	case POP_XOR:
		if ((loperand && !lwprinproc && !roperand) ||
		    (roperand && !lwplinproc && !loperand))
			return (1);
		else
			return (0);

	default:
#ifdef DEBUG
		cmn_err(CE_WARN, "procinset called with bad set");
		return (0);
#else
		return (0);
#endif
	}
	/* NOTREACHED */
}
예제 #16
0
파일: zfs_fuid.c 프로젝트: glycerine/zfs
/*
 * Create a file system FUID for an ACL ace
 * or a chown/chgrp of the file.
 * This is similar to zfs_fuid_create_cred, except that
 * we can't find the domain + rid information in the
 * cred.  Instead we have to query Winchester for the
 * domain and rid.
 *
 * During replay operations the domain+rid information is
 * found in the zfs_fuid_info_t that the replay code has
 * attached to the zfsvfs of the file system.
 */
uint64_t
zfs_fuid_create(zfsvfs_t *zfsvfs, uint64_t id, cred_t *cr,
    zfs_fuid_type_t type, zfs_fuid_info_t **fuidpp)
{
#ifdef HAVE_ZPL
	const char *domain;
	char *kdomain;
	uint32_t fuid_idx = FUID_INDEX(id);
	uint32_t rid;
	idmap_stat status;
	uint64_t idx;
	zfs_fuid_t *zfuid = NULL;
	zfs_fuid_info_t *fuidp;

	/*
	 * If POSIX ID, or entry is already a FUID then
	 * just return the id
	 *
	 * We may also be handed an already FUID'ized id via
	 * chmod.
	 */

	if (!zfsvfs->z_use_fuids || !IS_EPHEMERAL(id) || fuid_idx != 0)
		return (id);

	if (zfsvfs->z_replay) {
		fuidp = zfsvfs->z_fuid_replay;

		/*
		 * If we are passed an ephemeral id, but no
		 * fuid_info was logged then return NOBODY.
		 * This is most likely a result of idmap service
		 * not being available.
		 */
		if (fuidp == NULL)
			return (UID_NOBODY);

		switch (type) {
		case ZFS_ACE_USER:
		case ZFS_ACE_GROUP:
			zfuid = list_head(&fuidp->z_fuids);
			rid = FUID_RID(zfuid->z_logfuid);
			idx = FUID_INDEX(zfuid->z_logfuid);
			break;
		case ZFS_OWNER:
			rid = FUID_RID(fuidp->z_fuid_owner);
			idx = FUID_INDEX(fuidp->z_fuid_owner);
			break;
		case ZFS_GROUP:
			rid = FUID_RID(fuidp->z_fuid_group);
			idx = FUID_INDEX(fuidp->z_fuid_group);
			break;
		};
		domain = fuidp->z_domain_table[idx -1];
	} else {
		if (type == ZFS_OWNER || type == ZFS_ACE_USER)
			status = kidmap_getsidbyuid(crgetzone(cr), id,
			    &domain, &rid);
		else
			status = kidmap_getsidbygid(crgetzone(cr), id,
			    &domain, &rid);

		if (status != 0) {
			/*
			 * When returning nobody we will need to
			 * make a dummy fuid table entry for logging
			 * purposes.
			 */
			rid = UID_NOBODY;
			domain = nulldomain;
		}
	}

	idx = zfs_fuid_find_by_domain(zfsvfs, domain, &kdomain, B_TRUE);

	if (!zfsvfs->z_replay)
		zfs_fuid_node_add(fuidpp, kdomain,
		    rid, idx, id, type);
	else if (zfuid != NULL) {
		list_remove(&fuidp->z_fuids, zfuid);
		kmem_free(zfuid, sizeof (zfs_fuid_t));
	}
	return (FUID_ENCODE(idx, rid));
#endif
 /* return cred uid which is set to  acls uid */
        if (type == ZFS_OWNER)
		return crgetuid(cr);
        else
                return crgetgid(cr);
}
예제 #17
0
static bool_t
authkern_marshal(AUTH *auth, XDR *xdrs, struct cred *cr)
{
	char *sercred;
	XDR xdrm;
	struct opaque_auth *cred;
	bool_t ret = FALSE;
	const gid_t *gp, *gpend;
	int gidlen, credsize, namelen, rounded_namelen;
	int32_t *ptr;
	char *nodename = uts_nodename();

	/*
	 * First we try a fast path to get through
	 * this very common operation.
	 */
	gp = crgetgroups(cr);
	gidlen = crgetngroups(cr);
	if (gidlen > NGRPS)
		gidlen = NGRPS;
	gpend = &gp[gidlen-1];

	namelen = (int)strlen(nodename);
	rounded_namelen = RNDUP(namelen);
	credsize = 4 + 4 + rounded_namelen + 4 + 4 + 4 + gidlen * 4;
	ptr = XDR_INLINE(xdrs, 4 + 4 + credsize + 4 + 4);
	if (ptr) {
		/*
		 * We can do the fast path.
		 */
		IXDR_PUT_INT32(ptr, AUTH_UNIX);	/* cred flavor */
		IXDR_PUT_INT32(ptr, credsize);	/* cred len */
		IXDR_PUT_INT32(ptr, gethrestime_sec());
		IXDR_PUT_INT32(ptr, namelen);
		bcopy(nodename, (caddr_t)ptr, namelen);
		if (rounded_namelen - namelen)
			bzero(((caddr_t)ptr) + namelen,
			    rounded_namelen - namelen);
		ptr += rounded_namelen / BYTES_PER_XDR_UNIT;
		IXDR_PUT_INT32(ptr, crgetuid(cr));
		IXDR_PUT_INT32(ptr, crgetgid(cr));
		IXDR_PUT_INT32(ptr, gidlen);
		while (gp <= gpend) {
			IXDR_PUT_INT32(ptr, *gp++);
		}
		IXDR_PUT_INT32(ptr, AUTH_NULL);	/* verf flavor */
		IXDR_PUT_INT32(ptr, 0);	/* verf len */
		return (TRUE);
	}
	sercred = kmem_alloc(MAX_AUTH_BYTES, KM_SLEEP);
	/*
	 * serialize u struct stuff into sercred
	 */
	xdrmem_create(&xdrm, sercred, MAX_AUTH_BYTES, XDR_ENCODE);
	if (!xdr_authkern(&xdrm)) {
		printf("authkern_marshal: xdr_authkern failed\n");
		ret = FALSE;
		goto done;
	}

	/*
	 * Make opaque auth credentials that point at serialized u struct
	 */
	cred = &(auth->ah_cred);
	cred->oa_length = XDR_GETPOS(&xdrm);
	cred->oa_base = sercred;

	/*
	 * serialize credentials and verifiers (null)
	 */
	if ((xdr_opaque_auth(xdrs, &(auth->ah_cred))) &&
	    (xdr_opaque_auth(xdrs, &(auth->ah_verf))))
		ret = TRUE;
	else
		ret = FALSE;
done:
	kmem_free(sercred, MAX_AUTH_BYTES);
	return (ret);
}
예제 #18
0
파일: xmem_dir.c 프로젝트: andreiw/polaris
static int
xdirmakexnode(
	struct xmemnode *dir,
	struct xmount	*xm,
	struct vattr	*va,
	enum	de_op	op,
	struct xmemnode **newnode,
	struct cred	*cred)
{
	struct xmemnode *xp;
	enum vtype	type;

	ASSERT(va != NULL);
	ASSERT(op == DE_CREATE || op == DE_MKDIR);
	if (((va->va_mask & AT_ATIME) && TIMESPEC_OVERFLOW(&va->va_atime)) ||
	    ((va->va_mask & AT_MTIME) && TIMESPEC_OVERFLOW(&va->va_mtime)))
		return (EOVERFLOW);
	type = va->va_type;
	xp = xmem_memalloc(sizeof (struct xmemnode), 1);
	xp->xn_vnode = vn_alloc(KM_SLEEP);
	xmemnode_init(xm, xp, va, cred);
	if (type == VBLK || type == VCHR) {
		xp->xn_vnode->v_rdev = xp->xn_rdev = va->va_rdev;
	} else {
		xp->xn_vnode->v_rdev = xp->xn_rdev = NODEV;
	}
	xp->xn_vnode->v_type = type;
	xp->xn_uid = crgetuid(cred);

	/*
	 * To determine the group-id of the created file:
	 *   1) If the gid is set in the attribute list (non-Sun & pre-4.0
	 *	clients are not likely to set the gid), then use it if
	 *	the process is privileged, belongs to the target group,
	 *	or the group is the same as the parent directory.
	 *   2) If the filesystem was not mounted with the Old-BSD-compatible
	 *	GRPID option, and the directory's set-gid bit is clear,
	 *	then use the process's gid.
	 *   3) Otherwise, set the group-id to the gid of the parent directory.
	 */
	if ((va->va_mask & AT_GID) &&
	    ((va->va_gid == dir->xn_gid) || groupmember(va->va_gid, cred) ||
	    secpolicy_vnode_create_gid(cred) == 0)) {
		xp->xn_gid = va->va_gid;
	} else {
		if (dir->xn_mode & VSGID)
			xp->xn_gid = dir->xn_gid;
		else
			xp->xn_gid = crgetgid(cred);
	}
	/*
	 * If we're creating a directory, and the parent directory has the
	 * set-GID bit set, set it 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.
	 */
	if (dir->xn_mode & VSGID && type == VDIR)
		xp->xn_mode |= VSGID;
	else if ((xp->xn_mode & VSGID) &&
		secpolicy_vnode_setids_setgids(cred, xp->xn_gid) != 0)
			xp->xn_mode &= ~VSGID;

	if (va->va_mask & AT_ATIME)
		xp->xn_atime = va->va_atime;
	if (va->va_mask & AT_MTIME)
		xp->xn_mtime = va->va_mtime;

	if (op == DE_MKDIR)
		xdirinit(dir, xp);

	*newnode = xp;
	return (0);
}
예제 #19
0
void
zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *zplprops, dmu_tx_t *tx)
{
	struct super_block *sb;
	zfs_sb_t	*zsb;
	uint64_t	moid, obj, sa_obj, version;
	uint64_t	sense = ZFS_CASE_SENSITIVE;
	uint64_t	norm = 0;
	nvpair_t	*elem;
	int		error;
	int		i;
	znode_t		*rootzp = NULL;
	vattr_t		vattr;
	znode_t		*zp;
	zfs_acl_ids_t	acl_ids;

	/*
	 * First attempt to create master node.
	 */
	/*
	 * In an empty objset, there are no blocks to read and thus
	 * there can be no i/o errors (which we assert below).
	 */
	moid = MASTER_NODE_OBJ;
	error = zap_create_claim(os, moid, DMU_OT_MASTER_NODE,
	    DMU_OT_NONE, 0, tx);
	ASSERT(error == 0);

	/*
	 * Set starting attributes.
	 */
	version = zfs_zpl_version_map(spa_version(dmu_objset_spa(os)));
	elem = NULL;
	while ((elem = nvlist_next_nvpair(zplprops, elem)) != NULL) {
		/* For the moment we expect all zpl props to be uint64_ts */
		uint64_t val;
		char *name;

		ASSERT(nvpair_type(elem) == DATA_TYPE_UINT64);
		VERIFY(nvpair_value_uint64(elem, &val) == 0);
		name = nvpair_name(elem);
		if (strcmp(name, zfs_prop_to_name(ZFS_PROP_VERSION)) == 0) {
			if (val < version)
				version = val;
		} else {
			error = zap_update(os, moid, name, 8, 1, &val, tx);
		}
		ASSERT(error == 0);
		if (strcmp(name, zfs_prop_to_name(ZFS_PROP_NORMALIZE)) == 0)
			norm = val;
		else if (strcmp(name, zfs_prop_to_name(ZFS_PROP_CASE)) == 0)
			sense = val;
	}
	ASSERT(version != 0);
	error = zap_update(os, moid, ZPL_VERSION_STR, 8, 1, &version, tx);

	/*
	 * Create zap object used for SA attribute registration
	 */

	if (version >= ZPL_VERSION_SA) {
		sa_obj = zap_create(os, DMU_OT_SA_MASTER_NODE,
		    DMU_OT_NONE, 0, tx);
		error = zap_add(os, moid, ZFS_SA_ATTRS, 8, 1, &sa_obj, tx);
		ASSERT(error == 0);
	} else {
		sa_obj = 0;
	}
	/*
	 * Create a delete queue.
	 */
	obj = zap_create(os, DMU_OT_UNLINKED_SET, DMU_OT_NONE, 0, tx);

	error = zap_add(os, moid, ZFS_UNLINKED_SET, 8, 1, &obj, tx);
	ASSERT(error == 0);

	/*
	 * Create root znode.  Create minimal znode/inode/zsb/sb
	 * to allow zfs_mknode to work.
	 */
	vattr.va_mask = ATTR_MODE|ATTR_UID|ATTR_GID;
	vattr.va_mode = S_IFDIR|0755;
	vattr.va_uid = crgetuid(cr);
	vattr.va_gid = crgetgid(cr);

	rootzp = kmem_cache_alloc(znode_cache, KM_PUSHPAGE);
	rootzp->z_moved = 0;
	rootzp->z_unlinked = 0;
	rootzp->z_atime_dirty = 0;
	rootzp->z_is_sa = USE_SA(version, os);

	zsb = kmem_zalloc(sizeof (zfs_sb_t), KM_PUSHPAGE | KM_NODEBUG);
	zsb->z_os = os;
	zsb->z_parent = zsb;
	zsb->z_version = version;
	zsb->z_use_fuids = USE_FUIDS(version, os);
	zsb->z_use_sa = USE_SA(version, os);
	zsb->z_norm = norm;

	sb = kmem_zalloc(sizeof (struct super_block), KM_PUSHPAGE);
	sb->s_fs_info = zsb;

	ZTOI(rootzp)->i_sb = sb;

	error = sa_setup(os, sa_obj, zfs_attr_table, ZPL_END,
	    &zsb->z_attr_table);

	ASSERT(error == 0);

	/*
	 * Fold case on file systems that are always or sometimes case
	 * insensitive.
	 */
	if (sense == ZFS_CASE_INSENSITIVE || sense == ZFS_CASE_MIXED)
		zsb->z_norm |= U8_TEXTPREP_TOUPPER;

	mutex_init(&zsb->z_znodes_lock, NULL, MUTEX_DEFAULT, NULL);
	list_create(&zsb->z_all_znodes, sizeof (znode_t),
	    offsetof(znode_t, z_link_node));

	for (i = 0; i != ZFS_OBJ_MTX_SZ; i++)
		mutex_init(&zsb->z_hold_mtx[i], NULL, MUTEX_DEFAULT, NULL);

	VERIFY(0 == zfs_acl_ids_create(rootzp, IS_ROOT_NODE, &vattr,
	    cr, NULL, &acl_ids));
	zfs_mknode(rootzp, &vattr, tx, cr, IS_ROOT_NODE, &zp, &acl_ids);
	ASSERT3P(zp, ==, rootzp);
	error = zap_add(os, moid, ZFS_ROOT_OBJ, 8, 1, &rootzp->z_id, tx);
	ASSERT(error == 0);
	zfs_acl_ids_free(&acl_ids);

	atomic_set(&ZTOI(rootzp)->i_count, 0);
	sa_handle_destroy(rootzp->z_sa_hdl);
	kmem_cache_free(znode_cache, rootzp);

	/*
	 * Create shares directory
	 */
	error = zfs_create_share_dir(zsb, tx);
	ASSERT(error == 0);

	for (i = 0; i != ZFS_OBJ_MTX_SZ; i++)
		mutex_destroy(&zsb->z_hold_mtx[i]);

	kmem_free(sb, sizeof (struct super_block));
	kmem_free(zsb, sizeof (zfs_sb_t));
}