1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * DSL permissions are stored in a two level zap attribute 28 * mechanism. The first level identifies the "class" of 29 * entry. The class is identified by the first 2 letters of 30 * the attribute. The second letter "l" or "d" identifies whether 31 * it is a local or descendent permission. The first letter 32 * identifies the type of entry. 33 * 34 * ul$<id> identifies permissions granted locally for this userid. 35 * ud$<id> identifies permissions granted on descendent datasets for 36 * this userid. 37 * Ul$<id> identifies permission sets granted locally for this userid. 38 * Ud$<id> identifies permission sets granted on descendent datasets for 39 * this userid. 40 * gl$<id> identifies permissions granted locally for this groupid. 41 * gd$<id> identifies permissions granted on descendent datasets for 42 * this groupid. 43 * Gl$<id> identifies permission sets granted locally for this groupid. 44 * Gd$<id> identifies permission sets granted on descendent datasets for 45 * this groupid. 46 * el$ identifies permissions granted locally for everyone. 47 * ed$ identifies permissions granted on descendent datasets 48 * for everyone. 49 * El$ identifies permission sets granted locally for everyone. 50 * Ed$ identifies permission sets granted to descendent datasets for 51 * everyone. 52 * c-$ identifies permission to create at dataset creation time. 53 * C-$ identifies permission sets to grant locally at dataset creation 54 * time. 55 * s-$@<name> permissions defined in specified set @<name> 56 * S-$@<name> Sets defined in named set @<name> 57 * 58 * Each of the above entities points to another zap attribute that contains one 59 * attribute for each allowed permission, such as create, destroy,... 60 * All of the "upper" case class types will specify permission set names 61 * rather than permissions. 62 * 63 * Basically it looks something like this: 64 * ul$12 -> ZAP OBJ -> permissions... 65 * 66 * The ZAP OBJ is referred to as the jump object. 67 */ 68 69 #include <sys/dmu.h> 70 #include <sys/dmu_objset.h> 71 #include <sys/dmu_tx.h> 72 #include <sys/dsl_dataset.h> 73 #include <sys/dsl_dir.h> 74 #include <sys/dsl_prop.h> 75 #include <sys/dsl_synctask.h> 76 #include <sys/dsl_deleg.h> 77 #include <sys/spa.h> 78 #include <sys/spa_impl.h> 79 #include <sys/zio_checksum.h> /* for the default checksum value */ 80 #include <sys/zap.h> 81 #include <sys/fs/zfs.h> 82 #include <sys/cred.h> 83 #include <sys/sunddi.h> 84 85 #include "zfs_deleg.h" 86 87 /* 88 * Validate that user is allowed to delegate specified permissions. 89 * 90 * In order to delegate "create" you must have "create" 91 * and "allow". 92 */ 93 int 94 dsl_deleg_can_allow(char *ddname, nvlist_t *nvp, cred_t *cr) 95 { 96 nvpair_t *whopair = NULL; 97 int error; 98 99 if ((error = dsl_deleg_access(ddname, ZFS_DELEG_PERM_ALLOW, cr)) != 0) 100 return (error); 101 102 while (whopair = nvlist_next_nvpair(nvp, whopair)) { 103 nvlist_t *perms; 104 nvpair_t *permpair = NULL; 105 106 VERIFY(nvpair_value_nvlist(whopair, &perms) == 0); 107 108 while (permpair = nvlist_next_nvpair(perms, permpair)) { 109 const char *perm = nvpair_name(permpair); 110 111 if (strcmp(perm, ZFS_DELEG_PERM_ALLOW) == 0) 112 return (EPERM); 113 114 if ((error = dsl_deleg_access(ddname, perm, cr)) != 0) 115 return (error); 116 } 117 } 118 return (0); 119 } 120 121 /* 122 * Validate that user is allowed to unallow specified permissions. They 123 * must have the 'allow' permission, and even then can only unallow 124 * perms for their uid. 125 */ 126 int 127 dsl_deleg_can_unallow(char *ddname, nvlist_t *nvp, cred_t *cr) 128 { 129 nvpair_t *whopair = NULL; 130 int error; 131 char idstr[32]; 132 133 if ((error = dsl_deleg_access(ddname, ZFS_DELEG_PERM_ALLOW, cr)) != 0) 134 return (error); 135 136 (void) snprintf(idstr, sizeof (idstr), "%lld", 137 (longlong_t)crgetuid(cr)); 138 139 while (whopair = nvlist_next_nvpair(nvp, whopair)) { 140 zfs_deleg_who_type_t type = nvpair_name(whopair)[0]; 141 142 if (type != ZFS_DELEG_USER && 143 type != ZFS_DELEG_USER_SETS) 144 return (EPERM); 145 146 if (strcmp(idstr, &nvpair_name(whopair)[3]) != 0) 147 return (EPERM); 148 } 149 return (0); 150 } 151 152 static void 153 dsl_deleg_set_sync(void *arg1, void *arg2, cred_t *cr, dmu_tx_t *tx) 154 { 155 dsl_dir_t *dd = arg1; 156 nvlist_t *nvp = arg2; 157 objset_t *mos = dd->dd_pool->dp_meta_objset; 158 nvpair_t *whopair = NULL; 159 uint64_t zapobj = dd->dd_phys->dd_deleg_zapobj; 160 161 if (zapobj == 0) { 162 dmu_buf_will_dirty(dd->dd_dbuf, tx); 163 zapobj = dd->dd_phys->dd_deleg_zapobj = zap_create(mos, 164 DMU_OT_DSL_PERMS, DMU_OT_NONE, 0, tx); 165 } 166 167 while (whopair = nvlist_next_nvpair(nvp, whopair)) { 168 const char *whokey = nvpair_name(whopair); 169 nvlist_t *perms; 170 nvpair_t *permpair = NULL; 171 uint64_t jumpobj; 172 173 VERIFY(nvpair_value_nvlist(whopair, &perms) == 0); 174 175 if (zap_lookup(mos, zapobj, whokey, 8, 1, &jumpobj) != 0) { 176 jumpobj = zap_create(mos, DMU_OT_DSL_PERMS, 177 DMU_OT_NONE, 0, tx); 178 VERIFY(zap_update(mos, zapobj, 179 whokey, 8, 1, &jumpobj, tx) == 0); 180 } 181 182 while (permpair = nvlist_next_nvpair(perms, permpair)) { 183 const char *perm = nvpair_name(permpair); 184 uint64_t n = 0; 185 186 VERIFY(zap_update(mos, jumpobj, 187 perm, 8, 1, &n, tx) == 0); 188 spa_history_internal_log(LOG_DS_PERM_UPDATE, 189 dd->dd_pool->dp_spa, tx, cr, 190 "%s %s dataset = %llu", whokey, perm, 191 dd->dd_phys->dd_head_dataset_obj); 192 } 193 } 194 } 195 196 static void 197 dsl_deleg_unset_sync(void *arg1, void *arg2, cred_t *cr, dmu_tx_t *tx) 198 { 199 dsl_dir_t *dd = arg1; 200 nvlist_t *nvp = arg2; 201 objset_t *mos = dd->dd_pool->dp_meta_objset; 202 nvpair_t *whopair = NULL; 203 uint64_t zapobj = dd->dd_phys->dd_deleg_zapobj; 204 205 if (zapobj == 0) 206 return; 207 208 while (whopair = nvlist_next_nvpair(nvp, whopair)) { 209 const char *whokey = nvpair_name(whopair); 210 nvlist_t *perms; 211 nvpair_t *permpair = NULL; 212 uint64_t jumpobj; 213 214 if (nvpair_value_nvlist(whopair, &perms) != 0) { 215 if (zap_lookup(mos, zapobj, whokey, 8, 216 1, &jumpobj) == 0) { 217 (void) zap_remove(mos, zapobj, whokey, tx); 218 VERIFY(0 == zap_destroy(mos, jumpobj, tx)); 219 } 220 spa_history_internal_log(LOG_DS_PERM_WHO_REMOVE, 221 dd->dd_pool->dp_spa, tx, cr, 222 "%s dataset = %llu", whokey, 223 dd->dd_phys->dd_head_dataset_obj); 224 continue; 225 } 226 227 if (zap_lookup(mos, zapobj, whokey, 8, 1, &jumpobj) != 0) 228 continue; 229 230 while (permpair = nvlist_next_nvpair(perms, permpair)) { 231 const char *perm = nvpair_name(permpair); 232 uint64_t n = 0; 233 234 (void) zap_remove(mos, jumpobj, perm, tx); 235 if (zap_count(mos, jumpobj, &n) == 0 && n == 0) { 236 (void) zap_remove(mos, zapobj, 237 whokey, tx); 238 VERIFY(0 == zap_destroy(mos, 239 jumpobj, tx)); 240 } 241 spa_history_internal_log(LOG_DS_PERM_REMOVE, 242 dd->dd_pool->dp_spa, tx, cr, 243 "%s %s dataset = %llu", whokey, perm, 244 dd->dd_phys->dd_head_dataset_obj); 245 } 246 } 247 } 248 249 int 250 dsl_deleg_set(const char *ddname, nvlist_t *nvp, boolean_t unset) 251 { 252 dsl_dir_t *dd; 253 int error; 254 nvpair_t *whopair = NULL; 255 int blocks_modified = 0; 256 257 error = dsl_dir_open(ddname, FTAG, &dd, NULL); 258 if (error) 259 return (error); 260 261 if (spa_version(dmu_objset_spa(dd->dd_pool->dp_meta_objset)) < 262 SPA_VERSION_DELEGATED_PERMS) { 263 dsl_dir_close(dd, FTAG); 264 return (ENOTSUP); 265 } 266 267 while (whopair = nvlist_next_nvpair(nvp, whopair)) 268 blocks_modified++; 269 270 error = dsl_sync_task_do(dd->dd_pool, NULL, 271 unset ? dsl_deleg_unset_sync : dsl_deleg_set_sync, 272 dd, nvp, blocks_modified); 273 dsl_dir_close(dd, FTAG); 274 275 return (error); 276 } 277 278 /* 279 * Find all 'allow' permissions from a given point and then continue 280 * traversing up to the root. 281 * 282 * This function constructs an nvlist of nvlists. 283 * each setpoint is an nvlist composed of an nvlist of an nvlist 284 * of the individual * users/groups/everyone/create 285 * permissions. 286 * 287 * The nvlist will look like this. 288 * 289 * { source fsname -> { whokeys { permissions,...}, ...}} 290 * 291 * The fsname nvpairs will be arranged in a bottom up order. For example, 292 * if we have the following structure a/b/c then the nvpairs for the fsnames 293 * will be ordered a/b/c, a/b, a. 294 */ 295 int 296 dsl_deleg_get(const char *ddname, nvlist_t **nvp) 297 { 298 dsl_dir_t *dd, *startdd; 299 dsl_pool_t *dp; 300 int error; 301 objset_t *mos; 302 303 error = dsl_dir_open(ddname, FTAG, &startdd, NULL); 304 if (error) 305 return (error); 306 307 dp = startdd->dd_pool; 308 mos = dp->dp_meta_objset; 309 310 VERIFY(nvlist_alloc(nvp, NV_UNIQUE_NAME, KM_SLEEP) == 0); 311 312 rw_enter(&dp->dp_config_rwlock, RW_READER); 313 for (dd = startdd; dd != NULL; dd = dd->dd_parent) { 314 zap_cursor_t basezc; 315 zap_attribute_t baseza; 316 nvlist_t *sp_nvp; 317 uint64_t n; 318 char source[MAXNAMELEN]; 319 320 if (dd->dd_phys->dd_deleg_zapobj && 321 (zap_count(mos, dd->dd_phys->dd_deleg_zapobj, 322 &n) == 0) && n) { 323 VERIFY(nvlist_alloc(&sp_nvp, 324 NV_UNIQUE_NAME, KM_SLEEP) == 0); 325 } else { 326 continue; 327 } 328 329 for (zap_cursor_init(&basezc, mos, 330 dd->dd_phys->dd_deleg_zapobj); 331 zap_cursor_retrieve(&basezc, &baseza) == 0; 332 zap_cursor_advance(&basezc)) { 333 zap_cursor_t zc; 334 zap_attribute_t za; 335 nvlist_t *perms_nvp; 336 337 ASSERT(baseza.za_integer_length == 8); 338 ASSERT(baseza.za_num_integers == 1); 339 340 VERIFY(nvlist_alloc(&perms_nvp, 341 NV_UNIQUE_NAME, KM_SLEEP) == 0); 342 for (zap_cursor_init(&zc, mos, baseza.za_first_integer); 343 zap_cursor_retrieve(&zc, &za) == 0; 344 zap_cursor_advance(&zc)) { 345 VERIFY(nvlist_add_boolean(perms_nvp, 346 za.za_name) == 0); 347 } 348 zap_cursor_fini(&zc); 349 VERIFY(nvlist_add_nvlist(sp_nvp, baseza.za_name, 350 perms_nvp) == 0); 351 nvlist_free(perms_nvp); 352 } 353 354 zap_cursor_fini(&basezc); 355 356 dsl_dir_name(dd, source); 357 VERIFY(nvlist_add_nvlist(*nvp, source, sp_nvp) == 0); 358 nvlist_free(sp_nvp); 359 } 360 rw_exit(&dp->dp_config_rwlock); 361 362 dsl_dir_close(startdd, FTAG); 363 return (0); 364 } 365 366 /* 367 * Routines for dsl_deleg_access() -- access checking. 368 */ 369 typedef struct perm_set { 370 avl_node_t p_node; 371 boolean_t p_matched; 372 char p_setname[ZFS_MAX_DELEG_NAME]; 373 } perm_set_t; 374 375 static int 376 perm_set_compare(const void *arg1, const void *arg2) 377 { 378 const perm_set_t *node1 = arg1; 379 const perm_set_t *node2 = arg2; 380 int val; 381 382 val = strcmp(node1->p_setname, node2->p_setname); 383 if (val == 0) 384 return (0); 385 return (val > 0 ? 1 : -1); 386 } 387 388 /* 389 * Determine whether a specified permission exists. 390 * 391 * First the base attribute has to be retrieved. i.e. ul$12 392 * Once the base object has been retrieved the actual permission 393 * is lookup up in the zap object the base object points to. 394 * 395 * Return 0 if permission exists, ENOENT if there is no whokey, EPERM if 396 * there is no perm in that jumpobj. 397 */ 398 static int 399 dsl_check_access(objset_t *mos, uint64_t zapobj, 400 char type, char checkflag, void *valp, const char *perm) 401 { 402 int error; 403 uint64_t jumpobj, zero; 404 char whokey[ZFS_MAX_DELEG_NAME]; 405 406 zfs_deleg_whokey(whokey, type, checkflag, valp); 407 error = zap_lookup(mos, zapobj, whokey, 8, 1, &jumpobj); 408 if (error == 0) { 409 error = zap_lookup(mos, jumpobj, perm, 8, 1, &zero); 410 if (error == ENOENT) 411 error = EPERM; 412 } 413 return (error); 414 } 415 416 /* 417 * check a specified user/group for a requested permission 418 */ 419 static int 420 dsl_check_user_access(objset_t *mos, uint64_t zapobj, const char *perm, 421 int checkflag, cred_t *cr) 422 { 423 const gid_t *gids; 424 int ngids; 425 int i; 426 uint64_t id; 427 428 /* check for user */ 429 id = crgetuid(cr); 430 if (dsl_check_access(mos, zapobj, 431 ZFS_DELEG_USER, checkflag, &id, perm) == 0) 432 return (0); 433 434 /* check for users primary group */ 435 id = crgetgid(cr); 436 if (dsl_check_access(mos, zapobj, 437 ZFS_DELEG_GROUP, checkflag, &id, perm) == 0) 438 return (0); 439 440 /* check for everyone entry */ 441 id = -1; 442 if (dsl_check_access(mos, zapobj, 443 ZFS_DELEG_EVERYONE, checkflag, &id, perm) == 0) 444 return (0); 445 446 /* check each supplemental group user is a member of */ 447 ngids = crgetngroups(cr); 448 gids = crgetgroups(cr); 449 for (i = 0; i != ngids; i++) { 450 id = gids[i]; 451 if (dsl_check_access(mos, zapobj, 452 ZFS_DELEG_GROUP, checkflag, &id, perm) == 0) 453 return (0); 454 } 455 456 return (EPERM); 457 } 458 459 /* 460 * Iterate over the sets specified in the specified zapobj 461 * and load them into the permsets avl tree. 462 */ 463 static int 464 dsl_load_sets(objset_t *mos, uint64_t zapobj, 465 char type, char checkflag, void *valp, avl_tree_t *avl) 466 { 467 zap_cursor_t zc; 468 zap_attribute_t za; 469 perm_set_t *permnode; 470 avl_index_t idx; 471 uint64_t jumpobj; 472 int error; 473 char whokey[ZFS_MAX_DELEG_NAME]; 474 475 zfs_deleg_whokey(whokey, type, checkflag, valp); 476 477 error = zap_lookup(mos, zapobj, whokey, 8, 1, &jumpobj); 478 if (error != 0) 479 return (error); 480 481 for (zap_cursor_init(&zc, mos, jumpobj); 482 zap_cursor_retrieve(&zc, &za) == 0; 483 zap_cursor_advance(&zc)) { 484 permnode = kmem_alloc(sizeof (perm_set_t), KM_SLEEP); 485 (void) strlcpy(permnode->p_setname, za.za_name, 486 sizeof (permnode->p_setname)); 487 permnode->p_matched = B_FALSE; 488 489 if (avl_find(avl, permnode, &idx) == NULL) { 490 avl_insert(avl, permnode, idx); 491 } else { 492 kmem_free(permnode, sizeof (perm_set_t)); 493 } 494 } 495 zap_cursor_fini(&zc); 496 return (0); 497 } 498 499 /* 500 * Load all permissions user based on cred belongs to. 501 */ 502 static void 503 dsl_load_user_sets(objset_t *mos, uint64_t zapobj, avl_tree_t *avl, 504 char checkflag, cred_t *cr) 505 { 506 const gid_t *gids; 507 int ngids, i; 508 uint64_t id; 509 510 id = crgetuid(cr); 511 (void) dsl_load_sets(mos, zapobj, 512 ZFS_DELEG_USER_SETS, checkflag, &id, avl); 513 514 id = crgetgid(cr); 515 (void) dsl_load_sets(mos, zapobj, 516 ZFS_DELEG_GROUP_SETS, checkflag, &id, avl); 517 518 (void) dsl_load_sets(mos, zapobj, 519 ZFS_DELEG_EVERYONE_SETS, checkflag, NULL, avl); 520 521 ngids = crgetngroups(cr); 522 gids = crgetgroups(cr); 523 for (i = 0; i != ngids; i++) { 524 id = gids[i]; 525 (void) dsl_load_sets(mos, zapobj, 526 ZFS_DELEG_GROUP_SETS, checkflag, &id, avl); 527 } 528 } 529 530 /* 531 * Check if user has requested permission. 532 */ 533 int 534 dsl_deleg_access(const char *dsname, const char *perm, cred_t *cr) 535 { 536 dsl_dataset_t *ds; 537 dsl_dir_t *dd; 538 dsl_pool_t *dp; 539 void *cookie; 540 int error; 541 char checkflag; 542 objset_t *mos; 543 avl_tree_t permsets; 544 perm_set_t *setnode; 545 546 error = dsl_dataset_hold(dsname, FTAG, &ds); 547 if (error) 548 return (error); 549 550 dp = ds->ds_dir->dd_pool; 551 mos = dp->dp_meta_objset; 552 553 if (dsl_delegation_on(mos) == B_FALSE) { 554 dsl_dataset_rele(ds, FTAG); 555 return (ECANCELED); 556 } 557 558 if (spa_version(dmu_objset_spa(dp->dp_meta_objset)) < 559 SPA_VERSION_DELEGATED_PERMS) { 560 dsl_dataset_rele(ds, FTAG); 561 return (EPERM); 562 } 563 564 if (dsl_dataset_is_snapshot(ds)) { 565 /* 566 * Snapshots are treated as descendents only, 567 * local permissions do not apply. 568 */ 569 checkflag = ZFS_DELEG_DESCENDENT; 570 } else { 571 checkflag = ZFS_DELEG_LOCAL; 572 } 573 574 avl_create(&permsets, perm_set_compare, sizeof (perm_set_t), 575 offsetof(perm_set_t, p_node)); 576 577 rw_enter(&dp->dp_config_rwlock, RW_READER); 578 for (dd = ds->ds_dir; dd != NULL; dd = dd->dd_parent, 579 checkflag = ZFS_DELEG_DESCENDENT) { 580 uint64_t zapobj; 581 boolean_t expanded; 582 583 /* 584 * If not in global zone then make sure 585 * the zoned property is set 586 */ 587 if (!INGLOBALZONE(curproc)) { 588 uint64_t zoned; 589 590 if (dsl_prop_get_dd(dd, 591 zfs_prop_to_name(ZFS_PROP_ZONED), 592 8, 1, &zoned, NULL) != 0) 593 break; 594 if (!zoned) 595 break; 596 } 597 zapobj = dd->dd_phys->dd_deleg_zapobj; 598 599 if (zapobj == 0) 600 continue; 601 602 dsl_load_user_sets(mos, zapobj, &permsets, checkflag, cr); 603 again: 604 expanded = B_FALSE; 605 for (setnode = avl_first(&permsets); setnode; 606 setnode = AVL_NEXT(&permsets, setnode)) { 607 if (setnode->p_matched == B_TRUE) 608 continue; 609 610 /* See if this set directly grants this permission */ 611 error = dsl_check_access(mos, zapobj, 612 ZFS_DELEG_NAMED_SET, 0, setnode->p_setname, perm); 613 if (error == 0) 614 goto success; 615 if (error == EPERM) 616 setnode->p_matched = B_TRUE; 617 618 /* See if this set includes other sets */ 619 error = dsl_load_sets(mos, zapobj, 620 ZFS_DELEG_NAMED_SET_SETS, 0, 621 setnode->p_setname, &permsets); 622 if (error == 0) 623 setnode->p_matched = expanded = B_TRUE; 624 } 625 /* 626 * If we expanded any sets, that will define more sets, 627 * which we need to check. 628 */ 629 if (expanded) 630 goto again; 631 632 error = dsl_check_user_access(mos, zapobj, perm, checkflag, cr); 633 if (error == 0) 634 goto success; 635 } 636 error = EPERM; 637 success: 638 rw_exit(&dp->dp_config_rwlock); 639 dsl_dataset_rele(ds, FTAG); 640 641 cookie = NULL; 642 while ((setnode = avl_destroy_nodes(&permsets, &cookie)) != NULL) 643 kmem_free(setnode, sizeof (perm_set_t)); 644 645 return (error); 646 } 647 648 /* 649 * Other routines. 650 */ 651 652 static void 653 copy_create_perms(dsl_dir_t *dd, uint64_t pzapobj, 654 boolean_t dosets, uint64_t uid, dmu_tx_t *tx) 655 { 656 objset_t *mos = dd->dd_pool->dp_meta_objset; 657 uint64_t jumpobj, pjumpobj; 658 uint64_t zapobj = dd->dd_phys->dd_deleg_zapobj; 659 zap_cursor_t zc; 660 zap_attribute_t za; 661 char whokey[ZFS_MAX_DELEG_NAME]; 662 663 zfs_deleg_whokey(whokey, 664 dosets ? ZFS_DELEG_CREATE_SETS : ZFS_DELEG_CREATE, 665 ZFS_DELEG_LOCAL, NULL); 666 if (zap_lookup(mos, pzapobj, whokey, 8, 1, &pjumpobj) != 0) 667 return; 668 669 if (zapobj == 0) { 670 dmu_buf_will_dirty(dd->dd_dbuf, tx); 671 zapobj = dd->dd_phys->dd_deleg_zapobj = zap_create(mos, 672 DMU_OT_DSL_PERMS, DMU_OT_NONE, 0, tx); 673 } 674 675 zfs_deleg_whokey(whokey, 676 dosets ? ZFS_DELEG_USER_SETS : ZFS_DELEG_USER, 677 ZFS_DELEG_LOCAL, &uid); 678 if (zap_lookup(mos, zapobj, whokey, 8, 1, &jumpobj) == ENOENT) { 679 jumpobj = zap_create(mos, DMU_OT_DSL_PERMS, DMU_OT_NONE, 0, tx); 680 VERIFY(zap_add(mos, zapobj, whokey, 8, 1, &jumpobj, tx) == 0); 681 } 682 683 for (zap_cursor_init(&zc, mos, pjumpobj); 684 zap_cursor_retrieve(&zc, &za) == 0; 685 zap_cursor_advance(&zc)) { 686 uint64_t zero = 0; 687 ASSERT(za.za_integer_length == 8 && za.za_num_integers == 1); 688 689 VERIFY(zap_update(mos, jumpobj, za.za_name, 690 8, 1, &zero, tx) == 0); 691 } 692 zap_cursor_fini(&zc); 693 } 694 695 /* 696 * set all create time permission on new dataset. 697 */ 698 void 699 dsl_deleg_set_create_perms(dsl_dir_t *sdd, dmu_tx_t *tx, cred_t *cr) 700 { 701 dsl_dir_t *dd; 702 uint64_t uid = crgetuid(cr); 703 704 if (spa_version(dmu_objset_spa(sdd->dd_pool->dp_meta_objset)) < 705 SPA_VERSION_DELEGATED_PERMS) 706 return; 707 708 for (dd = sdd->dd_parent; dd != NULL; dd = dd->dd_parent) { 709 uint64_t pzapobj = dd->dd_phys->dd_deleg_zapobj; 710 711 if (pzapobj == 0) 712 continue; 713 714 copy_create_perms(sdd, pzapobj, B_FALSE, uid, tx); 715 copy_create_perms(sdd, pzapobj, B_TRUE, uid, tx); 716 } 717 } 718 719 int 720 dsl_deleg_destroy(objset_t *mos, uint64_t zapobj, dmu_tx_t *tx) 721 { 722 zap_cursor_t zc; 723 zap_attribute_t za; 724 725 if (zapobj == 0) 726 return (0); 727 728 for (zap_cursor_init(&zc, mos, zapobj); 729 zap_cursor_retrieve(&zc, &za) == 0; 730 zap_cursor_advance(&zc)) { 731 ASSERT(za.za_integer_length == 8 && za.za_num_integers == 1); 732 VERIFY(0 == zap_destroy(mos, za.za_first_integer, tx)); 733 } 734 zap_cursor_fini(&zc); 735 VERIFY(0 == zap_destroy(mos, zapobj, tx)); 736 return (0); 737 } 738 739 boolean_t 740 dsl_delegation_on(objset_t *os) 741 { 742 return (os->os->os_spa->spa_delegation); 743 } 744