Skip to content

Commit

Permalink
zfs_ioc_snapshot: check user-prop permissions on snapshotted datasets
Browse files Browse the repository at this point in the history
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
  • Loading branch information
avg-I authored and behlendorf committed Aug 27, 2019
1 parent f335b8f commit e6203d2
Showing 1 changed file with 16 additions and 10 deletions.
26 changes: 16 additions & 10 deletions module/zfs/zfs_ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -2739,10 +2739,9 @@ zfs_set_prop_nvlist(const char *dsname, zprop_source_t source, nvlist_t *nvl,
* 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);
Expand All @@ -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));

Expand Down Expand Up @@ -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
Expand All @@ -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)) {
Expand Down

0 comments on commit e6203d2

Please sign in to comment.