]> granicus.if.org Git - zfs/commitdiff
zfs_ioc_snapshot: check user-prop permissions on snapshotted datasets
authorAndriy Gapon <avg@FreeBSD.org>
Tue, 27 Aug 2019 20:45:53 +0000 (23:45 +0300)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Tue, 27 Aug 2019 20:45:53 +0000 (13:45 -0700)
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 <behlendorf1@llnl.gov>
Reviewed-by: Matt Ahrens <mahrens@delphix.com>
Signed-off-by: Andriy Gapon <avg@FreeBSD.org>
Closes #9179
Closes #9180

module/zfs/zfs_ioctl.c

index 9f4991162ff430a5503eb413ae3184b8665d40a7..399b15cbdef4a69487666a205d649be002ab0cab 100644 (file)
@@ -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)) {