Fix userland memory leak in zfs_do_send()

Clang 15's static analyzer caught this.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Richard Yao <richard.yao@alumni.stonybrook.edu>
Closes #14045
This commit is contained in:
Richard Yao 2022-10-19 20:08:33 -04:00 committed by GitHub
parent 5405be0365
commit 219cf0f928
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -4504,6 +4504,7 @@ zfs_do_send(int argc, char **argv)
gettext("missing argument for '%s' " gettext("missing argument for '%s' "
"option\n"), argv[optind - 1]); "option\n"), argv[optind - 1]);
} }
free(excludes.list);
usage(B_FALSE); usage(B_FALSE);
break; break;
case '?': case '?':
@ -4522,6 +4523,7 @@ zfs_do_send(int argc, char **argv)
argv[optind - 1]); argv[optind - 1]);
} }
free(excludes.list);
usage(B_FALSE); usage(B_FALSE);
} }
} }
@ -4530,6 +4532,7 @@ zfs_do_send(int argc, char **argv)
flags.verbosity = 1; flags.verbosity = 1;
if (excludes.count > 0 && !flags.replicate) { if (excludes.count > 0 && !flags.replicate) {
free(excludes.list);
(void) fprintf(stderr, gettext("Cannot specify " (void) fprintf(stderr, gettext("Cannot specify "
"dataset exclusion (-X) on a non-recursive " "dataset exclusion (-X) on a non-recursive "
"send.\n")); "send.\n"));
@ -4543,21 +4546,25 @@ zfs_do_send(int argc, char **argv)
if (fromname != NULL || flags.replicate || flags.props || if (fromname != NULL || flags.replicate || flags.props ||
flags.backup || flags.holds || flags.backup || flags.holds ||
flags.saved || redactbook != NULL) { flags.saved || redactbook != NULL) {
free(excludes.list);
(void) fprintf(stderr, (void) fprintf(stderr,
gettext("invalid flags combined with -t\n")); gettext("invalid flags combined with -t\n"));
usage(B_FALSE); usage(B_FALSE);
} }
if (argc > 0) { if (argc > 0) {
free(excludes.list);
(void) fprintf(stderr, gettext("too many arguments\n")); (void) fprintf(stderr, gettext("too many arguments\n"));
usage(B_FALSE); usage(B_FALSE);
} }
} else { } else {
if (argc < 1) { if (argc < 1) {
free(excludes.list);
(void) fprintf(stderr, (void) fprintf(stderr,
gettext("missing snapshot argument\n")); gettext("missing snapshot argument\n"));
usage(B_FALSE); usage(B_FALSE);
} }
if (argc > 1) { if (argc > 1) {
free(excludes.list);
(void) fprintf(stderr, gettext("too many arguments\n")); (void) fprintf(stderr, gettext("too many arguments\n"));
usage(B_FALSE); usage(B_FALSE);
} }
@ -4568,11 +4575,15 @@ zfs_do_send(int argc, char **argv)
flags.doall || flags.backup || flags.doall || flags.backup ||
flags.holds || flags.largeblock || flags.embed_data || flags.holds || flags.largeblock || flags.embed_data ||
flags.compress || flags.raw || redactbook != NULL) { flags.compress || flags.raw || redactbook != NULL) {
free(excludes.list);
(void) fprintf(stderr, gettext("incompatible flags " (void) fprintf(stderr, gettext("incompatible flags "
"combined with saved send flag\n")); "combined with saved send flag\n"));
usage(B_FALSE); usage(B_FALSE);
} }
if (strchr(argv[0], '@') != NULL) { if (strchr(argv[0], '@') != NULL) {
free(excludes.list);
(void) fprintf(stderr, gettext("saved send must " (void) fprintf(stderr, gettext("saved send must "
"specify the dataset with partially-received " "specify the dataset with partially-received "
"state\n")); "state\n"));
@ -4581,12 +4592,14 @@ zfs_do_send(int argc, char **argv)
} }
if (flags.raw && redactbook != NULL) { if (flags.raw && redactbook != NULL) {
free(excludes.list);
(void) fprintf(stderr, (void) fprintf(stderr,
gettext("Error: raw sends may not be redacted.\n")); gettext("Error: raw sends may not be redacted.\n"));
return (1); return (1);
} }
if (!flags.dryrun && isatty(STDOUT_FILENO)) { if (!flags.dryrun && isatty(STDOUT_FILENO)) {
free(excludes.list);
(void) fprintf(stderr, (void) fprintf(stderr,
gettext("Error: Stream can not be written to a terminal.\n" gettext("Error: Stream can not be written to a terminal.\n"
"You must redirect standard output.\n")); "You must redirect standard output.\n"));
@ -4595,19 +4608,24 @@ zfs_do_send(int argc, char **argv)
if (flags.saved) { if (flags.saved) {
zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_DATASET); zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_DATASET);
if (zhp == NULL) if (zhp == NULL) {
free(excludes.list);
return (1); return (1);
}
err = zfs_send_saved(zhp, &flags, STDOUT_FILENO, err = zfs_send_saved(zhp, &flags, STDOUT_FILENO,
resume_token); resume_token);
free(excludes.list);
zfs_close(zhp); zfs_close(zhp);
return (err != 0); return (err != 0);
} else if (resume_token != NULL) { } else if (resume_token != NULL) {
free(excludes.list);
return (zfs_send_resume(g_zfs, &flags, STDOUT_FILENO, return (zfs_send_resume(g_zfs, &flags, STDOUT_FILENO,
resume_token)); resume_token));
} }
if (flags.skipmissing && !flags.replicate) { if (flags.skipmissing && !flags.replicate) {
free(excludes.list);
(void) fprintf(stderr, (void) fprintf(stderr,
gettext("skip-missing flag can only be used in " gettext("skip-missing flag can only be used in "
"conjunction with replicate\n")); "conjunction with replicate\n"));
@ -4650,10 +4668,14 @@ zfs_do_send(int argc, char **argv)
} }
zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_DATASET); zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_DATASET);
if (zhp == NULL) if (zhp == NULL) {
free(excludes.list);
return (1); return (1);
}
err = zfs_send_one(zhp, fromname, STDOUT_FILENO, &flags, err = zfs_send_one(zhp, fromname, STDOUT_FILENO, &flags,
redactbook); redactbook);
free(excludes.list);
zfs_close(zhp); zfs_close(zhp);
return (err != 0); return (err != 0);
} }
@ -4662,25 +4684,30 @@ zfs_do_send(int argc, char **argv)
(void) fprintf(stderr, (void) fprintf(stderr,
gettext("Error: multiple snapshots cannot be " gettext("Error: multiple snapshots cannot be "
"sent from a bookmark.\n")); "sent from a bookmark.\n"));
free(excludes.list);
return (1); return (1);
} }
if (redactbook != NULL) { if (redactbook != NULL) {
(void) fprintf(stderr, gettext("Error: multiple snapshots " (void) fprintf(stderr, gettext("Error: multiple snapshots "
"cannot be sent redacted.\n")); "cannot be sent redacted.\n"));
free(excludes.list);
return (1); return (1);
} }
if ((cp = strchr(argv[0], '@')) == NULL) { if ((cp = strchr(argv[0], '@')) == NULL) {
(void) fprintf(stderr, gettext("Error: " (void) fprintf(stderr, gettext("Error: "
"Unsupported flag with filesystem or bookmark.\n")); "Unsupported flag with filesystem or bookmark.\n"));
free(excludes.list);
return (1); return (1);
} }
*cp = '\0'; *cp = '\0';
toname = cp + 1; toname = cp + 1;
zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME); zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME);
if (zhp == NULL) if (zhp == NULL) {
free(excludes.list);
return (1); return (1);
}
/* /*
* If they specified the full path to the snapshot, chop off * If they specified the full path to the snapshot, chop off
@ -4700,6 +4727,8 @@ zfs_do_send(int argc, char **argv)
} else { } else {
*cp = '\0'; *cp = '\0';
if (cp != fromname && strcmp(argv[0], fromname)) { if (cp != fromname && strcmp(argv[0], fromname)) {
zfs_close(zhp);
free(excludes.list);
(void) fprintf(stderr, (void) fprintf(stderr,
gettext("incremental source must be " gettext("incremental source must be "
"in same filesystem\n")); "in same filesystem\n"));
@ -4707,6 +4736,8 @@ zfs_do_send(int argc, char **argv)
} }
fromname = cp + 1; fromname = cp + 1;
if (strchr(fromname, '@') || strchr(fromname, '/')) { if (strchr(fromname, '@') || strchr(fromname, '/')) {
zfs_close(zhp);
free(excludes.list);
(void) fprintf(stderr, (void) fprintf(stderr,
gettext("invalid incremental source\n")); gettext("invalid incremental source\n"));
usage(B_FALSE); usage(B_FALSE);