busybox/backport-awk-fix-use-after-realloc-CVE-2021-42380-closes-1560.patch
liuxu ff3c86d804 fix CVE-2023-42364 CVE-2023-42365 CVE-2023-42366 CVE-2023-42363
Signed-off-by: liuxu <liuxu156@huawei.com>
(cherry picked from commit 5bdec6d07aad71a4f8be4e43076a290b72c2cd96)
2024-06-19 14:50:50 +08:00

100 lines
2.9 KiB
Diff

From 09656b9beb583eee73b58f64e0e43c0df262c99c Mon Sep 17 00:00:00 2001
From: liuxu <liuxu156@huawei.com>
Date: Wed, 19 Jun 2024 11:32:49 +0800
Subject: [PATCH 3/4] awk: fix use-after-realloc (CVE-2021-42380), closes 15601
backport from upstream:
https://git.alpinelinux.org/aports/plain/main/busybox/0029-awk-fix-use-after-realloc-CVE-2021-42380-closes-1560.patch
Signed-off-by: liuxu <liuxu156@huawei.com>
---
editors/awk.c | 34 ++++++++++++++++++++++++++++------
1 file changed, 28 insertions(+), 6 deletions(-)
diff --git a/editors/awk.c b/editors/awk.c
index e1d510c..7a73f04 100644
--- a/editors/awk.c
+++ b/editors/awk.c
@@ -558,7 +558,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;
@@ -1965,9 +1965,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;
@@ -2925,6 +2925,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);
@@ -2933,10 +2934,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);
@@ -2955,14 +2962,29 @@ 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);
}
}
+ /* Must get L.s after R.v is evaluated in case it realloc's L.v.
+ * eg: x = (v = "abc", gsub("b", "X", v));
+ */
+ if ((opinfo & OF_RES1) && (opinfo & OF_STR1)) {
+ L.s = getvar_s(L.v);
+ debug_printf_eval("L.s:'%s'\n", L.s);
+ }
+
debug_printf_eval("switch(0x%x)\n", XC(opinfo & OPCLSMASK));
switch (XC(opinfo & OPCLSMASK)) {
--
2.43.0