[Buildroot] [git commit] package/libssh2: fix CVE-2025-15661
Julien Olivain via buildroot <[email protected]>
| Newsgroups | net.busybox.buildroot |
|---|---|
| Message-ID | <[email protected]> |
commit: https://gitlab.com/buildroot.org/buildroot/-/commit/546fd31c70d5c380c59dfe12eef1811876c32b44 branch: https://gitlab.com/buildroot.org/buildroot/-/tree/master Backport the SFTP symlink bounds checking fix for CVE-2025-15661. The initial fix requires the LIBSSH2_UNCONST compatibility backport on libssh2 1.11.1. Also include the upstream follow-up fixing SSH_FXP_STATUS handling introduced by the initial security fix. The patches are based on the upstream fixes and Debian's libssh2 1.11.1 backports. Signed-off-by: Stefan Müller <[email protected]> [Julien: add links to Debian patches] Signed-off-by: Julien Olivain <[email protected]> --- .../0004-sftp-symlink-fix-out-of-bounds-read.patch | 117 +++++++++++++++++++++ ...005-libssh2-priv-backport-LIBSSH2_UNCONST.patch | 30 ++++++ ...-sftp-symlink-fix-SSH_FXP_STATUS-response.patch | 46 ++++++++ package/libssh2/libssh2.mk | 5 + 4 files changed, 198 insertions(+) diff --git a/package/libssh2/0004-sftp-symlink-fix-out-of-bounds-read.patch b/package/libssh2/0004-sftp-symlink-fix-out-of-bounds-read.patch new file mode 100644 index 0000000000..a855697046 --- /dev/null +++ b/package/libssh2/0004-sftp-symlink-fix-out-of-bounds-read.patch @@ -0,0 +1,117 @@ +From 2dae3024897e1898d389835151f4e9606227721d Mon Sep 17 00:00:00 2001 +From: Will Cosgrove <[email protected]> +Date: Fri, 10 Oct 2025 08:26:20 -0700 +Subject: [PATCH] Update sftp_symlink to avoid out of bounds read on malformed + packet #1705 (#1717) + + +CVE: CVE-2025-15661 +Upstream: https://sources.debian.org/patches/libssh2/1.11.1-6/CVE-2025-15661.patch/ +Upstream: https://github.com/libssh2/libssh2/commit/2dae3024897e1898d389835151f4e9606227721d +Signed-off-by: Stefan Müller <[email protected]> +--- +--- libssh2-1.11.1.orig/src/sftp.c ++++ libssh2-1.11.1/src/sftp.c +@@ -3795,15 +3795,19 @@ static int sftp_symlink(LIBSSH2_SFTP *sf + { + LIBSSH2_CHANNEL *channel = sftp->channel; + LIBSSH2_SESSION *session = channel->session; +- size_t data_len = 0, link_len; ++ size_t data_len = 0, lk_len; + /* 13 = packet_len(4) + packet_type(1) + request_id(4) + path_len(4) */ + ssize_t packet_len = + path_len + 13 + + ((link_type == LIBSSH2_SFTP_SYMLINK) ? (4 + target_len) : 0); + unsigned char *s, *data = NULL; ++ struct string_buf buf; + static const unsigned char link_responses[2] = + { SSH_FXP_NAME, SSH_FXP_STATUS }; + int retcode; ++ unsigned char packet_type; ++ uint32_t tmp_u32; ++ unsigned char *lk_target; + + if(sftp->symlink_state == libssh2_NB_state_idle) { + sftp->last_errno = LIBSSH2_FX_OK; +@@ -3891,8 +3895,25 @@ static int sftp_symlink(LIBSSH2_SFTP *sf + + sftp->symlink_state = libssh2_NB_state_idle; + +- if(data[0] == SSH_FXP_STATUS) { +- retcode = _libssh2_ntohu32(data + 5); ++ buf.data = (unsigned char *)LIBSSH2_UNCONST(data); ++ buf.dataptr = buf.data; ++ buf.len = data_len; ++ ++ if(_libssh2_get_byte(&buf, &packet_type)) { ++ LIBSSH2_FREE(session, data); ++ return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, ++ "SFTP Protocol Error (type)"); ++ } ++ ++ if(packet_type == SSH_FXP_STATUS) { ++ if(_libssh2_get_u32(&buf, &tmp_u32)) { ++ LIBSSH2_FREE(session, data); ++ return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, ++ "SFTP Protocol Error (code)"); ++ } ++ ++ retcode = (int)tmp_u32; ++ + LIBSSH2_FREE(session, data); + if(retcode == LIBSSH2_FX_OK) + return LIBSSH2_ERROR_NONE; +@@ -3903,30 +3924,37 @@ static int sftp_symlink(LIBSSH2_SFTP *sf + } + } + +- if(_libssh2_ntohu32(data + 5) < 1) { ++ /* advance past id */ ++ if(_libssh2_get_u32(&buf, &tmp_u32)) { + LIBSSH2_FREE(session, data); + return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, +- "Invalid READLINK/REALPATH response, " +- "no name entries"); ++ "SFTP Protocol Error (id)"); + } + +- if(data_len < 13) { +- if(data_len > 0) { +- LIBSSH2_FREE(session, data); +- } ++ /* look for at least one link */ ++ if(_libssh2_get_u32(&buf, &tmp_u32) || tmp_u32 < 1) { ++ LIBSSH2_FREE(session, data); + return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, +- "SFTP stat packet too short"); ++ "Invalid READLINK/REALPATH response, " ++ "no name entries"); + } + +- /* this reads a u32 and stores it into a signed 32bit value */ +- link_len = _libssh2_ntohu32(data + 9); +- if(link_len < target_len) { +- memcpy(target, data + 13, link_len); +- target[link_len] = 0; +- retcode = (int)link_len; ++ if(_libssh2_get_string(&buf, &lk_target, &lk_len) == LIBSSH2_ERROR_NONE) { ++ if(lk_len < target_len) { ++ memcpy(target, lk_target, lk_len); ++ target[lk_len] = '\0'; ++ retcode = (int)lk_len; ++ } ++ else { ++ retcode = LIBSSH2_ERROR_BUFFER_TOO_SMALL; ++ } + } +- else +- retcode = LIBSSH2_ERROR_BUFFER_TOO_SMALL; ++ else { ++ LIBSSH2_FREE(session, data); ++ return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, ++ "SFTP Protocol Error (filename)"); ++ } ++ + LIBSSH2_FREE(session, data); + + return retcode; diff --git a/package/libssh2/0005-libssh2-priv-backport-LIBSSH2_UNCONST.patch b/package/libssh2/0005-libssh2-priv-backport-LIBSSH2_UNCONST.patch new file mode 100644 index 0000000000..7b91d22039 --- /dev/null +++ b/package/libssh2/0005-libssh2-priv-backport-LIBSSH2_UNCONST.patch @@ -0,0 +1,30 @@ +Needed by the fix for CVE-2025-15661 + +Cherrypicked from +commit 606c102e52f8447de2b745dd6c5ddf418defc519 +Author: Viktor Szakats <[email protected]> +Date: Thu Jan 30 21:18:23 2025 +0100 + + +CVE: CVE-2025-15661 +Upstream: https://sources.debian.org/patches/libssh2/1.11.1-6/libssh-unconst-backport.patch/ +Upstream: https://github.com/libssh2/libssh2/commit/606c102e52f8447de2b745dd6c5ddf418defc519 +Signed-off-by: Stefan Müller <[email protected]> +--- +--- libssh2-1.11.1.orig/src/libssh2_priv.h ++++ libssh2-1.11.1/src/libssh2_priv.h +@@ -117,6 +117,14 @@ + #define UINT32_MAX 0xffffffffU + #endif + ++#ifdef _WIN64 ++#define LIBSSH2_UNCONST(p) ((void *)(libssh2_uint64_t)(const void *)(p)) ++#elif defined(_MSC_VER) ++#define LIBSSH2_UNCONST(p) ((void *)(unsigned int)(const void *)(p)) ++#else ++#define LIBSSH2_UNCONST(p) ((void *)(uintptr_t)(const void *)(p)) ++#endif ++ + #if (defined(__GNUC__) || defined(__clang__)) && \ + defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ + !defined(LIBSSH2_NO_FMT_CHECKS) diff --git a/package/libssh2/0006-sftp-symlink-fix-SSH_FXP_STATUS-response.patch b/package/libssh2/0006-sftp-symlink-fix-SSH_FXP_STATUS-response.patch new file mode 100644 index 0000000000..2883c102dc --- /dev/null +++ b/package/libssh2/0006-sftp-symlink-fix-SSH_FXP_STATUS-response.patch @@ -0,0 +1,46 @@ +From 4ed26f5740bdd409269ed9fb48a28bf8f565b681 Mon Sep 17 00:00:00 2001 +From: Will Cosgrove <[email protected]> +Date: Mon, 20 Oct 2025 14:04:52 -0700 +Subject: [PATCH] Fix sftp_symlink when getting SSH_FXP_STATUS response (#1731) + +Move advancing past packet ID before reading the FXP_STATUS response. + +CVE: CVE-2025-15661 +Upstream: https://github.com/libssh2/libssh2/commit/4ed26f5740bdd409269ed9fb48a28bf8f565b681 +Signed-off-by: Stefan Müller <[email protected]> +--- + src/sftp.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/src/sftp.c b/src/sftp.c +index 70d7686daf..bb297b831a 100644 +--- a/src/sftp.c ++++ b/src/sftp.c +@@ -4006,6 +4006,13 @@ static int sftp_symlink(LIBSSH2_SFTP *sftp, const char *path, + "SFTP Protocol Error (type)"); + } + ++ /* advance past id */ ++ if(_libssh2_get_u32(&buf, &tmp_u32)) { ++ LIBSSH2_FREE(session, data); ++ return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, ++ "SFTP Protocol Error (id)"); ++ } ++ + if(packet_type == SSH_FXP_STATUS) { + if(_libssh2_get_u32(&buf, &tmp_u32)) { + LIBSSH2_FREE(session, data); +@@ -4025,13 +4032,6 @@ static int sftp_symlink(LIBSSH2_SFTP *sftp, const char *path, + } + } + +- /* advance past id */ +- if(_libssh2_get_u32(&buf, &tmp_u32)) { +- LIBSSH2_FREE(session, data); +- return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL, +- "SFTP Protocol Error (id)"); +- } +- + /* look for at least one link */ + if(_libssh2_get_u32(&buf, &tmp_u32) || tmp_u32 < 1) { + LIBSSH2_FREE(session, data); diff --git a/package/libssh2/libssh2.mk b/package/libssh2/libssh2.mk index 0ccf5effb3..6b2d774b38 100644 --- a/package/libssh2/libssh2.mk +++ b/package/libssh2/libssh2.mk @@ -22,6 +22,11 @@ LIBSSH2_IGNORE_CVES += CVE-2026-55199 # 0003-transport-c-Additional-boundary-checks-for-packet-length.patch LIBSSH2_IGNORE_CVES += CVE-2026-55200 +# 0004-sftp-symlink-fix-out-of-bounds-read.patch +# 0005-libssh2-priv-backport-LIBSSH2_UNCONST.patch +# 0006-sftp-symlink-fix-SSH_FXP_STATUS-response.patch +LIBSSH2_IGNORE_CVES += CVE-2025-15661 + ifeq ($(BR2_PACKAGE_LIBSSH2_MBEDTLS),y) LIBSSH2_DEPENDENCIES += mbedtls LIBSSH2_CONF_OPTS += --with-libmbedcrypto-prefix=$(STAGING_DIR)/usr \ _______________________________________________ buildroot mailing list [email protected] https://lists.buildroot.org/mailman/listinfo/buildroot