summaryrefslogtreecommitdiffstats
path: root/meta/recipes-core/busybox/files/CVE-2021-423xx-awk.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-core/busybox/files/CVE-2021-423xx-awk.patch')
-rw-r--r--meta/recipes-core/busybox/files/CVE-2021-423xx-awk.patch215
1 files changed, 215 insertions, 0 deletions
diff --git a/meta/recipes-core/busybox/files/CVE-2021-423xx-awk.patch b/meta/recipes-core/busybox/files/CVE-2021-423xx-awk.patch
new file mode 100644
index 0000000000..7e3d47b88c
--- /dev/null
+++ b/meta/recipes-core/busybox/files/CVE-2021-423xx-awk.patch
@@ -0,0 +1,215 @@
1From a21708eb8d07b4a6dbc1d3e4ace4c5721515a84c Mon Sep 17 00:00:00 2001
2From: Sana Kazi <Sana.Kazi@kpit.com>
3Date: Wed, 8 Dec 2021 12:25:34 +0530
4Subject: [PATCH] busybox: Fix multiple security issues in awk
5
6Description: fix multiple security issues in awk
7Origin: backported awk.c from busybox 1.34.1
8
9CVE: CVE-2021-42378
10CVE: CVE-2021-42379
11CVE: CVE-2021-42380
12CVE: CVE-2021-42381
13CVE: CVE-2021-42382
14CVE: CVE-2021-42384
15CVE: CVE-2021-42385
16CVE: CVE-2021-42386
17
18Upstream-Status: Backport [https://launchpad.net/ubuntu/+archive/primary/+sourcefiles/busybox/1:1.30.1-6ubuntu3.1/busybox_1.30.1-6ubuntu3.1.debian.tar.xz]
19
20Comment: Refreshed first hunk and removed few hunks as they are already present in source.
21
22Signed-off-by: Sana Kazi <Sana.Kazi@kpit.com>
23Signed-off-by: Ranjitsinh Rathod <Ranjitsinh.Rathod@kpit.com>
24
25---
26 editors/awk.c | 80 ++++++++++++++++++++++++++++++++++++++-------------
27 1 file changed, 60 insertions(+), 20 deletions(-)
28
29diff --git a/editors/awk.c b/editors/awk.c
30index d25508e..4e4f282 100644
31--- a/editors/awk.c
32+++ b/editors/awk.c
33@@ -272,7 +272,8 @@ typedef struct tsplitter_s {
34 /* if previous token class is CONCAT1 and next is CONCAT2, concatenation */
35 /* operator is inserted between them */
36 #define TC_CONCAT1 (TC_VARIABLE | TC_ARRTERM | TC_SEQTERM \
37- | TC_STRING | TC_NUMBER | TC_UOPPOST)
38+ | TC_STRING | TC_NUMBER | TC_UOPPOST \
39+ | TC_LENGTH)
40 #define TC_CONCAT2 (TC_OPERAND | TC_UOPPRE)
41
42 #define OF_RES1 0x010000
43@@ -404,7 +405,7 @@ static const char tokenlist[] ALIGN1 =
44
45 #define OC_B OC_BUILTIN
46
47-static const uint32_t tokeninfo[] = {
48+static const uint32_t tokeninfo[] ALIGN4 = {
49 0,
50 0,
51 OC_REGEXP,
52@@ -1070,8 +1071,10 @@ static uint32_t next_token(uint32_t expected)
53 const uint32_t *ti;
54
55 if (t_rollback) {
56+ debug_printf_parse("%s: using rolled-back token\n", __func__);
57 t_rollback = FALSE;
58 } else if (concat_inserted) {
59+ debug_printf_parse("%s: using concat-inserted token\n", __func__);
60 concat_inserted = FALSE;
61 t_tclass = save_tclass;
62 t_info = save_info;
63@@ -1200,7 +1203,11 @@ static uint32_t next_token(uint32_t expected)
64 goto readnext;
65
66 /* insert concatenation operator when needed */
67- if ((ltclass & TC_CONCAT1) && (tc & TC_CONCAT2) && (expected & TC_BINOP)) {
68+ debug_printf_parse("%s: %x %x %x concat_inserted?\n", __func__,
69+ (ltclass & TC_CONCAT1), (tc & TC_CONCAT2), (expected & TC_BINOP));
70+ if ((ltclass & TC_CONCAT1) && (tc & TC_CONCAT2) && (expected & TC_BINOP)
71+ && !(ltclass == TC_LENGTH && tc == TC_SEQSTART) /* but not for "length(..." */
72+ ) {
73 concat_inserted = TRUE;
74 save_tclass = tc;
75 save_info = t_info;
76@@ -1208,6 +1215,7 @@ static uint32_t next_token(uint32_t expected)
77 t_info = OC_CONCAT | SS | P(35);
78 }
79
80+ debug_printf_parse("%s: t_tclass=tc=%x\n", __func__, t_tclass);
81 t_tclass = tc;
82 }
83 ltclass = t_tclass;
84@@ -1218,6 +1226,7 @@ static uint32_t next_token(uint32_t expected)
85 EMSG_UNEXP_EOS : EMSG_UNEXP_TOKEN);
86 }
87
88+ debug_printf_parse("%s: returning, ltclass:%x t_double:%f\n", __func__, ltclass, t_double);
89 return ltclass;
90 #undef concat_inserted
91 #undef save_tclass
92@@ -1282,7 +1291,7 @@ static node *parse_expr(uint32_t iexp)
93 glptr = NULL;
94
95 } else if (tc & (TC_BINOP | TC_UOPPOST)) {
96- debug_printf_parse("%s: TC_BINOP | TC_UOPPOST\n", __func__);
97+ debug_printf_parse("%s: TC_BINOP | TC_UOPPOST tc:%x\n", __func__, tc);
98 /* for binary and postfix-unary operators, jump back over
99 * previous operators with higher priority */
100 vn = cn;
101@@ -1350,8 +1359,10 @@ static node *parse_expr(uint32_t iexp)
102 v = cn->l.v = xzalloc(sizeof(var));
103 if (tc & TC_NUMBER)
104 setvar_i(v, t_double);
105- else
106+ else {
107 setvar_s(v, t_string);
108+ xtc &= ~TC_UOPPOST; /* "str"++ is not allowed */
109+ }
110 break;
111
112 case TC_REGEXP:
113@@ -1387,7 +1398,12 @@ static node *parse_expr(uint32_t iexp)
114
115 case TC_LENGTH:
116 debug_printf_parse("%s: TC_LENGTH\n", __func__);
117- next_token(TC_SEQSTART | TC_OPTERM | TC_GRPTERM);
118+ next_token(TC_SEQSTART /* length(...) */
119+ | TC_OPTERM /* length; (or newline)*/
120+ | TC_GRPTERM /* length } */
121+ | TC_BINOPX /* length <op> NUM */
122+ | TC_COMMA /* print length, 1 */
123+ );
124 rollback_token();
125 if (t_tclass & TC_SEQSTART) {
126 /* It was a "(" token. Handle just like TC_BUILTIN */
127@@ -1747,12 +1763,34 @@ static void fsrealloc(int size)
128 nfields = size;
129 }
130
131+static int regexec1_nonempty(const regex_t *preg, const char *s, regmatch_t pmatch[])
132+{
133+ int r = regexec(preg, s, 1, pmatch, 0);
134+ if (r == 0 && pmatch[0].rm_eo == 0) {
135+ /* For example, happens when FS can match
136+ * an empty string (awk -F ' *'). Logically,
137+ * this should split into one-char fields.
138+ * However, gawk 5.0.1 searches for first
139+ * _non-empty_ separator string match:
140+ */
141+ size_t ofs = 0;
142+ do {
143+ ofs++;
144+ if (!s[ofs])
145+ return REG_NOMATCH;
146+ regexec(preg, s + ofs, 1, pmatch, 0);
147+ } while (pmatch[0].rm_eo == 0);
148+ pmatch[0].rm_so += ofs;
149+ pmatch[0].rm_eo += ofs;
150+ }
151+ return r;
152+}
153+
154 static int awk_split(const char *s, node *spl, char **slist)
155 {
156- int l, n;
157+ int n;
158 char c[4];
159 char *s1;
160- regmatch_t pmatch[2]; // TODO: why [2]? [1] is enough...
161
162 /* in worst case, each char would be a separate field */
163 *slist = s1 = xzalloc(strlen(s) * 2 + 3);
164@@ -1769,29 +1807,31 @@ static int awk_split(const char *s, node *spl, char **slist)
165 return n; /* "": zero fields */
166 n++; /* at least one field will be there */
167 do {
168+ int l;
169+ regmatch_t pmatch[2]; // TODO: why [2]? [1] is enough...
170+
171 l = strcspn(s, c+2); /* len till next NUL or \n */
172- if (regexec(icase ? spl->r.ire : spl->l.re, s, 1, pmatch, 0) == 0
173+ if (regexec1_nonempty(icase ? spl->r.ire : spl->l.re, s, pmatch) == 0
174 && pmatch[0].rm_so <= l
175 ) {
176+ /* if (pmatch[0].rm_eo == 0) ... - impossible */
177 l = pmatch[0].rm_so;
178- if (pmatch[0].rm_eo == 0) {
179- l++;
180- pmatch[0].rm_eo++;
181- }
182 n++; /* we saw yet another delimiter */
183 } else {
184 pmatch[0].rm_eo = l;
185 if (s[l])
186 pmatch[0].rm_eo++;
187 }
188- memcpy(s1, s, l);
189- /* make sure we remove *all* of the separator chars */
190- do {
191- s1[l] = '\0';
192- } while (++l < pmatch[0].rm_eo);
193- nextword(&s1);
194+ s1 = mempcpy(s1, s, l);
195+ *s1++ = '\0';
196 s += pmatch[0].rm_eo;
197 } while (*s);
198+
199+ /* echo a-- | awk -F-- '{ print NF, length($NF), $NF }'
200+ * should print "2 0 ":
201+ */
202+ *s1 = '\0';
203+
204 return n;
205 }
206 if (c[0] == '\0') { /* null split */
207@@ -1995,7 +2035,7 @@ static int ptest(node *pattern)
208 static int awk_getline(rstream *rsm, var *v)
209 {
210 char *b;
211- regmatch_t pmatch[2];
212+ regmatch_t pmatch[2]; // TODO: why [2]? [1] is enough...
213 int size, a, p, pp = 0;
214 int fd, so, eo, r, rp;
215 char c, *m, *s;