summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNalin Dahyabhai <nalin@dahyabhai.net>2014-01-28 11:22:26 +0100
committerAndreas Schneider <asn@samba.org>2014-01-28 13:23:32 +0100
commit1462a69c0a96605081f9f1c0dc5bb54aa98aa202 (patch)
treeec785742ae300e5a791ab202c289c199469af962
parent019e4f3bb6e5589ad8fe0ca0c07b197cb8cbb677 (diff)
downloadsocket_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.c61
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
***************************************************************************/