mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2024-11-18 10:21:01 +03:00
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 <behlendorf1@llnl.gov> Reviewed-by: Matt Ahrens <mahrens@delphix.com> Signed-off-by: Andriy Gapon <avg@FreeBSD.org> Closes #9179 Closes #9180
This commit is contained in:
parent
ea34735203
commit
931bef81c8
@ -2744,10 +2744,9 @@ retry:
|
|||||||
* Check that all the properties are valid user properties.
|
* Check that all the properties are valid user properties.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
zfs_check_userprops(const char *fsname, nvlist_t *nvl)
|
zfs_check_userprops(nvlist_t *nvl)
|
||||||
{
|
{
|
||||||
nvpair_t *pair = NULL;
|
nvpair_t *pair = NULL;
|
||||||
int error = 0;
|
|
||||||
|
|
||||||
while ((pair = nvlist_next_nvpair(nvl, pair)) != NULL) {
|
while ((pair = nvlist_next_nvpair(nvl, pair)) != NULL) {
|
||||||
const char *propname = nvpair_name(pair);
|
const char *propname = nvpair_name(pair);
|
||||||
@ -2756,10 +2755,6 @@ zfs_check_userprops(const char *fsname, nvlist_t *nvl)
|
|||||||
nvpair_type(pair) != DATA_TYPE_STRING)
|
nvpair_type(pair) != DATA_TYPE_STRING)
|
||||||
return (SET_ERROR(EINVAL));
|
return (SET_ERROR(EINVAL));
|
||||||
|
|
||||||
if ((error = zfs_secpolicy_write_perms(fsname,
|
|
||||||
ZFS_DELEG_PERM_USERPROP, CRED())))
|
|
||||||
return (error);
|
|
||||||
|
|
||||||
if (strlen(propname) >= ZAP_MAXNAMELEN)
|
if (strlen(propname) >= ZAP_MAXNAMELEN)
|
||||||
return (SET_ERROR(ENAMETOOLONG));
|
return (SET_ERROR(ENAMETOOLONG));
|
||||||
|
|
||||||
@ -3473,19 +3468,18 @@ zfs_ioc_snapshot(const char *poolname, nvlist_t *innvl, nvlist_t *outnvl)
|
|||||||
nvpair_t *pair;
|
nvpair_t *pair;
|
||||||
|
|
||||||
(void) nvlist_lookup_nvlist(innvl, "props", &props);
|
(void) nvlist_lookup_nvlist(innvl, "props", &props);
|
||||||
if ((error = zfs_check_userprops(poolname, props)) != 0)
|
|
||||||
return (error);
|
|
||||||
|
|
||||||
if (!nvlist_empty(props) &&
|
if (!nvlist_empty(props) &&
|
||||||
zfs_earlier_version(poolname, SPA_VERSION_SNAP_PROPS))
|
zfs_earlier_version(poolname, SPA_VERSION_SNAP_PROPS))
|
||||||
return (SET_ERROR(ENOTSUP));
|
return (SET_ERROR(ENOTSUP));
|
||||||
|
if ((error = zfs_check_userprops(props)) != 0)
|
||||||
|
return (error);
|
||||||
|
|
||||||
snaps = fnvlist_lookup_nvlist(innvl, "snaps");
|
snaps = fnvlist_lookup_nvlist(innvl, "snaps");
|
||||||
poollen = strlen(poolname);
|
poollen = strlen(poolname);
|
||||||
for (pair = nvlist_next_nvpair(snaps, NULL); pair != NULL;
|
for (pair = nvlist_next_nvpair(snaps, NULL); pair != NULL;
|
||||||
pair = nvlist_next_nvpair(snaps, pair)) {
|
pair = nvlist_next_nvpair(snaps, pair)) {
|
||||||
const char *name = nvpair_name(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
|
* The snap name must contain an @, and the part after it must
|
||||||
@ -3502,6 +3496,18 @@ zfs_ioc_snapshot(const char *poolname, nvlist_t *innvl, nvlist_t *outnvl)
|
|||||||
(name[poollen] != '/' && name[poollen] != '@'))
|
(name[poollen] != '/' && name[poollen] != '@'))
|
||||||
return (SET_ERROR(EXDEV));
|
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. */
|
/* This must be the only snap of this fs. */
|
||||||
for (nvpair_t *pair2 = nvlist_next_nvpair(snaps, pair);
|
for (nvpair_t *pair2 = nvlist_next_nvpair(snaps, pair);
|
||||||
pair2 != NULL; pair2 = nvlist_next_nvpair(snaps, pair2)) {
|
pair2 != NULL; pair2 = nvlist_next_nvpair(snaps, pair2)) {
|
||||||
|
Loading…
Reference in New Issue
Block a user