Patches for socket_wrapper
Nalin Dahyabhai
nalin at redhat.com
Mon Jan 27 13:46:55 MST 2014
Hello, here are a couple of patches for socket_wrapper.
The first keeps the wrapper from incorrectly attempting to treat a
previously-closed socket descriptor, which is now pointing to a file, as
a socket.
The second handles cases where a client socket has been explicitly bound
to the wildcard address, but then implicitly bound to a particular
address when it was subsequently used to open a connection.
Thanks,
Nalin
-------------- next part --------------
>From 4cd05dee165f6a08dcdbdc627464232a8abc3e4b Mon Sep 17 00:00:00 2001
From: Nalin Dahyabhai <nalin at dahyabhai.net>
Date: Thu, 23 Jan 2014 14:27:19 -0500
Subject: [PATCH 1/2] 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.
* When attempting to read or writev to a descriptor, if an underlying
autobind fails because it's not a socket, stop intercepting uses of
that descriptor.
---
src/socket_wrapper.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 71 insertions(+), 3 deletions(-)
diff --git a/src/socket_wrapper.c b/src/socket_wrapper.c
index 3047eb1..8408af7 100644
--- a/src/socket_wrapper.c
+++ b/src/socket_wrapper.c
@@ -297,6 +297,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);
@@ -564,6 +565,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);
@@ -1096,6 +1104,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,
@@ -2436,6 +2465,32 @@ 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) {
+ 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
***************************************************************************/
@@ -3379,8 +3434,13 @@ static ssize_t swrap_read(int s, void *buf, size_t len)
tret = swrap_recvmsg_before(s, si, &msg, &tmp);
if (tret == -1) {
- SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_recvmsg_before failed");
- return -1;
+ if (errno == ENOTSOCK) {
+ swrap_remove_stale(s);
+ return libc_read(s, buf, len);
+ } else {
+ SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_recvmsg_before failed");
+ return -1;
+ }
}
buf = msg.msg_iov[0].iov_base;
@@ -3725,7 +3785,15 @@ static ssize_t swrap_writev(int s, const struct iovec *vector, int count)
#endif
ret = swrap_sendmsg_before(s, si, &msg, &tmp, &un_addr, NULL, NULL, NULL);
- if (ret == -1) return -1;
+ if (ret == -1) {
+ if (errno == ENOTSOCK) {
+ swrap_remove_stale(s);
+ return libc_writev(s, msg.msg_iov, msg.msg_iovlen);
+ } else {
+ SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_recvmsg_before failed");
+ return -1;
+ }
+ }
ret = libc_writev(s, msg.msg_iov, msg.msg_iovlen);
--
1.8.5.3
-------------- next part --------------
>From 7853ac5d8b2d30bc0a4e18bdca57acc031ccbd28 Mon Sep 17 00:00:00 2001
From: Nalin Dahyabhai <nalin at dahyabhai.net>
Date: Sat, 25 Jan 2014 00:58:15 -0500
Subject: [PATCH 2/2] Rebind wildcard sockets on connect
When we connect() on a socket that was previously bound to the wildcard
listening address, adjust its idea of its bound address to the address
we would have assigned if it hadn't been explicitly bound.
---
src/socket_wrapper.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/src/socket_wrapper.c b/src/socket_wrapper.c
index 8408af7..d35e1ac 100644
--- a/src/socket_wrapper.c
+++ b/src/socket_wrapper.c
@@ -2388,6 +2388,26 @@ static int swrap_connect(int s, const struct sockaddr *serv_addr,
swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_RECV, NULL, 0);
swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_ACK, NULL, 0);
+
+ switch (si->family) {
+ case AF_INET: {
+ struct sockaddr_in *sin = (struct sockaddr_in *) si->myname;
+ if (sin->sin_addr.s_addr == htonl(INADDR_ANY)) {
+ sin->sin_addr.s_addr = htonl(0x7F000000 | socket_wrapper_default_iface());
+ }
+ break;
+ }
+#ifdef HAVE_IPV6
+ case AF_INET6: {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) si->myname;
+ struct in6_addr cmp6 = *swrap_ipv6();
+ if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &cmp6)) {
+ sin6->sin6_addr.s6_addr[15] = socket_wrapper_default_iface();
+ }
+ break;
+ }
+#endif
+ }
} else {
swrap_dump_packet(si, serv_addr, SWRAP_CONNECT_UNREACH, NULL, 0);
}
--
1.8.5.3
More information about the samba-technical
mailing list