usr/src/uts/common/fs/zfs/dsl_deleg.c
changeset 4787 602d3f97842c
parent 4543 12bb2876a62e
child 5094 71a3e95fb9e2
equal deleted inserted replaced
4786:9c83486af455 4787:602d3f97842c
    87 #include "zfs_deleg.h"
    87 #include "zfs_deleg.h"
    88 
    88 
    89 /*
    89 /*
    90  * Validate that user is allowed to delegate specified permissions.
    90  * Validate that user is allowed to delegate specified permissions.
    91  *
    91  *
    92  * In order to delegate "create" you must have create"
    92  * In order to delegate "create" you must have "create"
    93  * and "allow".
    93  * and "allow".
    94  */
    94  */
    95 int
    95 int
    96 dsl_deleg_can_allow(char *ddname, nvlist_t *nvp, cred_t *cr)
    96 dsl_deleg_can_allow(char *ddname, nvlist_t *nvp, cred_t *cr)
    97 {
    97 {
    98 	nvpair_t *whopair = NULL;
    98 	nvpair_t *whopair = NULL;
    99 	int error = 0;
    99 	int error;
   100 
   100 
   101 	if ((error = dsl_deleg_access(ddname,
   101 	if ((error = dsl_deleg_access(ddname, ZFS_DELEG_PERM_ALLOW, cr)) != 0)
   102 	    ZFS_DELEG_PERM_ALLOW, cr)) != 0)
       
   103 		return (error);
   102 		return (error);
   104 
   103 
   105 	while (whopair = nvlist_next_nvpair(nvp, whopair)) {
   104 	while (whopair = nvlist_next_nvpair(nvp, whopair)) {
   106 		nvlist_t *perms;
   105 		nvlist_t *perms;
   107 		nvpair_t *permpair = NULL;
   106 		nvpair_t *permpair = NULL;
   112 			const char *perm = nvpair_name(permpair);
   111 			const char *perm = nvpair_name(permpair);
   113 
   112 
   114 			if (strcmp(perm, ZFS_DELEG_PERM_ALLOW) == 0)
   113 			if (strcmp(perm, ZFS_DELEG_PERM_ALLOW) == 0)
   115 				return (EPERM);
   114 				return (EPERM);
   116 
   115 
   117 			if ((error = dsl_deleg_access(ddname,
   116 			if ((error = dsl_deleg_access(ddname, perm, cr)) != 0)
   118 			    perm, cr)) != 0)
       
   119 				return (error);
   117 				return (error);
   120 		}
   118 		}
   121 	}
   119 	}
   122 	return (error);
   120 	return (0);
   123 }
   121 }
   124 
   122 
   125 /*
   123 /*
   126  * Validate that user is allowed to unallow specified permissions.  They
   124  * Validate that user is allowed to unallow specified permissions.  They
   127  * must have the 'allow' permission, and even then can only unallow
   125  * must have the 'allow' permission, and even then can only unallow
   130 int
   128 int
   131 dsl_deleg_can_unallow(char *ddname, nvlist_t *nvp, cred_t *cr)
   129 dsl_deleg_can_unallow(char *ddname, nvlist_t *nvp, cred_t *cr)
   132 {
   130 {
   133 	nvpair_t *whopair = NULL;
   131 	nvpair_t *whopair = NULL;
   134 	int error;
   132 	int error;
   135 
   133 	char idstr[32];
   136 	if ((error = dsl_deleg_access(ddname,
   134 
   137 	    ZFS_DELEG_PERM_ALLOW, cr)) != 0)
   135 	if ((error = dsl_deleg_access(ddname, ZFS_DELEG_PERM_ALLOW, cr)) != 0)
   138 		return (error);
   136 		return (error);
       
   137 
       
   138 	(void) snprintf(idstr, sizeof (idstr), "%lld",
       
   139 	    (longlong_t)crgetuid(cr));
   139 
   140 
   140 	while (whopair = nvlist_next_nvpair(nvp, whopair)) {
   141 	while (whopair = nvlist_next_nvpair(nvp, whopair)) {
   141 		zfs_deleg_who_type_t type = nvpair_name(whopair)[0];
   142 		zfs_deleg_who_type_t type = nvpair_name(whopair)[0];
   142 		char idstr[32];
       
   143 
   143 
   144 		if (type != ZFS_DELEG_USER &&
   144 		if (type != ZFS_DELEG_USER &&
   145 		    type != ZFS_DELEG_USER_SETS)
   145 		    type != ZFS_DELEG_USER_SETS)
   146 			return (EPERM);
   146 			return (EPERM);
   147 
   147 
   148 		(void) snprintf(idstr, sizeof (idstr), "%lld",
       
   149 		    (longlong_t)crgetuid(cr));
       
   150 		if (strcmp(idstr, &nvpair_name(whopair)[3]) != 0)
   148 		if (strcmp(idstr, &nvpair_name(whopair)[3]) != 0)
   151 			return (EPERM);
   149 			return (EPERM);
   152 
       
   153 		continue;
       
   154 	}
   150 	}
   155 	return (0);
   151 	return (0);
   156 }
   152 }
   157 
   153 
   158 typedef struct {
   154 typedef struct {
   182 		nvlist_t *perms;
   178 		nvlist_t *perms;
   183 		nvpair_t *permpair = NULL;
   179 		nvpair_t *permpair = NULL;
   184 		uint64_t jumpobj;
   180 		uint64_t jumpobj;
   185 
   181 
   186 		if (nvpair_value_nvlist(whopair, &perms) != 0) {
   182 		if (nvpair_value_nvlist(whopair, &perms) != 0) {
       
   183 			ASSERT(pa->p_unset);
   187 			if (zap_lookup(mos, zapobj, whokey, 8,
   184 			if (zap_lookup(mos, zapobj, whokey, 8,
   188 			    1, &jumpobj) == 0) {
   185 			    1, &jumpobj) == 0) {
   189 				(void) zap_remove(mos, zapobj, whokey, tx);
   186 				(void) zap_remove(mos, zapobj, whokey, tx);
   190 				VERIFY(0 == zap_destroy(mos, jumpobj, tx));
   187 				VERIFY(0 == zap_destroy(mos, jumpobj, tx));
   191 			}
   188 			}
   199 		if (zap_lookup(mos, zapobj, whokey, 8, 1, &jumpobj) != 0) {
   196 		if (zap_lookup(mos, zapobj, whokey, 8, 1, &jumpobj) != 0) {
   200 			/*
   197 			/*
   201 			 * If object doesn't exist and we are removing
   198 			 * If object doesn't exist and we are removing
   202 			 * it, then just continue to next item in nvlist
   199 			 * it, then just continue to next item in nvlist
   203 			 */
   200 			 */
   204 			if (pa->p_unset == 1)
   201 			if (pa->p_unset)
   205 				continue;
   202 				continue;
   206 			jumpobj = zap_create(mos, DMU_OT_DSL_PERMS,
   203 			jumpobj = zap_create(mos, DMU_OT_DSL_PERMS,
   207 			    DMU_OT_NONE, 0, tx);
   204 			    DMU_OT_NONE, 0, tx);
   208 			VERIFY(zap_update(mos, zapobj,
   205 			VERIFY(zap_update(mos, zapobj,
   209 			    whokey, 8, 1, &jumpobj, tx) == 0);
   206 			    whokey, 8, 1, &jumpobj, tx) == 0);
   357 /*
   354 /*
   358  * Routines for dsl_deleg_access() -- access checking.
   355  * Routines for dsl_deleg_access() -- access checking.
   359  */
   356  */
   360 typedef struct perm_set {
   357 typedef struct perm_set {
   361 	avl_node_t	p_node;
   358 	avl_node_t	p_node;
       
   359 	boolean_t	p_matched;
   362 	char		p_setname[ZFS_MAX_DELEG_NAME];
   360 	char		p_setname[ZFS_MAX_DELEG_NAME];
   363 	boolean_t	p_matched;
       
   364 } perm_set_t;
   361 } perm_set_t;
   365 
   362 
   366 static int
   363 static int
   367 perm_set_compare(const void *arg1, const void *arg2)
   364 perm_set_compare(const void *arg1, const void *arg2)
   368 {
   365 {
   406 
   403 
   407 /*
   404 /*
   408  * check a specified user/group for a requested permission
   405  * check a specified user/group for a requested permission
   409  */
   406  */
   410 static int
   407 static int
   411 dsl_check_user_access(objset_t *os, uint64_t zapobj, const char *perm,
   408 dsl_check_user_access(objset_t *mos, uint64_t zapobj, const char *perm,
   412     int checkflag, cred_t *cr)
   409     int checkflag, cred_t *cr)
   413 {
   410 {
   414 	const	gid_t *gids;
   411 	const	gid_t *gids;
   415 	int	ngids;
   412 	int	ngids;
   416 	int	i;
   413 	int	i;
   417 	uint64_t id;
   414 	uint64_t id;
   418 
   415 
   419 	/* check for user */
   416 	/* check for user */
   420 	id = crgetuid(cr);
   417 	id = crgetuid(cr);
   421 	if (dsl_check_access(os, zapobj,
   418 	if (dsl_check_access(mos, zapobj,
   422 	    ZFS_DELEG_USER, checkflag, &id, perm) == 0)
   419 	    ZFS_DELEG_USER, checkflag, &id, perm) == 0)
   423 		return (0);
   420 		return (0);
   424 
   421 
   425 	/* check for users primary group */
   422 	/* check for users primary group */
   426 	id = crgetgid(cr);
   423 	id = crgetgid(cr);
   427 	if (dsl_check_access(os, zapobj,
   424 	if (dsl_check_access(mos, zapobj,
   428 	    ZFS_DELEG_GROUP, checkflag, &id, perm) == 0)
   425 	    ZFS_DELEG_GROUP, checkflag, &id, perm) == 0)
   429 		return (0);
   426 		return (0);
   430 
   427 
   431 	/* check for everyone entry */
   428 	/* check for everyone entry */
   432 	id = -1;
   429 	id = -1;
   433 	if (dsl_check_access(os, zapobj,
   430 	if (dsl_check_access(mos, zapobj,
   434 	    ZFS_DELEG_EVERYONE, checkflag, &id, perm) == 0)
   431 	    ZFS_DELEG_EVERYONE, checkflag, &id, perm) == 0)
   435 		return (0);
   432 		return (0);
   436 
   433 
   437 	/* check each supplemental group user is a member of */
   434 	/* check each supplemental group user is a member of */
   438 	ngids = crgetngroups(cr);
   435 	ngids = crgetngroups(cr);
   439 	gids = crgetgroups(cr);
   436 	gids = crgetgroups(cr);
   440 	for (i = 0; i != ngids; i++) {
   437 	for (i = 0; i != ngids; i++) {
   441 		id = gids[i];
   438 		id = gids[i];
   442 		if (dsl_check_access(os, zapobj,
   439 		if (dsl_check_access(mos, zapobj,
   443 		    ZFS_DELEG_GROUP, checkflag, &id, perm) == 0)
   440 		    ZFS_DELEG_GROUP, checkflag, &id, perm) == 0)
   444 			return (0);
   441 			return (0);
   445 	}
   442 	}
   446 
   443 
   447 	return (EPERM);
   444 	return (EPERM);
   579 
   576 
   580 			if (dsl_prop_get_ds_locked(dd,
   577 			if (dsl_prop_get_ds_locked(dd,
   581 			    zfs_prop_to_name(ZFS_PROP_ZONED),
   578 			    zfs_prop_to_name(ZFS_PROP_ZONED),
   582 			    8, 1, &zoned, NULL) != 0)
   579 			    8, 1, &zoned, NULL) != 0)
   583 				break;
   580 				break;
   584 
       
   585 			/*
       
   586 			 * if zoned property isn't set then break
       
   587 			 * out and return EPERM.
       
   588 			 */
       
   589 			if (!zoned)
   581 			if (!zoned)
   590 				break;
   582 				break;
   591 		}
   583 		}
   592 		zapobj = dd->dd_phys->dd_deleg_zapobj;
   584 		zapobj = dd->dd_phys->dd_deleg_zapobj;
   593 
   585 
   594 		if (zapobj == 0)
   586 		if (zapobj == 0)
   595 			continue;
   587 			continue;
   596 
   588 
   597 		dsl_load_user_sets(mos, zapobj, &permsets, checkflag, cr);
   589 		dsl_load_user_sets(mos, zapobj, &permsets, checkflag, cr);
   598 		setnode = avl_first(&permsets);
       
   599 again:
   590 again:
   600 		expanded = B_FALSE;
   591 		expanded = B_FALSE;
   601 		for (setnode = avl_first(&permsets); setnode;
   592 		for (setnode = avl_first(&permsets); setnode;
   602 		    setnode = AVL_NEXT(&permsets, setnode)) {
   593 		    setnode = AVL_NEXT(&permsets, setnode)) {
   603 
       
   604 			if (setnode->p_matched == B_TRUE)
   594 			if (setnode->p_matched == B_TRUE)
   605 				continue;
   595 				continue;
   606 
   596 
   607 			/* See if this set directly grants this permission */
   597 			/* See if this set directly grants this permission */
   608 			error = dsl_check_access(mos, zapobj,
   598 			error = dsl_check_access(mos, zapobj,
   634 success:
   624 success:
   635 	rw_exit(&dp->dp_config_rwlock);
   625 	rw_exit(&dp->dp_config_rwlock);
   636 	dsl_dir_close(startdd, FTAG);
   626 	dsl_dir_close(startdd, FTAG);
   637 
   627 
   638 	cookie = NULL;
   628 	cookie = NULL;
   639 	while ((setnode = avl_destroy_nodes(&permsets, &cookie)) != NULL) {
   629 	while ((setnode = avl_destroy_nodes(&permsets, &cookie)) != NULL)
   640 		/* These sets were used but never defined! */
       
   641 		kmem_free(setnode, sizeof (perm_set_t));
   630 		kmem_free(setnode, sizeof (perm_set_t));
   642 	}
       
   643 
   631 
   644 	return (error);
   632 	return (error);
   645 }
   633 }
   646 
   634 
   647 /*
   635 /*
   648  * Other routines.
   636  * Other routines.
   649  */
   637  */
   650 
   638 
   651 static void
   639 static void
   652 copy_create_perms(objset_t *mos, uint64_t pzapobj, dsl_dir_t *dd,
   640 copy_create_perms(dsl_dir_t *dd, uint64_t pzapobj,
   653     boolean_t dosets, uint64_t uid, dmu_tx_t *tx)
   641     boolean_t dosets, uint64_t uid, dmu_tx_t *tx)
   654 {
   642 {
   655 	int error;
   643 	objset_t *mos = dd->dd_pool->dp_meta_objset;
   656 	uint64_t jumpobj, pjumpobj;
   644 	uint64_t jumpobj, pjumpobj;
   657 	uint64_t zero = 0;
       
   658 	uint64_t zapobj = dd->dd_phys->dd_deleg_zapobj;
   645 	uint64_t zapobj = dd->dd_phys->dd_deleg_zapobj;
   659 	zap_cursor_t zc;
   646 	zap_cursor_t zc;
   660 	zap_attribute_t za;
   647 	zap_attribute_t za;
   661 	char whokey[ZFS_MAX_DELEG_NAME];
   648 	char whokey[ZFS_MAX_DELEG_NAME];
   662 
   649 
   663 	zfs_deleg_whokey(whokey,
   650 	zfs_deleg_whokey(whokey,
   664 	    dosets ? ZFS_DELEG_CREATE_SETS : ZFS_DELEG_CREATE,
   651 	    dosets ? ZFS_DELEG_CREATE_SETS : ZFS_DELEG_CREATE,
   665 	    ZFS_DELEG_LOCAL, NULL);
   652 	    ZFS_DELEG_LOCAL, NULL);
   666 	error = zap_lookup(mos, pzapobj, whokey, 8, 1, &pjumpobj);
   653 	if (zap_lookup(mos, pzapobj, whokey, 8, 1, &pjumpobj) != 0)
   667 	if (error != 0)
       
   668 		return;
   654 		return;
   669 
       
   670 	zfs_deleg_whokey(whokey,
       
   671 	    dosets ? ZFS_DELEG_USER_SETS : ZFS_DELEG_USER,
       
   672 	    ZFS_DELEG_LOCAL, &uid);
       
   673 
   655 
   674 	if (zapobj == 0) {
   656 	if (zapobj == 0) {
   675 		dmu_buf_will_dirty(dd->dd_dbuf, tx);
   657 		dmu_buf_will_dirty(dd->dd_dbuf, tx);
   676 		zapobj = dd->dd_phys->dd_deleg_zapobj = zap_create(mos,
   658 		zapobj = dd->dd_phys->dd_deleg_zapobj = zap_create(mos,
   677 		    DMU_OT_DSL_PERMS, DMU_OT_NONE, 0, tx);
   659 		    DMU_OT_DSL_PERMS, DMU_OT_NONE, 0, tx);
   678 	}
   660 	}
   679 
   661 
       
   662 	zfs_deleg_whokey(whokey,
       
   663 	    dosets ? ZFS_DELEG_USER_SETS : ZFS_DELEG_USER,
       
   664 	    ZFS_DELEG_LOCAL, &uid);
   680 	if (zap_lookup(mos, zapobj, whokey, 8, 1, &jumpobj) == ENOENT) {
   665 	if (zap_lookup(mos, zapobj, whokey, 8, 1, &jumpobj) == ENOENT) {
   681 		jumpobj = zap_create(mos, DMU_OT_DSL_PERMS, DMU_OT_NONE, 0, tx);
   666 		jumpobj = zap_create(mos, DMU_OT_DSL_PERMS, DMU_OT_NONE, 0, tx);
   682 		VERIFY(zap_add(mos, zapobj, whokey, 8, 1, &jumpobj, tx) == 0);
   667 		VERIFY(zap_add(mos, zapobj, whokey, 8, 1, &jumpobj, tx) == 0);
   683 	}
   668 	}
   684 
   669 
   685 	for (zap_cursor_init(&zc, mos, pjumpobj);
   670 	for (zap_cursor_init(&zc, mos, pjumpobj);
   686 	    zap_cursor_retrieve(&zc, &za) == 0;
   671 	    zap_cursor_retrieve(&zc, &za) == 0;
   687 	    zap_cursor_advance(&zc)) {
   672 	    zap_cursor_advance(&zc)) {
       
   673 		uint64_t zero = 0;
   688 		ASSERT(za.za_integer_length == 8 && za.za_num_integers == 1);
   674 		ASSERT(za.za_integer_length == 8 && za.za_num_integers == 1);
   689 
   675 
   690 		VERIFY(zap_update(mos, jumpobj, za.za_name,
   676 		VERIFY(zap_update(mos, jumpobj, za.za_name,
   691 		    8, 1, &zero, tx) == 0);
   677 		    8, 1, &zero, tx) == 0);
   692 	}
   678 	}
   698  */
   684  */
   699 void
   685 void
   700 dsl_deleg_set_create_perms(dsl_dir_t *sdd, dmu_tx_t *tx, cred_t *cr)
   686 dsl_deleg_set_create_perms(dsl_dir_t *sdd, dmu_tx_t *tx, cred_t *cr)
   701 {
   687 {
   702 	dsl_dir_t *dd;
   688 	dsl_dir_t *dd;
   703 	objset_t *mos = sdd->dd_pool->dp_meta_objset;
   689 	uint64_t uid = crgetuid(cr);
   704 
   690 
   705 	if (spa_version(dmu_objset_spa(sdd->dd_pool->dp_meta_objset)) <
   691 	if (spa_version(dmu_objset_spa(sdd->dd_pool->dp_meta_objset)) <
   706 	    ZFS_VERSION_DELEGATED_PERMS)
   692 	    ZFS_VERSION_DELEGATED_PERMS)
   707 		return;
   693 		return;
   708 
   694 
   709 	for (dd = sdd->dd_parent; dd != NULL; dd = dd->dd_parent) {
   695 	for (dd = sdd->dd_parent; dd != NULL; dd = dd->dd_parent) {
   710 		uint64_t pobj = dd->dd_phys->dd_deleg_zapobj;
   696 		uint64_t pzapobj = dd->dd_phys->dd_deleg_zapobj;
   711 
   697 
   712 		if (pobj == 0)
   698 		if (pzapobj == 0)
   713 			continue;
   699 			continue;
   714 
   700 
   715 		copy_create_perms(mos, pobj, sdd, B_FALSE, crgetuid(cr), tx);
   701 		copy_create_perms(sdd, pzapobj, B_FALSE, uid, tx);
   716 		copy_create_perms(mos, pobj, sdd, B_TRUE, crgetuid(cr), tx);
   702 		copy_create_perms(sdd, pzapobj, B_TRUE, uid, tx);
   717 	}
   703 	}
   718 }
   704 }
   719 
   705 
   720 int
   706 int
   721 dsl_deleg_destroy(objset_t *mos, uint64_t zapobj, dmu_tx_t *tx)
   707 dsl_deleg_destroy(objset_t *mos, uint64_t zapobj, dmu_tx_t *tx)