aboutsummaryrefslogtreecommitdiffstats
path: root/cmd
diff options
context:
space:
mode:
authorsterlingjensen <[email protected]>2020-11-10 17:50:44 -0600
committerGitHub <[email protected]>2020-11-10 15:50:44 -0800
commita4ae4998cbae3bb451642272738ab4d59b9714c4 (patch)
treee94430fcab27bb829098ed6bf6de1648c5e2bbea /cmd
parentb60ae3a5dc42bc62adb1507eb8785cf6fee57912 (diff)
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 <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Signed-off-by: Sterling Jensen <[email protected]> Closes #11098
Diffstat (limited to 'cmd')
-rw-r--r--cmd/mount_zfs/mount_zfs.c70
1 files changed, 28 insertions, 42 deletions
diff --git a/cmd/mount_zfs/mount_zfs.c b/cmd/mount_zfs/mount_zfs.c
index ed9f167cc..13935a9cc 100644
--- a/cmd/mount_zfs/mount_zfs.c
+++ b/cmd/mount_zfs/mount_zfs.c
@@ -47,46 +47,34 @@ libzfs_handle_t *g_zfs;
* 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.
*/
-static char *
-parse_dataset(char *dataset)
+static void
+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
* given a device which is a member of a zpool we attempt to
* extract the pool name stored in the label. Given the pool
* name we can mount the root dataset.
*/
- error = stat64(dataset, &statbuf);
- if (error == 0) {
- nvlist_t *config;
- char *name;
- int fd;
-
- fd = open(dataset, O_RDONLY);
- if (fd < 0)
- goto out;
-
- error = zpool_read_label(fd, &config, NULL);
- (void) close(fd);
- if (error)
- goto out;
-
- error = nvlist_lookup_string(config,
- ZPOOL_CONFIG_POOL_NAME, &name);
- if (error) {
- nvlist_free(config);
- } else {
- dataset = strdup(name);
+ int fd = open(target, O_RDONLY);
+ if (fd >= 0) {
+ nvlist_t *config = NULL;
+ if (zpool_read_label(fd, &config, NULL) != 0)
+ config = NULL;
+ if (close(fd))
+ perror("close");
+
+ if (config) {
+ char *name = NULL;
+ if (!nvlist_lookup_string(config,
+ ZPOOL_CONFIG_POOL_NAME, &name))
+ (void) strlcpy(*dataset, name, PATH_MAX);
nvlist_free(config);
- return (dataset);
+ if (name)
+ return;
}
}
-out:
+
/*
* If a file or directory in your current working directory is
* 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
* patch when it is added.
*/
- if (getcwd(cwd, PATH_MAX) == NULL)
- return (dataset);
-
- len = strlen(cwd);
-
- /* Do not add one when cwd already ends in a trailing '/' */
- if (strncmp(cwd, dataset, len) == 0)
- return (dataset + len + (cwd[len-1] != '/'));
-
- return (dataset);
+ char cwd[PATH_MAX];
+ if (getcwd(cwd, PATH_MAX) != NULL) {
+ int len = strlen(cwd);
+ /* Do not add one when cwd already ends in a trailing '/' */
+ if (strncmp(cwd, target, len) == 0)
+ target += len + (cwd[len-1] != '/');
+ }
+ strlcpy(*dataset, target, PATH_MAX);
}
/*
@@ -176,7 +162,7 @@ main(int argc, char **argv)
char badopt[MNT_LINE_MAX] = { '\0' };
char mtabopt[MNT_LINE_MAX] = { '\0' };
char mntpoint[PATH_MAX];
- char *dataset;
+ char dataset[PATH_MAX], *pdataset = dataset;
unsigned long mntflags = 0, zfsflags = 0, remount = 0;
int sloppy = 0, fake = 0, verbose = 0, nomtab = 0, zfsutil = 0;
int error, c;
@@ -232,7 +218,7 @@ main(int argc, char **argv)
return (MOUNT_USAGE);
}
- dataset = parse_dataset(argv[0]);
+ parse_dataset(argv[0], &pdataset);
/* canonicalize the mount point */
if (realpath(argv[1], mntpoint) == NULL) {