diff options
author | Nalin Dahyabhai <nalin@dahyabhai.net> | 2014-01-28 11:22:26 +0100 |
---|---|---|
committer | Andreas Schneider <asn@samba.org> | 2014-01-28 13:23:32 +0100 |
commit | 1462a69c0a96605081f9f1c0dc5bb54aa98aa202 (patch) | |
tree | ec785742ae300e5a791ab202c289c199469af962 | |
parent | 019e4f3bb6e5589ad8fe0ca0c07b197cb8cbb677 (diff) | |
download | socket_wrapper-1462a69c0a96605081f9f1c0dc5bb54aa98aa202.tar.gz socket_wrapper-1462a69c0a96605081f9f1c0dc5bb54aa98aa202.tar.xz socket_wrapper-1462a69c0a96605081f9f1c0dc5bb54aa98aa202.zip |
src: Try to recover when sockets are closed elsewhere.
There are methods for closing descriptors (libc-internal code paths,
direct syscalls) which close descriptors in ways that we
can't intercept, so try to recover when we notice that that's happened:
* If we see a descriptor being handed back from open() that we thought
was a socket, stop intercepting uses of that descriptor.
Reviewed-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
-rw-r--r-- | src/socket_wrapper.c | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/src/socket_wrapper.c b/src/socket_wrapper.c index b442d28..4b9f200 100644 --- a/src/socket_wrapper.c +++ b/src/socket_wrapper.c @@ -296,6 +296,7 @@ struct swrap_libc_fns { socklen_t *optlen); int (*libc_ioctl)(int d, unsigned long int request, ...); int (*libc_listen)(int sockfd, int backlog); + int (*libc_open)(const char *pathname, int flags, mode_t mode); int (*libc_read)(int fd, void *buf, size_t count); ssize_t (*libc_readv)(int fd, const struct iovec *iov, int iovcnt); int (*libc_recv)(int sockfd, void *buf, size_t len, int flags); @@ -563,6 +564,13 @@ static int libc_listen(int sockfd, int backlog) return swrap.fns.libc_listen(sockfd, backlog); } +static int libc_open(const char *pathname, int flags, mode_t mode) +{ + swrap_load_lib_function(SWRAP_LIBC, open); + + return swrap.fns.libc_open(pathname, flags, mode); +} + static int libc_read(int fd, void *buf, size_t count) { swrap_load_lib_function(SWRAP_LIBC, read); @@ -1095,6 +1103,27 @@ static struct socket_info *find_socket_info(int fd) return NULL; } +static void swrap_remove_stale(int fd) +{ + struct socket_info *si = find_socket_info(fd); + struct socket_info_fd *fi; + + if (si != NULL) { + for (fi = si->fds; fi; fi = fi->next) { + if (fi->fd == fd) { + SWRAP_LOG(SWRAP_LOG_TRACE, "remove stale wrapper for %d", fd); + SWRAP_DLIST_REMOVE(si->fds, fi); + free(fi); + break; + } + } + + if (si->fds == NULL) { + SWRAP_DLIST_REMOVE(sockets, si); + } + } +} + static int sockaddr_convert_to_un(struct socket_info *si, const struct sockaddr *in_addr, socklen_t in_len, @@ -2435,6 +2464,38 @@ int listen(int s, int backlog) } /**************************************************************************** + * OPEN + ***************************************************************************/ + +static int swrap_open(const char *pathname, int flags, mode_t mode) +{ + int ret; + + ret = libc_open(pathname, flags, mode); + if (ret != -1) { + /* + * There are methods for closing descriptors (libc-internal code + * paths, direct syscalls) which close descriptors in ways that + * we can't intercept, so try to recover when we notice that + * that's happened + */ + swrap_remove_stale(ret); + } + return ret; +} + +int open(const char *pathname, int flags, ...) +{ + mode_t mode; + va_list ap; + + va_start(ap, flags); + mode = va_arg(ap, mode_t); + va_end(ap); + return swrap_open(pathname, flags, mode); +} + +/**************************************************************************** * GETPEERNAME ***************************************************************************/ |