Example #1
0
/*
 * Decide whether it is okay to remove within a sticky directory.
 *
 * In sticky directories, write access is not sufficient;
 * you can remove entries from a directory only if:
 *
 *	you own the directory,
 *	you own the entry,
 *	the entry is a plain file and you have write access,
 *	or you are privileged (checked in secpolicy...).
 *
 * The function returns 0 if remove access is granted.
 */
int
zfs_sticky_remove_access(znode_t *zdp, znode_t *zp, cred_t *cr)
{
	uid_t		uid;
	uid_t		downer;
	uid_t		fowner;
	zfsvfs_t	*zfsvfs = ZTOZSB(zdp);

	if (zfsvfs->z_replay)
		return (0);

	if ((zdp->z_mode & S_ISVTX) == 0)
		return (0);

	downer = zfs_fuid_map_id(zfsvfs, KUID_TO_SUID(ZTOI(zdp)->i_uid),
	    cr, ZFS_OWNER);
	fowner = zfs_fuid_map_id(zfsvfs, KUID_TO_SUID(ZTOI(zp)->i_uid),
	    cr, ZFS_OWNER);

	if ((uid = crgetuid(cr)) == downer || uid == fowner ||
	    (S_ISDIR(ZTOI(zp)->i_mode) &&
	    zfs_zaccess(zp, ACE_WRITE_DATA, 0, B_FALSE, cr) == 0))
		return (0);
	else
		return (secpolicy_vnode_remove(cr));
}
Example #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);
	}
}
Example #3
0
/*
 * Validate that user is allowed to unallow specified permissions.  They
 * must have the 'allow' permission, and even then can only unallow
 * perms for their uid.
 */
int
dsl_deleg_can_unallow(char *ddname, nvlist_t *nvp, cred_t *cr)
{
	nvpair_t *whopair = NULL;
	int error;
	char idstr[32];

	if ((error = dsl_deleg_access(ddname, ZFS_DELEG_PERM_ALLOW, cr)) != 0)
		return (error);

	(void) snprintf(idstr, sizeof (idstr), "%lld",
	    (longlong_t)crgetuid(cr));

	while (whopair = nvlist_next_nvpair(nvp, whopair)) {
		zfs_deleg_who_type_t type = nvpair_name(whopair)[0];

		if (type != ZFS_DELEG_USER &&
		    type != ZFS_DELEG_USER_SETS)
			return (EPERM);

		if (strcmp(idstr, &nvpair_name(whopair)[3]) != 0)
			return (EPERM);
	}
	return (0);
}
Example #4
0
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));

}
Example #5
0
/*
 * Decide whether it is okay to remove within a sticky directory.
 *
 * In sticky directories, write access is not sufficient;
 * you can remove entries from a directory only if:
 *
 *	you own the directory,
 *	you own the entry,
 *	the entry is a plain file and you have write access,
 *	or you are privileged (checked in secpolicy...).
 *
 * The function returns 0 if remove access is granted.
 */
int
zfs_sticky_remove_access(znode_t *zdp, znode_t *zp, cred_t *cr)
{
#ifdef HAVE_ZPL
	uid_t  		uid;
	uid_t		downer;
	uid_t		fowner;
	zfsvfs_t	*zfsvfs = zdp->z_zfsvfs;

	if (zdp->z_zfsvfs->z_replay)
		return (0);

	if ((zdp->z_mode & S_ISVTX) == 0)
		return (0);

	downer = zfs_fuid_map_id(zfsvfs, zdp->z_uid, cr, ZFS_OWNER);
	fowner = zfs_fuid_map_id(zfsvfs, zp->z_uid, cr, ZFS_OWNER);

	if ((uid = crgetuid(cr)) == downer || uid == fowner ||
	    (ZTOV(zp)->v_type == VREG &&
	    zfs_zaccess(zp, ACE_WRITE_DATA, 0, B_FALSE, cr) == 0))
		return (0);
	else
		return (secpolicy_vnode_remove(cr));
#endif 
	return 0;
}
Example #6
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);
}
Example #7
0
/*
 * Write out a history event.
 */
int
spa_history_log(spa_t *spa, const char *history_str, history_log_type_t what)
{
	history_arg_t *ha;
	int err = 0;
	dmu_tx_t *tx;

	ASSERT(what != LOG_INTERNAL);

	tx = dmu_tx_create_dd(spa_get_dsl(spa)->dp_mos_dir);
	err = dmu_tx_assign(tx, TXG_WAIT);
	if (err) {
		dmu_tx_abort(tx);
		return (err);
	}

	ha = kmem_alloc(sizeof (history_arg_t), KM_SLEEP);
	ha->ha_history_str = strdup(history_str);
	ha->ha_zone = strdup(spa_history_zone());
	ha->ha_log_type = what;
	ha->ha_uid = crgetuid(CRED());

	/* Kick this off asynchronously; errors are ignored. */
	dsl_sync_task_do_nowait(spa_get_dsl(spa), NULL,
	    spa_history_log_sync, spa, ha, 0, tx);
	dmu_tx_commit(tx);

	/* spa_history_log_sync will free ha and strings */
	return (err);
}
Example #8
0
static int
VMBlockOpen(struct vnode **vpp,    // IN: Vnode for file to open
            int flag,              // IN: Open flags
            struct cred *cr        // IN: Credentials of caller
#if OS_VFS_VERSION >= 5
          , caller_context_t *ctx  // IN: Caller's context
#endif
           )
{
   VMBlockMountInfo *mip;
   Bool isRoot = TRUE;

   Debug(VMBLOCK_ENTRY_LOGLEVEL, "VMBlockOpen: entry\n");

   /*
    * The opened vnode is held for us, so we don't need to do anything here
    * except make sure only root opens the mount point.
    */
   mip = VPTOMIP(*vpp);
   if (mip->root == *vpp) {
      isRoot = crgetuid(cr) == 0;
   }

   return isRoot ? 0 : EACCES;
}
Example #9
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));
}
Example #10
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() */
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);
}
Example #12
0
static void
smb_tree_set_execsub_info(smb_tree_t *tree, smb_execsub_info_t *subs)
{
		subs->e_winname = tree->t_user->u_name;
		subs->e_userdom = tree->t_user->u_domain;
		subs->e_srv_ipaddr = tree->t_session->local_ipaddr;
		subs->e_cli_ipaddr = tree->t_session->ipaddr;
		subs->e_cli_netbiosname = tree->t_session->workstation;
		subs->e_uid = crgetuid(tree->t_user->u_cred);
}
Example #13
0
int				/* ERRNO if error, 0 if successful. */
sam_access_ino(
	sam_node_t *ip,		/* pointer to inode. */
	int mode,		/* mode of access to be verified */
	boolean_t locked,	/* is ip->inode_rwl held by caller? */
	cred_t *credp)		/* credentials pointer. */
{
	int shift = 0;

	ASSERT(!locked || RW_LOCK_HELD(&ip->inode_rwl));

	/*
	 * If requesting write access, and read only filesystem or WORM file
	 * return error.
	 */
	if (mode & S_IWRITE) {
		if (ip->mp->mt.fi_mflag & MS_RDONLY) {
			return (EROFS);
		}
		if (ip->di.status.b.worm_rdonly && !S_ISDIR(ip->di.mode)) {
			return (EROFS);
		}
	}

	if (!locked) {
		RW_LOCK_OS(&ip->inode_rwl, RW_READER);
	}

	/* Use ACL, if present, to check access. */
	if (ip->di.status.b.acl) {
		int error;

		error = sam_acl_access(ip, mode, credp);
		if (!locked) {
			RW_UNLOCK_OS(&ip->inode_rwl, RW_READER);
		}
		return (error);
	}

	if (!locked) {
		RW_UNLOCK_OS(&ip->inode_rwl, RW_READER);
	}

	if (crgetuid(credp) != ip->di.uid) {
		shift += 3;
		if (!groupmember((uid_t)ip->di.gid, credp)) {
			shift += 3;
		}
	}
	mode &= ~(ip->di.mode << shift);
	if (mode == 0) {
		return (0);
	}
	return (secpolicy_vnode_access(credp, SAM_ITOV(ip), ip->di.uid, mode));
}
Example #14
0
int				/* ERRNO if error, 0 if successful. */
sam_access_ino(
	sam_node_t *ip,		/* pointer to inode. */
	int mode,		/* mode of access to be verified, */
				/*   owner position. */
	boolean_t locked,	/* is ip->inode_rwl held by caller? */
	cred_t *credp)		/* credentials pointer. */
{

	ASSERT(!locked);

	/*
	 * If requesting write access, and read only filesystem or WORM file
	 * return error.
	 */
	if (mode & S_IWRITE) {
		if (ip->mp->mt.fi_mflag & MS_RDONLY) {
			return (EROFS);
		}
		if (ip->di.status.b.worm_rdonly && !S_ISDIR(ip->di.mode)) {
			return (EROFS);
		}
	}
	if (crgetuid(credp) == 0) {
		return (0);		/* all accesses allowed for root */
	}

	if (crgetuid(credp) != ip->di.uid) {
		/*
		 * caller not owner, check group
		 */
		mode >>= 3;
		if (!in_group_p(ip->di.gid)) {
			/*
			 * caller not in group, check other
			 */
			mode >>= 3;
		}
/*
 * find_ids(packet, mp)
 *
 * attempt to discern the uid and projid of the originator of a packet by
 * looking at the dblks making up the packet - yeuch!
 *
 * We do it by skipping any fragments with a credp of NULL (originated in
 * kernel), taking the first value that isn't NULL to be the credp for the
 * whole packet. We also suck the projid from the same fragment.
 */
static void
find_ids(ipgpc_packet_t *packet, mblk_t *mp)
{
	cred_t *cr;

	cr = msg_getcred(mp, NULL);
	if (cr != NULL) {
		packet->uid = crgetuid(cr);
		packet->projid = crgetprojid(cr);
	} else {
		packet->uid = (uid_t)-1;
		packet->projid = -1;
	}
}
Example #16
0
int
tmp_sticky_remove_access(struct tmpnode *dir, struct tmpnode *entry,
	struct cred *cr)
{
	uid_t uid = crgetuid(cr);

	if ((dir->tn_mode & S_ISVTX) &&
	    uid != dir->tn_uid &&
	    uid != entry->tn_uid &&
	    (entry->tn_type != VREG ||
	    tmp_taccess(entry, VWRITE, cr) != 0))
		return (secpolicy_vnode_remove(cr));

	return (0);
}
Example #17
0
/*ARGSUSED*/
static int
bootfs_access(vnode_t *vp, int mode, int flags, cred_t *cr,
    caller_context_t *ct)
{
	int shift = 0;
	bootfs_node_t *bpn = (bootfs_node_t *)vp->v_data;

	if (crgetuid(cr) != bpn->bvn_attr.va_uid) {
		shift += 3;
		if (groupmember(bpn->bvn_attr.va_gid, cr) == 0)
			shift += 3;
	}

	return (secpolicy_vnode_access2(cr, vp, bpn->bvn_attr.va_uid,
	    bpn->bvn_attr.va_mode << shift, mode));
}
Example #18
0
/*
 * Standard access() like check.  Figure out which mode bits apply
 * to the caller then pass the missing mode bits to the secpolicy function.
 */
static int
nm_access_unlocked(void *vnp, int mode, cred_t *crp)
{
	struct namenode *nodep = vnp;
	int shift = 0;

	if (crgetuid(crp) != nodep->nm_vattr.va_uid) {
		shift += 3;
		if (!groupmember(nodep->nm_vattr.va_gid, crp))
			shift += 3;
	}

	return (secpolicy_vnode_access2(crp, NMTOV(nodep),
	    nodep->nm_vattr.va_uid, nodep->nm_vattr.va_mode << shift,
	    mode));
}
Example #19
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 */
}
Example #20
0
/*
 * Decide whether it is okay to remove within a sticky directory.
 *
 * In sticky directories, write access is not sufficient;
 * you can remove entries from a directory only if:
 *
 *	you own the directory,
 *	you own the entry,
 *	the entry is a plain file and you have write access,
 *	or you are privileged (checked in secpolicy...).
 *
 * The function returns 0 if remove access is granted.
 */
int
zfs_sticky_remove_access(znode_t *zdp, znode_t *zp, cred_t *cr)
{
	uid_t  		uid;

	if (zdp->z_zfsvfs->z_assign >= TXG_INITIAL)	/* ZIL replay */
		return (0);

	if ((zdp->z_phys->zp_mode & S_ISVTX) == 0 ||
	    (uid = crgetuid(cr)) == zdp->z_phys->zp_uid ||
	    uid == zp->z_phys->zp_uid ||
	    (ZTOV(zp)->v_type == VREG &&
	    zfs_zaccess(zp, ACE_WRITE_DATA, cr) == 0))
		return (0);
	else
		return (secpolicy_vnode_remove(cr));
}
Example #21
0
/*
 * 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));
}
Example #22
0
File: dsl_deleg.c Project: 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;
}
Example #23
0
/* ARGSUSED */
static int
auto_access(
	vnode_t *vp,
	int mode,
	int flags,
	cred_t *cred,
	caller_context_t *ct)
{
	fnnode_t *fnp = vntofn(vp);
	vnode_t *newvp;
	int error;

	AUTOFS_DPRINT((4, "auto_access: vp=%p\n", (void *)vp));

	if (error = auto_trigger_mount(vp, cred, &newvp))
		goto done;

	if (newvp != NULL) {
		/*
		 * Node is mounted on.
		 */
		error = VOP_ACCESS(newvp, mode, 0, cred, ct);
		VN_RELE(newvp);
	} else {
		int shift = 0;

		/*
		 * really interested in the autofs node, check the
		 * access on it
		 */
		ASSERT(error == 0);
		if (crgetuid(cred) != fnp->fn_uid) {
			shift += 3;
			if (groupmember(fnp->fn_gid, cred) == 0)
				shift += 3;
		}
		error = secpolicy_vnode_access2(cred, vp, fnp->fn_uid,
		    fnp->fn_mode << shift, mode);
	}

done:
	AUTOFS_DPRINT((5, "auto_access: error=%d\n", error));
	return (error);
}
Example #24
0
/*
 * set all create time permission on new dataset.
 */
void
dsl_deleg_set_create_perms(dsl_dir_t *sdd, dmu_tx_t *tx, cred_t *cr)
{
	dsl_dir_t *dd;
	uint64_t uid = crgetuid(cr);

	if (spa_version(dmu_objset_spa(sdd->dd_pool->dp_meta_objset)) <
	    SPA_VERSION_DELEGATED_PERMS)
		return;

	for (dd = sdd->dd_parent; dd != NULL; dd = dd->dd_parent) {
		uint64_t pzapobj = dd->dd_phys->dd_deleg_zapobj;

		if (pzapobj == 0)
			continue;

		copy_create_perms(sdd, pzapobj, B_FALSE, uid, tx);
		copy_create_perms(sdd, pzapobj, B_TRUE, uid, tx);
	}
}
/*
 *
 * 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));
}
Example #26
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);
}
Example #27
0
/*
 * This function is used for secpolicy_setattr().  It must call an
 * access() like function while it is already holding the
 * dv_contents lock.  We only care about this when dv_attr != NULL;
 * so the unlocked access call only concerns itself with that
 * particular branch of devfs_access().
 */
static int
devfs_unlocked_access(void *vdv, int mode, struct cred *cr)
{
	struct dv_node *dv = vdv;
	int shift = 0;
	uid_t owner = dv->dv_attr->va_uid;

	/* Check access based on owner, group and public permissions. */
	if (crgetuid(cr) != owner) {
		shift += 3;
		if (groupmember(dv->dv_attr->va_gid, cr) == 0)
			shift += 3;
	}

	/* compute missing mode bits */
	mode &= ~(dv->dv_attr->va_mode << shift);

	if (mode == 0)
		return (0);

	return (secpolicy_vnode_access(cr, DVTOV(dv), owner, mode));
}
Example #28
0
int
tmp_taccess(void *vtp, int mode, struct cred *cred)
{
	struct tmpnode *tp = vtp;
	int shift = 0;
	/*
	 * Check access based on owner, group and
	 * public permissions in tmpnode.
	 */
	if (crgetuid(cred) != tp->tn_uid) {
		shift += MODESHIFT;
		if (groupmember(tp->tn_gid, cred) == 0)
			shift += MODESHIFT;
	}

	/* compute missing mode bits */
	mode &= ~(tp->tn_mode << shift);

	if (mode == 0)
		return (0);

	return (secpolicy_vnode_access(cred, TNTOV(tp), tp->tn_uid, mode));
}
Example #29
0
/*
 * Decide whether it is okay to remove within a sticky directory.
 *
 * In sticky directories, write access is not sufficient;
 * you can remove entries from a directory only if:
 *
 *	you own the directory,
 *	you own the entry,
 *	the entry is a plain file and you have write access,
 *	or you are privileged (checked in secpolicy...).
 *
 * The function returns 0 if remove access is granted.
 */
int
zfs_sticky_remove_access(znode_t *zdp, znode_t *zp, cred_t *cr)
{
    uid_t  		uid;

    if (zdp->z_zfsvfs->z_assign >= TXG_INITIAL)	/* ZIL replay */
        return (0);

    if ((zdp->z_mode & S_ISVTX) == 0 ||
            (uid = crgetuid(cr)) == zdp->z_uid ||
            uid == zp->z_uid ||
            (
#ifdef __APPLE__
                vnode_isreg(ZTOV(zp)) &&
#else
                ZTOV(zp)->v_type == VREG &&
#endif
                zfs_zaccess(zp, ACE_WRITE_DATA, 0, B_FALSE, cr) == 0)
       )
        return (0);
    else
        return (secpolicy_vnode_remove(cr));
}
Example #30
0
static int
xmem_link(struct vnode *dvp, struct vnode *srcvp, char *tnm, struct cred *cred)
{
	struct xmemnode *parent;
	struct xmemnode *from;
	struct xmount *xm = (struct xmount *)VTOXM(dvp);
	int error;
	struct xmemnode *found = NULL;
	struct vnode *realvp;

	if (VOP_REALVP(srcvp, &realvp) == 0)
		srcvp = realvp;

	parent = (struct xmemnode *)VTOXN(dvp);
	from = (struct xmemnode *)VTOXN(srcvp);

	if ((srcvp->v_type == VDIR &&
	    secpolicy_fs_linkdir(cred, dvp->v_vfsp) != 0) ||
	    (from->xn_uid != crgetuid(cred) && secpolicy_basic_link(cred) != 0))
		return (EPERM);

	error = xdirlookup(parent, tnm, &found, cred);
	if (error == 0) {
		ASSERT(found);
		xmemnode_rele(found);
		return (EEXIST);
	}

	if (error != ENOENT)
		return (error);

	rw_enter(&parent->xn_rwlock, RW_WRITER);
	error = xdirenter(xm, parent, tnm, DE_LINK, (struct xmemnode *)NULL,
		from, NULL, (struct xmemnode **)NULL, cred);
	rw_exit(&parent->xn_rwlock);
	return (error);
}