Backport CVE patches from 0.11.5

Resolves: RHEL-215674
Resolves: RHEL-215675
Resolves: RHEL-215676
Resolves: RHEL-215677
Resolves: RHEL-215678
Resolves: RHEL-215679
Resolves: RHEL-215680

Assisted-by: Ymir
This commit is contained in:
Pavol Žáčik 2026-07-30 12:05:16 +02:00
parent 05d5d52a42
commit a97adc51f9
No known key found for this signature in database
GPG Key ID: 4EE16C6E333F70A8
8 changed files with 1395 additions and 1 deletions

76
CVE-2026-59843.patch Normal file
View File

@ -0,0 +1,76 @@
From 68bcbcc1d78c5109417c367bdfaf00142f5d8847 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavol=20=C5=BD=C3=A1=C4=8Dik?= <pzacik@redhat.com>
Date: Fri, 6 Mar 2026 13:58:30 +0100
Subject: [PATCH] channels: Fail when receiving max packet size 0
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Do this both for SSH2_MSG_CHANNEL_OPEN and for
SSH2_MSG_CHANNEL_OPEN_CONFIRMATION. Using the
max packet size 0 would lead to an infinite loop
in channel_write_common.
Originally reported by Rinku Das on on 23th February.
Independently reported by Yi Lin on 26th February and
Haruto Kimura on 22nd March.
We do not consider this as a security issue as connecting
to untrusted servers on the internet brings much worse
security consequences than hanging your clinet.
Signed-off-by: Pavol Žáčik <pzacik@redhat.com>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
---
src/channels.c | 7 +++++++
src/messages.c | 19 +++++++++++++++----
2 files changed, 22 insertions(+), 4 deletions(-)
diff --git a/src/channels.c b/src/channels.c
index 36e1959..df84b90 100644
--- a/src/channels.c
+++ b/src/channels.c
@@ -187,6 +187,13 @@ SSH_PACKET_CALLBACK(ssh_packet_channel_open_conf){
if (rc != SSH_OK)
goto error;
+ if (channel->remote_maxpacket == 0) {
+ SSH_LOG(SSH_LOG_RARE,
+ "Invalid maximum packet size 0 in "
+ "SSH2_MSG_CHANNEL_OPEN_CONFIRMATION");
+ goto error;
+ }
+
SSH_LOG(SSH_LOG_DEBUG,
"Received a CHANNEL_OPEN_CONFIRMATION for channel %d:%d",
channel->local_channel,
diff --git a/src/messages.c b/src/messages.c
index 2f4f99f..8c37b59 100644
--- a/src/messages.c
+++ b/src/messages.c
@@ -1154,10 +1154,21 @@ SSH_PACKET_CALLBACK(ssh_packet_channel_open){
SSH_LOG(SSH_LOG_PACKET,
"Clients wants to open a %s channel", type_c);
- ssh_buffer_unpack(packet,"ddd",
- &msg->channel_request_open.sender,
- &msg->channel_request_open.window,
- &msg->channel_request_open.packet_size);
+ rc = ssh_buffer_unpack(packet,
+ "ddd",
+ &msg->channel_request_open.sender,
+ &msg->channel_request_open.window,
+ &msg->channel_request_open.packet_size);
+ if (rc != SSH_OK){
+ goto error;
+ }
+
+ if (msg->channel_request_open.packet_size == 0) {
+ ssh_set_error(session,
+ SSH_FATAL,
+ "Invalid maximum packet size 0 in SSH2_MSG_CHANNEL_OPEN");
+ goto error;
+ }
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED){
ssh_set_error(session,SSH_FATAL, "Invalid state when receiving channel open request (must be authenticated)");

42
CVE-2026-59844.patch Normal file
View File

@ -0,0 +1,42 @@
From 0647bf3cc06e4bac01596b4f8ca8e00ee4148ca5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavol=20=C5=BD=C3=A1=C4=8Dik?= <pzacik@redhat.com>
Date: Fri, 6 Mar 2026 18:05:29 +0100
Subject: [PATCH] CVE-2026-59844 sftpserver: cap accepted values of len in
SSH_FXP_READ
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The client-provided length is directly used in
a malloc in process_read(), so not restricting it
leads to allocations bounded only by UINT32_MAX.
The new cap is the same as the one currently used
by OpenSSH.
Signed-off-by: Pavol Žáčik <pzacik@redhat.com>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
(cherry picked from commit 6dba2e06f0713c04ad5eca7d4315d0104be7e627)
---
src/sftpserver.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/src/sftpserver.c b/src/sftpserver.c
index b3349e16..34bea3d9 100644
--- a/src/sftpserver.c
+++ b/src/sftpserver.c
@@ -105,6 +105,14 @@ sftp_client_message sftp_get_client_message(sftp_session sftp) {
sftp_client_message_free(msg);
return NULL;
}
+ if (msg->len > MAX_PACKET_LEN - 1024) {
+ ssh_set_error(session,
+ SSH_FATAL,
+ "Too large SSH_FXP_READ length: %" PRIu32,
+ msg->len);
+ sftp_client_message_free(msg);
+ return NULL;
+ }
break;
case SSH_FXP_WRITE:
rc = ssh_buffer_unpack(payload,

53
CVE-2026-59845.patch Normal file
View File

@ -0,0 +1,53 @@
From 363cb74e6b68bdf507ba6070620df9d77208254a Mon Sep 17 00:00:00 2001
From: Jakub Jelen <jjelen@redhat.com>
Date: Thu, 26 Mar 2026 16:32:24 +0100
Subject: [PATCH] CVE-2026-59845 socket: Properly check fork() return code
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
During execution of proxy command, when fork() fails, its return value
is stored in pid and when the parent process attempts to kill it,
it sends the kill signal to all processes the calling application has
access to (except for init).
This caused nard to debug issues when the system under the load was hitting
fork failures, which resulted in killing of all the system processes
(of given user).
Reported and first patch iteration provided by: Halil Oktay (oblivionsage).
This code missing fork return value check is in libssh since 2010
(f31a14b7932ef4cc165ddd8f1f1a5b23eb21beb3), but this issue is exploitable only
since libssh 0.9.0 as previously there was no implementation of killing
ProxyCommand children.
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Pavol Žáčik <pzacik@redhat.com>
---
src/socket.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/src/socket.c b/src/socket.c
index f470bb28..84777058 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -918,7 +918,17 @@ ssh_socket_connect_proxycommand(ssh_socket s, const char *command)
pid = fork();
if (pid == 0) {
ssh_execute_command(command, pair[0], pair[0]);
- /* Does not return */
+ /* child: Does not return */
+ }
+ /* parent */
+ if (pid == -1) {
+ close(pair[0]);
+ close(pair[1]);
+ ssh_set_error(s->session,
+ SSH_FATAL,
+ "fork failed: %s",
+ strerror(errno));
+ return SSH_ERROR;
}
s->proxy_pid = pid;
close(pair[0]);

255
CVE-2026-59846.patch Normal file
View File

@ -0,0 +1,255 @@
From 18ca8c90663b800a21bdce39dab4e402b8ad4bc0 Mon Sep 17 00:00:00 2001
From: Norbert Pocs <norbertpocs0@gmail.com>
Date: Wed, 27 Dec 2023 20:32:18 +0100
Subject: [PATCH 1/3] misc: Add function to check username syntax
Malicious code can be injected using the username with metacharacters,
therefore the username must be validated before using it with any %u.
Signed-off-by: Norbert Pocs <norbertpocs0@gmail.com>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
---
include/libssh/misc.h | 1 +
src/misc.c | 32 ++++++++++++++++++++++++++++++++
tests/unittests/torture_misc.c | 34 ++++++++++++++++++++++++++++++++++
3 files changed, 67 insertions(+)
diff --git a/include/libssh/misc.h b/include/libssh/misc.h
index a5bee930..c8328722 100644
--- a/include/libssh/misc.h
+++ b/include/libssh/misc.h
@@ -98,5 +98,6 @@ int ssh_quote_file_name(const char *file_name, char *buf, size_t buf_len);
int ssh_newline_vis(const char *string, char *buf, size_t buf_len);
int ssh_check_hostname_syntax(const char *hostname);
+int ssh_check_username_syntax(const char *username);
#endif /* MISC_H_ */
diff --git a/src/misc.c b/src/misc.c
index 8bbb2587..23fad83d 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -1835,4 +1835,36 @@ int ssh_check_hostname_syntax(const char *hostname)
return SSH_OK;
}
+/**
+ * @brief Checks syntax of a username
+ *
+ * This check disallows metacharacters in the username
+ *
+ * @param username The username to be checked, has to be null terminated
+ *
+ * @return SSH_OK if the username passes syntax check
+ * SSH_ERROR otherwise or if username is NULL or empty string
+ */
+int ssh_check_username_syntax(const char *username)
+{
+ size_t username_len;
+
+ if (username == NULL || *username == '-') {
+ return SSH_ERROR;
+ }
+
+ username_len = strlen(username);
+ if (username_len == 0 || username[username_len - 1] == '\\' ||
+ strpbrk(username, "'`\";&<>|(){}") != NULL) {
+ return SSH_ERROR;
+ }
+ for (size_t i = 0; i < username_len; i++) {
+ if (isspace(username[i]) != 0 && username[i + 1] == '-') {
+ return SSH_ERROR;
+ }
+ }
+
+ return SSH_OK;
+}
+
/** @} */
diff --git a/tests/unittests/torture_misc.c b/tests/unittests/torture_misc.c
index f16b766e..3737ed27 100644
--- a/tests/unittests/torture_misc.c
+++ b/tests/unittests/torture_misc.c
@@ -735,6 +735,39 @@ static void torture_ssh_check_hostname_syntax(void **state)
assert_int_equal(rc, SSH_ERROR);
}
+static void torture_ssh_check_username_syntax(void **state) {
+ int rc;
+ (void)state;
+
+ rc = ssh_check_username_syntax("username");
+ assert_int_equal(rc, SSH_OK);
+ rc = ssh_check_username_syntax("Alice");
+ assert_int_equal(rc, SSH_OK);
+ rc = ssh_check_username_syntax("Alice and Bob");
+ assert_int_equal(rc, SSH_OK);
+ rc = ssh_check_username_syntax("n4me?");
+ assert_int_equal(rc, SSH_OK);
+
+ rc = ssh_check_username_syntax("alice&bob");
+ assert_int_equal(rc, SSH_ERROR);
+ rc = ssh_check_username_syntax("backslash\\");
+ assert_int_equal(rc, SSH_ERROR);
+ rc = ssh_check_username_syntax("&var|()us\"<ha`r{}'");
+ assert_int_equal(rc, SSH_ERROR);
+ rc = ssh_check_username_syntax(" -");
+ assert_int_equal(rc, SSH_ERROR);
+ rc = ssh_check_username_syntax("me and -");
+ assert_int_equal(rc, SSH_ERROR);
+ rc = ssh_check_username_syntax("los -santos");
+ assert_int_equal(rc, SSH_ERROR);
+ rc = ssh_check_username_syntax("- who?");
+ assert_int_equal(rc, SSH_ERROR);
+ rc = ssh_check_username_syntax(NULL);
+ assert_int_equal(rc, SSH_ERROR);
+ rc = ssh_check_username_syntax("");
+ assert_int_equal(rc, SSH_ERROR);
+}
+
static void torture_ssh_is_ipaddr(void **state) {
int rc;
char *interf = malloc(64);
@@ -796,6 +829,7 @@ int torture_run_tests(void) {
cmocka_unit_test(torture_ssh_mkdirs),
cmocka_unit_test(torture_ssh_quote_file_name),
cmocka_unit_test(torture_ssh_check_hostname_syntax),
+ cmocka_unit_test(torture_ssh_check_username_syntax),
cmocka_unit_test(torture_ssh_is_ipaddr),
};
From e02b26abd4b34aac065beb1860c54782055334ac Mon Sep 17 00:00:00 2001
From: Norbert Pocs <norbertpocs0@gmail.com>
Date: Thu, 28 Dec 2023 12:16:29 +0100
Subject: [PATCH 2/3] Check any input username for validity
Check possible inputs of username for malicious code.
Signed-off-by: Norbert Pocs <norbertpocs0@gmail.com>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
---
src/config_parser.c | 4 ++++
src/misc.c | 10 ++++++++--
src/options.c | 5 +++++
3 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/src/config_parser.c b/src/config_parser.c
index 9e07a0b7..3c43b806 100644
--- a/src/config_parser.c
+++ b/src/config_parser.c
@@ -166,6 +166,10 @@ int ssh_config_parse_uri(const char *tok,
if (*username == NULL) {
goto error;
}
+ rc = ssh_check_username_syntax(*username);
+ if (rc != SSH_OK) {
+ goto error;
+ }
}
tok = endp + 1;
/* If there is second @ character, this does not look like our URI */
diff --git a/src/misc.c b/src/misc.c
index 23fad83d..c1c4dcfa 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -178,6 +178,7 @@ int gettimeofday(struct timeval *__p, void *__t) {
char *ssh_get_local_username(void) {
DWORD size = 0;
char *user;
+ int rc;
/* get the size */
GetUserName(NULL, &size);
@@ -188,7 +189,10 @@ char *ssh_get_local_username(void) {
}
if (GetUserName(user, &size)) {
- return user;
+ rc = ssh_check_username_syntax(user);
+ if (rc == SSH_OK) {
+ return user;
+ }
}
return NULL;
@@ -330,8 +334,10 @@ char *ssh_get_local_username(void)
}
name = strdup(pwd.pw_name);
+ rc = ssh_check_username_syntax(name);
- if (name == NULL) {
+ if (rc != SSH_OK) {
+ free(name);
return NULL;
}
diff --git a/src/options.c b/src/options.c
index 082c6cf4..f7eaab42 100644
--- a/src/options.c
+++ b/src/options.c
@@ -595,6 +595,11 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
ssh_set_error_oom(session);
return -1;
}
+ rc = ssh_check_username_syntax(session->opts.username);
+ if (rc != SSH_OK) {
+ ssh_set_error_invalid(session);
+ return -1;
+ }
}
break;
case SSH_OPTIONS_SSH_DIR:
From bf16e4df1809e1fa12aaff2fab6c43b31a108011 Mon Sep 17 00:00:00 2001
From: Jakub Jelen <jjelen@redhat.com>
Date: Thu, 2 Apr 2026 15:39:25 +0200
Subject: [PATCH 3/3] CVE-2026-59846 Block shell metacharacters from usernames
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
When an attacker could sneak the dollar sign or backslash into the username
expanded for example in proxy command, it can result in printing environment
variables that might contain secrets.
This is a fixup of CVE-2023-6004 which fixed this for hostnames, but these
two metacharacters were left out from the username filter.
This keeps the list in one place to simplify maintenance.
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Pavol Žáčik <pzacik@redhat.com>
(cherry picked from commit 6309df220e3431deb41946f892f4bb5af8b59dba)
---
include/libssh/priv.h | 2 ++
src/misc.c | 2 +-
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/include/libssh/priv.h b/include/libssh/priv.h
index 3e910860..dee941c4 100644
--- a/include/libssh/priv.h
+++ b/include/libssh/priv.h
@@ -218,6 +218,8 @@ int gettimeofday(struct timeval *__p, void *__t);
# define LIBSSH_MEM_PROTECTION
#endif
+#define SSH_DANGEROUS_SHELL_CHARS "'`\";&<>|(){}$\\,"
+
/* forward declarations */
struct ssh_common_struct;
struct ssh_kex_struct;
diff --git a/src/misc.c b/src/misc.c
index c1c4dcfa..11f799e1 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -1861,7 +1861,7 @@ int ssh_check_username_syntax(const char *username)
username_len = strlen(username);
if (username_len == 0 || username[username_len - 1] == '\\' ||
- strpbrk(username, "'`\";&<>|(){}") != NULL) {
+ strpbrk(username, SSH_DANGEROUS_SHELL_CHARS) != NULL) {
return SSH_ERROR;
}
for (size_t i = 0; i < username_len; i++) {

64
CVE-2026-59847.patch Normal file
View File

@ -0,0 +1,64 @@
From 742f080646e1825393ddd353e653c148eba96e40 Mon Sep 17 00:00:00 2001
From: Jakub Jelen <jjelen@redhat.com>
Date: Fri, 15 May 2026 17:01:21 +0200
Subject: [PATCH 1/2] CVE-2026-59847 libcrypto: Fix tag verification of AES-GCM
ciphers
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
EVP_DecryptFinal() returns 0 errors, which was wrongly checked since
its introduction.
Reported by Ben Smyth discuss@bensmyth.com
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Pavol Žáčik <pzacik@redhat.com>
(cherry picked from commit 6d6cb6cb4d1684bb3f2b9fd23f3635e79d1e5495)
---
src/libcrypto.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/libcrypto.c b/src/libcrypto.c
index c92b11e0..1376d404 100644
--- a/src/libcrypto.c
+++ b/src/libcrypto.c
@@ -924,7 +924,7 @@ evp_cipher_aead_decrypt(struct ssh_cipher_struct *cipher,
rc = EVP_DecryptFinal(cipher->ctx,
NULL,
&outlen);
- if (rc < 0) {
+ if (rc != 1 || outlen != 0) {
SSH_LOG(SSH_LOG_TRACE, "EVP_DecryptFinal failed: Failed authentication");
return SSH_ERROR;
}
From 4237a6bfe3322a4148506bdaf483e1aedb4d88d9 Mon Sep 17 00:00:00 2001
From: Jakub Jelen <jjelen@redhat.com>
Date: Mon, 18 May 2026 08:56:31 +0200
Subject: [PATCH 2/2] CVE-2026-59847 libcrypto: Fix symmetric issue during
encryption
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Pavol Žáčik <pzacik@redhat.com>
(cherry picked from commit a5173c6ad249f7960bc7c1cc75a6a05ead8e3eba)
---
src/libcrypto.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/libcrypto.c b/src/libcrypto.c
index 1376d404..0e5f99fc 100644
--- a/src/libcrypto.c
+++ b/src/libcrypto.c
@@ -836,7 +836,7 @@ evp_cipher_aead_encrypt(struct ssh_cipher_struct *cipher,
rc = EVP_EncryptFinal(cipher->ctx,
NULL,
&tmplen);
- if (rc < 0) {
+ if (rc != 1) {
SSH_LOG(SSH_LOG_TRACE, "EVP_EncryptFinal failed: Failed to create a tag");
return;
}

854
CVE-2026-59848.patch Normal file
View File

@ -0,0 +1,854 @@
From 104b189167d79d76955844acd0fe4b393eccfe42 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavol=20=C5=BD=C3=A1=C4=8Dik?= <pzacik@redhat.com>
Date: Mon, 1 Jun 2026 16:33:03 +0200
Subject: [PATCH 1/2] CVE-2026-59848 sftp: handle responses with unknown
request IDs
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This adds a new field to sftp_session_struct,
containing a list of outstanding request IDs.
An ID is added to the list when a request
is constructed and removed when the corresponding
request is received. If a client receives a response
with an unknown request ID, it reports an error.
Storing responses with unknown request IDs in
the response queue could be abused by a malicious
SFTP server which could deplete client memory
this way.
Signed-off-by: Pavol Žáčik <pzacik@redhat.com>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
---
include/libssh/sftp.h | 1 +
src/sftp.c | 227 ++++++++++++++++++++-----
tests/client/CMakeLists.txt | 1 +
tests/client/torture_sftp_request_id.c | 183 ++++++++++++++++++++
4 files changed, 370 insertions(+), 42 deletions(-)
create mode 100644 tests/client/torture_sftp_request_id.c
diff --git a/include/libssh/sftp.h b/include/libssh/sftp.h
index 8c14b21d..f2344ad3 100644
--- a/include/libssh/sftp.h
+++ b/include/libssh/sftp.h
@@ -90,6 +90,7 @@ struct sftp_session_struct {
void **handles;
sftp_ext ext;
sftp_packet read_packet;
+ struct ssh_list *outstanding_ids;
};
struct sftp_packet_struct {
diff --git a/src/sftp.c b/src/sftp.c
index e3a842d5..68fa5972 100644
--- a/src/sftp.c
+++ b/src/sftp.c
@@ -27,6 +27,7 @@
#include "config.h"
#include <stdbool.h>
+#include <inttypes.h>
#include <errno.h>
#include <ctype.h>
#include <fcntl.h>
@@ -150,6 +151,12 @@ sftp_session sftp_new(ssh_session session)
goto error;
}
+ sftp->outstanding_ids = ssh_list_new();
+ if (sftp->outstanding_ids == NULL) {
+ ssh_set_error_oom(session);
+ goto error;
+ }
+
if (ssh_channel_open_session(sftp->channel)) {
goto error;
}
@@ -166,6 +173,7 @@ error:
if (sftp->channel != NULL) {
ssh_channel_free(sftp->channel);
}
+ ssh_list_free(sftp->outstanding_ids);
if (sftp->read_packet != NULL) {
if (sftp->read_packet->payload != NULL) {
SSH_BUFFER_FREE(sftp->read_packet->payload);
@@ -197,6 +205,12 @@ sftp_new_channel(ssh_session session, ssh_channel channel)
goto error;
}
+ sftp->outstanding_ids = ssh_list_new();
+ if (sftp->outstanding_ids == NULL) {
+ ssh_set_error_oom(session);
+ goto error;
+ }
+
sftp->read_packet = calloc(1, sizeof(struct sftp_packet_struct));
if (sftp->read_packet == NULL) {
ssh_set_error_oom(session);
@@ -218,6 +232,7 @@ error:
if (sftp->ext != NULL) {
sftp_ext_free(sftp->ext);
}
+ ssh_list_free(sftp->outstanding_ids);
if (sftp->read_packet != NULL) {
if (sftp->read_packet->payload != NULL) {
SSH_BUFFER_FREE(sftp->read_packet->payload);
@@ -357,6 +372,7 @@ void sftp_server_free(sftp_session sftp)
void sftp_free(sftp_session sftp)
{
sftp_request_queue ptr;
+ struct ssh_iterator *id_it = NULL;
if (sftp == NULL) {
return;
@@ -383,6 +399,12 @@ void sftp_free(sftp_session sftp)
sftp_ext_free(sftp->ext);
+ id_it = ssh_list_get_iterator(sftp->outstanding_ids);
+ for (; id_it != NULL; id_it = id_it->next) {
+ free((uint32_t *)id_it->data);
+ }
+ ssh_list_free(sftp->outstanding_ids);
+
SAFE_FREE(sftp);
}
@@ -577,6 +599,8 @@ static sftp_message sftp_get_message(sftp_packet packet)
{
sftp_session sftp = packet->sftp;
sftp_message msg = NULL;
+ struct ssh_iterator *id_it = NULL;
+ bool id_found = false;
int rc;
switch(packet->type) {
@@ -624,6 +648,28 @@ static sftp_message sftp_get_message(sftp_packet packet)
msg->id,
msg->packet_type);
+ /* Validate that this ID is in our outstanding requests list */
+ id_it = ssh_list_get_iterator(sftp->outstanding_ids);
+ for (; id_it != NULL; id_it = id_it->next) {
+ uint32_t *stored_id = (uint32_t *)id_it->data;
+ if (*stored_id == msg->id) {
+ id_found = true;
+ ssh_list_remove(sftp->outstanding_ids, id_it);
+ free(stored_id);
+ break;
+ }
+ }
+
+ if (!id_found) {
+ ssh_set_error(packet->sftp->session,
+ SSH_FATAL,
+ "Unknown request ID %" PRIu32,
+ msg->id);
+ sftp_message_free(msg);
+ sftp_set_error(packet->sftp, SSH_FX_FAILURE);
+ return NULL;
+ }
+
return msg;
}
@@ -911,10 +957,45 @@ static sftp_message sftp_dequeue(sftp_session sftp, uint32_t id){
/*
* Assigns a new SFTP ID for new requests and assures there is no collision
* between them.
- * Returns a new ID ready to use in a request
+ * @brief Assigns a new SFTP ID for new requests and assures there is no
+ * collision between them.
+ *
+ * @param sftp The sftp session handle.
+ * @param id_out Pointer to store the new ID.
+ *
+ * @returns SSH_OK on success with the new ID stored in *id_out
+ * @returns SSH_ERROR on failure with the sftp and ssh errors set
*/
-static inline uint32_t sftp_get_new_id(sftp_session session) {
- return ++session->id_counter;
+static int sftp_get_new_id(sftp_session sftp, uint32_t *id_out)
+{
+ uint32_t *id = NULL;
+ int rc;
+
+ if (id_out == NULL) {
+ ssh_set_error_invalid(sftp->session);
+ sftp_set_error(sftp, SSH_FX_FAILURE);
+ return SSH_ERROR;
+ }
+
+ id = malloc(sizeof(uint32_t));
+ if (id == NULL) {
+ ssh_set_error_oom(sftp->session);
+ sftp_set_error(sftp, SSH_FX_FAILURE);
+ return SSH_ERROR;
+ }
+
+ *id = ++sftp->id_counter;
+ rc = ssh_list_append(sftp->outstanding_ids, id);
+ if (rc != SSH_OK) {
+ free(id);
+ ssh_set_error_oom(sftp->session);
+ sftp_set_error(sftp, SSH_FX_FAILURE);
+ return SSH_ERROR;
+ }
+
+ *id_out = *id;
+
+ return SSH_OK;
}
static sftp_status_message parse_status_msg(sftp_message msg){
@@ -1028,6 +1109,11 @@ sftp_dir sftp_opendir(sftp_session sftp, const char *path)
return NULL;
}
+ rc = sftp_get_new_id(sftp, &id);
+ if (rc != SSH_OK) {
+ return NULL;
+ }
+
payload = ssh_buffer_new();
if (payload == NULL) {
ssh_set_error_oom(sftp->session);
@@ -1035,8 +1121,6 @@ sftp_dir sftp_opendir(sftp_session sftp, const char *path)
return NULL;
}
- id = sftp_get_new_id(sftp);
-
rc = ssh_buffer_pack(payload,
"ds",
id,
@@ -1560,6 +1644,11 @@ sftp_attributes sftp_readdir(sftp_session sftp, sftp_dir dir)
int rc;
if (dir->buffer == NULL) {
+ rc = sftp_get_new_id(sftp, &id);
+ if (rc != SSH_OK) {
+ return NULL;
+ }
+
payload = ssh_buffer_new();
if (payload == NULL) {
ssh_set_error_oom(sftp->session);
@@ -1567,8 +1656,6 @@ sftp_attributes sftp_readdir(sftp_session sftp, sftp_dir dir)
return NULL;
}
- id = sftp_get_new_id(sftp);
-
rc = ssh_buffer_pack(payload,
"dS",
id,
@@ -1693,6 +1780,11 @@ static int sftp_handle_close(sftp_session sftp, ssh_string handle)
uint32_t id;
int rc;
+ rc = sftp_get_new_id(sftp, &id);
+ if (rc != SSH_OK) {
+ return -1;
+ }
+
buffer = ssh_buffer_new();
if (buffer == NULL) {
ssh_set_error_oom(sftp->session);
@@ -1700,8 +1792,6 @@ static int sftp_handle_close(sftp_session sftp, ssh_string handle)
return -1;
}
- id = sftp_get_new_id(sftp);
-
rc = ssh_buffer_pack(buffer,
"dS",
id,
@@ -1804,6 +1894,11 @@ sftp_file sftp_open(sftp_session sftp,
uint32_t id;
int rc;
+ rc = sftp_get_new_id(sftp, &id);
+ if (rc != SSH_OK) {
+ return NULL;
+ }
+
buffer = ssh_buffer_new();
if (buffer == NULL) {
ssh_set_error_oom(sftp->session);
@@ -1831,7 +1926,6 @@ sftp_file sftp_open(sftp_session sftp,
sftp_flags |= SSH_FXF_APPEND;
}
SSH_LOG(SSH_LOG_PACKET,"Opening file %s with sftp flags %x",file,sftp_flags);
- id = sftp_get_new_id(sftp);
rc = ssh_buffer_pack(buffer,
"dsd",
@@ -1936,14 +2030,17 @@ ssize_t sftp_read(sftp_file handle, void *buf, size_t count) {
return 0;
}
+ rc = sftp_get_new_id(handle->sftp, &id);
+ if (rc != SSH_OK) {
+ return -1;
+ }
+
buffer = ssh_buffer_new();
if (buffer == NULL) {
ssh_set_error_oom(sftp->session);
return -1;
}
- id = sftp_get_new_id(handle->sftp);
-
rc = ssh_buffer_pack(buffer,
"dSqd",
id,
@@ -2036,6 +2133,11 @@ int sftp_async_read_begin(sftp_file file, uint32_t len){
uint32_t id;
int rc;
+ rc = sftp_get_new_id(sftp, &id);
+ if (rc != SSH_OK) {
+ return -1;
+ }
+
buffer = ssh_buffer_new();
if (buffer == NULL) {
ssh_set_error_oom(sftp->session);
@@ -2043,8 +2145,6 @@ int sftp_async_read_begin(sftp_file file, uint32_t len){
return -1;
}
- id = sftp_get_new_id(sftp);
-
rc = ssh_buffer_pack(buffer,
"dSqd",
id,
@@ -2162,6 +2262,11 @@ ssize_t sftp_write(sftp_file file, const void *buf, size_t count) {
size_t packetlen;
int rc;
+ rc = sftp_get_new_id(file->sftp, &id);
+ if (rc != SSH_OK) {
+ return -1;
+ }
+
buffer = ssh_buffer_new();
if (buffer == NULL) {
ssh_set_error_oom(sftp->session);
@@ -2169,8 +2274,6 @@ ssize_t sftp_write(sftp_file file, const void *buf, size_t count) {
return -1;
}
- id = sftp_get_new_id(file->sftp);
-
rc = ssh_buffer_pack(buffer,
"dSqdP",
id,
@@ -2280,6 +2383,11 @@ int sftp_unlink(sftp_session sftp, const char *file) {
uint32_t id;
int rc;
+ rc = sftp_get_new_id(sftp, &id);
+ if (rc != SSH_OK) {
+ return -1;
+ }
+
buffer = ssh_buffer_new();
if (buffer == NULL) {
ssh_set_error_oom(sftp->session);
@@ -2287,8 +2395,6 @@ int sftp_unlink(sftp_session sftp, const char *file) {
return -1;
}
- id = sftp_get_new_id(sftp);
-
rc = ssh_buffer_pack(buffer,
"ds",
id,
@@ -2355,6 +2461,11 @@ int sftp_rmdir(sftp_session sftp, const char *directory) {
uint32_t id;
int rc;
+ rc = sftp_get_new_id(sftp, &id);
+ if (rc != SSH_OK) {
+ return -1;
+ }
+
buffer = ssh_buffer_new();
if (buffer == NULL) {
ssh_set_error_oom(sftp->session);
@@ -2362,8 +2473,6 @@ int sftp_rmdir(sftp_session sftp, const char *directory) {
return -1;
}
- id = sftp_get_new_id(sftp);
-
rc = ssh_buffer_pack(buffer,
"ds",
id,
@@ -2428,6 +2537,11 @@ int sftp_mkdir(sftp_session sftp, const char *directory, mode_t mode)
uint32_t id;
int rc;
+ rc = sftp_get_new_id(sftp, &id);
+ if (rc != SSH_OK) {
+ return -1;
+ }
+
buffer = ssh_buffer_new();
if (buffer == NULL) {
ssh_set_error_oom(sftp->session);
@@ -2439,8 +2553,6 @@ int sftp_mkdir(sftp_session sftp, const char *directory, mode_t mode)
attr.permissions = mode;
attr.flags = SSH_FILEXFER_ATTR_PERMISSIONS;
- id = sftp_get_new_id(sftp);
-
rc = ssh_buffer_pack(buffer,
"ds",
id,
@@ -2527,6 +2639,11 @@ int sftp_rename(sftp_session sftp, const char *original, const char *newname) {
uint32_t id;
int rc;
+ rc = sftp_get_new_id(sftp, &id);
+ if (rc != SSH_OK) {
+ return -1;
+ }
+
buffer = ssh_buffer_new();
if (buffer == NULL) {
ssh_set_error_oom(sftp->session);
@@ -2534,8 +2651,6 @@ int sftp_rename(sftp_session sftp, const char *original, const char *newname) {
return -1;
}
- id = sftp_get_new_id(sftp);
-
rc = ssh_buffer_pack(buffer,
"dss",
id,
@@ -2611,6 +2726,11 @@ int sftp_setstat(sftp_session sftp, const char *file, sftp_attributes attr)
sftp_status_message status = NULL;
int rc;
+ rc = sftp_get_new_id(sftp, &id);
+ if (rc != SSH_OK) {
+ return -1;
+ }
+
buffer = ssh_buffer_new();
if (buffer == NULL) {
ssh_set_error_oom(sftp->session);
@@ -2618,8 +2738,6 @@ int sftp_setstat(sftp_session sftp, const char *file, sftp_attributes attr)
return -1;
}
- id = sftp_get_new_id(sftp);
-
rc = ssh_buffer_pack(buffer,
"ds",
id,
@@ -2741,6 +2859,11 @@ int sftp_symlink(sftp_session sftp, const char *target, const char *dest) {
return -1;
}
+ rc = sftp_get_new_id(sftp, &id);
+ if (rc != SSH_OK) {
+ return -1;
+ }
+
buffer = ssh_buffer_new();
if (buffer == NULL) {
ssh_set_error_oom(sftp->session);
@@ -2748,8 +2871,6 @@ int sftp_symlink(sftp_session sftp, const char *target, const char *dest) {
return -1;
}
- id = sftp_get_new_id(sftp);
-
/* TODO check for version number if they ever fix it. */
if (ssh_get_openssh_version(sftp->session)) {
rc = ssh_buffer_pack(buffer,
@@ -2839,6 +2960,12 @@ char *sftp_readlink(sftp_session sftp, const char *path)
sftp_set_error(sftp, SSH_FX_FAILURE);
return NULL;
}
+
+ rc = sftp_get_new_id(sftp, &id);
+ if (rc != SSH_OK) {
+ return NULL;
+ }
+
buffer = ssh_buffer_new();
if (buffer == NULL) {
ssh_set_error_oom(sftp->session);
@@ -2846,8 +2973,6 @@ char *sftp_readlink(sftp_session sftp, const char *path)
return NULL;
}
- id = sftp_get_new_id(sftp);
-
rc = ssh_buffer_pack(buffer,
"ds",
id,
@@ -2965,6 +3090,11 @@ sftp_statvfs_t sftp_statvfs(sftp_session sftp, const char *path)
return NULL;
}
+ rc = sftp_get_new_id(sftp, &id);
+ if (rc != SSH_OK) {
+ return NULL;
+ }
+
buffer = ssh_buffer_new();
if (buffer == NULL) {
ssh_set_error_oom(sftp->session);
@@ -2972,8 +3102,6 @@ sftp_statvfs_t sftp_statvfs(sftp_session sftp, const char *path)
return NULL;
}
- id = sftp_get_new_id(sftp);
-
rc = ssh_buffer_pack(buffer,
"dss",
id,
@@ -3040,6 +3168,11 @@ int sftp_fsync(sftp_file file)
}
sftp = file->sftp;
+ rc = sftp_get_new_id(sftp, &id);
+ if (rc != SSH_OK) {
+ return -1;
+ }
+
buffer = ssh_buffer_new();
if (buffer == NULL) {
ssh_set_error_oom(sftp->session);
@@ -3047,8 +3180,6 @@ int sftp_fsync(sftp_file file)
return -1;
}
- id = sftp_get_new_id(sftp);
-
rc = ssh_buffer_pack(buffer,
"dsS",
id,
@@ -3140,6 +3271,11 @@ sftp_statvfs_t sftp_fstatvfs(sftp_file file)
}
sftp = file->sftp;
+ rc = sftp_get_new_id(sftp, &id);
+ if (rc != SSH_OK) {
+ return NULL;
+ }
+
buffer = ssh_buffer_new();
if (buffer == NULL) {
ssh_set_error_oom(sftp->session);
@@ -3147,8 +3283,6 @@ sftp_statvfs_t sftp_fstatvfs(sftp_file file)
return NULL;
}
- id = sftp_get_new_id(sftp);
-
rc = ssh_buffer_pack(buffer,
"dsS",
id,
@@ -3227,6 +3361,11 @@ char *sftp_canonicalize_path(sftp_session sftp, const char *path)
return NULL;
}
+ rc = sftp_get_new_id(sftp, &id);
+ if (rc != SSH_OK) {
+ return NULL;
+ }
+
buffer = ssh_buffer_new();
if (buffer == NULL) {
ssh_set_error_oom(sftp->session);
@@ -3234,8 +3373,6 @@ char *sftp_canonicalize_path(sftp_session sftp, const char *path)
return NULL;
}
- id = sftp_get_new_id(sftp);
-
rc = ssh_buffer_pack(buffer,
"ds",
id,
@@ -3318,6 +3455,11 @@ static sftp_attributes sftp_xstat(sftp_session sftp,
return NULL;
}
+ rc = sftp_get_new_id(sftp, &id);
+ if (rc != SSH_OK) {
+ return NULL;
+ }
+
buffer = ssh_buffer_new();
if (buffer == NULL) {
ssh_set_error_oom(sftp->session);
@@ -3325,8 +3467,6 @@ static sftp_attributes sftp_xstat(sftp_session sftp,
return NULL;
}
- id = sftp_get_new_id(sftp);
-
rc = ssh_buffer_pack(buffer,
"ds",
id,
@@ -3396,6 +3536,11 @@ sftp_attributes sftp_fstat(sftp_file file)
return NULL;
}
+ rc = sftp_get_new_id(file->sftp, &id);
+ if (rc != SSH_OK) {
+ return NULL;
+ }
+
buffer = ssh_buffer_new();
if (buffer == NULL) {
ssh_set_error_oom(file->sftp->session);
@@ -3403,8 +3548,6 @@ sftp_attributes sftp_fstat(sftp_file file)
return NULL;
}
- id = sftp_get_new_id(file->sftp);
-
rc = ssh_buffer_pack(buffer,
"dS",
id,
diff --git a/tests/client/CMakeLists.txt b/tests/client/CMakeLists.txt
index 14f24c26..56aaa805 100644
--- a/tests/client/CMakeLists.txt
+++ b/tests/client/CMakeLists.txt
@@ -43,6 +43,7 @@ if (WITH_SFTP)
torture_sftp_dir
torture_sftp_read
torture_sftp_fsync
+ torture_sftp_request_id
${SFTP_BENCHMARK_TESTS})
endif (WITH_SFTP)
diff --git a/tests/client/torture_sftp_request_id.c b/tests/client/torture_sftp_request_id.c
new file mode 100644
index 00000000..f75ab696
--- /dev/null
+++ b/tests/client/torture_sftp_request_id.c
@@ -0,0 +1,183 @@
+#include "config.h"
+
+#define LIBSSH_STATIC
+
+#include "sftp.c"
+#include "torture.h"
+
+#include <pwd.h>
+#include <sys/types.h>
+
+static int sshd_setup(void **state)
+{
+ torture_setup_sshd_server(state, false);
+
+ return 0;
+}
+
+static int sshd_teardown(void **state)
+{
+ torture_teardown_sshd_server(state);
+
+ return 0;
+}
+
+static int session_setup(void **state)
+{
+ struct torture_state *s = *state;
+ struct passwd *pwd = NULL;
+ int rc;
+
+ pwd = getpwnam("bob");
+ assert_non_null(pwd);
+
+ rc = setuid(pwd->pw_uid);
+ assert_return_code(rc, errno);
+
+ s->ssh.session = torture_ssh_session(s,
+ TORTURE_SSH_SERVER,
+ NULL,
+ TORTURE_SSH_USER_ALICE,
+ NULL);
+ assert_non_null(s->ssh.session);
+
+ s->ssh.tsftp = torture_sftp_session(s->ssh.session);
+ assert_non_null(s->ssh.tsftp);
+
+ return 0;
+}
+
+static int session_teardown(void **state)
+{
+ struct torture_state *s = *state;
+
+ torture_rmdirs(s->ssh.tsftp->testdir);
+ torture_sftp_close(s->ssh.tsftp);
+ ssh_disconnect(s->ssh.session);
+ ssh_free(s->ssh.session);
+
+ return 0;
+}
+
+static void torture_sftp_request_id_null(void **state)
+{
+ struct torture_state *s = *state;
+ struct torture_sftp *t = s->ssh.tsftp;
+ sftp_session sftp = t->sftp;
+ int rc;
+
+ rc = sftp_get_new_id(sftp, NULL);
+ assert_int_equal(rc, SSH_ERROR);
+}
+
+static void torture_sftp_request_id_add(void **state)
+{
+ struct torture_state *s = *state;
+ struct torture_sftp *t = s->ssh.tsftp;
+ sftp_session sftp = t->sftp;
+ uint32_t id1, id2;
+ int rc;
+ size_t count;
+
+ /* The list of IDs should be empty at first */
+ count = ssh_list_count(sftp->outstanding_ids);
+ assert_int_equal(count, 0);
+
+ /* Request a new ID */
+ rc = sftp_get_new_id(sftp, &id1);
+ assert_int_equal(rc, SSH_OK);
+
+ /* Check that the list has one ID now */
+ count = ssh_list_count(sftp->outstanding_ids);
+ assert_int_equal(count, 1);
+
+ /* Request another ID */
+ rc = sftp_get_new_id(sftp, &id2);
+ assert_int_equal(rc, SSH_OK);
+
+ /* Check that the IDs differ */
+ assert_int_not_equal(id1, id2);
+
+ /* Check that the list has two IDs now */
+ count = ssh_list_count(sftp->outstanding_ids);
+ assert_int_equal(count, 2);
+}
+
+static void torture_sftp_request_id_remove(void **state)
+{
+ struct torture_state *s = *state;
+ struct torture_sftp *t = s->ssh.tsftp;
+ sftp_session sftp = t->sftp;
+ sftp_attributes attr = NULL;
+ size_t count;
+
+ count = ssh_list_count(sftp->outstanding_ids);
+ assert_int_equal(count, 0);
+
+ /* We send a request and receive a response */
+ attr = sftp_stat(sftp, SSH_EXECUTABLE);
+ assert_non_null(attr);
+
+ /* The number of outstanding requests should be back to 0 */
+ count = ssh_list_count(sftp->outstanding_ids);
+ assert_int_equal(count, 0);
+
+ sftp_attributes_free(attr);
+}
+
+static void torture_sftp_request_id_unknown(void **state)
+{
+ struct torture_state *s = *state;
+ struct torture_sftp *t = s->ssh.tsftp;
+ sftp_session sftp = t->sftp;
+ ssh_buffer buffer = NULL;
+ uint32_t id = 0;
+ int rc;
+ size_t count;
+
+ count = ssh_list_count(sftp->outstanding_ids);
+ assert_int_equal(count, 0);
+
+ buffer = ssh_buffer_new();
+ assert_non_null(buffer);
+
+ rc = ssh_buffer_pack(buffer, "ds", id, "/tmp");
+ assert_int_equal(rc, SSH_OK);
+
+ /* Send a request without saving the request ID */
+ rc = sftp_packet_write(sftp, SSH_FXP_OPENDIR, buffer);
+ assert_int_not_equal(rc, -1);
+ SSH_BUFFER_FREE(buffer);
+
+ /* An attempt to read and dispatch the response should fail
+ * because the ID is not in the outstanding list */
+ rc = sftp_read_and_dispatch(sftp);
+ assert_int_equal(rc, -1);
+}
+
+int torture_run_tests(void)
+{
+ int rc;
+ struct CMUnitTest tests[] = {
+ cmocka_unit_test_setup_teardown(torture_sftp_request_id_null,
+ session_setup,
+ session_teardown),
+ cmocka_unit_test_setup_teardown(torture_sftp_request_id_add,
+ session_setup,
+ session_teardown),
+ cmocka_unit_test_setup_teardown(torture_sftp_request_id_remove,
+ session_setup,
+ session_teardown),
+ cmocka_unit_test_setup_teardown(torture_sftp_request_id_unknown,
+ session_setup,
+ session_teardown),
+ };
+
+ ssh_init();
+
+ torture_filter_tests(tests);
+ rc = cmocka_run_group_tests(tests, sshd_setup, sshd_teardown);
+ ssh_finalize();
+
+ return rc;
+}
From af4c693af9557ea4a2cb8f3f2e94f15038c9779a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavol=20=C5=BD=C3=A1=C4=8Dik?= <pzacik@redhat.com>
Date: Wed, 3 Jun 2026 12:56:09 +0200
Subject: [PATCH 2/2] CVE-2026-59848 sftp: Initialize sftp_request_queue ptr in
sftp_free
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Pavol Žáčik <pzacik@redhat.com>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
---
src/sftp.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/sftp.c b/src/sftp.c
index 68fa5972..870758a8 100644
--- a/src/sftp.c
+++ b/src/sftp.c
@@ -371,7 +371,7 @@ void sftp_server_free(sftp_session sftp)
void sftp_free(sftp_session sftp)
{
- sftp_request_queue ptr;
+ sftp_request_queue ptr = NULL;
struct ssh_iterator *id_it = NULL;
if (sftp == NULL) {

33
CVE-2026-59850.patch Normal file
View File

@ -0,0 +1,33 @@
From 5f8c72ac1d3ebf87de088e08035dafbab3fb23ee Mon Sep 17 00:00:00 2001
From: Jakub Jelen <jjelen@redhat.com>
Date: Wed, 1 Jul 2026 16:43:08 +0200
Subject: [PATCH] CVE-2026-59850 channels: Avoid processing DATA packets on
closed channels
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Pavol Žáčik <pzacik@redhat.com>
---
src/channels.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/src/channels.c b/src/channels.c
index 36e19598..88430791 100644
--- a/src/channels.c
+++ b/src/channels.c
@@ -563,6 +563,13 @@ SSH_PACKET_CALLBACK(channel_rcv_data){
channel->local_window,
channel->remote_window);
+ if (channel->flags & SSH_CHANNEL_FLAG_CLOSED_REMOTE) {
+ SSH_LOG(SSH_LOG_WARNING, "Received data on (remotely) closed channel");
+ ssh_set_error(session, SSH_FATAL, "Received data on (remotely) closed channel");
+ SSH_STRING_FREE(str);
+ return SSH_PACKET_USED;
+ }
+
/* What shall we do in this case? Let's accept it anyway */
if (len > channel->local_window) {
SSH_LOG(SSH_LOG_RARE,

View File

@ -1,6 +1,6 @@
Name: libssh
Version: 0.9.6
Release: 16%{?dist}
Release: 17%{?dist}
Summary: A library implementing the SSH protocol
License: LGPLv2+
URL: http://www.libssh.org
@ -22,6 +22,13 @@ Patch7: CVE-2023-6004.patch
Patch8: CVE-2023-6918.patch
Patch9: CVE-2025-5318.patch
Patch10: CVE-2025-5372.patch
Patch11: CVE-2026-59843.patch
Patch12: CVE-2026-59844.patch
Patch13: CVE-2026-59845.patch
Patch14: CVE-2026-59846.patch
Patch15: CVE-2026-59847.patch
Patch16: CVE-2026-59848.patch
Patch17: CVE-2026-59850.patch
BuildRequires: cmake
BuildRequires: doxygen
@ -150,6 +157,16 @@ popd
%attr(0644,root,root) %config(noreplace) %{_sysconfdir}/libssh/libssh_server.config
%changelog
* Sat Jul 25 2026 RHEL Packaging Agent <redhat-ymir-agent@redhat.com> - 0.9.6-17
- Backport CVE patches from 0.11.5
Resolves: RHEL-215677
Resolves: RHEL-215674
Resolves: RHEL-215680
Resolves: RHEL-215678
Resolves: RHEL-215675
Resolves: RHEL-215676
Resolves: RHEL-215679
* Wed Nov 05 2025 Pavol Žáčik <pzacik@redhat.com> - 0.9.6-16
- Fix CVE-2025-5372
Resolves: RHEL-121232