From ed4a24dfd10539e144ed4b7de008f8791d09a551 Mon Sep 17 00:00:00 2001 From: zhuyan Date: Tue, 29 Aug 2023 20:50:32 +0800 Subject: ash: initialize basepf.buf in ash When I planned to print the command in read_line_input, I found that after the system started, the command printed for the first time was always garbled. After analysis, it is found that in the init() function of ash, the variable basepf.buf is not initialized after applying for memory, resulting in garbled initial data. Then assign it to the global variable g_parsefile->buf in ash.c, and then pass g_parsefile->buf to the parameter command of the function read_line_input in the function preadfd(), and finally cause it to be garbled when the command is printed by read_line_input. The call stack is as follows: #0 read_line_input (st=0xb6fff220, prompt=0xb6ffc910 "\\[\\033[32m\\]\\h \\w\\[\\033[m\\] \\$ ", command=command@entry=0xb6ffc230 "P\325\377\266P\325\377\266", maxsize=maxsize@entry=1024) at libbb/lineedit.c:2461 #1 0x0043ef8c in preadfd () at shell/ash.c:10812 #2 preadbuffer () at shell/ash.c:10914 #3 pgetc () at shell/ash.c:10997 #4 0x00440c20 in pgetc_eatbnl () at shell/ash.c:11039 #5 0x00440cbc in xxreadtoken () at shell/ash.c:13157 #6 0x00440f40 in readtoken () at shell/ash.c:13268 #7 0x00441234 in list (nlflag=nlflag@entry=1) at shell/ash.c:11782 #8 0x004420e8 in parsecmd (interact=) at shell/ash.c:13344 #9 0x00442c34 in cmdloop (top=top@entry=1) at shell/ash.c:13549 #10 0x00444e4c in ash_main (argc=, argv=0x444e4c ) at shell/ash.c:14747 #11 0x00407954 in run_applet_no_and_exit (applet_no=9, name=, argv=0xbefffd34) at libbb/appletlib.c:1024 #12 0x00407b68 in run_applet_and_exit (name=0xbefffe56 "ash", argv=0x9) at libbb/appletlib.c:1047 #13 0x00407f88 in main (argc=, argv=0xbefffd34) at libbb/appletlib.c:1181 Fixes: 82dd14a510ca ("ash: use CONFIG_FEATURE_EDITING_MAX_LEN") Signed-off-by: zhuyan Signed-off-by: Denys Vlasenko --- shell/ash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/ash.c b/shell/ash.c index e1d93da73..771fc8bf9 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -14484,7 +14484,7 @@ static NOINLINE void init(void) { /* we will never free this */ - basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ); + basepf.next_to_pgetc = basepf.buf = ckzalloc(IBUFSIZ); basepf.linno = 1; sigmode[SIGCHLD - 1] = S_DFL; /* ensure we install handler even if it is SIG_IGNed */ -- cgit v1.2.3-55-g6feb From 2cc9d436e80632157b99e18d413a62b2d44d321a Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Tue, 22 Aug 2023 09:38:03 +0100 Subject: tsort: avoid use-after-free When the input data contained a cycle it was possible for tsort to attempt to access freed nodes. This sometimes resulted in the test case 'echo a b b a | tsort' crashing. Don't free nodes when they're removed from the graph. function old new delta tsort_main 621 596 -25 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-25) Total: -25 bytes Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- coreutils/tsort.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/coreutils/tsort.c b/coreutils/tsort.c index a451ed2ff..e1ee6bcd7 100644 --- a/coreutils/tsort.c +++ b/coreutils/tsort.c @@ -101,6 +101,10 @@ int tsort_main(int argc UNUSED_PARAM, char **argv) ssize_t len; struct node *a; int cycles; + unsigned i; +#if ENABLE_FEATURE_CLEAN_UP + unsigned max_len; +#endif INIT_G(); @@ -152,9 +156,11 @@ int tsort_main(int argc UNUSED_PARAM, char **argv) * - if any nodes are left, they form cycles. */ cycles = 0; +#if ENABLE_FEATURE_CLEAN_UP + max_len = G.nodes_len; +#endif while (G.nodes_len) { struct node *n; - unsigned i; /* Search for first node with no incoming edges */ for (i = 0; i < G.nodes_len; i++) { @@ -173,16 +179,24 @@ int tsort_main(int argc UNUSED_PARAM, char **argv) /* Remove the node (need no longer maintain sort) */ n = G.nodes[i]; G.nodes[i] = G.nodes[--G.nodes_len]; +#if ENABLE_FEATURE_CLEAN_UP + /* Keep reference to removed node so it can be freed */ + G.nodes[G.nodes_len] = n; +#endif /* And remove its outgoing edges */ for (i = 0; i < n->out_count; i++) n->out[i]->in_count--; - free(n->out); puts(n->name); - free(n); + } +#if ENABLE_FEATURE_CLEAN_UP + for (i = 0; i < max_len; i++) { + free(G.nodes[i]->out); + free(G.nodes[i]); } free(G.nodes); +#endif fflush_stdout_and_exit(cycles ? 1 : 0); } -- cgit v1.2.3-55-g6feb