mirror of
https://github.com/openembedded/meta-openembedded.git
synced 2026-10-20 19:58:34 +00:00
pjproject: patch CVE-2026-57166
Details: https://nvd.nist.gov/vuln/detail/cve-2026-57166 (cherry picked from commit 59a6a134d6ff923bf9ee081a62755cdbde2a88c0) Signed-off-by: Ankur Tyagi <ankur.tyagi85@gmail.com> Signed-off-by: Khem Raj <khem.raj@oss.qualcomm.com>
This commit is contained in:
1 parent
0851231b2d
commit
f1274b1221
2 files changed
+229
No files matched your search
@@ -0,0 +1,228 @@
|
||||
From d0b42b902bb6ca8a0a1393799db487642d3bf8ae Mon Sep 17 00:00:00 2001
|
||||
From: Nanang Izzuddin <nanang@teluu.com>
|
||||
Date: Wed, 17 Jun 2026 15:55:53 +0700
|
||||
Subject: [PATCH] Merge commit from fork
|
||||
|
||||
* Fix pre-auth stack overflow formatting telnet CLI error indicator
|
||||
|
||||
send_err_arg() in cli_telnet.c rendered the error caret into a fixed
|
||||
256-byte stack buffer using unchecked pj_strcat2; info->err_pos is
|
||||
bounded only by PJ_CLI_MAX_CMDBUF, so a long command line overflowed
|
||||
the buffer. Stream the spaces in bounded chunks via telnet_sess_send2,
|
||||
clamp the caret offset to PJ_CLI_MAX_CMDBUF, and send the message,
|
||||
prompt and echoed command separately, removing the stack buffer.
|
||||
|
||||
Co-Authored-By Claude Code
|
||||
|
||||
* Apply the same overflow fix to send_ambi_arg()
|
||||
|
||||
Per review, send_ambi_arg() has the same issue as send_err_arg(): it
|
||||
renders an attacker-influenced number of caret spaces and appends the
|
||||
last command into a fixed 1028-byte stack buffer with unchecked
|
||||
pj_strcat2. info->err_pos and sess->rcmd->rbuf are bounded only by
|
||||
PJ_CLI_MAX_CMDBUF, so a long ambiguous command line could overflow it.
|
||||
|
||||
Stream the caret offset in bounded chunks (clamped to PJ_CLI_MAX_CMDBUF)
|
||||
and stream the clamped last command separately, mirroring the
|
||||
send_err_arg() fix, instead of writing them into the fixed buffer. The
|
||||
shared SPACES constant is hoisted to file scope.
|
||||
|
||||
Co-Authored-By Claude Code
|
||||
|
||||
* Bound completion append in handle_tab()
|
||||
|
||||
handle_tab() appended the matched command name into the fixed-size
|
||||
sess->rcmd->rbuf at offset len (the current command length) without
|
||||
checking that len + name length fits the buffer. len is bounded by the
|
||||
receive path, but the completion suffix is added on top, so a long
|
||||
completable command line could write past rbuf and its NUL terminator.
|
||||
|
||||
Clamp the appended length to the space remaining in rbuf, leaving room
|
||||
for the terminator. Found while auditing the telnet CLI for the same
|
||||
fixed-buffer overflow pattern as send_err_arg()/send_ambi_arg().
|
||||
|
||||
Co-Authored-By Claude Code
|
||||
|
||||
(cherry picked from commit 4472a31d77a7506ff175dad5abef490f4e31bed1)
|
||||
|
||||
CVE: CVE-2026-57166
|
||||
Upstream-Status: Backport [https://github.com/pjsip/pjproject/commit/4472a31d77a7506ff175dad5abef490f4e31bed1]
|
||||
|
||||
Signed-off-by: Ankur Tyagi <ankur.tyagi85@gmail.com>
|
||||
---
|
||||
pjlib-util/src/pjlib-util/cli_telnet.c | 116 ++++++++++++++++++-------
|
||||
1 file changed, 84 insertions(+), 32 deletions(-)
|
||||
|
||||
diff --git a/pjlib-util/src/pjlib-util/cli_telnet.c b/pjlib-util/src/pjlib-util/cli_telnet.c
|
||||
index 0a2954bd4..67898fdd8 100644
|
||||
--- a/pjlib-util/src/pjlib-util/cli_telnet.c
|
||||
+++ b/pjlib-util/src/pjlib-util/cli_telnet.c
|
||||
@@ -680,6 +680,13 @@ static void send_prompt_str(cli_telnet_sess *sess)
|
||||
telnet_sess_send(sess, &send_data);
|
||||
}
|
||||
|
||||
+/* Buffer of spaces, used to stream the caret offset in bounded chunks
|
||||
+ * instead of writing an attacker-influenced number of spaces into a
|
||||
+ * fixed-size stack buffer. Shared by send_err_arg() and send_ambi_arg().
|
||||
+ */
|
||||
+static const unsigned char SPACES[64] =
|
||||
+ " ";
|
||||
+
|
||||
/*
|
||||
* This method is used to send error message to client, including
|
||||
* the error position of the source command.
|
||||
@@ -690,32 +697,45 @@ static void send_err_arg(cli_telnet_sess *sess,
|
||||
pj_bool_t with_return,
|
||||
pj_bool_t with_last_cmd)
|
||||
{
|
||||
- pj_str_t send_data;
|
||||
- char data_str[256];
|
||||
- pj_size_t len;
|
||||
- unsigned i;
|
||||
+ pj_size_t len, remaining;
|
||||
cli_telnet_fe *fe = (cli_telnet_fe *)sess->base.fe;
|
||||
|
||||
- send_data.ptr = data_str;
|
||||
- send_data.slen = 0;
|
||||
-
|
||||
if (with_return)
|
||||
- pj_strcat2(&send_data, "\r\n");
|
||||
+ telnet_sess_send2(sess, (const unsigned char*)"\r\n", 2);
|
||||
|
||||
+ /* Compute the caret offset. info->err_pos is derived from
|
||||
+ * attacker-supplied input (pj_cli_sess_parse) and is bounded only by
|
||||
+ * PJ_CLI_MAX_CMDBUF, so clamp it before emitting spaces. Otherwise a
|
||||
+ * ~500-byte command line would overflow the fixed-size stack buffer
|
||||
+ * this function previously used.
|
||||
+ */
|
||||
len = fe->cfg.prompt_str.slen + info->err_pos;
|
||||
-
|
||||
- /* Set the error pointer mark */
|
||||
- for (i=0;i<len;++i) {
|
||||
- pj_strcat2(&send_data, " ");
|
||||
+ if (len > PJ_CLI_MAX_CMDBUF)
|
||||
+ len = PJ_CLI_MAX_CMDBUF;
|
||||
+
|
||||
+ remaining = len;
|
||||
+ while (remaining > 0) {
|
||||
+ pj_size_t chunk = (remaining > sizeof(SPACES)) ? sizeof(SPACES)
|
||||
+ : remaining;
|
||||
+ telnet_sess_send2(sess, SPACES, (int)chunk);
|
||||
+ remaining -= chunk;
|
||||
}
|
||||
- pj_strcat2(&send_data, "^");
|
||||
- pj_strcat2(&send_data, "\r\n");
|
||||
- pj_strcat(&send_data, msg);
|
||||
- pj_strcat(&send_data, &fe->cfg.prompt_str);
|
||||
- if (with_last_cmd)
|
||||
- pj_strcat2(&send_data, (char *)sess->rcmd->rbuf);
|
||||
|
||||
- telnet_sess_send(sess, &send_data);
|
||||
+ telnet_sess_send2(sess, (const unsigned char*)"^\r\n", 3);
|
||||
+
|
||||
+ if (msg && msg->slen > 0)
|
||||
+ telnet_sess_send(sess, msg);
|
||||
+ if (fe->cfg.prompt_str.slen > 0)
|
||||
+ telnet_sess_send(sess, &fe->cfg.prompt_str);
|
||||
+ if (with_last_cmd) {
|
||||
+ pj_str_t last;
|
||||
+ last.ptr = (char *)sess->rcmd->rbuf;
|
||||
+ last.slen = (pj_ssize_t)pj_ansi_strlen((const char *)sess->rcmd->rbuf);
|
||||
+ if (last.slen > PJ_CLI_MAX_CMDBUF)
|
||||
+ last.slen = PJ_CLI_MAX_CMDBUF;
|
||||
+ if (last.slen > 0)
|
||||
+ telnet_sess_send(sess, &last);
|
||||
+ }
|
||||
}
|
||||
|
||||
static void send_inv_arg(cli_telnet_sess *sess,
|
||||
@@ -765,7 +785,7 @@ static void send_ambi_arg(cli_telnet_sess *sess,
|
||||
pj_bool_t with_last_cmd)
|
||||
{
|
||||
unsigned i;
|
||||
- pj_size_t len;
|
||||
+ pj_size_t len, remaining;
|
||||
pj_str_t send_data;
|
||||
char data[1028];
|
||||
cli_telnet_fe *fe = (cli_telnet_fe *)sess->base.fe;
|
||||
@@ -779,14 +799,25 @@ static void send_ambi_arg(cli_telnet_sess *sess,
|
||||
send_data.slen = 0;
|
||||
|
||||
if (with_return)
|
||||
- pj_strcat2(&send_data, "\r\n");
|
||||
+ telnet_sess_send2(sess, (const unsigned char*)"\r\n", 2);
|
||||
|
||||
+ /* Compute and clamp the caret offset, then stream the spaces, like
|
||||
+ * send_err_arg(). info->err_pos is attacker-bounded only by
|
||||
+ * PJ_CLI_MAX_CMDBUF, so it must not drive writes into data[].
|
||||
+ */
|
||||
len = fe->cfg.prompt_str.slen + info->err_pos;
|
||||
-
|
||||
- for (i=0;i<len;++i) {
|
||||
- pj_strcat2(&send_data, " ");
|
||||
+ if (len > PJ_CLI_MAX_CMDBUF)
|
||||
+ len = PJ_CLI_MAX_CMDBUF;
|
||||
+
|
||||
+ remaining = len;
|
||||
+ while (remaining > 0) {
|
||||
+ pj_size_t chunk = (remaining > sizeof(SPACES)) ? sizeof(SPACES)
|
||||
+ : remaining;
|
||||
+ telnet_sess_send2(sess, SPACES, (int)chunk);
|
||||
+ remaining -= chunk;
|
||||
}
|
||||
- pj_strcat2(&send_data, "^");
|
||||
+ telnet_sess_send2(sess, (const unsigned char*)"^", 1);
|
||||
+
|
||||
/* Get the max length of the command name */
|
||||
for (i=0;i<info->hint_cnt;++i) {
|
||||
if (hint[i].type.slen > 0) {
|
||||
@@ -874,10 +905,21 @@ static void send_ambi_arg(cli_telnet_sess *sess,
|
||||
}
|
||||
pj_strcat2(&send_data, "\r\n");
|
||||
pj_strcat(&send_data, &fe->cfg.prompt_str);
|
||||
- if (with_last_cmd)
|
||||
- pj_strcat2(&send_data, (char *)sess->rcmd->rbuf);
|
||||
-
|
||||
telnet_sess_send(sess, &send_data);
|
||||
+
|
||||
+ /* Stream the last command separately with a clamp; sess->rcmd->rbuf
|
||||
+ * is attacker-bounded only by PJ_CLI_MAX_CMDBUF, so appending it into
|
||||
+ * data[] could overflow the fixed-size buffer.
|
||||
+ */
|
||||
+ if (with_last_cmd) {
|
||||
+ pj_str_t last;
|
||||
+ last.ptr = (char *)sess->rcmd->rbuf;
|
||||
+ last.slen = (pj_ssize_t)pj_ansi_strlen((const char *)sess->rcmd->rbuf);
|
||||
+ if (last.slen > PJ_CLI_MAX_CMDBUF)
|
||||
+ last.slen = PJ_CLI_MAX_CMDBUF;
|
||||
+ if (last.slen > 0)
|
||||
+ telnet_sess_send(sess, &last);
|
||||
+ }
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1035,10 +1077,20 @@ static pj_bool_t handle_tab(cli_telnet_sess *sess)
|
||||
}
|
||||
send_comp_arg(sess, &info);
|
||||
|
||||
- pj_memcpy(&sess->rcmd->rbuf[len], info.hint[0].name.ptr,
|
||||
- info.hint[0].name.slen);
|
||||
-
|
||||
- len += (unsigned)info.hint[0].name.slen;
|
||||
+ /* Append the matched name into the fixed-size rbuf. len is
|
||||
+ * attacker-influenced (the typed command length), so clamp
|
||||
+ * the copy to leave room for the NUL terminator and avoid
|
||||
+ * overflowing rbuf.
|
||||
+ */
|
||||
+ if (len < sizeof(sess->rcmd->rbuf) - 1) {
|
||||
+ pj_size_t avail = sizeof(sess->rcmd->rbuf) - 1 - len;
|
||||
+ pj_size_t cplen = (pj_size_t)info.hint[0].name.slen;
|
||||
+ if (cplen > avail)
|
||||
+ cplen = avail;
|
||||
+ pj_memcpy(&sess->rcmd->rbuf[len],
|
||||
+ info.hint[0].name.ptr, cplen);
|
||||
+ len += (unsigned)cplen;
|
||||
+ }
|
||||
sess->rcmd->rbuf[len] = 0;
|
||||
}
|
||||
} else {
|
||||
@@ -20,6 +20,7 @@ SRC_URI = "git://github.com/pjsip/pjproject.git;protocol=https;branch=master;tag
|
||||
file://CVE-2026-57163.patch \
|
||||
file://CVE-2026-57164.patch \
|
||||
file://CVE-2026-57165.patch \
|
||||
file://CVE-2026-57166.patch \
|
||||
"
|
||||
SRCREV = "5a457451fa2712ba18e12b01738e8ff3af2b26fd"
|
||||
|
||||
|
||||
Reference in new issue
Block a user