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