Merge remote-tracking branch 'origin/maint-0.2.2'

This commit is contained in:
Nick Mathewson 2011-12-21 11:20:56 -05:00
commit f75660958c
2 changed files with 18 additions and 17 deletions

8
changes/bug1240 Normal file
View File

@ -0,0 +1,8 @@
o Minor bugfixes:
- When running with an older Linux kernel that erroneously responds
to strange nmap behavior by having accept() return successfully
with a zero-length socket, just close the connection. Previously,
we would try harder to learn the remote address: but there was no
such remote address to learn, and our method for trying to learn
it was incorrect. Fixes bugs #1240, #4745, and #4747. Bugfix on
0.1.0.3-rc. Reported and diagnosed by "r1eo".

View File

@ -1051,7 +1051,12 @@ connection_create_listener(const struct sockaddr *listensockaddr,
}
/** Do basic sanity checking on a newly received socket. Return 0
* if it looks ok, else return -1. */
* if it looks ok, else return -1.
*
* Notably, some TCP stacks can erroneously have accept() return successfully
* with socklen 0, when the client sends an RST before the accept call (as
* nmap does). We want to detect that, and not go on with the connection.
*/
static int
check_sockaddr(struct sockaddr *sa, int len, int level)
{
@ -1117,7 +1122,7 @@ connection_handle_listener_read(connection_t *conn, int new_type)
tor_socket_t news; /* the new socket */
connection_t *newconn;
/* information about the remote peer when connecting to other routers */
char addrbuf[256];
char addrbuf[256]; /*XXX023 use sockaddr_storage instead*/
struct sockaddr *remote = (struct sockaddr*)addrbuf;
/* length of the remote address. Must be whatever accept() needs. */
socklen_t remotelen = (socklen_t)sizeof(addrbuf);
@ -1161,22 +1166,10 @@ connection_handle_listener_read(connection_t *conn, int new_type)
uint16_t port;
if (check_sockaddr(remote, remotelen, LOG_INFO)<0) {
log_info(LD_NET,
"accept() returned a strange address; trying getsockname().");
remotelen=sizeof(addrbuf);
memset(addrbuf, 0, sizeof(addrbuf));
if (getsockname(news, remote, &remotelen)<0) {
int e = tor_socket_errno(news);
log_warn(LD_NET, "getsockname() for new connection failed: %s",
tor_socket_strerror(e));
} else {
if (check_sockaddr((struct sockaddr*)addrbuf, remotelen,
LOG_WARN) < 0) {
log_warn(LD_NET,"Something's wrong with this conn. Closing it.");
"accept() returned a strange address; closing connection.");
tor_close_socket(news);
return 0;
}
}
}
if (check_sockaddr_family_match(remote->sa_family, conn) < 0) {
tor_close_socket(news);