[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[tor-commits] [torsocks/master] Add recvmsg() FD passing check



commit eecc1152a9c86459081711240991991de2b24204
Author: David Goulet <dgoulet@xxxxxxxxx>
Date:   Wed Aug 7 11:17:54 2013 -0400

    Add recvmsg() FD passing check
    
    Signed-off-by: David Goulet <dgoulet@xxxxxxxxx>
---
 TODO                |    2 +-
 src/lib/Makefile.am |    2 +-
 src/lib/recv.c      |  100 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/lib/torsocks.h  |   13 +++++++
 4 files changed, 115 insertions(+), 2 deletions(-)

diff --git a/TODO b/TODO
index ad99fc2..fdd2365 100644
--- a/TODO
+++ b/TODO
@@ -1,7 +1,7 @@
 Version 2.0
 -----------
 * Support res_* API
-* Get sendmsg FD passing on Unix socket and for TCP socket, clean exit
+* Check recvmmsg() FD passing on Unix socket and for TCP socket, clean exit
 * Deny ICMP
 * Support the complete list of dangerous syscall number with syscall()
 
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index 0fe0233..f445c01 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -12,7 +12,7 @@ lib_LTLIBRARIES = libtorsocks.la
 
 libtorsocks_la_SOURCES = torsocks.c torsocks.h \
                          connect.c gethostbyname.c getaddrinfo.c close.c \
-                         getpeername.c socket.c syscall.c socketpair.c
+                         getpeername.c socket.c syscall.c socketpair.c recv.c
 
 libtorsocks_la_LIBADD = \
 		$(top_builddir)/src/common/libcommon.la \
diff --git a/src/lib/recv.c b/src/lib/recv.c
new file mode 100644
index 0000000..9a70dd3
--- /dev/null
+++ b/src/lib/recv.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2013 - David Goulet <dgoulet@xxxxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License, version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include <common/log.h>
+
+#include "torsocks.h"
+
+/*
+ * Torsocks call for recvmsg(2)
+ *
+ * We only hijack this call to handle the FD passing between process on Unix
+ * socket. If an INET/INET6 socket is recevied, we stop everything because at
+ * that point we can't guarantee traffic going through Tor.
+ */
+LIBC_RECVMSG_RET_TYPE tsocks_recvmsg(LIBC_RECVMSG_SIG)
+{
+	int fd;
+	ssize_t ret = 0;
+	char dummy, recv_fd[CMSG_SPACE(sizeof(fd))];
+	struct iovec iov[1];
+	struct cmsghdr *cmsg;
+	struct msghdr msg;
+
+	memset(&msg, 0, sizeof(msg));
+
+	/* Prepare to receive the structures */
+	iov[0].iov_base = &dummy;
+	iov[0].iov_len = 1;
+	msg.msg_iov = iov;
+	msg.msg_iovlen = 1;
+	msg.msg_control = recv_fd;
+	msg.msg_controllen = sizeof(recv_fd);
+
+	do {
+		/* Just peek the data to inspect the payload for fd. */
+		ret = tsocks_libc_recvmsg(__sockfd, &msg, MSG_PEEK);
+	} while (ret < 0 && errno == EINTR);
+
+	cmsg = CMSG_FIRSTHDR(&msg);
+	if (!cmsg) {
+		goto end;
+	}
+
+	/*
+	 * Detecting FD passing, the next snippet of code will check if we get a
+	 * inet/inet6 socket. If so, everything stops immediately before going
+	 * further.
+	 */
+	if (cmsg->cmsg_type == SCM_RIGHTS || cmsg->cmsg_level == SOL_SOCKET) {
+		socklen_t optlen;
+		int sock_dom;
+
+		memcpy(&fd, CMSG_DATA(cmsg), sizeof(fd));
+
+		/* Get socket domain. */
+		optlen = sizeof(sock_dom);
+		ret = getsockopt(fd, SOL_SOCKET, SO_DOMAIN, &sock_dom, &optlen);
+		if (ret < 0) {
+			/* Use the getsockopt() errno value. */
+			goto end;
+		}
+
+		if (sock_dom == AF_INET || sock_dom == AF_INET6) {
+			ERR("[recvmsg] Inet socket passing detected. Aborting everything! "
+					"A non Tor socket could be used thus leaking information.");
+			exit(EXIT_FAILURE);
+		}
+	}
+
+end:
+	return tsocks_libc_recvmsg(LIBC_RECVMSG_ARGS);
+}
+
+/*
+ * Libc hijacked symbol recvmsg(2).
+ */
+LIBC_RECVMSG_DECL
+{
+	/* Find symbol if not already set. Exit if not found. */
+	tsocks_libc_recvmsg = tsocks_find_libc_symbol(LIBC_RECVMSG_NAME_STR,
+			TSOCKS_SYM_EXIT_NOT_FOUND);
+	return tsocks_recvmsg(LIBC_RECVMSG_ARGS);
+}
diff --git a/src/lib/torsocks.h b/src/lib/torsocks.h
index 953446b..65edeba 100644
--- a/src/lib/torsocks.h
+++ b/src/lib/torsocks.h
@@ -161,6 +161,14 @@ struct hostent **__result, int *__h_errnop
 	int __sockfd, struct sockaddr *__addr, socklen_t *__addrlen
 #define LIBC_GETPEERNAME_ARGS  __sockfd, __addr, __addrlen
 
+#define LIBC_RECVMSG_NAME recvmsg
+#define LIBC_RECVMSG_NAME_STR XSTR(LIBC_RECVMSG_NAME)
+#define LIBC_RECVMSG_RET_TYPE ssize_t
+#define LIBC_RECVMSG_SIG \
+	int __sockfd, struct msghdr *__msg, int __flags
+#define LIBC_RECVMSG_ARGS \
+	__sockfd, __msg, __flags
+
 #else
 #error "OS not supported."
 #endif /* __linux__ , __FreeBSD__, __darwin__ */
@@ -191,6 +199,11 @@ TSOCKS_DECL(connect, LIBC_CONNECT_RET_TYPE, LIBC_CONNECT_SIG)
 #define LIBC_CONNECT_DECL \
 	LIBC_CONNECT_RET_TYPE LIBC_CONNECT_NAME(LIBC_CONNECT_SIG)
 
+/* recvmsg(2) */
+TSOCKS_LIBC_DECL(recvmsg, LIBC_RECVMSG_RET_TYPE, LIBC_RECVMSG_SIG)
+#define LIBC_RECVMSG_DECL \
+		LIBC_RECVMSG_RET_TYPE LIBC_RECVMSG_NAME(LIBC_RECVMSG_SIG)
+
 /* socket(2) */
 TSOCKS_LIBC_DECL(socket, LIBC_SOCKET_RET_TYPE, LIBC_SOCKET_SIG)
 TSOCKS_DECL(socket, LIBC_SOCKET_RET_TYPE, LIBC_SOCKET_SIG)



_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits