From 4989aa7031235efbca98571b49780a52dc895da9 Mon Sep 17 00:00:00 2001 From: Philippe Antoine Date: Wed, 23 Jul 2025 14:37:45 +0200 Subject: [PATCH 1/2] socket: do not free poll object if it is locked As it may a cause a use after free if `send` fails when ssh_poll_ctx_dopoll does its callback ssh_poll_ctx_dopoll still wants to use the poll object later Signed-off-by: Philippe Antoine --- include/libssh/poll.h | 1 + src/poll.c | 11 +++++++++++ src/socket.c | 2 +- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/include/libssh/poll.h b/include/libssh/poll.h index 8e30676e3..8ed7372dc 100644 --- a/include/libssh/poll.h +++ b/include/libssh/poll.h @@ -157,6 +157,7 @@ void ssh_poll_ctx_free(ssh_poll_ctx ctx); int ssh_poll_ctx_add(ssh_poll_ctx ctx, ssh_poll_handle p); int ssh_poll_ctx_add_socket (ssh_poll_ctx ctx, struct ssh_socket_struct *s); void ssh_poll_ctx_remove(ssh_poll_ctx ctx, ssh_poll_handle p); +bool ssh_poll_locked(ssh_poll_handle p); int ssh_poll_ctx_dopoll(ssh_poll_ctx ctx, int timeout); ssh_poll_ctx ssh_poll_get_default_ctx(ssh_session session); int ssh_event_add_poll(ssh_event event, ssh_poll_handle p); diff --git a/src/poll.c b/src/poll.c index 80903049f..514cecbb0 100644 --- a/src/poll.c +++ b/src/poll.c @@ -670,6 +670,17 @@ void ssh_poll_ctx_remove(ssh_poll_ctx ctx, ssh_poll_handle p) } } +/** + * @brief Returns if a poll object is locked. + * + * @param p Pointer to an already allocated poll object. + * @returns true if the poll object is locked; false otherwise. + */ +bool ssh_poll_locked(ssh_poll_handle p) +{ + return p->lock_cnt > 0; +} + /** * @brief Poll all the sockets associated through a poll object with a * poll context. If any of the events are set after the poll, the diff --git a/src/socket.c b/src/socket.c index 857a7bd5d..3909e486c 100644 --- a/src/socket.c +++ b/src/socket.c @@ -479,7 +479,7 @@ void ssh_socket_close(ssh_socket s) #endif } - if (s->poll_handle != NULL) { + if (s->poll_handle != NULL && !ssh_poll_locked(s->poll_handle)) { ssh_poll_free(s->poll_handle); s->poll_handle = NULL; } -- GitLab From aff3a05964f937346507d81597b2f57ec45b459e Mon Sep 17 00:00:00 2001 From: Philippe Antoine Date: Wed, 23 Jul 2025 21:24:07 +0200 Subject: [PATCH 2/2] fixup! socket: do not free poll object if it is locked --- src/poll.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/poll.c b/src/poll.c index 514cecbb0..4b1763637 100644 --- a/src/poll.c +++ b/src/poll.c @@ -678,6 +678,9 @@ void ssh_poll_ctx_remove(ssh_poll_ctx ctx, ssh_poll_handle p) */ bool ssh_poll_locked(ssh_poll_handle p) { + if (p == NULL) { + return false; + } return p->lock_cnt > 0; } -- GitLab