mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2024-12-26 03:09:34 +03:00
Fix memleak in cmd/mount_zfs.c
Convert dynamic allocation to static buffer, simplify parse_dataset function return path. Add tests specific to the mount helper. Reviewed-by: Mateusz Guzik <mjguzik@gmail.com> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Sterling Jensen <sterlingjensen@users.noreply.github.com> Closes #11098
This commit is contained in:
parent
b60ae3a5dc
commit
a4ae4998cb
@ -47,46 +47,34 @@ libzfs_handle_t *g_zfs;
|
|||||||
* is expected to be of the form pool/dataset, however may also refer to
|
* is expected to be of the form pool/dataset, however may also refer to
|
||||||
* a block device if that device contains a valid zfs label.
|
* a block device if that device contains a valid zfs label.
|
||||||
*/
|
*/
|
||||||
static char *
|
static void
|
||||||
parse_dataset(char *dataset)
|
parse_dataset(const char *target, char **dataset)
|
||||||
{
|
{
|
||||||
char cwd[PATH_MAX];
|
|
||||||
struct stat64 statbuf;
|
|
||||||
int error;
|
|
||||||
int len;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We expect a pool/dataset to be provided, however if we're
|
* We expect a pool/dataset to be provided, however if we're
|
||||||
* given a device which is a member of a zpool we attempt to
|
* given a device which is a member of a zpool we attempt to
|
||||||
* extract the pool name stored in the label. Given the pool
|
* extract the pool name stored in the label. Given the pool
|
||||||
* name we can mount the root dataset.
|
* name we can mount the root dataset.
|
||||||
*/
|
*/
|
||||||
error = stat64(dataset, &statbuf);
|
int fd = open(target, O_RDONLY);
|
||||||
if (error == 0) {
|
if (fd >= 0) {
|
||||||
nvlist_t *config;
|
nvlist_t *config = NULL;
|
||||||
char *name;
|
if (zpool_read_label(fd, &config, NULL) != 0)
|
||||||
int fd;
|
config = NULL;
|
||||||
|
if (close(fd))
|
||||||
|
perror("close");
|
||||||
|
|
||||||
fd = open(dataset, O_RDONLY);
|
if (config) {
|
||||||
if (fd < 0)
|
char *name = NULL;
|
||||||
goto out;
|
if (!nvlist_lookup_string(config,
|
||||||
|
ZPOOL_CONFIG_POOL_NAME, &name))
|
||||||
error = zpool_read_label(fd, &config, NULL);
|
(void) strlcpy(*dataset, name, PATH_MAX);
|
||||||
(void) close(fd);
|
|
||||||
if (error)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
error = nvlist_lookup_string(config,
|
|
||||||
ZPOOL_CONFIG_POOL_NAME, &name);
|
|
||||||
if (error) {
|
|
||||||
nvlist_free(config);
|
nvlist_free(config);
|
||||||
} else {
|
if (name)
|
||||||
dataset = strdup(name);
|
return;
|
||||||
nvlist_free(config);
|
|
||||||
return (dataset);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out:
|
|
||||||
/*
|
/*
|
||||||
* If a file or directory in your current working directory is
|
* If a file or directory in your current working directory is
|
||||||
* named 'dataset' then mount(8) will prepend your current working
|
* named 'dataset' then mount(8) will prepend your current working
|
||||||
@ -94,16 +82,14 @@ out:
|
|||||||
* behavior so we simply check for it and strip the prepended
|
* behavior so we simply check for it and strip the prepended
|
||||||
* patch when it is added.
|
* patch when it is added.
|
||||||
*/
|
*/
|
||||||
if (getcwd(cwd, PATH_MAX) == NULL)
|
char cwd[PATH_MAX];
|
||||||
return (dataset);
|
if (getcwd(cwd, PATH_MAX) != NULL) {
|
||||||
|
int len = strlen(cwd);
|
||||||
len = strlen(cwd);
|
|
||||||
|
|
||||||
/* Do not add one when cwd already ends in a trailing '/' */
|
/* Do not add one when cwd already ends in a trailing '/' */
|
||||||
if (strncmp(cwd, dataset, len) == 0)
|
if (strncmp(cwd, target, len) == 0)
|
||||||
return (dataset + len + (cwd[len-1] != '/'));
|
target += len + (cwd[len-1] != '/');
|
||||||
|
}
|
||||||
return (dataset);
|
strlcpy(*dataset, target, PATH_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -176,7 +162,7 @@ main(int argc, char **argv)
|
|||||||
char badopt[MNT_LINE_MAX] = { '\0' };
|
char badopt[MNT_LINE_MAX] = { '\0' };
|
||||||
char mtabopt[MNT_LINE_MAX] = { '\0' };
|
char mtabopt[MNT_LINE_MAX] = { '\0' };
|
||||||
char mntpoint[PATH_MAX];
|
char mntpoint[PATH_MAX];
|
||||||
char *dataset;
|
char dataset[PATH_MAX], *pdataset = dataset;
|
||||||
unsigned long mntflags = 0, zfsflags = 0, remount = 0;
|
unsigned long mntflags = 0, zfsflags = 0, remount = 0;
|
||||||
int sloppy = 0, fake = 0, verbose = 0, nomtab = 0, zfsutil = 0;
|
int sloppy = 0, fake = 0, verbose = 0, nomtab = 0, zfsutil = 0;
|
||||||
int error, c;
|
int error, c;
|
||||||
@ -232,7 +218,7 @@ main(int argc, char **argv)
|
|||||||
return (MOUNT_USAGE);
|
return (MOUNT_USAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
dataset = parse_dataset(argv[0]);
|
parse_dataset(argv[0], &pdataset);
|
||||||
|
|
||||||
/* canonicalize the mount point */
|
/* canonicalize the mount point */
|
||||||
if (realpath(argv[1], mntpoint) == NULL) {
|
if (realpath(argv[1], mntpoint) == NULL) {
|
||||||
|
@ -47,7 +47,8 @@ tests = ['zfs_003_neg']
|
|||||||
tags = ['functional', 'cli_root', 'zfs']
|
tags = ['functional', 'cli_root', 'zfs']
|
||||||
|
|
||||||
[tests/functional/cli_root/zfs_mount:Linux]
|
[tests/functional/cli_root/zfs_mount:Linux]
|
||||||
tests = ['zfs_mount_006_pos', 'zfs_mount_008_pos', 'zfs_multi_mount']
|
tests = ['zfs_mount_006_pos', 'zfs_mount_008_pos', 'zfs_mount_013_pos',
|
||||||
|
'zfs_mount_014_neg', 'zfs_multi_mount']
|
||||||
tags = ['functional', 'cli_root', 'zfs_mount']
|
tags = ['functional', 'cli_root', 'zfs_mount']
|
||||||
|
|
||||||
[tests/functional/cli_root/zfs_share:Linux]
|
[tests/functional/cli_root/zfs_share:Linux]
|
||||||
|
@ -184,6 +184,7 @@ export ZFS_FILES='zdb
|
|||||||
arc_summary
|
arc_summary
|
||||||
arcstat
|
arcstat
|
||||||
dbufstat
|
dbufstat
|
||||||
|
mount.zfs
|
||||||
zed
|
zed
|
||||||
zgenhostid
|
zgenhostid
|
||||||
zstream
|
zstream
|
||||||
|
@ -14,6 +14,8 @@ dist_pkgdata_SCRIPTS = \
|
|||||||
zfs_mount_010_neg.ksh \
|
zfs_mount_010_neg.ksh \
|
||||||
zfs_mount_011_neg.ksh \
|
zfs_mount_011_neg.ksh \
|
||||||
zfs_mount_012_pos.ksh \
|
zfs_mount_012_pos.ksh \
|
||||||
|
zfs_mount_013_pos.ksh \
|
||||||
|
zfs_mount_014_neg.ksh \
|
||||||
zfs_mount_all_001_pos.ksh \
|
zfs_mount_all_001_pos.ksh \
|
||||||
zfs_mount_all_fail.ksh \
|
zfs_mount_all_fail.ksh \
|
||||||
zfs_mount_all_mountpoints.ksh \
|
zfs_mount_all_mountpoints.ksh \
|
||||||
|
76
tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_013_pos.ksh
Executable file
76
tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_013_pos.ksh
Executable file
@ -0,0 +1,76 @@
|
|||||||
|
#!/bin/ksh -p
|
||||||
|
#
|
||||||
|
# CDDL HEADER START
|
||||||
|
#
|
||||||
|
# This file and its contents are supplied under the terms of the
|
||||||
|
# Common Development and Distribution License ("CDDL"), version 1.0.
|
||||||
|
# You may only use this file in accordance with the terms of version
|
||||||
|
# 1.0 of the CDDL.
|
||||||
|
#
|
||||||
|
# A full copy of the text of the CDDL should have accompanied this
|
||||||
|
# source. A copy of the CDDL is also available via the Internet at
|
||||||
|
# http://www.illumos.org/license/CDDL.
|
||||||
|
#
|
||||||
|
# CDDL HEADER END
|
||||||
|
#
|
||||||
|
|
||||||
|
. $STF_SUITE/include/libtest.shlib
|
||||||
|
. $STF_SUITE/tests/functional/cli_root/zfs_mount/zfs_mount.kshlib
|
||||||
|
|
||||||
|
#
|
||||||
|
# DESCRIPTION:
|
||||||
|
# Verify zfs mount helper functions for both devices and pools.
|
||||||
|
#
|
||||||
|
|
||||||
|
verify_runnable "both"
|
||||||
|
|
||||||
|
set -A vdevs $(get_disklist_fullpath $TESTPOOL)
|
||||||
|
vdev=${vdevs[0]}
|
||||||
|
mntpoint=$TESTDIR/$TESTPOOL
|
||||||
|
helper="mount.zfs -o zfsutil"
|
||||||
|
fs=$TESTPOOL/$TESTFS
|
||||||
|
|
||||||
|
function cleanup
|
||||||
|
{
|
||||||
|
log_must force_unmount $vdev
|
||||||
|
[[ -d $mntpoint ]] && log_must rm -rf $mntpoint
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
log_onexit cleanup
|
||||||
|
|
||||||
|
log_note "Verify zfs mount helper functions for both devices and pools"
|
||||||
|
|
||||||
|
# Ensure that the ZFS filesystem is unmounted
|
||||||
|
force_unmount $fs
|
||||||
|
log_must mkdir -p $mntpoint
|
||||||
|
|
||||||
|
log_note "Verify '<dataset> <path>'"
|
||||||
|
log_must $helper $fs $mntpoint
|
||||||
|
log_must ismounted $fs
|
||||||
|
force_unmount $fs
|
||||||
|
|
||||||
|
log_note "Verify '\$PWD/<pool> <path>' prefix workaround"
|
||||||
|
log_must $helper $PWD/$fs $mntpoint
|
||||||
|
log_must ismounted $fs
|
||||||
|
force_unmount $fs
|
||||||
|
|
||||||
|
log_note "Verify '-f <dataset> <path>' fakemount"
|
||||||
|
log_must $helper -f $fs $mntpoint
|
||||||
|
log_mustnot ismounted $fs
|
||||||
|
|
||||||
|
log_note "Verify '-o ro -v <dataset> <path>' verbose RO"
|
||||||
|
log_must ${helper},ro -v $fs $mntpoint
|
||||||
|
log_must ismounted $fs
|
||||||
|
force_unmount $fs
|
||||||
|
|
||||||
|
log_note "Verify '<device> <path>'"
|
||||||
|
log_must $helper $vdev $mntpoint
|
||||||
|
log_must ismounted $mntpoint
|
||||||
|
log_must umount $TESTPOOL
|
||||||
|
|
||||||
|
log_note "Verify '-o abc -s <device> <path>' sloppy option"
|
||||||
|
log_must ${helper},abc -s $vdev $mntpoint
|
||||||
|
log_must ismounted $mntpoint
|
||||||
|
log_must umount $TESTPOOL
|
||||||
|
|
||||||
|
log_pass "zfs mount helper correctly handles both device and pool strings"
|
68
tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_014_neg.ksh
Executable file
68
tests/zfs-tests/tests/functional/cli_root/zfs_mount/zfs_mount_014_neg.ksh
Executable file
@ -0,0 +1,68 @@
|
|||||||
|
#!/bin/ksh -p
|
||||||
|
#
|
||||||
|
# CDDL HEADER START
|
||||||
|
#
|
||||||
|
# This file and its contents are supplied under the terms of the
|
||||||
|
# Common Development and Distribution License ("CDDL"), version 1.0.
|
||||||
|
# You may only use this file in accordance with the terms of version
|
||||||
|
# 1.0 of the CDDL.
|
||||||
|
#
|
||||||
|
# A full copy of the text of the CDDL should have accompanied this
|
||||||
|
# source. A copy of the CDDL is also available via the Internet at
|
||||||
|
# http://www.illumos.org/license/CDDL.
|
||||||
|
#
|
||||||
|
# CDDL HEADER END
|
||||||
|
#
|
||||||
|
|
||||||
|
. $STF_SUITE/include/libtest.shlib
|
||||||
|
. $STF_SUITE/tests/functional/cli_root/zfs_mount/zfs_mount.kshlib
|
||||||
|
|
||||||
|
#
|
||||||
|
# DESCRIPTION:
|
||||||
|
# Verify zfs mount helper failure on known bad parameters
|
||||||
|
#
|
||||||
|
|
||||||
|
verify_runnable "both"
|
||||||
|
|
||||||
|
set -A vdevs $(get_disklist_fullpath $TESTPOOL)
|
||||||
|
vdev=${vdevs[0]}
|
||||||
|
|
||||||
|
mntpoint="$(get_prop mountpoint $TESTPOOL)"
|
||||||
|
helper="mount.zfs -o zfsutil"
|
||||||
|
fs=$TESTPOOL/$TESTFS
|
||||||
|
|
||||||
|
function cleanup
|
||||||
|
{
|
||||||
|
log_must force_unmount $vdev
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
log_onexit cleanup
|
||||||
|
|
||||||
|
log_note "Verify zfs mount helper failure on known bad parameters"
|
||||||
|
|
||||||
|
# Ensure that the ZFS filesystem is unmounted.
|
||||||
|
force_unmount $fs
|
||||||
|
|
||||||
|
log_note "Verify failure without '-o zfsutil'"
|
||||||
|
log_mustnot mount.zfs $fs $mntpoint
|
||||||
|
|
||||||
|
log_note "Verify '-o abc <device> <path>' bad option fails"
|
||||||
|
log_mustnot ${helper},abc $vdev $mntpoint
|
||||||
|
|
||||||
|
log_note "Verify '\$NONEXISTFSNAME <path>' fails"
|
||||||
|
log_mustnot $helper $NONEXISTFSNAME $mntpoint
|
||||||
|
|
||||||
|
log_note "Verify '<dataset> (\$NONEXISTFSNAME|/dev/null)' fails"
|
||||||
|
log_mustnot $helper $fs $NONEXISTFSNAME
|
||||||
|
log_mustnot $helper $fs /dev/null
|
||||||
|
|
||||||
|
log_note "Verify '/dev/null <path>' fails"
|
||||||
|
log_mustnot $helper /dev/null $mntpoint
|
||||||
|
|
||||||
|
log_note "Verify '[device|pool]' fails"
|
||||||
|
log_mustnot mount.zfs
|
||||||
|
log_mustnot $helper
|
||||||
|
log_mustnot $helper $vdev
|
||||||
|
log_mustnot $helper $TESTPOOL
|
||||||
|
|
||||||
|
log_pass "zfs mount helper fails when expected"
|
Loading…
Reference in New Issue
Block a user