diff mbox series

[kirkstone] busybox: CVE-2023-42364, CVE-2023-42365 & CVE-2023-42366 fixes

Message ID 20240807072049.229288-1-hprajapati@mvista.com
State Superseded
Delegated to: Steve Sakoman
Headers show
Series [kirkstone] busybox: CVE-2023-42364, CVE-2023-42365 & CVE-2023-42366 fixes | expand

Commit Message

Hitendra Prajapati Aug. 7, 2024, 7:20 a.m. UTC
backport upstream fix for CVEs and fix the regression that introduced [1]

[1] http://lists.busybox.net/pipermail/busybox/2024-May/090766.html

Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
---
 ...01-awk-fix-precedence-of-relative-to.patch | 197 ++++++++++++++++++
 ...1-awk.c-fix-CVE-2023-42366-bug-15874.patch |  36 ++++
 ...x-ternary-operator-and-precedence-of.patch |  96 +++++++++
 meta/recipes-core/busybox/busybox_1.35.0.bb   |   3 +
 4 files changed, 332 insertions(+)
 create mode 100644 meta/recipes-core/busybox/busybox/0001-awk-fix-precedence-of-relative-to.patch
 create mode 100644 meta/recipes-core/busybox/busybox/0001-awk.c-fix-CVE-2023-42366-bug-15874.patch
 create mode 100644 meta/recipes-core/busybox/busybox/0002-awk-fix-ternary-operator-and-precedence-of.patch

Comments

Steve Sakoman Aug. 7, 2024, 4:53 p.m. UTC | #1
On Wed, Aug 7, 2024 at 12:21 AM Hitendra Prajapati via
lists.openembedded.org <hprajapati=mvista.com@lists.openembedded.org>
wrote:
>
> backport upstream fix for CVEs and fix the regression that introduced [1]
>
> [1] http://lists.busybox.net/pipermail/busybox/2024-May/090766.html
>
> Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
> ---
>  ...01-awk-fix-precedence-of-relative-to.patch | 197 ++++++++++++++++++
>  ...1-awk.c-fix-CVE-2023-42366-bug-15874.patch |  36 ++++
>  ...x-ternary-operator-and-precedence-of.patch |  96 +++++++++
>  meta/recipes-core/busybox/busybox_1.35.0.bb   |   3 +
>  4 files changed, 332 insertions(+)
>  create mode 100644 meta/recipes-core/busybox/busybox/0001-awk-fix-precedence-of-relative-to.patch
>  create mode 100644 meta/recipes-core/busybox/busybox/0001-awk.c-fix-CVE-2023-42366-bug-15874.patch
>  create mode 100644 meta/recipes-core/busybox/busybox/0002-awk-fix-ternary-operator-and-precedence-of.patch

The naming convention is to indicate the CVE number in the file name,
so the file name for the CVE-2023-42366 fix should be
CVE-2023-42366.patch.

For the patches that fix 2 CVE's perhaps: CVE-2023-42364_42365-1.patch
and CVE-2023-42364_42365-2.patch

> diff --git a/meta/recipes-core/busybox/busybox/0001-awk-fix-precedence-of-relative-to.patch b/meta/recipes-core/busybox/busybox/0001-awk-fix-precedence-of-relative-to.patch
> new file mode 100644
> index 0000000000..e3d623498c
> --- /dev/null
> +++ b/meta/recipes-core/busybox/busybox/0001-awk-fix-precedence-of-relative-to.patch
> @@ -0,0 +1,197 @@
> +From dedc9380c76834ba64c8b526aef6f461ea4e7f2e Mon Sep 17 00:00:00 2001
> +From: Denys Vlasenko <vda.linux@googlemail.com>
> +Date: Tue, 30 May 2023 16:42:18 +0200
> +Subject: [PATCH 1/2] awk: fix precedence of = relative to ==
> +
> +Discovered while adding code to disallow assignments to non-lvalues
> +
> +function                                             old     new   delta
> +parse_expr                                           936     991     +55
> +.rodata                                           105243  105247      +4
> +------------------------------------------------------------------------------
> +(add/remove: 0/0 grow/shrink: 2/0 up/down: 59/0)               Total: 59 bytes
> +
> +Upstream-Status: Backport [https://git.busybox.net/busybox/commit/?id=0256e00a9d077588bd3a39f5a1ef7e2eaa2911e4]
> +Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
> +(cherry picked from commit 0256e00a9d077588bd3a39f5a1ef7e2eaa2911e4)
> +
> +CVE: CVE-2023-42364 & CVE-2023-42365

Don't use an ampersand, a space separator is sufficient.

Thanks,

Steve

> +Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
> +---
> + editors/awk.c       | 66 ++++++++++++++++++++++++++++++---------------
> + testsuite/awk.tests |  5 ++++
> + 2 files changed, 50 insertions(+), 21 deletions(-)
> +
> +diff --git a/editors/awk.c b/editors/awk.c
> +index ec9301e..aff86fe 100644
> +--- a/editors/awk.c
> ++++ b/editors/awk.c
> +@@ -337,7 +337,9 @@ static void debug_parse_print_tc(uint32_t n)
> + #undef P
> + #undef PRIMASK
> + #undef PRIMASK2
> +-#define P(x)      (x << 24)
> ++/* Smaller 'x' means _higher_ operator precedence */
> ++#define PRECEDENCE(x) (x << 24)
> ++#define P(x)      PRECEDENCE(x)
> + #define PRIMASK   0x7F000000
> + #define PRIMASK2  0x7E000000
> +
> +@@ -360,7 +362,7 @@ enum {
> +       OC_MOVE = 0x1f00,       OC_PGETLINE = 0x2000,   OC_REGEXP = 0x2100,
> +       OC_REPLACE = 0x2200,    OC_RETURN = 0x2300,     OC_SPRINTF = 0x2400,
> +       OC_TERNARY = 0x2500,    OC_UNARY = 0x2600,      OC_VAR = 0x2700,
> +-      OC_DONE = 0x2800,
> ++      OC_CONST = 0x2800,      OC_DONE = 0x2900,
> +
> +       ST_IF = 0x3000,         ST_DO = 0x3100,         ST_FOR = 0x3200,
> +       ST_WHILE = 0x3300
> +@@ -440,9 +442,9 @@ static const uint32_t tokeninfo[] ALIGN4 = {
> + #define TI_PREINC (OC_UNARY|xV|P(9)|'P')
> + #define TI_PREDEC (OC_UNARY|xV|P(9)|'M')
> +       TI_PREINC,               TI_PREDEC,               OC_FIELD|xV|P(5),
> +-      OC_COMPARE|VV|P(39)|5,   OC_MOVE|VV|P(74),        OC_REPLACE|NV|P(74)|'+', OC_REPLACE|NV|P(74)|'-',
> +-      OC_REPLACE|NV|P(74)|'*', OC_REPLACE|NV|P(74)|'/', OC_REPLACE|NV|P(74)|'%', OC_REPLACE|NV|P(74)|'&',
> +-      OC_BINARY|NV|P(29)|'+',  OC_BINARY|NV|P(29)|'-',  OC_REPLACE|NV|P(74)|'&', OC_BINARY|NV|P(15)|'&',
> ++      OC_COMPARE|VV|P(39)|5,   OC_MOVE|VV|P(38),        OC_REPLACE|NV|P(38)|'+', OC_REPLACE|NV|P(38)|'-',
> ++      OC_REPLACE|NV|P(38)|'*', OC_REPLACE|NV|P(38)|'/', OC_REPLACE|NV|P(38)|'%', OC_REPLACE|NV|P(38)|'&',
> ++      OC_BINARY|NV|P(29)|'+',  OC_BINARY|NV|P(29)|'-',  OC_REPLACE|NV|P(38)|'&', OC_BINARY|NV|P(15)|'&',
> +       OC_BINARY|NV|P(25)|'/',  OC_BINARY|NV|P(25)|'%',  OC_BINARY|NV|P(15)|'&',  OC_BINARY|NV|P(25)|'*',
> +       OC_COMPARE|VV|P(39)|4,   OC_COMPARE|VV|P(39)|3,   OC_COMPARE|VV|P(39)|0,   OC_COMPARE|VV|P(39)|1,
> + #define TI_LESS     (OC_COMPARE|VV|P(39)|2)
> +@@ -1290,7 +1292,7 @@ static uint32_t next_token(uint32_t expected)
> +                       save_tclass = tc;
> +                       save_info = t_info;
> +                       tc = TC_BINOPX;
> +-                      t_info = OC_CONCAT | SS | P(35);
> ++                      t_info = OC_CONCAT | SS | PRECEDENCE(35);
> +               }
> +
> +               t_tclass = tc;
> +@@ -1350,9 +1352,8 @@ static node *parse_expr(uint32_t term_tc)
> + {
> +       node sn;
> +       node *cn = &sn;
> +-      node *vn, *glptr;
> ++      node *glptr;
> +       uint32_t tc, expected_tc;
> +-      var *v;
> +
> +       debug_printf_parse("%s() term_tc(%x):", __func__, term_tc);
> +       debug_parse_print_tc(term_tc);
> +@@ -1363,11 +1364,12 @@ static node *parse_expr(uint32_t term_tc)
> +       expected_tc = TS_OPERAND | TS_UOPPRE | TC_REGEXP | term_tc;
> +
> +       while (!((tc = next_token(expected_tc)) & term_tc)) {
> ++              node *vn;
> +
> +               if (glptr && (t_info == TI_LESS)) {
> +                       /* input redirection (<) attached to glptr node */
> +                       debug_printf_parse("%s: input redir\n", __func__);
> +-                      cn = glptr->l.n = new_node(OC_CONCAT | SS | P(37));
> ++                      cn = glptr->l.n = new_node(OC_CONCAT | SS | PRECEDENCE(37));
> +                       cn->a.n = glptr;
> +                       expected_tc = TS_OPERAND | TS_UOPPRE;
> +                       glptr = NULL;
> +@@ -1379,24 +1381,42 @@ static node *parse_expr(uint32_t term_tc)
> +                        * previous operators with higher priority */
> +                       vn = cn;
> +                       while (((t_info & PRIMASK) > (vn->a.n->info & PRIMASK2))
> +-                          || ((t_info == vn->info) && t_info == TI_COLON)
> ++                          || (t_info == vn->info && t_info == TI_COLON)
> +                       ) {
> +                               vn = vn->a.n;
> +                               if (!vn->a.n) syntax_error(EMSG_UNEXP_TOKEN);
> +                       }
> +                       if (t_info == TI_TERNARY)
> + //TODO: why?
> +-                              t_info += P(6);
> ++                              t_info += PRECEDENCE(6);
> +                       cn = vn->a.n->r.n = new_node(t_info);
> +                       cn->a.n = vn->a.n;
> +                       if (tc & TS_BINOP) {
> +                               cn->l.n = vn;
> +-//FIXME: this is the place to detect and reject assignments to non-lvalues.
> +-//Currently we allow "assignments" to consts and temporaries, nonsense like this:
> +-// awk 'BEGIN { "qwe" = 1 }'
> +-// awk 'BEGIN { 7 *= 7 }'
> +-// awk 'BEGIN { length("qwe") = 1 }'
> +-// awk 'BEGIN { (1+1) += 3 }'
> ++
> ++                              /* Prevent:
> ++                               * awk 'BEGIN { "qwe" = 1 }'
> ++                               * awk 'BEGIN { 7 *= 7 }'
> ++                               * awk 'BEGIN { length("qwe") = 1 }'
> ++                               * awk 'BEGIN { (1+1) += 3 }'
> ++                               */
> ++                              /* Assignment? (including *= and friends) */
> ++                              if (((t_info & OPCLSMASK) == OC_MOVE)
> ++                               || ((t_info & OPCLSMASK) == OC_REPLACE)
> ++                              ) {
> ++                                      debug_printf_parse("%s: MOVE/REPLACE vn->info:%08x\n", __func__, vn->info);
> ++                                      /* Left side is a (variable or array element)
> ++                                       * or function argument
> ++                                       * or $FIELD ?
> ++                                       */
> ++                                      if ((vn->info & OPCLSMASK) != OC_VAR
> ++                                       && (vn->info & OPCLSMASK) != OC_FNARG
> ++                                       && (vn->info & OPCLSMASK) != OC_FIELD
> ++                                      ) {
> ++                                              syntax_error(EMSG_UNEXP_TOKEN); /* no. bad */
> ++                                      }
> ++                              }
> ++
> +                               expected_tc = TS_OPERAND | TS_UOPPRE | TC_REGEXP;
> +                               if (t_info == TI_PGETLINE) {
> +                                       /* it's a pipe */
> +@@ -1432,6 +1452,8 @@ static node *parse_expr(uint32_t term_tc)
> +               /* one should be very careful with switch on tclass -
> +                * only simple tclasses should be used (TC_xyz, not TS_xyz) */
> +               switch (tc) {
> ++                      var *v;
> ++
> +               case TC_VARIABLE:
> +               case TC_ARRAY:
> +                       debug_printf_parse("%s: TC_VARIABLE | TC_ARRAY\n", __func__);
> +@@ -1452,14 +1474,14 @@ static node *parse_expr(uint32_t term_tc)
> +               case TC_NUMBER:
> +               case TC_STRING:
> +                       debug_printf_parse("%s: TC_NUMBER | TC_STRING\n", __func__);
> +-                      cn->info = OC_VAR;
> ++                      cn->info = OC_CONST;
> +                       v = cn->l.v = xzalloc(sizeof(var));
> +-                      if (tc & TC_NUMBER)
> ++                      if (tc & TC_NUMBER) {
> +                               setvar_i(v, t_double);
> +-                      else {
> ++                       } else {
> +                               setvar_s(v, t_string);
> +-                              expected_tc &= ~TC_UOPPOST; /* "str"++ is not allowed */
> +                       }
> ++                      expected_tc &= ~TC_UOPPOST; /* NUM++, "str"++ not allowed */
> +                       break;
> +
> +               case TC_REGEXP:
> +@@ -3107,6 +3129,8 @@ static var *evaluate(node *op, var *res)
> +
> +               /* -- recursive node type -- */
> +
> ++              case XC( OC_CONST ):
> ++                      debug_printf_eval("CONST ");
> +               case XC( OC_VAR ):
> +                       debug_printf_eval("VAR\n");
> +                       L.v = op->l.v;
> +diff --git a/testsuite/awk.tests b/testsuite/awk.tests
> +index ddc5104..a78fdcd 100755
> +--- a/testsuite/awk.tests
> ++++ b/testsuite/awk.tests
> +@@ -540,4 +540,9 @@ testing 'awk assign while assign' \
> + │    trim/eff : 57.02%/26, 0.00%                     │          [cpu000:100%]
> + └────────────────────────────────────────────────────┘^C"
> +
> ++testing "awk = has higher precedence than == (despite what gawk manpage claims)" \
> ++      "awk 'BEGIN { v=1; print 2==v; print 2==v=2; print v; print v=3==3; print v}'" \
> ++      '0\n1\n2\n1\n3\n' \
> ++      '' ''
> ++
> + exit $FAILCOUNT
> diff --git a/meta/recipes-core/busybox/busybox/0001-awk.c-fix-CVE-2023-42366-bug-15874.patch b/meta/recipes-core/busybox/busybox/0001-awk.c-fix-CVE-2023-42366-bug-15874.patch
> new file mode 100644
> index 0000000000..d660768e2f
> --- /dev/null
> +++ b/meta/recipes-core/busybox/busybox/0001-awk.c-fix-CVE-2023-42366-bug-15874.patch
> @@ -0,0 +1,36 @@
> +From 8542236894a8d5f7393327117bc7f64787444efc Mon Sep 17 00:00:00 2001
> +From: Valery Ushakov <uwe@stderr.spb.ru>
> +Date: Wed, 24 Jan 2024 22:24:41 +0300
> +Subject: [PATCH] awk.c: fix CVE-2023-42366 (bug #15874)
> +
> +Make sure we don't read past the end of the string in next_token()
> +when backslash is the last character in an (invalid) regexp.
> +a fix and issue reported in bugzilla
> +
> +https://bugs.busybox.net/show_bug.cgi?id=15874
> +
> +Upstream-Status: Submitted [http://lists.busybox.net/pipermail/busybox/2024-May/090766.html]
> +CVE: CVE-2023-42366
> +Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
> +---
> + editors/awk.c | 6 ++++--
> + 1 file changed, 4 insertions(+), 2 deletions(-)
> +
> +diff --git a/editors/awk.c b/editors/awk.c
> +index f320d8c..a53b193 100644
> +--- a/editors/awk.c
> ++++ b/editors/awk.c
> +@@ -1168,9 +1168,11 @@ static uint32_t next_token(uint32_t expected)
> +                                       s[-1] = bb_process_escape_sequence((const char **)&pp);
> +                                       if (*p == '\\')
> +                                               *s++ = '\\';
> +-                                      if (pp == p)
> ++                                      if (pp == p) {
> ++                                              if (*p == '\0')
> ++                                                      syntax_error(EMSG_UNEXP_EOS);
> +                                               *s++ = *p++;
> +-                                      else
> ++                                      } else
> +                                               p = pp;
> +                               }
> +                       }
> diff --git a/meta/recipes-core/busybox/busybox/0002-awk-fix-ternary-operator-and-precedence-of.patch b/meta/recipes-core/busybox/busybox/0002-awk-fix-ternary-operator-and-precedence-of.patch
> new file mode 100644
> index 0000000000..2d11efb1cf
> --- /dev/null
> +++ b/meta/recipes-core/busybox/busybox/0002-awk-fix-ternary-operator-and-precedence-of.patch
> @@ -0,0 +1,96 @@
> +From c3bfdac8e0e9a21d524ad72036953f68d2193e52 Mon Sep 17 00:00:00 2001
> +From: Natanael Copa <ncopa@alpinelinux.org>
> +Date: Tue, 21 May 2024 14:46:08 +0200
> +Subject: [PATCH 2/2] awk: fix ternary operator and precedence of =
> +
> +Adjust the = precedence test to match behavior of gawk, mawk and
> +FreeBSD.  awk 'BEGIN {print v=3==3; print v}' should print two '1'.
> +
> +To fix this, and to unbreak the ternary conditional operator, we restore
> +the precedence of = in the token list, but override this with a lower
> +priority when the assignment is on the right side of a compare.
> +
> +This fixes commit 0256e00a9d07 (awk: fix precedence of = relative to ==) [1]
> +
> +Upstream-Status: Submitted [http://lists.busybox.net/pipermail/busybox/2024-May/090766.html]
> +
> +[1] https://bugs.busybox.net/show_bug.cgi?id=15871#c6
> +
> +Signed-off-by: Natanael Copa <ncopa@alpinelinux.org>
> +(cherry picked from commit 1714301c405ef03b39605c85c23f22a190cddd95)
> +
> +CVE: CVE-2023-42364 & CVE-2023-42365
> +Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
> +---
> + editors/awk.c       | 18 ++++++++++++++----
> + testsuite/awk.tests |  9 +++++++--
> + 2 files changed, 21 insertions(+), 6 deletions(-)
> +
> +diff --git a/editors/awk.c b/editors/awk.c
> +index aff86fe..f320d8c 100644
> +--- a/editors/awk.c
> ++++ b/editors/awk.c
> +@@ -442,9 +442,10 @@ static const uint32_t tokeninfo[] ALIGN4 = {
> + #define TI_PREINC (OC_UNARY|xV|P(9)|'P')
> + #define TI_PREDEC (OC_UNARY|xV|P(9)|'M')
> +       TI_PREINC,               TI_PREDEC,               OC_FIELD|xV|P(5),
> +-      OC_COMPARE|VV|P(39)|5,   OC_MOVE|VV|P(38),        OC_REPLACE|NV|P(38)|'+', OC_REPLACE|NV|P(38)|'-',
> +-      OC_REPLACE|NV|P(38)|'*', OC_REPLACE|NV|P(38)|'/', OC_REPLACE|NV|P(38)|'%', OC_REPLACE|NV|P(38)|'&',
> +-      OC_BINARY|NV|P(29)|'+',  OC_BINARY|NV|P(29)|'-',  OC_REPLACE|NV|P(38)|'&', OC_BINARY|NV|P(15)|'&',
> ++#define TI_ASSIGN (OC_MOVE|VV|P(74))
> ++      OC_COMPARE|VV|P(39)|5,   TI_ASSIGN,               OC_REPLACE|NV|P(74)|'+', OC_REPLACE|NV|P(74)|'-',
> ++      OC_REPLACE|NV|P(74)|'*', OC_REPLACE|NV|P(74)|'/', OC_REPLACE|NV|P(74)|'%', OC_REPLACE|NV|P(74)|'&',
> ++      OC_BINARY|NV|P(29)|'+',  OC_BINARY|NV|P(29)|'-',  OC_REPLACE|NV|P(74)|'&', OC_BINARY|NV|P(15)|'&',
> +       OC_BINARY|NV|P(25)|'/',  OC_BINARY|NV|P(25)|'%',  OC_BINARY|NV|P(15)|'&',  OC_BINARY|NV|P(25)|'*',
> +       OC_COMPARE|VV|P(39)|4,   OC_COMPARE|VV|P(39)|3,   OC_COMPARE|VV|P(39)|0,   OC_COMPARE|VV|P(39)|1,
> + #define TI_LESS     (OC_COMPARE|VV|P(39)|2)
> +@@ -1376,11 +1377,19 @@ static node *parse_expr(uint32_t term_tc)
> +                       continue;
> +               }
> +               if (tc & (TS_BINOP | TC_UOPPOST)) {
> ++                      int prio;
> +                       debug_printf_parse("%s: TS_BINOP | TC_UOPPOST tc:%x\n", __func__, tc);
> +                       /* for binary and postfix-unary operators, jump back over
> +                        * previous operators with higher priority */
> +                       vn = cn;
> +-                      while (((t_info & PRIMASK) > (vn->a.n->info & PRIMASK2))
> ++                      /* Let assignment get higher priority when used on right
> ++                       * side in compare. i.e: 2==v=3 */
> ++                      if (t_info == TI_ASSIGN && (vn->a.n->info & OPCLSMASK) == OC_COMPARE) {
> ++                              prio = PRECEDENCE(38);
> ++                      } else {
> ++                              prio = (t_info & PRIMASK);
> ++                      }
> ++                      while ((prio > (vn->a.n->info & PRIMASK2))
> +                           || (t_info == vn->info && t_info == TI_COLON)
> +                       ) {
> +                               vn = vn->a.n;
> +@@ -1412,6 +1421,7 @@ static node *parse_expr(uint32_t term_tc)
> +                                       if ((vn->info & OPCLSMASK) != OC_VAR
> +                                        && (vn->info & OPCLSMASK) != OC_FNARG
> +                                        && (vn->info & OPCLSMASK) != OC_FIELD
> ++                                       && (vn->info & OPCLSMASK) != OC_COMPARE
> +                                       ) {
> +                                               syntax_error(EMSG_UNEXP_TOKEN); /* no. bad */
> +                                       }
> +diff --git a/testsuite/awk.tests b/testsuite/awk.tests
> +index a78fdcd..d2706de 100755
> +--- a/testsuite/awk.tests
> ++++ b/testsuite/awk.tests
> +@@ -540,9 +540,14 @@ testing 'awk assign while assign' \
> + │    trim/eff : 57.02%/26, 0.00%                     │          [cpu000:100%]
> + └────────────────────────────────────────────────────┘^C"
> +
> +-testing "awk = has higher precedence than == (despite what gawk manpage claims)" \
> ++testing "awk = has higher precedence than == on right side" \
> +       "awk 'BEGIN { v=1; print 2==v; print 2==v=2; print v; print v=3==3; print v}'" \
> +-      '0\n1\n2\n1\n3\n' \
> ++      '0\n1\n2\n1\n1\n' \
> ++      '' ''
> ++
> ++testing 'awk ternary precedence' \
> ++      "awk 'BEGIN { a = 0 ? \"yes\": \"no\"; print a }'" \
> ++      'no\n' \
> +       '' ''
> +
> + exit $FAILCOUNT
> diff --git a/meta/recipes-core/busybox/busybox_1.35.0.bb b/meta/recipes-core/busybox/busybox_1.35.0.bb
> index 1c7fe2f43e..ead931bc41 100644
> --- a/meta/recipes-core/busybox/busybox_1.35.0.bb
> +++ b/meta/recipes-core/busybox/busybox_1.35.0.bb
> @@ -54,6 +54,9 @@ SRC_URI = "https://busybox.net/downloads/busybox-${PV}.tar.bz2;name=tarball \
>            file://CVE-2022-48174.patch \
>             file://CVE-2021-42380.patch \
>             file://CVE-2023-42363.patch \
> +           file://0001-awk-fix-precedence-of-relative-to.patch \
> +           file://0002-awk-fix-ternary-operator-and-precedence-of.patch \
> +           file://0001-awk.c-fix-CVE-2023-42366-bug-15874.patch \
>             "
>  SRC_URI:append:libc-musl = " file://musl.cfg "
>
> --
> 2.25.1
>
>
> -=-=-=-=-=-=-=-=-=-=-=-
> Links: You receive all messages sent to this group.
> View/Reply Online (#203060): https://lists.openembedded.org/g/openembedded-core/message/203060
> Mute This Topic: https://lists.openembedded.org/mt/107765584/3620601
> Group Owner: openembedded-core+owner@lists.openembedded.org
> Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub [steve@sakoman.com]
> -=-=-=-=-=-=-=-=-=-=-=-
>
diff mbox series

Patch

diff --git a/meta/recipes-core/busybox/busybox/0001-awk-fix-precedence-of-relative-to.patch b/meta/recipes-core/busybox/busybox/0001-awk-fix-precedence-of-relative-to.patch
new file mode 100644
index 0000000000..e3d623498c
--- /dev/null
+++ b/meta/recipes-core/busybox/busybox/0001-awk-fix-precedence-of-relative-to.patch
@@ -0,0 +1,197 @@ 
+From dedc9380c76834ba64c8b526aef6f461ea4e7f2e Mon Sep 17 00:00:00 2001
+From: Denys Vlasenko <vda.linux@googlemail.com>
+Date: Tue, 30 May 2023 16:42:18 +0200
+Subject: [PATCH 1/2] awk: fix precedence of = relative to ==
+
+Discovered while adding code to disallow assignments to non-lvalues
+
+function                                             old     new   delta
+parse_expr                                           936     991     +55
+.rodata                                           105243  105247      +4
+------------------------------------------------------------------------------
+(add/remove: 0/0 grow/shrink: 2/0 up/down: 59/0)               Total: 59 bytes
+
+Upstream-Status: Backport [https://git.busybox.net/busybox/commit/?id=0256e00a9d077588bd3a39f5a1ef7e2eaa2911e4]
+Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
+(cherry picked from commit 0256e00a9d077588bd3a39f5a1ef7e2eaa2911e4)
+
+CVE: CVE-2023-42364 & CVE-2023-42365
+Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
+---
+ editors/awk.c       | 66 ++++++++++++++++++++++++++++++---------------
+ testsuite/awk.tests |  5 ++++
+ 2 files changed, 50 insertions(+), 21 deletions(-)
+
+diff --git a/editors/awk.c b/editors/awk.c
+index ec9301e..aff86fe 100644
+--- a/editors/awk.c
++++ b/editors/awk.c
+@@ -337,7 +337,9 @@ static void debug_parse_print_tc(uint32_t n)
+ #undef P
+ #undef PRIMASK
+ #undef PRIMASK2
+-#define P(x)      (x << 24)
++/* Smaller 'x' means _higher_ operator precedence */
++#define PRECEDENCE(x) (x << 24)
++#define P(x)      PRECEDENCE(x)
+ #define PRIMASK   0x7F000000
+ #define PRIMASK2  0x7E000000
+ 
+@@ -360,7 +362,7 @@ enum {
+ 	OC_MOVE = 0x1f00,       OC_PGETLINE = 0x2000,   OC_REGEXP = 0x2100,
+ 	OC_REPLACE = 0x2200,    OC_RETURN = 0x2300,     OC_SPRINTF = 0x2400,
+ 	OC_TERNARY = 0x2500,    OC_UNARY = 0x2600,      OC_VAR = 0x2700,
+-	OC_DONE = 0x2800,
++	OC_CONST = 0x2800,      OC_DONE = 0x2900,
+ 
+ 	ST_IF = 0x3000,         ST_DO = 0x3100,         ST_FOR = 0x3200,
+ 	ST_WHILE = 0x3300
+@@ -440,9 +442,9 @@ static const uint32_t tokeninfo[] ALIGN4 = {
+ #define TI_PREINC (OC_UNARY|xV|P(9)|'P')
+ #define TI_PREDEC (OC_UNARY|xV|P(9)|'M')
+ 	TI_PREINC,               TI_PREDEC,               OC_FIELD|xV|P(5),
+-	OC_COMPARE|VV|P(39)|5,   OC_MOVE|VV|P(74),        OC_REPLACE|NV|P(74)|'+', OC_REPLACE|NV|P(74)|'-',
+-	OC_REPLACE|NV|P(74)|'*', OC_REPLACE|NV|P(74)|'/', OC_REPLACE|NV|P(74)|'%', OC_REPLACE|NV|P(74)|'&',
+-	OC_BINARY|NV|P(29)|'+',  OC_BINARY|NV|P(29)|'-',  OC_REPLACE|NV|P(74)|'&', OC_BINARY|NV|P(15)|'&',
++	OC_COMPARE|VV|P(39)|5,   OC_MOVE|VV|P(38),        OC_REPLACE|NV|P(38)|'+', OC_REPLACE|NV|P(38)|'-',
++	OC_REPLACE|NV|P(38)|'*', OC_REPLACE|NV|P(38)|'/', OC_REPLACE|NV|P(38)|'%', OC_REPLACE|NV|P(38)|'&',
++	OC_BINARY|NV|P(29)|'+',  OC_BINARY|NV|P(29)|'-',  OC_REPLACE|NV|P(38)|'&', OC_BINARY|NV|P(15)|'&',
+ 	OC_BINARY|NV|P(25)|'/',  OC_BINARY|NV|P(25)|'%',  OC_BINARY|NV|P(15)|'&',  OC_BINARY|NV|P(25)|'*',
+ 	OC_COMPARE|VV|P(39)|4,   OC_COMPARE|VV|P(39)|3,   OC_COMPARE|VV|P(39)|0,   OC_COMPARE|VV|P(39)|1,
+ #define TI_LESS     (OC_COMPARE|VV|P(39)|2)
+@@ -1290,7 +1292,7 @@ static uint32_t next_token(uint32_t expected)
+ 			save_tclass = tc;
+ 			save_info = t_info;
+ 			tc = TC_BINOPX;
+-			t_info = OC_CONCAT | SS | P(35);
++			t_info = OC_CONCAT | SS | PRECEDENCE(35);
+ 		}
+ 
+ 		t_tclass = tc;
+@@ -1350,9 +1352,8 @@ static node *parse_expr(uint32_t term_tc)
+ {
+ 	node sn;
+ 	node *cn = &sn;
+-	node *vn, *glptr;
++	node *glptr;
+ 	uint32_t tc, expected_tc;
+-	var *v;
+ 
+ 	debug_printf_parse("%s() term_tc(%x):", __func__, term_tc);
+ 	debug_parse_print_tc(term_tc);
+@@ -1363,11 +1364,12 @@ static node *parse_expr(uint32_t term_tc)
+ 	expected_tc = TS_OPERAND | TS_UOPPRE | TC_REGEXP | term_tc;
+ 
+ 	while (!((tc = next_token(expected_tc)) & term_tc)) {
++		node *vn;
+ 
+ 		if (glptr && (t_info == TI_LESS)) {
+ 			/* input redirection (<) attached to glptr node */
+ 			debug_printf_parse("%s: input redir\n", __func__);
+-			cn = glptr->l.n = new_node(OC_CONCAT | SS | P(37));
++			cn = glptr->l.n = new_node(OC_CONCAT | SS | PRECEDENCE(37));
+ 			cn->a.n = glptr;
+ 			expected_tc = TS_OPERAND | TS_UOPPRE;
+ 			glptr = NULL;
+@@ -1379,24 +1381,42 @@ static node *parse_expr(uint32_t term_tc)
+ 			 * previous operators with higher priority */
+ 			vn = cn;
+ 			while (((t_info & PRIMASK) > (vn->a.n->info & PRIMASK2))
+-			    || ((t_info == vn->info) && t_info == TI_COLON)
++			    || (t_info == vn->info && t_info == TI_COLON)
+ 			) {
+ 				vn = vn->a.n;
+ 				if (!vn->a.n) syntax_error(EMSG_UNEXP_TOKEN);
+ 			}
+ 			if (t_info == TI_TERNARY)
+ //TODO: why?
+-				t_info += P(6);
++				t_info += PRECEDENCE(6);
+ 			cn = vn->a.n->r.n = new_node(t_info);
+ 			cn->a.n = vn->a.n;
+ 			if (tc & TS_BINOP) {
+ 				cn->l.n = vn;
+-//FIXME: this is the place to detect and reject assignments to non-lvalues.
+-//Currently we allow "assignments" to consts and temporaries, nonsense like this:
+-// awk 'BEGIN { "qwe" = 1 }'
+-// awk 'BEGIN { 7 *= 7 }'
+-// awk 'BEGIN { length("qwe") = 1 }'
+-// awk 'BEGIN { (1+1) += 3 }'
++
++				/* Prevent:
++				 * awk 'BEGIN { "qwe" = 1 }'
++				 * awk 'BEGIN { 7 *= 7 }'
++				 * awk 'BEGIN { length("qwe") = 1 }'
++				 * awk 'BEGIN { (1+1) += 3 }'
++				 */
++				/* Assignment? (including *= and friends) */
++				if (((t_info & OPCLSMASK) == OC_MOVE)
++				 || ((t_info & OPCLSMASK) == OC_REPLACE)
++				) {
++					debug_printf_parse("%s: MOVE/REPLACE vn->info:%08x\n", __func__, vn->info);
++					/* Left side is a (variable or array element)
++					 * or function argument
++					 * or $FIELD ?
++					 */
++					if ((vn->info & OPCLSMASK) != OC_VAR
++					 && (vn->info & OPCLSMASK) != OC_FNARG
++					 && (vn->info & OPCLSMASK) != OC_FIELD
++					) {
++						syntax_error(EMSG_UNEXP_TOKEN); /* no. bad */
++					}
++				}
++
+ 				expected_tc = TS_OPERAND | TS_UOPPRE | TC_REGEXP;
+ 				if (t_info == TI_PGETLINE) {
+ 					/* it's a pipe */
+@@ -1432,6 +1452,8 @@ static node *parse_expr(uint32_t term_tc)
+ 		/* one should be very careful with switch on tclass -
+ 		 * only simple tclasses should be used (TC_xyz, not TS_xyz) */
+ 		switch (tc) {
++			var *v;
++
+ 		case TC_VARIABLE:
+ 		case TC_ARRAY:
+ 			debug_printf_parse("%s: TC_VARIABLE | TC_ARRAY\n", __func__);
+@@ -1452,14 +1474,14 @@ static node *parse_expr(uint32_t term_tc)
+ 		case TC_NUMBER:
+ 		case TC_STRING:
+ 			debug_printf_parse("%s: TC_NUMBER | TC_STRING\n", __func__);
+-			cn->info = OC_VAR;
++			cn->info = OC_CONST;
+ 			v = cn->l.v = xzalloc(sizeof(var));
+-			if (tc & TC_NUMBER)
++			if (tc & TC_NUMBER) {
+ 				setvar_i(v, t_double);
+-			else {
++			 } else {
+ 				setvar_s(v, t_string);
+-				expected_tc &= ~TC_UOPPOST; /* "str"++ is not allowed */
+ 			}
++			expected_tc &= ~TC_UOPPOST; /* NUM++, "str"++ not allowed */
+ 			break;
+ 
+ 		case TC_REGEXP:
+@@ -3107,6 +3129,8 @@ static var *evaluate(node *op, var *res)
+ 
+ 		/* -- recursive node type -- */
+ 
++		case XC( OC_CONST ):
++			debug_printf_eval("CONST ");
+ 		case XC( OC_VAR ):
+ 			debug_printf_eval("VAR\n");
+ 			L.v = op->l.v;
+diff --git a/testsuite/awk.tests b/testsuite/awk.tests
+index ddc5104..a78fdcd 100755
+--- a/testsuite/awk.tests
++++ b/testsuite/awk.tests
+@@ -540,4 +540,9 @@ testing 'awk assign while assign' \
+ │    trim/eff : 57.02%/26, 0.00%                     │          [cpu000:100%]
+ └────────────────────────────────────────────────────┘^C"
+ 
++testing "awk = has higher precedence than == (despite what gawk manpage claims)" \
++	"awk 'BEGIN { v=1; print 2==v; print 2==v=2; print v; print v=3==3; print v}'" \
++	'0\n1\n2\n1\n3\n' \
++	'' ''
++
+ exit $FAILCOUNT
diff --git a/meta/recipes-core/busybox/busybox/0001-awk.c-fix-CVE-2023-42366-bug-15874.patch b/meta/recipes-core/busybox/busybox/0001-awk.c-fix-CVE-2023-42366-bug-15874.patch
new file mode 100644
index 0000000000..d660768e2f
--- /dev/null
+++ b/meta/recipes-core/busybox/busybox/0001-awk.c-fix-CVE-2023-42366-bug-15874.patch
@@ -0,0 +1,36 @@ 
+From 8542236894a8d5f7393327117bc7f64787444efc Mon Sep 17 00:00:00 2001
+From: Valery Ushakov <uwe@stderr.spb.ru>
+Date: Wed, 24 Jan 2024 22:24:41 +0300
+Subject: [PATCH] awk.c: fix CVE-2023-42366 (bug #15874)
+
+Make sure we don't read past the end of the string in next_token()
+when backslash is the last character in an (invalid) regexp.
+a fix and issue reported in bugzilla
+
+https://bugs.busybox.net/show_bug.cgi?id=15874
+
+Upstream-Status: Submitted [http://lists.busybox.net/pipermail/busybox/2024-May/090766.html]
+CVE: CVE-2023-42366
+Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
+---
+ editors/awk.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/editors/awk.c b/editors/awk.c
+index f320d8c..a53b193 100644
+--- a/editors/awk.c
++++ b/editors/awk.c
+@@ -1168,9 +1168,11 @@ static uint32_t next_token(uint32_t expected)
+ 					s[-1] = bb_process_escape_sequence((const char **)&pp);
+ 					if (*p == '\\')
+ 						*s++ = '\\';
+-					if (pp == p)
++					if (pp == p) {
++						if (*p == '\0')
++							syntax_error(EMSG_UNEXP_EOS);
+ 						*s++ = *p++;
+-					else
++					} else
+ 						p = pp;
+ 				}
+ 			}
diff --git a/meta/recipes-core/busybox/busybox/0002-awk-fix-ternary-operator-and-precedence-of.patch b/meta/recipes-core/busybox/busybox/0002-awk-fix-ternary-operator-and-precedence-of.patch
new file mode 100644
index 0000000000..2d11efb1cf
--- /dev/null
+++ b/meta/recipes-core/busybox/busybox/0002-awk-fix-ternary-operator-and-precedence-of.patch
@@ -0,0 +1,96 @@ 
+From c3bfdac8e0e9a21d524ad72036953f68d2193e52 Mon Sep 17 00:00:00 2001
+From: Natanael Copa <ncopa@alpinelinux.org>
+Date: Tue, 21 May 2024 14:46:08 +0200
+Subject: [PATCH 2/2] awk: fix ternary operator and precedence of =
+
+Adjust the = precedence test to match behavior of gawk, mawk and
+FreeBSD.  awk 'BEGIN {print v=3==3; print v}' should print two '1'.
+
+To fix this, and to unbreak the ternary conditional operator, we restore
+the precedence of = in the token list, but override this with a lower
+priority when the assignment is on the right side of a compare.
+
+This fixes commit 0256e00a9d07 (awk: fix precedence of = relative to ==) [1]
+
+Upstream-Status: Submitted [http://lists.busybox.net/pipermail/busybox/2024-May/090766.html]
+
+[1] https://bugs.busybox.net/show_bug.cgi?id=15871#c6
+
+Signed-off-by: Natanael Copa <ncopa@alpinelinux.org>
+(cherry picked from commit 1714301c405ef03b39605c85c23f22a190cddd95)
+
+CVE: CVE-2023-42364 & CVE-2023-42365
+Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
+---
+ editors/awk.c       | 18 ++++++++++++++----
+ testsuite/awk.tests |  9 +++++++--
+ 2 files changed, 21 insertions(+), 6 deletions(-)
+
+diff --git a/editors/awk.c b/editors/awk.c
+index aff86fe..f320d8c 100644
+--- a/editors/awk.c
++++ b/editors/awk.c
+@@ -442,9 +442,10 @@ static const uint32_t tokeninfo[] ALIGN4 = {
+ #define TI_PREINC (OC_UNARY|xV|P(9)|'P')
+ #define TI_PREDEC (OC_UNARY|xV|P(9)|'M')
+ 	TI_PREINC,               TI_PREDEC,               OC_FIELD|xV|P(5),
+-	OC_COMPARE|VV|P(39)|5,   OC_MOVE|VV|P(38),        OC_REPLACE|NV|P(38)|'+', OC_REPLACE|NV|P(38)|'-',
+-	OC_REPLACE|NV|P(38)|'*', OC_REPLACE|NV|P(38)|'/', OC_REPLACE|NV|P(38)|'%', OC_REPLACE|NV|P(38)|'&',
+-	OC_BINARY|NV|P(29)|'+',  OC_BINARY|NV|P(29)|'-',  OC_REPLACE|NV|P(38)|'&', OC_BINARY|NV|P(15)|'&',
++#define TI_ASSIGN (OC_MOVE|VV|P(74))
++	OC_COMPARE|VV|P(39)|5,   TI_ASSIGN,               OC_REPLACE|NV|P(74)|'+', OC_REPLACE|NV|P(74)|'-',
++	OC_REPLACE|NV|P(74)|'*', OC_REPLACE|NV|P(74)|'/', OC_REPLACE|NV|P(74)|'%', OC_REPLACE|NV|P(74)|'&',
++	OC_BINARY|NV|P(29)|'+',  OC_BINARY|NV|P(29)|'-',  OC_REPLACE|NV|P(74)|'&', OC_BINARY|NV|P(15)|'&',
+ 	OC_BINARY|NV|P(25)|'/',  OC_BINARY|NV|P(25)|'%',  OC_BINARY|NV|P(15)|'&',  OC_BINARY|NV|P(25)|'*',
+ 	OC_COMPARE|VV|P(39)|4,   OC_COMPARE|VV|P(39)|3,   OC_COMPARE|VV|P(39)|0,   OC_COMPARE|VV|P(39)|1,
+ #define TI_LESS     (OC_COMPARE|VV|P(39)|2)
+@@ -1376,11 +1377,19 @@ static node *parse_expr(uint32_t term_tc)
+ 			continue;
+ 		}
+ 		if (tc & (TS_BINOP | TC_UOPPOST)) {
++			int prio;
+ 			debug_printf_parse("%s: TS_BINOP | TC_UOPPOST tc:%x\n", __func__, tc);
+ 			/* for binary and postfix-unary operators, jump back over
+ 			 * previous operators with higher priority */
+ 			vn = cn;
+-			while (((t_info & PRIMASK) > (vn->a.n->info & PRIMASK2))
++			/* Let assignment get higher priority when used on right
++			 * side in compare. i.e: 2==v=3 */
++			if (t_info == TI_ASSIGN && (vn->a.n->info & OPCLSMASK) == OC_COMPARE) {
++				prio = PRECEDENCE(38);
++			} else {
++				prio = (t_info & PRIMASK);
++			}
++			while ((prio > (vn->a.n->info & PRIMASK2))
+ 			    || (t_info == vn->info && t_info == TI_COLON)
+ 			) {
+ 				vn = vn->a.n;
+@@ -1412,6 +1421,7 @@ static node *parse_expr(uint32_t term_tc)
+ 					if ((vn->info & OPCLSMASK) != OC_VAR
+ 					 && (vn->info & OPCLSMASK) != OC_FNARG
+ 					 && (vn->info & OPCLSMASK) != OC_FIELD
++					 && (vn->info & OPCLSMASK) != OC_COMPARE
+ 					) {
+ 						syntax_error(EMSG_UNEXP_TOKEN); /* no. bad */
+ 					}
+diff --git a/testsuite/awk.tests b/testsuite/awk.tests
+index a78fdcd..d2706de 100755
+--- a/testsuite/awk.tests
++++ b/testsuite/awk.tests
+@@ -540,9 +540,14 @@ testing 'awk assign while assign' \
+ │    trim/eff : 57.02%/26, 0.00%                     │          [cpu000:100%]
+ └────────────────────────────────────────────────────┘^C"
+ 
+-testing "awk = has higher precedence than == (despite what gawk manpage claims)" \
++testing "awk = has higher precedence than == on right side" \
+ 	"awk 'BEGIN { v=1; print 2==v; print 2==v=2; print v; print v=3==3; print v}'" \
+-	'0\n1\n2\n1\n3\n' \
++	'0\n1\n2\n1\n1\n' \
++	'' ''
++
++testing 'awk ternary precedence' \
++	"awk 'BEGIN { a = 0 ? \"yes\": \"no\"; print a }'" \
++	'no\n' \
+ 	'' ''
+ 
+ exit $FAILCOUNT
diff --git a/meta/recipes-core/busybox/busybox_1.35.0.bb b/meta/recipes-core/busybox/busybox_1.35.0.bb
index 1c7fe2f43e..ead931bc41 100644
--- a/meta/recipes-core/busybox/busybox_1.35.0.bb
+++ b/meta/recipes-core/busybox/busybox_1.35.0.bb
@@ -54,6 +54,9 @@  SRC_URI = "https://busybox.net/downloads/busybox-${PV}.tar.bz2;name=tarball \
 	   file://CVE-2022-48174.patch \
            file://CVE-2021-42380.patch \
            file://CVE-2023-42363.patch \
+           file://0001-awk-fix-precedence-of-relative-to.patch \
+           file://0002-awk-fix-ternary-operator-and-precedence-of.patch \
+           file://0001-awk.c-fix-CVE-2023-42366-bug-15874.patch \
            "
 SRC_URI:append:libc-musl = " file://musl.cfg "