diff --git a/meta-oe/recipes-support/libssh/libssh/CVE-2026-0968_p1.patch b/meta-oe/recipes-support/libssh/libssh/CVE-2026-0968_p1.patch new file mode 100644 index 0000000000..97ae88b2be --- /dev/null +++ b/meta-oe/recipes-support/libssh/libssh/CVE-2026-0968_p1.patch @@ -0,0 +1,64 @@ +From 14a1c80ce06cd2c3e4798ec08b25a55ddaf95076 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Mon, 22 Dec 2025 20:59:11 +0100 +Subject: [PATCH 1/4] CVE-2026-0968: sftp: Sanitize input handling in + sftp_parse_longname() + +CVE: CVE-2026-0968 +Upstream-Status: Backport [https://git.libssh.org/projects/libssh.git/commit/?id=796d85f786dff62bd4bcc4408d9b7bbc855841e9] + +Signed-off-by: Jakub Jelen +Reviewed-by: Andreas Schneider +(cherry picked from commit 20856f44c146468c830da61dcbbbaa8ce71e390b) +(cherry picked from commit 796d85f786dff62bd4bcc4408d9b7bbc855841e9) +Signed-off-by: Deepak Rathore +--- + src/sftp_common.c | 16 +++++++++++++--- + 1 file changed, 13 insertions(+), 3 deletions(-) + +diff --git a/src/sftp_common.c b/src/sftp_common.c +index 13512b8d..b05597d8 100644 +--- a/src/sftp_common.c ++++ b/src/sftp_common.c +@@ -461,16 +461,21 @@ static char * sftp_parse_longname(const char *longname, + const char *p, *q; + size_t len, field = 0; + ++ if (longname == NULL || longname_field < SFTP_LONGNAME_PERM || ++ longname_field > SFTP_LONGNAME_NAME) { ++ return NULL; ++ } ++ + p = longname; + /* + * Find the beginning of the field which is specified + * by sftp_longname_field_e. + */ +- while (field != longname_field) { ++ while (*p != '\0' && field != longname_field) { + if (isspace(*p)) { + field++; + p++; +- while (*p && isspace(*p)) { ++ while (*p != '\0' && isspace(*p)) { + p++; + } + } else { +@@ -478,8 +483,13 @@ static char * sftp_parse_longname(const char *longname, + } + } + ++ /* If we reached NULL before we got our field fail */ ++ if (field != longname_field) { ++ return NULL; ++ } ++ + q = p; +- while (! isspace(*q)) { ++ while (*q != '\0' && !isspace(*q)) { + q++; + } + +-- +2.51.0 + diff --git a/meta-oe/recipes-support/libssh/libssh/CVE-2026-0968_p2.patch b/meta-oe/recipes-support/libssh/libssh/CVE-2026-0968_p2.patch new file mode 100644 index 0000000000..6de0d6cb3d --- /dev/null +++ b/meta-oe/recipes-support/libssh/libssh/CVE-2026-0968_p2.patch @@ -0,0 +1,132 @@ +From 5ad81f0514bf547055fd17dd4ca05121f1e512c9 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Mon, 22 Dec 2025 21:00:03 +0100 +Subject: [PATCH 2/4] CVE-2026-0968 tests: Reproducer for invalid longname data + +CVE: CVE-2026-0968 +Upstream-Status: Backport [https://git.libssh.org/projects/libssh.git/commit/?id=212121971fb26e1e00b72bd5402c0454a4d84c03] + +Signed-off-by: Jakub Jelen +Reviewed-by: Andreas Schneider +(cherry picked from commit 90a5d8f47399e8db61b56793cd21476ff6a528e0) +(cherry picked from commit 212121971fb26e1e00b72bd5402c0454a4d84c03) +Signed-off-by: Deepak Rathore +--- + tests/unittests/CMakeLists.txt | 7 +++ + tests/unittests/torture_unit_sftp.c | 86 +++++++++++++++++++++++++++++ + 2 files changed, 93 insertions(+) + create mode 100644 tests/unittests/torture_unit_sftp.c + +diff --git a/tests/unittests/CMakeLists.txt b/tests/unittests/CMakeLists.txt +index 79f3856c..53478af9 100644 +--- a/tests/unittests/CMakeLists.txt ++++ b/tests/unittests/CMakeLists.txt +@@ -98,6 +98,13 @@ if (UNIX AND NOT WIN32) + endif (WITH_SERVER) + endif (UNIX AND NOT WIN32) + ++if (WITH_SFTP) ++ set(LIBSSH_UNIT_TESTS ++ ${LIBSSH_UNIT_TESTS} ++ torture_unit_sftp ++ ) ++endif (WITH_SFTP) ++ + foreach(_UNIT_TEST ${LIBSSH_UNIT_TESTS}) + add_cmocka_test(${_UNIT_TEST} + SOURCES ${_UNIT_TEST}.c +diff --git a/tests/unittests/torture_unit_sftp.c b/tests/unittests/torture_unit_sftp.c +new file mode 100644 +index 00000000..12940039 +--- /dev/null ++++ b/tests/unittests/torture_unit_sftp.c +@@ -0,0 +1,86 @@ ++#include "config.h" ++ ++#include "sftp_common.c" ++#include "torture.h" ++ ++#define LIBSSH_STATIC ++ ++static void test_sftp_parse_longname(void **state) ++{ ++ const char *lname = NULL; ++ char *value = NULL; ++ ++ /* state not used */ ++ (void)state; ++ ++ /* Valid example from SFTP draft, page 18: ++ * https://datatracker.ietf.org/doc/draft-spaghetti-sshm-filexfer/ ++ */ ++ lname = "-rwxr-xr-x 1 mjos staff 348911 Mar 25 14:29 t-filexfer"; ++ value = sftp_parse_longname(lname, SFTP_LONGNAME_PERM); ++ assert_string_equal(value, "-rwxr-xr-x"); ++ free(value); ++ value = sftp_parse_longname(lname, SFTP_LONGNAME_OWNER); ++ assert_string_equal(value, "mjos"); ++ free(value); ++ value = sftp_parse_longname(lname, SFTP_LONGNAME_GROUP); ++ assert_string_equal(value, "staff"); ++ free(value); ++ value = sftp_parse_longname(lname, SFTP_LONGNAME_SIZE); ++ assert_string_equal(value, "348911"); ++ free(value); ++ /* This function is broken further as the date contains space which breaks ++ * the parsing altogether */ ++ value = sftp_parse_longname(lname, SFTP_LONGNAME_DATE); ++ assert_string_equal(value, "Mar"); ++ free(value); ++ value = sftp_parse_longname(lname, SFTP_LONGNAME_TIME); ++ assert_string_equal(value, "25"); ++ free(value); ++ value = sftp_parse_longname(lname, SFTP_LONGNAME_NAME); ++ assert_string_equal(value, "14:29"); ++ free(value); ++} ++ ++static void test_sftp_parse_longname_invalid(void **state) ++{ ++ const char *lname = NULL; ++ char *value = NULL; ++ ++ /* state not used */ ++ (void)state; ++ ++ /* Invalid inputs should not crash ++ */ ++ lname = NULL; ++ value = sftp_parse_longname(lname, SFTP_LONGNAME_PERM); ++ assert_null(value); ++ value = sftp_parse_longname(lname, SFTP_LONGNAME_NAME); ++ assert_null(value); ++ ++ lname = ""; ++ value = sftp_parse_longname(lname, SFTP_LONGNAME_PERM); ++ assert_string_equal(value, ""); ++ free(value); ++ value = sftp_parse_longname(lname, SFTP_LONGNAME_NAME); ++ assert_null(value); ++ ++ lname = "-rwxr-xr-x 1"; ++ value = sftp_parse_longname(lname, SFTP_LONGNAME_PERM); ++ assert_string_equal(value, "-rwxr-xr-x"); ++ free(value); ++ value = sftp_parse_longname(lname, SFTP_LONGNAME_NAME); ++ assert_null(value); ++} ++ ++int torture_run_tests(void) ++{ ++ int rc; ++ const struct CMUnitTest tests[] = { ++ cmocka_unit_test(test_sftp_parse_longname), ++ cmocka_unit_test(test_sftp_parse_longname_invalid), ++ }; ++ ++ rc = cmocka_run_group_tests(tests, NULL, NULL); ++ return rc; ++} +-- +2.51.0 + diff --git a/meta-oe/recipes-support/libssh/libssh_0.11.3.bb b/meta-oe/recipes-support/libssh/libssh_0.11.3.bb index ab47931fa3..1d4fd637d9 100644 --- a/meta-oe/recipes-support/libssh/libssh_0.11.3.bb +++ b/meta-oe/recipes-support/libssh/libssh_0.11.3.bb @@ -11,6 +11,8 @@ SRC_URI = "git://git.libssh.org/projects/libssh.git;protocol=https;branch=stable file://run-ptest \ file://CVE-2026-3731_p1.patch \ file://CVE-2026-3731_p2.patch \ + file://CVE-2026-0968_p1.patch \ + file://CVE-2026-0968_p2.patch \ " SRC_URI:append:toolchain-clang = " file://0001-CompilerChecks.cmake-drop-Wunused-variable-flag.patch"