summaryrefslogtreecommitdiffstats
path: root/module/zfs/zfs_ioctl.c
diff options
context:
space:
mode:
authorAndriy Gapon <[email protected]>2019-08-27 23:45:53 +0300
committerBrian Behlendorf <[email protected]>2019-08-27 13:45:53 -0700
commite6203d288a787f7196bdc206edfc9148f9a58780 (patch)
treec9a7f2d18419d5aeb1d9aa74a37f34faf6672bf7 /module/zfs/zfs_ioctl.c
parentf335b8ffe178276c7a98bdc87965a3dc9e2b59f5 (diff)
zfs_ioc_snapshot: check user-prop permissions on snapshotted datasets
Previously, the permissions were checked on the pool which was obviously incorrect. After this change, zfs_check_userprops() only validates the properties without any permission checks. The permissions are checked individually for each snapshotted dataset. Reviewed-by: Brian Behlendorf <[email protected]> Reviewed-by: Matt Ahrens <[email protected]> Signed-off-by: Andriy Gapon <[email protected]> Closes #9179 Closes #9180
Diffstat (limited to 'module/zfs/zfs_ioctl.c')
-rw-r--r--module/zfs/zfs_ioctl.c26
1 files changed, 16 insertions, 10 deletions
diff --git a/module/zfs/zfs_ioctl.c b/module/zfs/zfs_ioctl.c
index 9f4991162..399b15cbd 100644
--- a/module/zfs/zfs_ioctl.c
+++ b/module/zfs/zfs_ioctl.c
@@ -2739,10 +2739,9 @@ retry:
* Check that all the properties are valid user properties.
*/
static int
-zfs_check_userprops(const char *fsname, nvlist_t *nvl)
+zfs_check_userprops(nvlist_t *nvl)
{
nvpair_t *pair = NULL;
- int error = 0;
while ((pair = nvlist_next_nvpair(nvl, pair)) != NULL) {
const char *propname = nvpair_name(pair);
@@ -2751,10 +2750,6 @@ zfs_check_userprops(const char *fsname, nvlist_t *nvl)
nvpair_type(pair) != DATA_TYPE_STRING)
return (SET_ERROR(EINVAL));
- if ((error = zfs_secpolicy_write_perms(fsname,
- ZFS_DELEG_PERM_USERPROP, CRED())))
- return (error);
-
if (strlen(propname) >= ZAP_MAXNAMELEN)
return (SET_ERROR(ENAMETOOLONG));
@@ -3465,19 +3460,18 @@ zfs_ioc_snapshot(const char *poolname, nvlist_t *innvl, nvlist_t *outnvl)
nvpair_t *pair;
(void) nvlist_lookup_nvlist(innvl, "props", &props);
- if ((error = zfs_check_userprops(poolname, props)) != 0)
- return (error);
-
if (!nvlist_empty(props) &&
zfs_earlier_version(poolname, SPA_VERSION_SNAP_PROPS))
return (SET_ERROR(ENOTSUP));
+ if ((error = zfs_check_userprops(props)) != 0)
+ return (error);
snaps = fnvlist_lookup_nvlist(innvl, "snaps");
poollen = strlen(poolname);
for (pair = nvlist_next_nvpair(snaps, NULL); pair != NULL;
pair = nvlist_next_nvpair(snaps, pair)) {
const char *name = nvpair_name(pair);
- const char *cp = strchr(name, '@');
+ char *cp = strchr(name, '@');
/*
* The snap name must contain an @, and the part after it must
@@ -3494,6 +3488,18 @@ zfs_ioc_snapshot(const char *poolname, nvlist_t *innvl, nvlist_t *outnvl)
(name[poollen] != '/' && name[poollen] != '@'))
return (SET_ERROR(EXDEV));
+ /*
+ * Check for permission to set the properties on the fs.
+ */
+ if (!nvlist_empty(props)) {
+ *cp = '\0';
+ error = zfs_secpolicy_write_perms(name,
+ ZFS_DELEG_PERM_USERPROP, CRED());
+ *cp = '@';
+ if (error != 0)
+ return (error);
+ }
+
/* This must be the only snap of this fs. */
for (nvpair_t *pair2 = nvlist_next_nvpair(snaps, pair);
pair2 != NULL; pair2 = nvlist_next_nvpair(snaps, pair2)) {