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