commit eecc1152a9c86459081711240991991de2b24204 Author: David Goulet <dgou...@ev0ke.net> Date: Wed Aug 7 11:17:54 2013 -0400
Add recvmsg() FD passing check Signed-off-by: David Goulet <dgou...@ev0ke.net> --- 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 <dgou...@ev0ke.net> + * + * 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@lists.torproject.org https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits