summaryrefslogtreecommitdiff
path: root/aports/busybox/0029-awk-fix-use-after-realloc-CVE-2021-42380-closes-1560.patch
blob: e49bff43992b64dbc5ae0c972ee5de827a673dcb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
From 5b1deb2b98a0513b101c600e856d64edd9d47a2e Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Fri, 26 May 2023 18:52:52 +0200
Subject: [PATCH] awk: fix use-after-realloc (CVE-2021-42380), closes 15601
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 editors/awk.c       | 26 ++++++++++++++++-----
 2 files changed, 75 insertions(+), 6 deletions(-)

diff --git a/editors/awk.c b/editors/awk.c
index 728ee8685..2af823808 100644
--- a/editors/awk.c
+++ b/editors/awk.c
@@ -555,7 +555,7 @@ struct globals {
 	const char *g_progname;
 	int g_lineno;
 	int nfields;
-	int maxfields; /* used in fsrealloc() only */
+	unsigned maxfields;
 	var *Fields;
 	char *g_pos;
 	char g_saved_ch;
@@ -1931,9 +1931,9 @@ static void fsrealloc(int size)
 {
 	int i, newsize;
 
-	if (size >= maxfields) {
-		/* Sanity cap, easier than catering for overflows */
-		if (size > 0xffffff)
+	if ((unsigned)size >= maxfields) {
+		/* Sanity cap, easier than catering for over/underflows */
+		if ((unsigned)size > 0xffffff)
 			bb_die_memory_exhausted();
 
 		i = maxfields;
@@ -2891,6 +2891,7 @@ static var *evaluate(node *op, var *res)
 		uint32_t opinfo;
 		int opn;
 		node *op1;
+		var *old_Fields_ptr;
 
 		opinfo = op->info;
 		opn = (opinfo & OPNMASK);
@@ -2899,10 +2900,16 @@ static var *evaluate(node *op, var *res)
 		debug_printf_eval("opinfo:%08x opn:%08x\n", opinfo, opn);
 
 		/* execute inevitable things */
+		old_Fields_ptr = NULL;
 		if (opinfo & OF_RES1) {
 			if ((opinfo & OF_REQUIRED) && !op1)
 				syntax_error(EMSG_TOO_FEW_ARGS);
 			L.v = evaluate(op1, TMPVAR0);
+			/* Does L.v point to $n variable? */
+			if ((size_t)(L.v - Fields) < maxfields) {
+				/* yes, remember where Fields[] is */
+				old_Fields_ptr = Fields;
+			}
 			if (opinfo & OF_STR1) {
 				L.s = getvar_s(L.v);
 				debug_printf_eval("L.s:'%s'\n", L.s);
@@ -2921,8 +2928,15 @@ static var *evaluate(node *op, var *res)
 		 */
 		if (opinfo & OF_RES2) {
 			R.v = evaluate(op->r.n, TMPVAR1);
-			//TODO: L.v may be invalid now, set L.v to NULL to catch bugs?
-			//L.v = NULL;
+			/* Seen in $5=$$5=$0:
+			 * Evaluation of R.v ($$5=$0 expression)
+			 * made L.v ($5) invalid. It's detected here.
+			 */
+			if (old_Fields_ptr) {
+				//if (old_Fields_ptr != Fields)
+				//	debug_printf_eval("L.v moved\n");
+				L.v += Fields - old_Fields_ptr;
+			}
 			if (opinfo & OF_STR2) {
 				R.s = getvar_s(R.v);
 				debug_printf_eval("R.s:'%s'\n", R.s);