diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2015-01-15 14:13:19 +0100 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2015-01-20 07:11:58 +0100 |
commit | f87ede57a2e97f0743a85b94072c7163fa485ae9 (patch) | |
tree | 827af0350535dde1db7f1ae5d80226eb3a62533d /cpukit/libnetworking/kern | |
parent | libnetworking: Delete dead code (diff) | |
download | rtems-f87ede57a2e97f0743a85b94072c7163fa485ae9.tar.bz2 |
libnetworking: Fix close of active sockets
Send a special event to notify tasks waiting for a socket state change
in case this socket gets closed. This prevents a use after free.
Close #785.
Diffstat (limited to 'cpukit/libnetworking/kern')
-rw-r--r-- | cpukit/libnetworking/kern/uipc_socket.c | 27 |
1 files changed, 26 insertions, 1 deletions
diff --git a/cpukit/libnetworking/kern/uipc_socket.c b/cpukit/libnetworking/kern/uipc_socket.c index 7ed3ad0d75..b221a377ca 100644 --- a/cpukit/libnetworking/kern/uipc_socket.c +++ b/cpukit/libnetworking/kern/uipc_socket.c @@ -145,6 +145,26 @@ sofree(struct socket *so) FREE(so, M_SOCKET); } +static void +rtems_socket_close_notify(struct socket *so) +{ + if (so->so_pgid) { + rtems_event_system_send(so->so_pgid, RTEMS_EVENT_SYSTEM_NETWORK_CLOSE); + } +} + +static void +rtems_sockbuf_close_notify(struct socket *so, struct sockbuf *sb) +{ + if (sb->sb_flags & SB_WAIT) { + rtems_event_system_send(sb->sb_sel.si_pid, + RTEMS_EVENT_SYSTEM_NETWORK_CLOSE); + } + + if (sb->sb_wakeup) + (*sb->sb_wakeup)(so, sb->sb_wakeuparg); +} + /* * Close a socket on last file table reference removal. * Initiate disconnect if connected. @@ -156,6 +176,10 @@ soclose(struct socket *so) int s = splnet(); /* conservative */ int error = 0; + rtems_socket_close_notify(so); + rtems_sockbuf_close_notify(so, &so->so_snd); + rtems_sockbuf_close_notify(so, &so->so_rcv); + if (so->so_options & SO_ACCEPTCONN) { struct socket *sp, *sonext; @@ -742,7 +766,8 @@ dontblock: break; error = sbwait(&so->so_rcv); if (error) { - sbunlock(&so->so_rcv); + if (error != ENXIO) + sbunlock(&so->so_rcv); splx(s); return (0); } |