[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH] channels: Fix segfaults when the channel data is freed
[Thread Prev] | [Thread Next]
- Subject: [PATCH] channels: Fix segfaults when the channel data is freed
- From: "Artyom V. Poptsov" <poptsov.artyom@xxxxxxxxx>
- Reply-to: libssh@xxxxxxxxxx
- Date: Sun, 15 Aug 2021 23:01:53 +0300
- To: libssh@xxxxxxxxxx
Hello,I've found that some channel procedures in libssh 0.9.3 on Ubuntu GNU/Linux 20.04 (and the latest versions from Git) fails with SEGFAULT when a parent session of a channel is freed.
I investigated the errors and found that some "channels.h" procedures (namely 'ssh_channel_is_open' and 'ssh_channel_is_closed') try to determine whether the parent session is alive by checking 'channel->session->alive' variable. But when a channel is freed by 'ssh_channel_do_free' procedure, its 'session' field is set to NULL. In that situation calling e.g. 'ssh_channel_is_open' on a channel will lead to a SEGFAULT.
The patch to fix that behavior is attached to the email.I ran "make test" on the libssh sources with my changes and all tests have passed successfully.
Thanks. -- Artyom "avp" Poptsov <poptsov.artyom@xxxxxxxxx> Home page: https://memory-heap.org/~avp/ CADR Hackerspace co-founder: https://cadrspace.ru/ GPG: D0C2 EAC1 3310 822D 98DE B57C E9C5 A2D9 0898 A02F
From f96c7ded5fb61589fd38056fd1431021e4f441cb Mon Sep 17 00:00:00 2001
From: "Artyom V. Poptsov" <poptsov.artyom@xxxxxxxxx>
Date: Sun, 15 Aug 2021 22:50:33 +0300
Subject: [PATCH] channels: Fix segfaults when the channel data is freed
libssh fails to properly determine whether the parent session of a
channel is alive or not, resulting in SEGFAULT errors. The reason is
that when a channel is freed with 'ssh_channel_do_free' procedure, its
'session' field is set to NULL; then when a channel procedure tries to
check the value of 'channel->session->alive' it effectively
dereferencing a NULL pointer.
The change fixes that behavior.
Signed-off-by: Artyom V. Poptsov <poptsov.artyom@xxxxxxxxx>
---
src/channels.c | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/src/channels.c b/src/channels.c
index 8d812477..a71b5c73 100644
--- a/src/channels.c
+++ b/src/channels.c
@@ -1613,7 +1613,9 @@ int ssh_channel_is_open(ssh_channel channel) {
if(channel == NULL) {
return 0;
}
- return (channel->state == SSH_CHANNEL_STATE_OPEN && channel->session->alive != 0);
+ return ((channel->session != NULL)
+ && (channel->state == SSH_CHANNEL_STATE_OPEN)
+ && (channel->session->alive != 0));
}
/**
@@ -1629,7 +1631,9 @@ int ssh_channel_is_closed(ssh_channel channel) {
if(channel == NULL) {
return SSH_ERROR;
}
- return (channel->state != SSH_CHANNEL_STATE_OPEN || channel->session->alive == 0);
+ return ((! channel->session)
+ || (channel->state != SSH_CHANNEL_STATE_OPEN)
+ || (channel->session->alive == 0));
}
/**
@@ -3094,7 +3098,7 @@ int ssh_channel_read_nonblocking(ssh_channel channel,
int ssh_channel_poll(ssh_channel channel, int is_stderr){
ssh_buffer stdbuf;
- if(channel == NULL) {
+ if((channel == NULL) || (channel->session == NULL)) {
return SSH_ERROR;
}
@@ -3151,7 +3155,7 @@ int ssh_channel_poll_timeout(ssh_channel channel, int timeout, int is_stderr)
size_t len;
int rc;
- if (channel == NULL) {
+ if ((channel == NULL) || (channel->session == NULL)) {
return SSH_ERROR;
}
@@ -3241,7 +3245,7 @@ static int ssh_channel_exit_status_termination(void *c){
*/
int ssh_channel_get_exit_status(ssh_channel channel) {
int rc;
- if(channel == NULL) {
+ if((channel == NULL) || (channel->session == NULL)) {
return SSH_ERROR;
}
rc = ssh_handle_packets_termination(channel->session,
--
2.25.1
Attachment:
OpenPGP_signature
Description: OpenPGP digital signature
| Re: [PATCH] channels: Fix segfaults when the channel data is freed | Jakub Jelen <jjelen@xxxxxxxxxx> |
| Re: [PATCH] channels: Fix segfaults when the channel data is freed | Jakub Jelen <jjelen@xxxxxxxxxx> |