diff options
author | Aris Adamantiadis <aris@0xbadc0de.be> | 2011-01-19 16:01:21 +0100 |
---|---|---|
committer | Aris Adamantiadis <aris@0xbadc0de.be> | 2011-01-19 16:01:21 +0100 |
commit | 84df46f805779d172e281d0a523a3b0d290e6c45 (patch) | |
tree | 45af55f2fd1bc6fb9b58e7211ac3dc0c49f153d0 | |
parent | 460d43f0508bb591afbf09b2548a6ab2d65601e9 (diff) | |
download | libssh-84df46f805779d172e281d0a523a3b0d290e6c45.tar.gz libssh-84df46f805779d172e281d0a523a3b0d290e6c45.tar.xz libssh-84df46f805779d172e281d0a523a3b0d290e6c45.zip |
Fix use-after-free when socket is closed in a callback handler
-rw-r--r-- | src/socket.c | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/src/socket.c b/src/socket.c index 2404a2ec..eae6a404 100644 --- a/src/socket.c +++ b/src/socket.c @@ -188,6 +188,19 @@ void ssh_socket_set_callbacks(ssh_socket s, ssh_socket_callbacks callbacks){ s->callbacks=callbacks; } +/** + * @brief SSH poll callback. This callback will be used when an event + * caught on the socket. + * + * @param p Poll object this callback belongs to. + * @param fd The raw socket. + * @param revents The current poll events on the socket. + * @param userdata Userdata to be passed to the callback function, + * in this case the socket object. + * + * @return 0 on success, < 0 when the poll object has been removed + * from its poll context. + */ int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p, socket_t fd, int revents, void *v_s){ ssh_socket s=(ssh_socket )v_s; char buffer[4096]; @@ -218,7 +231,6 @@ int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p, socket_t fd, int r s->read_wontblock=1; r=ssh_socket_unbuffered_read(s,buffer,sizeof(buffer)); if(r<0){ - err=-1; if(p != NULL) ssh_poll_set_events(p,ssh_poll_get_events(p) & ~POLLIN); if(s->callbacks && s->callbacks->exception){ @@ -274,7 +286,8 @@ int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p, socket_t fd, int r } /* TODO: Find a way to put back POLLOUT when buffering occurs */ } - return err; + /* Return -1 if one of the poll handlers disappeared */ + return (s->poll_in == NULL || s->poll_out == NULL) ? -1 : 0; } /** @internal |