diff options
| author | Sana Kazi <Sana.Kazi@partner.bmw.de> | 2021-12-11 16:43:29 +0530 |
|---|---|---|
| committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2021-12-14 22:49:22 +0000 |
| commit | 8967fcbcc4c273e641b4e1c1ebd97d7cf2a065e6 (patch) | |
| tree | 465ec293b0726b22930b7a942cb9586b855cc4b3 /meta | |
| parent | 22767ef3986a7ac90e7c566ed38044d298a20895 (diff) | |
| download | poky-8967fcbcc4c273e641b4e1c1ebd97d7cf2a065e6.tar.gz | |
busybox: Fix multiple security issues in awk
CVE-2021-423xx-awk.patch fixes below listed CVEs for busybox:
CVE-2021-42378, CVE-2021-42379, CVE-2021-42380, CVE-2021-42381,
CVE-2021-42382, CVE-2021-42384, CVE-2021-42385, CVE-2021-42386
(From OE-Core rev: 37a92e6d4399cdb36d24b988d77aa41b1e205a90)
Signed-off-by: Sana Kazi <Sana.Kazi@kpit.com>
Signed-off-by: Ranjitsinh Rathod <ranjitsinh.rathod@kpit.com>
Signed-off-by: Ranjitsinh Rathod <ranjitsinhrathod1991@gmail.com>
Signed-off-by: Steve Sakoman <steve@sakoman.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta')
| -rw-r--r-- | meta/recipes-core/busybox/busybox_1.31.1.bb | 1 | ||||
| -rw-r--r-- | meta/recipes-core/busybox/files/CVE-2021-423xx-awk.patch | 215 |
2 files changed, 216 insertions, 0 deletions
diff --git a/meta/recipes-core/busybox/busybox_1.31.1.bb b/meta/recipes-core/busybox/busybox_1.31.1.bb index 14ac710f3b..38b448b3e1 100644 --- a/meta/recipes-core/busybox/busybox_1.31.1.bb +++ b/meta/recipes-core/busybox/busybox_1.31.1.bb | |||
| @@ -54,6 +54,7 @@ SRC_URI = "https://busybox.net/downloads/busybox-${PV}.tar.bz2;name=tarball \ | |||
| 54 | file://0001-mktemp-add-tmpdir-option.patch \ | 54 | file://0001-mktemp-add-tmpdir-option.patch \ |
| 55 | file://CVE-2021-42374.patch \ | 55 | file://CVE-2021-42374.patch \ |
| 56 | file://CVE-2021-42376.patch \ | 56 | file://CVE-2021-42376.patch \ |
| 57 | file://CVE-2021-423xx-awk.patch \ | ||
| 57 | " | 58 | " |
| 58 | SRC_URI_append_libc-musl = " file://musl.cfg " | 59 | SRC_URI_append_libc-musl = " file://musl.cfg " |
| 59 | 60 | ||
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 @@ | |||
| 1 | From a21708eb8d07b4a6dbc1d3e4ace4c5721515a84c Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Sana Kazi <Sana.Kazi@kpit.com> | ||
| 3 | Date: Wed, 8 Dec 2021 12:25:34 +0530 | ||
| 4 | Subject: [PATCH] busybox: Fix multiple security issues in awk | ||
| 5 | |||
| 6 | Description: fix multiple security issues in awk | ||
| 7 | Origin: backported awk.c from busybox 1.34.1 | ||
| 8 | |||
| 9 | CVE: CVE-2021-42378 | ||
| 10 | CVE: CVE-2021-42379 | ||
| 11 | CVE: CVE-2021-42380 | ||
| 12 | CVE: CVE-2021-42381 | ||
| 13 | CVE: CVE-2021-42382 | ||
| 14 | CVE: CVE-2021-42384 | ||
| 15 | CVE: CVE-2021-42385 | ||
| 16 | CVE: CVE-2021-42386 | ||
| 17 | |||
| 18 | Upstream-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 | |||
| 20 | Comment: Refreshed first hunk and removed few hunks as they are already present in source. | ||
| 21 | |||
| 22 | Signed-off-by: Sana Kazi <Sana.Kazi@kpit.com> | ||
| 23 | Signed-off-by: Ranjitsinh Rathod <Ranjitsinh.Rathod@kpit.com> | ||
| 24 | |||
| 25 | --- | ||
| 26 | editors/awk.c | 80 ++++++++++++++++++++++++++++++++++++++------------- | ||
| 27 | 1 file changed, 60 insertions(+), 20 deletions(-) | ||
| 28 | |||
| 29 | diff --git a/editors/awk.c b/editors/awk.c | ||
| 30 | index 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; | ||
