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 * Copyright (c) 2012 by Delphix. All rights reserved.
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.
504 id = crgetgid(cr);
505 (void) dsl_load_sets(mos, zapobj,
506 ZFS_DELEG_GROUP_SETS, checkflag, &id, avl);
507
508 (void) dsl_load_sets(mos, zapobj,
509 ZFS_DELEG_EVERYONE_SETS, checkflag, NULL, avl);
510
511 ngids = crgetngroups(cr);
512 gids = crgetgroups(cr);
513 for (i = 0; i != ngids; i++) {
514 id = gids[i];
515 (void) dsl_load_sets(mos, zapobj,
516 ZFS_DELEG_GROUP_SETS, checkflag, &id, avl);
517 }
518 }
519
520 /*
521 * Check if user has requested permission.
522 */
523 int
524 dsl_deleg_access_impl(dsl_dataset_t *ds, const char *perm, cred_t *cr)
525 {
526 dsl_dir_t *dd;
527 dsl_pool_t *dp;
528 void *cookie;
529 int error;
530 char checkflag;
531 objset_t *mos;
532 avl_tree_t permsets;
533 perm_set_t *setnode;
534
535 dp = ds->ds_dir->dd_pool;
536 mos = dp->dp_meta_objset;
537
538 if (dsl_delegation_on(mos) == B_FALSE)
539 return (ECANCELED);
540
541 if (spa_version(dmu_objset_spa(dp->dp_meta_objset)) <
542 SPA_VERSION_DELEGATED_PERMS)
543 return (EPERM);
544
545 if (dsl_dataset_is_snapshot(ds)) {
546 /*
547 * Snapshots are treated as descendents only,
548 * local permissions do not apply.
549 */
550 checkflag = ZFS_DELEG_DESCENDENT;
551 } else {
552 checkflag = ZFS_DELEG_LOCAL;
553 }
554
555 avl_create(&permsets, perm_set_compare, sizeof (perm_set_t),
556 offsetof(perm_set_t, p_node));
557
558 rw_enter(&dp->dp_config_rwlock, RW_READER);
559 for (dd = ds->ds_dir; dd != NULL; dd = dd->dd_parent,
560 checkflag = ZFS_DELEG_DESCENDENT) {
561 uint64_t zapobj;
562 boolean_t expanded;
563
564 /*
565 * If not in global zone then make sure
566 * the zoned property is set
567 */
568 if (!INGLOBALZONE(curproc)) {
569 uint64_t zoned;
570
571 if (dsl_prop_get_dd(dd,
572 zfs_prop_to_name(ZFS_PROP_ZONED),
573 8, 1, &zoned, NULL, B_FALSE) != 0)
574 break;
575 if (!zoned)
576 break;
577 }
599 /* See if this set includes other sets */
600 error = dsl_load_sets(mos, zapobj,
601 ZFS_DELEG_NAMED_SET_SETS, 0,
602 setnode->p_setname, &permsets);
603 if (error == 0)
604 setnode->p_matched = expanded = B_TRUE;
605 }
606 /*
607 * If we expanded any sets, that will define more sets,
608 * which we need to check.
609 */
610 if (expanded)
611 goto again;
612
613 error = dsl_check_user_access(mos, zapobj, perm, checkflag, cr);
614 if (error == 0)
615 goto success;
616 }
617 error = EPERM;
618 success:
619 rw_exit(&dp->dp_config_rwlock);
620
621 cookie = NULL;
622 while ((setnode = avl_destroy_nodes(&permsets, &cookie)) != NULL)
623 kmem_free(setnode, sizeof (perm_set_t));
624
625 return (error);
626 }
627
628 int
629 dsl_deleg_access(const char *dsname, const char *perm, cred_t *cr)
630 {
631 dsl_dataset_t *ds;
632 int error;
633
634 error = dsl_dataset_hold(dsname, FTAG, &ds);
635 if (error)
636 return (error);
637
638 error = dsl_deleg_access_impl(ds, perm, cr);
639 dsl_dataset_rele(ds, FTAG);
640
641 return (error);
642 }
643
644 /*
645 * Other routines.
646 */
647
648 static void
649 copy_create_perms(dsl_dir_t *dd, uint64_t pzapobj,
650 boolean_t dosets, uint64_t uid, dmu_tx_t *tx)
651 {
652 objset_t *mos = dd->dd_pool->dp_meta_objset;
653 uint64_t jumpobj, pjumpobj;
654 uint64_t zapobj = dd->dd_phys->dd_deleg_zapobj;
655 zap_cursor_t zc;
656 zap_attribute_t za;
657 char whokey[ZFS_MAX_DELEG_NAME];
658
|
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 * Copyright (c) 2012 by Delphix. All rights reserved.
24 * Copyright (c) 2012 Joyent, Inc. All rights reserved.
25 */
26
27 /*
28 * DSL permissions are stored in a two level zap attribute
29 * mechanism. The first level identifies the "class" of
30 * entry. The class is identified by the first 2 letters of
31 * the attribute. The second letter "l" or "d" identifies whether
32 * it is a local or descendent permission. The first letter
33 * identifies the type of entry.
34 *
35 * ul$<id> identifies permissions granted locally for this userid.
36 * ud$<id> identifies permissions granted on descendent datasets for
37 * this userid.
38 * Ul$<id> identifies permission sets granted locally for this userid.
39 * Ud$<id> identifies permission sets granted on descendent datasets for
40 * this userid.
41 * gl$<id> identifies permissions granted locally for this groupid.
42 * gd$<id> identifies permissions granted on descendent datasets for
43 * this groupid.
44 * Gl$<id> identifies permission sets granted locally for this groupid.
505 id = crgetgid(cr);
506 (void) dsl_load_sets(mos, zapobj,
507 ZFS_DELEG_GROUP_SETS, checkflag, &id, avl);
508
509 (void) dsl_load_sets(mos, zapobj,
510 ZFS_DELEG_EVERYONE_SETS, checkflag, NULL, avl);
511
512 ngids = crgetngroups(cr);
513 gids = crgetgroups(cr);
514 for (i = 0; i != ngids; i++) {
515 id = gids[i];
516 (void) dsl_load_sets(mos, zapobj,
517 ZFS_DELEG_GROUP_SETS, checkflag, &id, avl);
518 }
519 }
520
521 /*
522 * Check if user has requested permission.
523 */
524 int
525 dsl_deleg_access_impl(dsl_dataset_t *ds, const char *perm, cred_t *cr,
526 boolean_t do_lock)
527 {
528 dsl_dir_t *dd;
529 dsl_pool_t *dp;
530 void *cookie;
531 int error;
532 char checkflag;
533 objset_t *mos;
534 avl_tree_t permsets;
535 perm_set_t *setnode;
536
537 dp = ds->ds_dir->dd_pool;
538 mos = dp->dp_meta_objset;
539
540 if (dsl_delegation_on(mos) == B_FALSE)
541 return (ECANCELED);
542
543 if (spa_version(dmu_objset_spa(dp->dp_meta_objset)) <
544 SPA_VERSION_DELEGATED_PERMS)
545 return (EPERM);
546
547 if (dsl_dataset_is_snapshot(ds)) {
548 /*
549 * Snapshots are treated as descendents only,
550 * local permissions do not apply.
551 */
552 checkflag = ZFS_DELEG_DESCENDENT;
553 } else {
554 checkflag = ZFS_DELEG_LOCAL;
555 }
556
557 avl_create(&permsets, perm_set_compare, sizeof (perm_set_t),
558 offsetof(perm_set_t, p_node));
559
560 if (do_lock)
561 rw_enter(&dp->dp_config_rwlock, RW_READER);
562 for (dd = ds->ds_dir; dd != NULL; dd = dd->dd_parent,
563 checkflag = ZFS_DELEG_DESCENDENT) {
564 uint64_t zapobj;
565 boolean_t expanded;
566
567 /*
568 * If not in global zone then make sure
569 * the zoned property is set
570 */
571 if (!INGLOBALZONE(curproc)) {
572 uint64_t zoned;
573
574 if (dsl_prop_get_dd(dd,
575 zfs_prop_to_name(ZFS_PROP_ZONED),
576 8, 1, &zoned, NULL, B_FALSE) != 0)
577 break;
578 if (!zoned)
579 break;
580 }
602 /* See if this set includes other sets */
603 error = dsl_load_sets(mos, zapobj,
604 ZFS_DELEG_NAMED_SET_SETS, 0,
605 setnode->p_setname, &permsets);
606 if (error == 0)
607 setnode->p_matched = expanded = B_TRUE;
608 }
609 /*
610 * If we expanded any sets, that will define more sets,
611 * which we need to check.
612 */
613 if (expanded)
614 goto again;
615
616 error = dsl_check_user_access(mos, zapobj, perm, checkflag, cr);
617 if (error == 0)
618 goto success;
619 }
620 error = EPERM;
621 success:
622 if (do_lock)
623 rw_exit(&dp->dp_config_rwlock);
624
625 cookie = NULL;
626 while ((setnode = avl_destroy_nodes(&permsets, &cookie)) != NULL)
627 kmem_free(setnode, sizeof (perm_set_t));
628
629 return (error);
630 }
631
632 int
633 dsl_deleg_access(const char *dsname, const char *perm, cred_t *cr)
634 {
635 dsl_dataset_t *ds;
636 int error;
637
638 error = dsl_dataset_hold(dsname, FTAG, &ds);
639 if (error)
640 return (error);
641
642 error = dsl_deleg_access_impl(ds, perm, cr, B_TRUE);
643 dsl_dataset_rele(ds, FTAG);
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
|