diff options
author | sterlingjensen <[email protected]> | 2020-11-10 17:50:44 -0600 |
---|---|---|
committer | GitHub <[email protected]> | 2020-11-10 15:50:44 -0800 |
commit | a4ae4998cbae3bb451642272738ab4d59b9714c4 (patch) | |
tree | e94430fcab27bb829098ed6bf6de1648c5e2bbea /cmd | |
parent | b60ae3a5dc42bc62adb1507eb8785cf6fee57912 (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.c | 70 |
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) { |