diff --git a/release/src/router/busybox/include/libbb.h b/release/src/router/busybox/include/libbb.h index 031a463103f..a396c753bce 100644 --- a/release/src/router/busybox/include/libbb.h +++ b/release/src/router/busybox/include/libbb.h @@ -1567,6 +1567,7 @@ line_input_t *new_line_input_t(int flags) FAST_FUNC; */ int read_line_input(line_input_t *st, const char *prompt, char *command, int maxsize, int timeout) FAST_FUNC; void show_history(const line_input_t *st) FAST_FUNC; +void clear_history(line_input_t *st) FAST_FUNC; # if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT void save_history(line_input_t *st); # endif diff --git a/release/src/router/busybox/libbb/lineedit.c b/release/src/router/busybox/libbb/lineedit.c index 3e62f46b4cf..c1856d14d59 100644 --- a/release/src/router/busybox/libbb/lineedit.c +++ b/release/src/router/busybox/libbb/lineedit.c @@ -1341,6 +1341,41 @@ void FAST_FUNC show_history(const line_input_t *st) printf("%4d %s\n", i, st->history[i]); } +// the function secure_memory_wipe(), aka OPENSSL_cleanse(), was stolen from +// OpenSSL because we need a way to securely wipe the ash command history from +// memory without the compiler optimizing it away +static unsigned char secure_memory_wipe_ctr = 0; +static void secure_memory_wipe(void *ptr, size_t len) +{ + unsigned char *p = ptr; + size_t loop = len, ctr = secure_memory_wipe_ctr; + while(loop--) + { + *(p++) = (unsigned char)ctr; + ctr += (17 + ((size_t)p & 0xF)); + } + p=memchr(ptr, (unsigned char)ctr, len); + if(p) + ctr += (63 + (size_t)p); + secure_memory_wipe_ctr = (unsigned char)ctr; +} + +/* Clears command history. Used by shell 'history' builtins */ +void FAST_FUNC clear_history(line_input_t *st) +{ + int i; + + if (!st) + return; + + for (i = 0; i < st->cnt_history; i++) { + secure_memory_wipe(st->history[i], strlen(st->history[i])); + free(st->history[i]); + st->history[i] = NULL; + } + st->cur_history = st->cnt_history = 0; +} + # if ENABLE_FEATURE_EDITING_SAVEHISTORY /* We try to ensure that concurrent additions to the history * do not overwrite each other. diff --git a/release/src/router/busybox/shell/ash.c b/release/src/router/busybox/shell/ash.c index faa45a8dc60..498c75230ae 100644 --- a/release/src/router/busybox/shell/ash.c +++ b/release/src/router/busybox/shell/ash.c @@ -12611,6 +12611,10 @@ helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) static int FAST_FUNC historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) { + if (nextopt("c") != '\0') { + clear_history(line_input_state); + return EXIT_SUCCESS; + } show_history(line_input_state); return EXIT_SUCCESS; } diff --git a/release/src/router/busybox/shell/hush.c b/release/src/router/busybox/shell/hush.c index dfbbb4122e6..bba7269ad8f 100644 --- a/release/src/router/busybox/shell/hush.c +++ b/release/src/router/busybox/shell/hush.c @@ -8715,6 +8715,15 @@ static int FAST_FUNC builtin_help(char **argv UNUSED_PARAM) #if MAX_HISTORY && ENABLE_FEATURE_EDITING static int FAST_FUNC builtin_history(char **argv UNUSED_PARAM) { + unsigned opts; + + opts = getopt32(argv, "!c"); + if (opts == (unsigned)-1) + return EXIT_FAILURE; + if (opts & 1) { + clear_history(G.line_input_state); + return EXIT_SUCCESS; + } show_history(G.line_input_state); return EXIT_SUCCESS; }