From: Chen Qi <qi.c...@windriver.com>

Backport patch to fix CVE-2023-29491.

Signed-off-by: Chen Qi <qi.c...@windriver.com>
---
 .../files/0001-Fix-CVE-2023-29491.patch       | 462 ++++++++++++++++++
 meta/recipes-core/ncurses/ncurses_6.4.bb      |   1 +
 2 files changed, 463 insertions(+)
 create mode 100644 
meta/recipes-core/ncurses/files/0001-Fix-CVE-2023-29491.patch

diff --git a/meta/recipes-core/ncurses/files/0001-Fix-CVE-2023-29491.patch 
b/meta/recipes-core/ncurses/files/0001-Fix-CVE-2023-29491.patch
new file mode 100644
index 0000000000..1232c8c2a8
--- /dev/null
+++ b/meta/recipes-core/ncurses/files/0001-Fix-CVE-2023-29491.patch
@@ -0,0 +1,462 @@
+From 3d54a41f12e9aa059f06e66e72d872f2283395b6 Mon Sep 17 00:00:00 2001
+From: Chen Qi <qi.c...@windriver.com>
+Date: Sun, 30 Jul 2023 21:14:00 -0700
+Subject: [PATCH] Fix CVE-2023-29491
+
+CVE: CVE-2023-29491
+
+Upstream-Status: Backport 
[http://ncurses.scripts.mit.edu/?p=ncurses.git;a=commitdiff;h=eb51b1ea1f75a0ec17c9c5937cb28df1e8eeec56]
+
+Signed-off-by: Chen Qi <qi.c...@windriver.com>
+---
+ ncurses/tinfo/lib_tgoto.c  |  10 +++-
+ ncurses/tinfo/lib_tparm.c  | 116 ++++++++++++++++++++++++++++++++-----
+ ncurses/tinfo/read_entry.c |   3 +
+ progs/tic.c                |   6 ++
+ progs/tparm_type.c         |   9 +++
+ progs/tparm_type.h         |   2 +
+ progs/tput.c               |  61 ++++++++++++++++---
+ 7 files changed, 185 insertions(+), 22 deletions(-)
+
+diff --git a/ncurses/tinfo/lib_tgoto.c b/ncurses/tinfo/lib_tgoto.c
+index 9cf5e100..c50ed4df 100644
+--- a/ncurses/tinfo/lib_tgoto.c
++++ b/ncurses/tinfo/lib_tgoto.c
+@@ -207,6 +207,14 @@ tgoto(const char *string, int x, int y)
+       result = tgoto_internal(string, x, y);
+     else
+ #endif
+-      result = TIPARM_2(string, y, x);
++    if ((result = TIPARM_2(string, y, x)) == NULL) {
++      /*
++       * Because termcap did not provide a more general solution such as
++       * tparm(), it was necessary to handle single-parameter capabilities
++       * using tgoto().  The internal _nc_tiparm() function returns a NULL
++       * for that case; retry for the single-parameter case.
++       */
++      result = TIPARM_1(string, y);
++    }
+     returnPtr(result);
+ }
+diff --git a/ncurses/tinfo/lib_tparm.c b/ncurses/tinfo/lib_tparm.c
+index d9bdfd8f..a10a3877 100644
+--- a/ncurses/tinfo/lib_tparm.c
++++ b/ncurses/tinfo/lib_tparm.c
+@@ -1086,6 +1086,64 @@ tparam_internal(TPARM_STATE *tps, const char *string, 
TPARM_DATA *data)
+     return (TPS(out_buff));
+ }
+ 
++#ifdef CUR
++/*
++ * Only a few standard capabilities accept string parameters.  The others that
++ * are parameterized accept only numeric parameters.
++ */
++static bool
++check_string_caps(TPARM_DATA *data, const char *string)
++{
++    bool result = FALSE;
++
++#define CHECK_CAP(name) (VALID_STRING(name) && !strcmp(name, string))
++
++    /*
++     * Disallow string parameters unless we can check them against a terminal
++     * description.
++     */
++    if (cur_term != NULL) {
++      int want_type = 0;
++
++      if (CHECK_CAP(pkey_key))
++          want_type = 2;      /* function key #1, type string #2 */
++      else if (CHECK_CAP(pkey_local))
++          want_type = 2;      /* function key #1, execute string #2 */
++      else if (CHECK_CAP(pkey_xmit))
++          want_type = 2;      /* function key #1, transmit string #2 */
++      else if (CHECK_CAP(plab_norm))
++          want_type = 2;      /* label #1, show string #2 */
++      else if (CHECK_CAP(pkey_plab))
++          want_type = 6;      /* function key #1, type string #2, show string 
#3 */
++#if NCURSES_XNAMES
++      else {
++          char *check;
++
++          check = tigetstr("Cs");
++          if (CHECK_CAP(check))
++              want_type = 1;  /* style #1 */
++
++          check = tigetstr("Ms");
++          if (CHECK_CAP(check))
++              want_type = 3;  /* storage unit #1, content #2 */
++      }
++#endif
++
++      if (want_type == data->tparm_type) {
++          result = TRUE;
++      } else {
++          T(("unexpected string-parameter"));
++      }
++    }
++    return result;
++}
++
++#define ValidCap() (myData.tparm_type == 0 || \
++                  check_string_caps(&myData, string))
++#else
++#define ValidCap() 1
++#endif
++
+ #if NCURSES_TPARM_VARARGS
+ 
+ NCURSES_EXPORT(char *)
+@@ -1100,7 +1158,7 @@ tparm(const char *string, ...)
+     tps->tname = "tparm";
+ #endif /* TRACE */
+ 
+-    if (tparm_setup(cur_term, string, &myData) == OK) {
++    if (tparm_setup(cur_term, string, &myData) == OK && ValidCap()) {
+       va_list ap;
+ 
+       va_start(ap, string);
+@@ -1135,7 +1193,7 @@ tparm(const char *string,
+     tps->tname = "tparm";
+ #endif /* TRACE */
+ 
+-    if (tparm_setup(cur_term, string, &myData) == OK) {
++    if (tparm_setup(cur_term, string, &myData) == OK && ValidCap()) {
+ 
+       myData.param[0] = a1;
+       myData.param[1] = a2;
+@@ -1166,7 +1224,7 @@ tiparm(const char *string, ...)
+     tps->tname = "tiparm";
+ #endif /* TRACE */
+ 
+-    if (tparm_setup(cur_term, string, &myData) == OK) {
++    if (tparm_setup(cur_term, string, &myData) == OK && ValidCap()) {
+       va_list ap;
+ 
+       va_start(ap, string);
+@@ -1179,7 +1237,25 @@ tiparm(const char *string, ...)
+ }
+ 
+ /*
+- * The internal-use flavor ensures that the parameters are numbers, not 
strings
++ * The internal-use flavor ensures that parameters are numbers, not strings.
++ * In addition to ensuring that they are numbers, it ensures that the 
parameter
++ * count is consistent with intended usage.
++ *
++ * Unlike the general-purpose tparm/tiparm, these internal calls are fairly
++ * well defined:
++ *
++ * expected == 0 - not applicable
++ * expected == 1 - set color, or vertical/horizontal addressing
++ * expected == 2 - cursor addressing
++ * expected == 4 - initialize color or color pair
++ * expected == 9 - set attributes
++ *
++ * Only for the last case (set attributes) should a parameter be optional.
++ * Also, a capability which calls for more parameters than expected should be
++ * ignored.
++ *
++ * Return a null if the parameter-checks fail.  Otherwise, return a pointer to
++ * the formatted capability string.
+  */
+ NCURSES_EXPORT(char *)
+ _nc_tiparm(int expected, const char *string, ...)
+@@ -1189,22 +1265,36 @@ _nc_tiparm(int expected, const char *string, ...)
+     char *result = NULL;
+ 
+     _nc_tparm_err = 0;
++    T((T_CALLED("_nc_tiparm(%d, %s, ...)"), expected, _nc_visbuf(string)));
+ #ifdef TRACE
+     tps->tname = "_nc_tiparm";
+ #endif /* TRACE */
+ 
+-    if (tparm_setup(cur_term, string, &myData) == OK
+-      && myData.num_actual <= expected
+-      && myData.tparm_type == 0) {
+-      va_list ap;
++    if (tparm_setup(cur_term, string, &myData) == OK && ValidCap()) {
++      if (myData.num_actual == 0) {
++          T(("missing parameter%s, expected %s%d",
++             expected > 1 ? "s" : "",
++             expected == 9 ? "up to " : "",
++             expected));
++      } else if (myData.num_actual > expected) {
++          T(("too many parameters, have %d, expected %d",
++             myData.num_actual,
++             expected));
++      } else if (expected != 9 && myData.num_actual != expected) {
++          T(("expected %d parameters, have %d",
++             myData.num_actual,
++             expected));
++      } else {
++          va_list ap;
+ 
+-      va_start(ap, string);
+-      tparm_copy_valist(&myData, FALSE, ap);
+-      va_end(ap);
++          va_start(ap, string);
++          tparm_copy_valist(&myData, FALSE, ap);
++          va_end(ap);
+ 
+-      result = tparam_internal(tps, string, &myData);
++          result = tparam_internal(tps, string, &myData);
++      }
+     }
+-    return result;
++    returnPtr(result);
+ }
+ 
+ /*
+diff --git a/ncurses/tinfo/read_entry.c b/ncurses/tinfo/read_entry.c
+index 2b1875ed..341337d2 100644
+--- a/ncurses/tinfo/read_entry.c
++++ b/ncurses/tinfo/read_entry.c
+@@ -323,6 +323,9 @@ _nc_read_termtype(TERMTYPE2 *ptr, char *buffer, int limit)
+       || bool_count < 0
+       || num_count < 0
+       || str_count < 0
++      || bool_count > BOOLCOUNT
++      || num_count > NUMCOUNT
++      || str_count > STRCOUNT
+       || str_size < 0) {
+       returnDB(TGETENT_NO);
+     }
+diff --git a/progs/tic.c b/progs/tic.c
+index 93a0b491..888927e2 100644
+--- a/progs/tic.c
++++ b/progs/tic.c
+@@ -2270,9 +2270,15 @@ check_1_infotocap(const char *name, NCURSES_CONST char 
*value, int count)
+ 
+     _nc_reset_tparm(NULL);
+     switch (actual) {
++    case Str:
++      result = TPARM_1(value, strings[1]);
++      break;
+     case Num_Str:
+       result = TPARM_2(value, numbers[1], strings[2]);
+       break;
++    case Str_Str:
++      result = TPARM_2(value, strings[1], strings[2]);
++      break;
+     case Num_Str_Str:
+       result = TPARM_3(value, numbers[1], strings[2], strings[3]);
+       break;
+diff --git a/progs/tparm_type.c b/progs/tparm_type.c
+index 3da4a077..644aa62a 100644
+--- a/progs/tparm_type.c
++++ b/progs/tparm_type.c
+@@ -47,6 +47,7 @@ tparm_type(const char *name)
+       {code, {longname} }, \
+       {code, {ti} }, \
+       {code, {tc} }
++#define XD(code, onlyname) TD(code, onlyname, onlyname, onlyname)
+     TParams result = Numbers;
+     /* *INDENT-OFF* */
+     static const struct {
+@@ -58,6 +59,10 @@ tparm_type(const char *name)
+       TD(Num_Str,     "pkey_xmit",    "pfx",          "px"),
+       TD(Num_Str,     "plab_norm",    "pln",          "pn"),
+       TD(Num_Str_Str, "pkey_plab",    "pfxl",         "xl"),
++#if NCURSES_XNAMES
++      XD(Str,         "Cs"),
++      XD(Str_Str,     "Ms"),
++#endif
+     };
+     /* *INDENT-ON* */
+ 
+@@ -80,12 +85,16 @@ guess_tparm_type(int nparam, char **p_is_s)
+     case 1:
+       if (!p_is_s[0])
+           result = Numbers;
++      if (p_is_s[0])
++          result = Str;
+       break;
+     case 2:
+       if (!p_is_s[0] && !p_is_s[1])
+           result = Numbers;
+       if (!p_is_s[0] && p_is_s[1])
+           result = Num_Str;
++      if (p_is_s[0] && p_is_s[1])
++          result = Str_Str;
+       break;
+     case 3:
+       if (!p_is_s[0] && !p_is_s[1] && !p_is_s[2])
+diff --git a/progs/tparm_type.h b/progs/tparm_type.h
+index 7c102a30..af5bcf0f 100644
+--- a/progs/tparm_type.h
++++ b/progs/tparm_type.h
+@@ -45,8 +45,10 @@
+ typedef enum {
+     Other = -1
+     ,Numbers = 0
++    ,Str
+     ,Num_Str
+     ,Num_Str_Str
++    ,Str_Str
+ } TParams;
+ 
+ extern TParams tparm_type(const char *name);
+diff --git a/progs/tput.c b/progs/tput.c
+index 4cd0c5ba..41508b72 100644
+--- a/progs/tput.c
++++ b/progs/tput.c
+@@ -1,5 +1,5 @@
+ /****************************************************************************
+- * Copyright 2018-2021,2022 Thomas E. Dickey                                *
++ * Copyright 2018-2022,2023 Thomas E. Dickey                                *
+  * Copyright 1998-2016,2017 Free Software Foundation, Inc.                  *
+  *                                                                          *
+  * Permission is hereby granted, free of charge, to any person obtaining a  *
+@@ -47,12 +47,15 @@
+ #include <transform.h>
+ #include <tty_settings.h>
+ 
+-MODULE_ID("$Id: tput.c,v 1.99 2022/02/26 23:19:31 tom Exp $")
++MODULE_ID("$Id: tput.c,v 1.102 2023/04/08 16:26:36 tom Exp $")
+ 
+ #define PUTS(s)               fputs(s, stdout)
+ 
+ const char *_nc_progname = "tput";
+ 
++static bool opt_v = FALSE;    /* quiet, do not show warnings */
++static bool opt_x = FALSE;    /* clear scrollback if possible */
++
+ static bool is_init = FALSE;
+ static bool is_reset = FALSE;
+ static bool is_clear = FALSE;
+@@ -81,6 +84,7 @@ usage(const char *optstring)
+       KEEP("  -S <<       read commands from standard input")
+       KEEP("  -T TERM     use this instead of $TERM")
+       KEEP("  -V          print curses-version")
++      KEEP("  -v          verbose, show warnings")
+       KEEP("  -x          do not try to clear scrollback")
+       KEEP("")
+       KEEP("Commands:")
+@@ -148,7 +152,7 @@ exit_code(int token, int value)
+  * Returns nonzero on error.
+  */
+ static int
+-tput_cmd(int fd, TTY * settings, bool opt_x, int argc, char **argv, int *used)
++tput_cmd(int fd, TTY * settings, int argc, char **argv, int *used)
+ {
+     NCURSES_CONST char *name;
+     char *s;
+@@ -231,7 +235,9 @@ tput_cmd(int fd, TTY * settings, bool opt_x, int argc, 
char **argv, int *used)
+     } else if (VALID_STRING(s)) {
+       if (argc > 1) {
+           int k;
++          int narg;
+           int analyzed;
++          int provided;
+           int popcount;
+           long numbers[1 + NUM_PARM];
+           char *strings[1 + NUM_PARM];
+@@ -271,14 +277,45 @@ tput_cmd(int fd, TTY * settings, bool opt_x, int argc, 
char **argv, int *used)
+ 
+           popcount = 0;
+           _nc_reset_tparm(NULL);
++          /*
++           * Count the number of numeric parameters which are provided.
++           */
++          provided = 0;
++          for (narg = 1; narg < argc; ++narg) {
++              char *ending = NULL;
++              long check = strtol(argv[narg], &ending, 10);
++              if (check < 0 || ending == argv[narg] || *ending != '\0')
++                  break;
++              provided = narg;
++          }
+           switch (paramType) {
++          case Str:
++              s = TPARM_1(s, strings[1]);
++              analyzed = 1;
++              if (provided == 0 && argc >= 1)
++                  provided++;
++              break;
++          case Str_Str:
++              s = TPARM_2(s, strings[1], strings[2]);
++              analyzed = 2;
++              if (provided == 0 && argc >= 1)
++                  provided++;
++              if (provided == 1 && argc >= 2)
++                  provided++;
++              break;
+           case Num_Str:
+               s = TPARM_2(s, numbers[1], strings[2]);
+               analyzed = 2;
++              if (provided == 1 && argc >= 2)
++                  provided++;
+               break;
+           case Num_Str_Str:
+               s = TPARM_3(s, numbers[1], strings[2], strings[3]);
+               analyzed = 3;
++              if (provided == 1 && argc >= 2)
++                  provided++;
++              if (provided == 2 && argc >= 3)
++                  provided++;
+               break;
+           case Numbers:
+               analyzed = _nc_tparm_analyze(NULL, s, p_is_s, &popcount);
+@@ -316,7 +353,13 @@ tput_cmd(int fd, TTY * settings, bool opt_x, int argc, 
char **argv, int *used)
+           if (analyzed < popcount) {
+               analyzed = popcount;
+           }
+-          *used += analyzed;
++          if (opt_v && (analyzed != provided)) {
++              fprintf(stderr, "%s: %s parameters for \"%s\"\n",
++                      _nc_progname,
++                      (analyzed < provided ? "extra" : "missing"),
++                      argv[0]);
++          }
++          *used += provided;
+       }
+ 
+       /* use putp() in order to perform padding */
+@@ -339,7 +382,6 @@ main(int argc, char **argv)
+     int used;
+     TTY old_settings;
+     TTY tty_settings;
+-    bool opt_x = FALSE;               /* clear scrollback if possible */
+     bool is_alias;
+     bool need_tty;
+ 
+@@ -348,7 +390,7 @@ main(int argc, char **argv)
+ 
+     term = getenv("TERM");
+ 
+-    while ((c = getopt(argc, argv, is_alias ? "T:Vx" : "ST:Vx")) != -1) {
++    while ((c = getopt(argc, argv, is_alias ? "T:Vvx" : "ST:Vvx")) != -1) {
+       switch (c) {
+       case 'S':
+           cmdline = FALSE;
+@@ -361,6 +403,9 @@ main(int argc, char **argv)
+       case 'V':
+           puts(curses_version());
+           ExitProgram(EXIT_SUCCESS);
++      case 'v':               /* verbose */
++          opt_v = TRUE;
++          break;
+       case 'x':               /* do not try to clear scrollback */
+           opt_x = TRUE;
+           break;
+@@ -404,7 +449,7 @@ main(int argc, char **argv)
+           usage(NULL);
+       while (argc > 0) {
+           tty_settings = old_settings;
+-          code = tput_cmd(fd, &tty_settings, opt_x, argc, argv, &used);
++          code = tput_cmd(fd, &tty_settings, argc, argv, &used);
+           if (code != 0)
+               break;
+           argc -= used;
+@@ -439,7 +484,7 @@ main(int argc, char **argv)
+       while (argnum > 0) {
+           int code;
+           tty_settings = old_settings;
+-          code = tput_cmd(fd, &tty_settings, opt_x, argnum, argnow, &used);
++          code = tput_cmd(fd, &tty_settings, argnum, argnow, &used);
+           if (code != 0) {
+               if (result == 0)
+                   result = ErrSystem(0);      /* will return value >4 */
+-- 
+2.40.0
+
diff --git a/meta/recipes-core/ncurses/ncurses_6.4.bb 
b/meta/recipes-core/ncurses/ncurses_6.4.bb
index 1eb15673d1..388cd8d407 100644
--- a/meta/recipes-core/ncurses/ncurses_6.4.bb
+++ b/meta/recipes-core/ncurses/ncurses_6.4.bb
@@ -4,6 +4,7 @@ SRC_URI += "file://0001-tic-hang.patch \
            file://0002-configure-reproducible.patch \
            
file://0003-gen-pkgconfig.in-Do-not-include-LDFLAGS-in-generated.patch \
            file://exit_prototype.patch \
+           file://0001-Fix-CVE-2023-29491.patch \
            "
 # commit id corresponds to the revision in package version
 SRCREV = "79b9071f2be20a24c7be031655a5638f6032f29f"
-- 
2.40.0

-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.
View/Reply Online (#185117): 
https://lists.openembedded.org/g/openembedded-core/message/185117
Mute This Topic: https://lists.openembedded.org/mt/100455939/21656
Group Owner: openembedded-core+ow...@lists.openembedded.org
Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub 
[arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to