ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks/*
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * CDDL HEADER START
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks *
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * The contents of this file are subject to the terms of the
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * Common Development and Distribution License (the "License").
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * You may not use this file except in compliance with the License.
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks *
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * or http://www.opensolaris.org/os/licensing.
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * See the License for the specific language governing permissions
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * and limitations under the License.
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks *
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * When distributing Covered Code, include this CDDL HEADER in each
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * If applicable, add the following below this CDDL HEADER, with the
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * fields enclosed by brackets "[]" replaced with your own identifying
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * information: Portions Copyright [yyyy] [name of copyright owner]
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks *
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * CDDL HEADER END
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks */
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks/*
99d5e173470cf967aa87653364ed614299e7b511Tim Haley * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
9adfa60d484ce2435f5af77cc99dcd4e692b6660Matthew Ahrens * Copyright (c) 2011, 2015 by Delphix. All rights reserved.
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks */
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks/*
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * DSL permissions are stored in a two level zap attribute
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * mechanism. The first level identifies the "class" of
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * entry. The class is identified by the first 2 letters of
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * the attribute. The second letter "l" or "d" identifies whether
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * it is a local or descendent permission. The first letter
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * identifies the type of entry.
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * ul$<id> identifies permissions granted locally for this userid.
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * ud$<id> identifies permissions granted on descendent datasets for
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * this userid.
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * Ul$<id> identifies permission sets granted locally for this userid.
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * Ud$<id> identifies permission sets granted on descendent datasets for
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * this userid.
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * gl$<id> identifies permissions granted locally for this groupid.
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * gd$<id> identifies permissions granted on descendent datasets for
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * this groupid.
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * Gl$<id> identifies permission sets granted locally for this groupid.
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * Gd$<id> identifies permission sets granted on descendent datasets for
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * this groupid.
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * el$ identifies permissions granted locally for everyone.
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * ed$ identifies permissions granted on descendent datasets
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * for everyone.
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * El$ identifies permission sets granted locally for everyone.
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * Ed$ identifies permission sets granted to descendent datasets for
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * everyone.
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * c-$ identifies permission to create at dataset creation time.
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * C-$ identifies permission sets to grant locally at dataset creation
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * time.
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * s-$@<name> permissions defined in specified set @<name>
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * S-$@<name> Sets defined in named set @<name>
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Each of the above entities points to another zap attribute that contains one
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * attribute for each allowed permission, such as create, destroy,...
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * All of the "upper" case class types will specify permission set names
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * rather than permissions.
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks *
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * Basically it looks something like this:
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * ul$12 -> ZAP OBJ -> permissions...
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks *
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * The ZAP OBJ is referred to as the jump object.
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks */
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks#include <sys/dmu.h>
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks#include <sys/dmu_objset.h>
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks#include <sys/dmu_tx.h>
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks#include <sys/dsl_dataset.h>
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks#include <sys/dsl_dir.h>
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks#include <sys/dsl_prop.h>
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks#include <sys/dsl_synctask.h>
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks#include <sys/dsl_deleg.h>
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks#include <sys/spa.h>
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks#include <sys/zap.h>
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks#include <sys/fs/zfs.h>
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks#include <sys/cred.h>
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks#include <sys/sunddi.h>
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks#include "zfs_deleg.h"
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks/*
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * Validate that user is allowed to delegate specified permissions.
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks *
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens * In order to delegate "create" you must have "create"
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * and "allow".
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks */
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarksint
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarksdsl_deleg_can_allow(char *ddname, nvlist_t *nvp, cred_t *cr)
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks{
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks nvpair_t *whopair = NULL;
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens int error;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens if ((error = dsl_deleg_access(ddname, ZFS_DELEG_PERM_ALLOW, cr)) != 0)
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks return (error);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks while (whopair = nvlist_next_nvpair(nvp, whopair)) {
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks nvlist_t *perms;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks nvpair_t *permpair = NULL;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks VERIFY(nvpair_value_nvlist(whopair, &perms) == 0);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks while (permpair = nvlist_next_nvpair(perms, permpair)) {
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks const char *perm = nvpair_name(permpair);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks if (strcmp(perm, ZFS_DELEG_PERM_ALLOW) == 0)
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens return (SET_ERROR(EPERM));
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens if ((error = dsl_deleg_access(ddname, perm, cr)) != 0)
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks return (error);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks }
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks }
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens return (0);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks}
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks/*
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * Validate that user is allowed to unallow specified permissions. They
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * must have the 'allow' permission, and even then can only unallow
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * perms for their uid.
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks */
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarksint
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarksdsl_deleg_can_unallow(char *ddname, nvlist_t *nvp, cred_t *cr)
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks{
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks nvpair_t *whopair = NULL;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks int error;
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens char idstr[32];
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens if ((error = dsl_deleg_access(ddname, ZFS_DELEG_PERM_ALLOW, cr)) != 0)
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks return (error);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens (void) snprintf(idstr, sizeof (idstr), "%lld",
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens (longlong_t)crgetuid(cr));
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks while (whopair = nvlist_next_nvpair(nvp, whopair)) {
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks zfs_deleg_who_type_t type = nvpair_name(whopair)[0];
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks if (type != ZFS_DELEG_USER &&
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks type != ZFS_DELEG_USER_SETS)
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens return (SET_ERROR(EPERM));
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks if (strcmp(idstr, &nvpair_name(whopair)[3]) != 0)
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens return (SET_ERROR(EPERM));
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks }
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks return (0);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks}
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrenstypedef struct dsl_deleg_arg {
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens const char *dda_name;
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens nvlist_t *dda_nvlist;
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens} dsl_deleg_arg_t;
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarksstatic void
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrensdsl_deleg_set_sync(void *arg, dmu_tx_t *tx)
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks{
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens dsl_deleg_arg_t *dda = arg;
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens dsl_dir_t *dd;
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens dsl_pool_t *dp = dmu_tx_pool(tx);
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens objset_t *mos = dp->dp_meta_objset;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks nvpair_t *whopair = NULL;
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens uint64_t zapobj;
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens VERIFY0(dsl_dir_hold(dp, dda->dda_name, FTAG, &dd, NULL));
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
c1379625401dfbe1c39b79136dd384a571d47fdeJustin T. Gibbs zapobj = dsl_dir_phys(dd)->dd_deleg_zapobj;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks if (zapobj == 0) {
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks dmu_buf_will_dirty(dd->dd_dbuf, tx);
c1379625401dfbe1c39b79136dd384a571d47fdeJustin T. Gibbs zapobj = dsl_dir_phys(dd)->dd_deleg_zapobj = zap_create(mos,
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks DMU_OT_DSL_PERMS, DMU_OT_NONE, 0, tx);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks }
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens while (whopair = nvlist_next_nvpair(dda->dda_nvlist, whopair)) {
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens const char *whokey = nvpair_name(whopair);
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens nvlist_t *perms;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens nvpair_t *permpair = NULL;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens uint64_t jumpobj;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens perms = fnvpair_value_nvlist(whopair);
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens if (zap_lookup(mos, zapobj, whokey, 8, 1, &jumpobj) != 0) {
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden jumpobj = zap_create_link(mos, DMU_OT_DSL_PERMS,
ad135b5d644628e791c3188a6ecbd9c257961ef8Christopher Siden zapobj, whokey, tx);
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens }
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens while (permpair = nvlist_next_nvpair(perms, permpair)) {
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens const char *perm = nvpair_name(permpair);
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens uint64_t n = 0;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens VERIFY(zap_update(mos, jumpobj,
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens perm, 8, 1, &n, tx) == 0);
4445fffbbb1ea25fd0e9ea68b9380dd7a6709025Matthew Ahrens spa_history_log_internal_dd(dd, "permission update", tx,
4445fffbbb1ea25fd0e9ea68b9380dd7a6709025Matthew Ahrens "%s %s", whokey, perm);
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens }
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens }
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens dsl_dir_rele(dd, FTAG);
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens}
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens
3cb34c601f3ef3016f638574f5982e80c3735c71ahrensstatic void
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrensdsl_deleg_unset_sync(void *arg, dmu_tx_t *tx)
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens{
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens dsl_deleg_arg_t *dda = arg;
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens dsl_dir_t *dd;
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens dsl_pool_t *dp = dmu_tx_pool(tx);
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens objset_t *mos = dp->dp_meta_objset;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens nvpair_t *whopair = NULL;
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens uint64_t zapobj;
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens VERIFY0(dsl_dir_hold(dp, dda->dda_name, FTAG, &dd, NULL));
c1379625401dfbe1c39b79136dd384a571d47fdeJustin T. Gibbs zapobj = dsl_dir_phys(dd)->dd_deleg_zapobj;
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens if (zapobj == 0) {
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens dsl_dir_rele(dd, FTAG);
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens return;
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens }
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens while (whopair = nvlist_next_nvpair(dda->dda_nvlist, whopair)) {
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks const char *whokey = nvpair_name(whopair);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks nvlist_t *perms;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks nvpair_t *permpair = NULL;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks uint64_t jumpobj;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks if (nvpair_value_nvlist(whopair, &perms) != 0) {
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks if (zap_lookup(mos, zapobj, whokey, 8,
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks 1, &jumpobj) == 0) {
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks (void) zap_remove(mos, zapobj, whokey, tx);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks VERIFY(0 == zap_destroy(mos, jumpobj, tx));
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks }
4445fffbbb1ea25fd0e9ea68b9380dd7a6709025Matthew Ahrens spa_history_log_internal_dd(dd, "permission who remove",
4445fffbbb1ea25fd0e9ea68b9380dd7a6709025Matthew Ahrens tx, "%s", whokey);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks continue;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks }
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens if (zap_lookup(mos, zapobj, whokey, 8, 1, &jumpobj) != 0)
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens continue;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks while (permpair = nvlist_next_nvpair(perms, permpair)) {
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks const char *perm = nvpair_name(permpair);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks uint64_t n = 0;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens (void) zap_remove(mos, jumpobj, perm, tx);
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens if (zap_count(mos, jumpobj, &n) == 0 && n == 0) {
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens (void) zap_remove(mos, zapobj,
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens whokey, tx);
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens VERIFY(0 == zap_destroy(mos,
3cb34c601f3ef3016f638574f5982e80c3735c71ahrens jumpobj, tx));
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks }
4445fffbbb1ea25fd0e9ea68b9380dd7a6709025Matthew Ahrens spa_history_log_internal_dd(dd, "permission remove", tx,
4445fffbbb1ea25fd0e9ea68b9380dd7a6709025Matthew Ahrens "%s %s", whokey, perm);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks }
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks }
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens dsl_dir_rele(dd, FTAG);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks}
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrensstatic int
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrensdsl_deleg_check(void *arg, dmu_tx_t *tx)
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks{
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens dsl_deleg_arg_t *dda = arg;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks dsl_dir_t *dd;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks int error;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens if (spa_version(dmu_tx_pool(tx)->dp_spa) <
990b4856d0eaada6f8140335733a1b1771ed2746lling SPA_VERSION_DELEGATED_PERMS) {
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens return (SET_ERROR(ENOTSUP));
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks }
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens error = dsl_dir_hold(dmu_tx_pool(tx), dda->dda_name, FTAG, &dd, NULL);
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens if (error == 0)
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens dsl_dir_rele(dd, FTAG);
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens return (error);
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens}
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrensint
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrensdsl_deleg_set(const char *ddname, nvlist_t *nvp, boolean_t unset)
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens{
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens dsl_deleg_arg_t dda;
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens /* nvp must already have been verified to be valid */
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens dda.dda_name = ddname;
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens dda.dda_nvlist = nvp;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens return (dsl_sync_task(ddname, dsl_deleg_check,
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens unset ? dsl_deleg_unset_sync : dsl_deleg_set_sync,
7d46dc6ca63a6f3f0d51aa655bfcf10cf2405a9eMatthew Ahrens &dda, fnvlist_num_pairs(nvp), ZFS_SPACE_CHECK_RESERVED));
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks}
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks/*
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * Find all 'allow' permissions from a given point and then continue
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * traversing up to the root.
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks *
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * This function constructs an nvlist of nvlists.
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * each setpoint is an nvlist composed of an nvlist of an nvlist
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * of the individual * users/groups/everyone/create
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * permissions.
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks *
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * The nvlist will look like this.
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks *
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * { source fsname -> { whokeys { permissions,...}, ...}}
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks *
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * The fsname nvpairs will be arranged in a bottom up order. For example,
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * if we have the following structure a/b/c then the nvpairs for the fsnames
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * will be ordered a/b/c, a/b, a.
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks */
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarksint
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarksdsl_deleg_get(const char *ddname, nvlist_t **nvp)
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks{
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks dsl_dir_t *dd, *startdd;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks dsl_pool_t *dp;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks int error;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks objset_t *mos;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens error = dsl_pool_hold(ddname, FTAG, &dp);
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens if (error != 0)
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens return (error);
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens error = dsl_dir_hold(dp, ddname, FTAG, &startdd, NULL);
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens if (error != 0) {
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens dsl_pool_rele(dp, FTAG);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks return (error);
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens }
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks dp = startdd->dd_pool;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks mos = dp->dp_meta_objset;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks VERIFY(nvlist_alloc(nvp, NV_UNIQUE_NAME, KM_SLEEP) == 0);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks for (dd = startdd; dd != NULL; dd = dd->dd_parent) {
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks zap_cursor_t basezc;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks zap_attribute_t baseza;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks nvlist_t *sp_nvp;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks uint64_t n;
9adfa60d484ce2435f5af77cc99dcd4e692b6660Matthew Ahrens char source[ZFS_MAX_DATASET_NAME_LEN];
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
c1379625401dfbe1c39b79136dd384a571d47fdeJustin T. Gibbs if (dsl_dir_phys(dd)->dd_deleg_zapobj == 0 ||
c1379625401dfbe1c39b79136dd384a571d47fdeJustin T. Gibbs zap_count(mos,
c1379625401dfbe1c39b79136dd384a571d47fdeJustin T. Gibbs dsl_dir_phys(dd)->dd_deleg_zapobj, &n) != 0 || n == 0)
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks continue;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens sp_nvp = fnvlist_alloc();
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks for (zap_cursor_init(&basezc, mos,
c1379625401dfbe1c39b79136dd384a571d47fdeJustin T. Gibbs dsl_dir_phys(dd)->dd_deleg_zapobj);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks zap_cursor_retrieve(&basezc, &baseza) == 0;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks zap_cursor_advance(&basezc)) {
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks zap_cursor_t zc;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks zap_attribute_t za;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks nvlist_t *perms_nvp;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks ASSERT(baseza.za_integer_length == 8);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks ASSERT(baseza.za_num_integers == 1);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens perms_nvp = fnvlist_alloc();
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks for (zap_cursor_init(&zc, mos, baseza.za_first_integer);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks zap_cursor_retrieve(&zc, &za) == 0;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks zap_cursor_advance(&zc)) {
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens fnvlist_add_boolean(perms_nvp, za.za_name);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks }
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks zap_cursor_fini(&zc);
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens fnvlist_add_nvlist(sp_nvp, baseza.za_name, perms_nvp);
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens fnvlist_free(perms_nvp);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks }
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks zap_cursor_fini(&basezc);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks dsl_dir_name(dd, source);
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens fnvlist_add_nvlist(*nvp, source, sp_nvp);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks nvlist_free(sp_nvp);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks }
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens dsl_dir_rele(startdd, FTAG);
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens dsl_pool_rele(dp, FTAG);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks return (0);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks}
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks/*
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * Routines for dsl_deleg_access() -- access checking.
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks */
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarkstypedef struct perm_set {
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks avl_node_t p_node;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks boolean_t p_matched;
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens char p_setname[ZFS_MAX_DELEG_NAME];
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks} perm_set_t;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarksstatic int
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarksperm_set_compare(const void *arg1, const void *arg2)
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks{
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks const perm_set_t *node1 = arg1;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks const perm_set_t *node2 = arg2;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks int val;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks val = strcmp(node1->p_setname, node2->p_setname);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks if (val == 0)
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks return (0);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks return (val > 0 ? 1 : -1);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks}
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks/*
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * Determine whether a specified permission exists.
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks *
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * First the base attribute has to be retrieved. i.e. ul$12
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * Once the base object has been retrieved the actual permission
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * is lookup up in the zap object the base object points to.
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks *
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * Return 0 if permission exists, ENOENT if there is no whokey, EPERM if
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * there is no perm in that jumpobj.
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks */
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarksstatic int
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarksdsl_check_access(objset_t *mos, uint64_t zapobj,
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks char type, char checkflag, void *valp, const char *perm)
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks{
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks int error;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks uint64_t jumpobj, zero;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks char whokey[ZFS_MAX_DELEG_NAME];
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks zfs_deleg_whokey(whokey, type, checkflag, valp);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks error = zap_lookup(mos, zapobj, whokey, 8, 1, &jumpobj);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks if (error == 0) {
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks error = zap_lookup(mos, jumpobj, perm, 8, 1, &zero);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks if (error == ENOENT)
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens error = SET_ERROR(EPERM);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks }
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks return (error);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks}
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks/*
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * check a specified user/group for a requested permission
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks */
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarksstatic int
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrensdsl_check_user_access(objset_t *mos, uint64_t zapobj, const char *perm,
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks int checkflag, cred_t *cr)
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks{
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks const gid_t *gids;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks int ngids;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks int i;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks uint64_t id;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks /* check for user */
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks id = crgetuid(cr);
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens if (dsl_check_access(mos, zapobj,
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks ZFS_DELEG_USER, checkflag, &id, perm) == 0)
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks return (0);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks /* check for users primary group */
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks id = crgetgid(cr);
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens if (dsl_check_access(mos, zapobj,
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks ZFS_DELEG_GROUP, checkflag, &id, perm) == 0)
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks return (0);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks /* check for everyone entry */
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks id = -1;
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens if (dsl_check_access(mos, zapobj,
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks ZFS_DELEG_EVERYONE, checkflag, &id, perm) == 0)
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks return (0);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks /* check each supplemental group user is a member of */
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks ngids = crgetngroups(cr);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks gids = crgetgroups(cr);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks for (i = 0; i != ngids; i++) {
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks id = gids[i];
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens if (dsl_check_access(mos, zapobj,
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks ZFS_DELEG_GROUP, checkflag, &id, perm) == 0)
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks return (0);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks }
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens return (SET_ERROR(EPERM));
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks}
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks/*
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * Iterate over the sets specified in the specified zapobj
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * and load them into the permsets avl tree.
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks */
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarksstatic int
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarksdsl_load_sets(objset_t *mos, uint64_t zapobj,
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks char type, char checkflag, void *valp, avl_tree_t *avl)
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks{
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks zap_cursor_t zc;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks zap_attribute_t za;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks perm_set_t *permnode;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks avl_index_t idx;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks uint64_t jumpobj;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks int error;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks char whokey[ZFS_MAX_DELEG_NAME];
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks zfs_deleg_whokey(whokey, type, checkflag, valp);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks error = zap_lookup(mos, zapobj, whokey, 8, 1, &jumpobj);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks if (error != 0)
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks return (error);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks for (zap_cursor_init(&zc, mos, jumpobj);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks zap_cursor_retrieve(&zc, &za) == 0;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks zap_cursor_advance(&zc)) {
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks permnode = kmem_alloc(sizeof (perm_set_t), KM_SLEEP);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks (void) strlcpy(permnode->p_setname, za.za_name,
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks sizeof (permnode->p_setname));
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks permnode->p_matched = B_FALSE;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks if (avl_find(avl, permnode, &idx) == NULL) {
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks avl_insert(avl, permnode, idx);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks } else {
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks kmem_free(permnode, sizeof (perm_set_t));
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks }
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks }
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks zap_cursor_fini(&zc);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks return (0);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks}
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks/*
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * Load all permissions user based on cred belongs to.
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks */
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarksstatic void
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarksdsl_load_user_sets(objset_t *mos, uint64_t zapobj, avl_tree_t *avl,
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks char checkflag, cred_t *cr)
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks{
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks const gid_t *gids;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks int ngids, i;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks uint64_t id;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks id = crgetuid(cr);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks (void) dsl_load_sets(mos, zapobj,
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks ZFS_DELEG_USER_SETS, checkflag, &id, avl);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks id = crgetgid(cr);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks (void) dsl_load_sets(mos, zapobj,
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks ZFS_DELEG_GROUP_SETS, checkflag, &id, avl);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks (void) dsl_load_sets(mos, zapobj,
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks ZFS_DELEG_EVERYONE_SETS, checkflag, NULL, avl);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks ngids = crgetngroups(cr);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks gids = crgetgroups(cr);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks for (i = 0; i != ngids; i++) {
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks id = gids[i];
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks (void) dsl_load_sets(mos, zapobj,
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks ZFS_DELEG_GROUP_SETS, checkflag, &id, avl);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks }
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks}
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks/*
4445fffbbb1ea25fd0e9ea68b9380dd7a6709025Matthew Ahrens * Check if user has requested permission.
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks */
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarksint
4445fffbbb1ea25fd0e9ea68b9380dd7a6709025Matthew Ahrensdsl_deleg_access_impl(dsl_dataset_t *ds, const char *perm, cred_t *cr)
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks{
bb0ade0978a02d3fe0b0165cd4725fdcb593fbfbahrens dsl_dir_t *dd;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks dsl_pool_t *dp;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks void *cookie;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks int error;
8b33e2134db3b64f2e6c6eae17656c335ad99addWilliam Gorrell char checkflag;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks objset_t *mos;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks avl_tree_t permsets;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks perm_set_t *setnode;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
bb0ade0978a02d3fe0b0165cd4725fdcb593fbfbahrens dp = ds->ds_dir->dd_pool;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks mos = dp->dp_meta_objset;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
a7f53a5629374ca27c5696ace9a1946c2ca050f4Chris Kirby if (dsl_delegation_on(mos) == B_FALSE)
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens return (SET_ERROR(ECANCELED));
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks if (spa_version(dmu_objset_spa(dp->dp_meta_objset)) <
a7f53a5629374ca27c5696ace9a1946c2ca050f4Chris Kirby SPA_VERSION_DELEGATED_PERMS)
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens return (SET_ERROR(EPERM));
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
bc9014e6a81272073b9854d9f65dd59e18d18c35Justin Gibbs if (ds->ds_is_snapshot) {
8b33e2134db3b64f2e6c6eae17656c335ad99addWilliam Gorrell /*
8b33e2134db3b64f2e6c6eae17656c335ad99addWilliam Gorrell * Snapshots are treated as descendents only,
8b33e2134db3b64f2e6c6eae17656c335ad99addWilliam Gorrell * local permissions do not apply.
8b33e2134db3b64f2e6c6eae17656c335ad99addWilliam Gorrell */
8b33e2134db3b64f2e6c6eae17656c335ad99addWilliam Gorrell checkflag = ZFS_DELEG_DESCENDENT;
8b33e2134db3b64f2e6c6eae17656c335ad99addWilliam Gorrell } else {
8b33e2134db3b64f2e6c6eae17656c335ad99addWilliam Gorrell checkflag = ZFS_DELEG_LOCAL;
8b33e2134db3b64f2e6c6eae17656c335ad99addWilliam Gorrell }
8b33e2134db3b64f2e6c6eae17656c335ad99addWilliam Gorrell
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks avl_create(&permsets, perm_set_compare, sizeof (perm_set_t),
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks offsetof(perm_set_t, p_node));
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens ASSERT(dsl_pool_config_held(dp));
bb0ade0978a02d3fe0b0165cd4725fdcb593fbfbahrens for (dd = ds->ds_dir; dd != NULL; dd = dd->dd_parent,
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks checkflag = ZFS_DELEG_DESCENDENT) {
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks uint64_t zapobj;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks boolean_t expanded;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks /*
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * If not in global zone then make sure
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * the zoned property is set
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks */
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks if (!INGLOBALZONE(curproc)) {
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks uint64_t zoned;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
bb0ade0978a02d3fe0b0165cd4725fdcb593fbfbahrens if (dsl_prop_get_dd(dd,
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks zfs_prop_to_name(ZFS_PROP_ZONED),
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson 8, 1, &zoned, NULL, B_FALSE) != 0)
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks break;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks if (!zoned)
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks break;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks }
c1379625401dfbe1c39b79136dd384a571d47fdeJustin T. Gibbs zapobj = dsl_dir_phys(dd)->dd_deleg_zapobj;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks if (zapobj == 0)
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks continue;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks dsl_load_user_sets(mos, zapobj, &permsets, checkflag, cr);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarksagain:
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks expanded = B_FALSE;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks for (setnode = avl_first(&permsets); setnode;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks setnode = AVL_NEXT(&permsets, setnode)) {
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks if (setnode->p_matched == B_TRUE)
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks continue;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks /* See if this set directly grants this permission */
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks error = dsl_check_access(mos, zapobj,
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks ZFS_DELEG_NAMED_SET, 0, setnode->p_setname, perm);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks if (error == 0)
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks goto success;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks if (error == EPERM)
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks setnode->p_matched = B_TRUE;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks /* See if this set includes other sets */
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks error = dsl_load_sets(mos, zapobj,
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks ZFS_DELEG_NAMED_SET_SETS, 0,
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks setnode->p_setname, &permsets);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks if (error == 0)
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks setnode->p_matched = expanded = B_TRUE;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks }
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks /*
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * If we expanded any sets, that will define more sets,
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * which we need to check.
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks */
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks if (expanded)
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks goto again;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks error = dsl_check_user_access(mos, zapobj, perm, checkflag, cr);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks if (error == 0)
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks goto success;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks }
be6fd75a69ae679453d9cda5bff3326111e6d1caMatthew Ahrens error = SET_ERROR(EPERM);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarkssuccess:
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks cookie = NULL;
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens while ((setnode = avl_destroy_nodes(&permsets, &cookie)) != NULL)
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks kmem_free(setnode, sizeof (perm_set_t));
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks return (error);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks}
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
a7f53a5629374ca27c5696ace9a1946c2ca050f4Chris Kirbyint
a7f53a5629374ca27c5696ace9a1946c2ca050f4Chris Kirbydsl_deleg_access(const char *dsname, const char *perm, cred_t *cr)
a7f53a5629374ca27c5696ace9a1946c2ca050f4Chris Kirby{
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens dsl_pool_t *dp;
a7f53a5629374ca27c5696ace9a1946c2ca050f4Chris Kirby dsl_dataset_t *ds;
a7f53a5629374ca27c5696ace9a1946c2ca050f4Chris Kirby int error;
a7f53a5629374ca27c5696ace9a1946c2ca050f4Chris Kirby
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens error = dsl_pool_hold(dsname, FTAG, &dp);
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens if (error != 0)
a7f53a5629374ca27c5696ace9a1946c2ca050f4Chris Kirby return (error);
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens error = dsl_dataset_hold(dp, dsname, FTAG, &ds);
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens if (error == 0) {
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens error = dsl_deleg_access_impl(ds, perm, cr);
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens dsl_dataset_rele(ds, FTAG);
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens }
3b2aab18808792cbd248a12f1edf139b89833c13Matthew Ahrens dsl_pool_rele(dp, FTAG);
a7f53a5629374ca27c5696ace9a1946c2ca050f4Chris Kirby
a7f53a5629374ca27c5696ace9a1946c2ca050f4Chris Kirby return (error);
a7f53a5629374ca27c5696ace9a1946c2ca050f4Chris Kirby}
a7f53a5629374ca27c5696ace9a1946c2ca050f4Chris Kirby
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks/*
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * Other routines.
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks */
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarksstatic void
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrenscopy_create_perms(dsl_dir_t *dd, uint64_t pzapobj,
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks boolean_t dosets, uint64_t uid, dmu_tx_t *tx)
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks{
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens objset_t *mos = dd->dd_pool->dp_meta_objset;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks uint64_t jumpobj, pjumpobj;
c1379625401dfbe1c39b79136dd384a571d47fdeJustin T. Gibbs uint64_t zapobj = dsl_dir_phys(dd)->dd_deleg_zapobj;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks zap_cursor_t zc;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks zap_attribute_t za;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks char whokey[ZFS_MAX_DELEG_NAME];
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks zfs_deleg_whokey(whokey,
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks dosets ? ZFS_DELEG_CREATE_SETS : ZFS_DELEG_CREATE,
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks ZFS_DELEG_LOCAL, NULL);
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens if (zap_lookup(mos, pzapobj, whokey, 8, 1, &pjumpobj) != 0)
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks return;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks if (zapobj == 0) {
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks dmu_buf_will_dirty(dd->dd_dbuf, tx);
c1379625401dfbe1c39b79136dd384a571d47fdeJustin T. Gibbs zapobj = dsl_dir_phys(dd)->dd_deleg_zapobj = zap_create(mos,
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks DMU_OT_DSL_PERMS, DMU_OT_NONE, 0, tx);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks }
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens zfs_deleg_whokey(whokey,
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens dosets ? ZFS_DELEG_USER_SETS : ZFS_DELEG_USER,
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens ZFS_DELEG_LOCAL, &uid);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks if (zap_lookup(mos, zapobj, whokey, 8, 1, &jumpobj) == ENOENT) {
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks jumpobj = zap_create(mos, DMU_OT_DSL_PERMS, DMU_OT_NONE, 0, tx);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks VERIFY(zap_add(mos, zapobj, whokey, 8, 1, &jumpobj, tx) == 0);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks }
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks for (zap_cursor_init(&zc, mos, pjumpobj);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks zap_cursor_retrieve(&zc, &za) == 0;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks zap_cursor_advance(&zc)) {
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens uint64_t zero = 0;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks ASSERT(za.za_integer_length == 8 && za.za_num_integers == 1);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks VERIFY(zap_update(mos, jumpobj, za.za_name,
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks 8, 1, &zero, tx) == 0);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks }
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks zap_cursor_fini(&zc);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks}
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks/*
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * set all create time permission on new dataset.
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks */
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarksvoid
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarksdsl_deleg_set_create_perms(dsl_dir_t *sdd, dmu_tx_t *tx, cred_t *cr)
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks{
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks dsl_dir_t *dd;
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens uint64_t uid = crgetuid(cr);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks if (spa_version(dmu_objset_spa(sdd->dd_pool->dp_meta_objset)) <
990b4856d0eaada6f8140335733a1b1771ed2746lling SPA_VERSION_DELEGATED_PERMS)
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks return;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks for (dd = sdd->dd_parent; dd != NULL; dd = dd->dd_parent) {
c1379625401dfbe1c39b79136dd384a571d47fdeJustin T. Gibbs uint64_t pzapobj = dsl_dir_phys(dd)->dd_deleg_zapobj;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens if (pzapobj == 0)
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks continue;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens copy_create_perms(sdd, pzapobj, B_FALSE, uid, tx);
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens copy_create_perms(sdd, pzapobj, B_TRUE, uid, tx);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks }
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks}
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarksint
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarksdsl_deleg_destroy(objset_t *mos, uint64_t zapobj, dmu_tx_t *tx)
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks{
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks zap_cursor_t zc;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks zap_attribute_t za;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks if (zapobj == 0)
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks return (0);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks for (zap_cursor_init(&zc, mos, zapobj);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks zap_cursor_retrieve(&zc, &za) == 0;
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks zap_cursor_advance(&zc)) {
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks ASSERT(za.za_integer_length == 8 && za.za_num_integers == 1);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks VERIFY(0 == zap_destroy(mos, za.za_first_integer, tx));
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks }
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks zap_cursor_fini(&zc);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks VERIFY(0 == zap_destroy(mos, zapobj, tx));
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks return (0);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks}
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarksboolean_t
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarksdsl_delegation_on(objset_t *os)
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks{
b24ab6762772a3f6a89393947930c7fa61306783Jeff Bonwick return (!!spa_delegation(os->os_spa));
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks}