Don't modify argv[] in user tools

argv[] gets modified during string parsing for input arguments. This
is reflected in the live process listing. Don't do that.

Reviewed-by: Serapheim Dimitropoulos <serapheim@delphix.com>
Reviewed-by: loli10K <ezomori.nozomu@gmail.com>
Reviewed-by: Giuseppe Di Natale <guss80@gmail.com>
Reviewed-by: George Melikov <mail@gmelikov.ru>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: DHE <git@dehacked.net>
Closes #7760
This commit is contained in:
DeHackEd 2018-08-20 12:55:18 -04:00 committed by Tony Hutter
parent 98bc8e0b23
commit 778290d5bc
2 changed files with 32 additions and 4 deletions

View File

@ -7041,6 +7041,7 @@ main(int argc, char **argv)
int ret = 0; int ret = 0;
int i = 0; int i = 0;
char *cmdname; char *cmdname;
char **newargv;
(void) setlocale(LC_ALL, ""); (void) setlocale(LC_ALL, "");
(void) textdomain(TEXT_DOMAIN); (void) textdomain(TEXT_DOMAIN);
@ -7095,17 +7096,26 @@ main(int argc, char **argv)
libzfs_print_on_error(g_zfs, B_TRUE); libzfs_print_on_error(g_zfs, B_TRUE);
/*
* Many commands modify input strings for string parsing reasons.
* We create a copy to protect the original argv.
*/
newargv = malloc((argc + 1) * sizeof (newargv[0]));
for (i = 0; i < argc; i++)
newargv[i] = strdup(argv[i]);
newargv[argc] = NULL;
/* /*
* Run the appropriate command. * Run the appropriate command.
*/ */
libzfs_mnttab_cache(g_zfs, B_TRUE); libzfs_mnttab_cache(g_zfs, B_TRUE);
if (find_command_idx(cmdname, &i) == 0) { if (find_command_idx(cmdname, &i) == 0) {
current_command = &command_table[i]; current_command = &command_table[i];
ret = command_table[i].func(argc - 1, argv + 1); ret = command_table[i].func(argc - 1, newargv + 1);
} else if (strchr(cmdname, '=') != NULL) { } else if (strchr(cmdname, '=') != NULL) {
verify(find_command_idx("set", &i) == 0); verify(find_command_idx("set", &i) == 0);
current_command = &command_table[i]; current_command = &command_table[i];
ret = command_table[i].func(argc, argv); ret = command_table[i].func(argc, newargv);
} else { } else {
(void) fprintf(stderr, gettext("unrecognized " (void) fprintf(stderr, gettext("unrecognized "
"command '%s'\n"), cmdname); "command '%s'\n"), cmdname);
@ -7113,6 +7123,10 @@ main(int argc, char **argv)
ret = 1; ret = 1;
} }
for (i = 0; i < argc; i++)
free(newargv[i]);
free(newargv);
if (ret == 0 && log_history) if (ret == 0 && log_history)
(void) zpool_log_history(g_zfs, history_str); (void) zpool_log_history(g_zfs, history_str);

View File

@ -7971,6 +7971,7 @@ main(int argc, char **argv)
int ret = 0; int ret = 0;
int i = 0; int i = 0;
char *cmdname; char *cmdname;
char **newargv;
(void) setlocale(LC_ALL, ""); (void) setlocale(LC_ALL, "");
(void) textdomain(TEXT_DOMAIN); (void) textdomain(TEXT_DOMAIN);
@ -8005,16 +8006,25 @@ main(int argc, char **argv)
zfs_save_arguments(argc, argv, history_str, sizeof (history_str)); zfs_save_arguments(argc, argv, history_str, sizeof (history_str));
/*
* Many commands modify input strings for string parsing reasons.
* We create a copy to protect the original argv.
*/
newargv = malloc((argc + 1) * sizeof (newargv[0]));
for (i = 0; i < argc; i++)
newargv[i] = strdup(argv[i]);
newargv[argc] = NULL;
/* /*
* Run the appropriate command. * Run the appropriate command.
*/ */
if (find_command_idx(cmdname, &i) == 0) { if (find_command_idx(cmdname, &i) == 0) {
current_command = &command_table[i]; current_command = &command_table[i];
ret = command_table[i].func(argc - 1, argv + 1); ret = command_table[i].func(argc - 1, newargv + 1);
} else if (strchr(cmdname, '=')) { } else if (strchr(cmdname, '=')) {
verify(find_command_idx("set", &i) == 0); verify(find_command_idx("set", &i) == 0);
current_command = &command_table[i]; current_command = &command_table[i];
ret = command_table[i].func(argc, argv); ret = command_table[i].func(argc, newargv);
} else if (strcmp(cmdname, "freeze") == 0 && argc == 3) { } else if (strcmp(cmdname, "freeze") == 0 && argc == 3) {
/* /*
* 'freeze' is a vile debugging abomination, so we treat * 'freeze' is a vile debugging abomination, so we treat
@ -8031,6 +8041,10 @@ main(int argc, char **argv)
ret = 1; ret = 1;
} }
for (i = 0; i < argc; i++)
free(newargv[i]);
free(newargv);
if (ret == 0 && log_history) if (ret == 0 && log_history)
(void) zpool_log_history(g_zfs, history_str); (void) zpool_log_history(g_zfs, history_str);