Skip to contentSkip to conversation

net/ipv4: commit d0733d2e29b breaks rtorrent

DISCUSSION Fabienne Ducroquet 4 participants 7 messages Jun 22, 2011

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

Hi,

With the latest versions of the Linux kernel (I've just tried 3.0.0-rc4-00034-g2992c4b) rtorrent (version 0.8.7 with libtorrent 0.12.7, from Debian unstable) fails to start with the error message:

rtorrent: Could not open/bind port for listening: Invalid argument

I bisected it down to:

	commit d0733d2e29b652b2e7b1438ececa732e4eed98eb
	Author: Marcus Meissner <[email protected]>
	Date:   Wed Jun 1 21:05:22 2011 -0700

	    net/ipv4: Check for mistakenly passed in non-IPv4 address

	    Check against mistakenly passing in IPv6 addresses (which would result
	    in an INADDR_ANY bind) or similar incompatible sockaddrs.

	    Signed-off-by: Marcus Meissner <[email protected]>
	    Cc: Reinhard Max <[email protected]>
	    Signed-off-by: David S. Miller <[email protected]>
	---
	 net/ipv4/af_inet.c |    3 +++
	 1 files changed, 3 insertions(+), 0 deletions(-)

	diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
	index cc14631..9c19260 100644
	--- a/net/ipv4/af_inet.c
	+++ b/net/ipv4/af_inet.c
	@@ -465,6 +465,9 @@ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
		if (addr_len < sizeof(struct sockaddr_in))
			goto out;

	+       if (addr->sin_family != AF_INET)
	+               goto out;
	+
		chk_addr_ret = inet_addr_type(sock_net(sk), addr->sin_addr.s_addr);

		/* Not specified by any standard per-se, however it breaks too

With this commit reverted rtorrent works again.

Fabienne

#1 lore raw
Quoted 41 lines · Fabienne Ducroquet

Hi,

With the latest versions of the Linux kernel (I've just tried 3.0.0-rc4-00034-g2992c4b) rtorrent (version 0.8.7 with libtorrent 0.12.7, from Debian unstable) fails to start with the error message:

rtorrent: Could not open/bind port for listening: Invalid argument

I bisected it down to:

	commit d0733d2e29b652b2e7b1438ececa732e4eed98eb
	Author: Marcus Meissner <[email protected]>
	Date:   Wed Jun 1 21:05:22 2011 -0700

	    net/ipv4: Check for mistakenly passed in non-IPv4 address

	    Check against mistakenly passing in IPv6 addresses (which would result
	    in an INADDR_ANY bind) or similar incompatible sockaddrs.

	    Signed-off-by: Marcus Meissner <[email protected]>
	    Cc: Reinhard Max <[email protected]>
	    Signed-off-by: David S. Miller <[email protected]>
	---
	 net/ipv4/af_inet.c |    3 +++
	 1 files changed, 3 insertions(+), 0 deletions(-)

	diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
	index cc14631..9c19260 100644
	--- a/net/ipv4/af_inet.c
	+++ b/net/ipv4/af_inet.c
	@@ -465,6 +465,9 @@ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
		if (addr_len < sizeof(struct sockaddr_in))
			goto out;

	+       if (addr->sin_family != AF_INET)
	+               goto out;
	+
		chk_addr_ret = inet_addr_type(sock_net(sk), addr->sin_addr.s_addr);

		/* Not specified by any standard per-se, however it breaks too
Quoted 1 line

With this commit reverted rtorrent works again.

Can you show us the code surrounding the bind in rtorrent?

You either do not set the sin_family member, or pass in a ipv6 address.

Ciao, Marcus

#2 lore raw

Hi,

Quoted 1 line · Marcus Meissner

Can you show us the code surrounding the bind in rtorrent?

... or short of that, the output of "strace -e socket,bind" when starting rtorrent with the kernel patch not reverted?

cu
Reinhard

#3 lore raw
Quoted 3 lines · Reinhard Max
Quoted 1 line · Marcus Meissner

Can you show us the code surrounding the bind in rtorrent?

Since I'm not a developer of rtorrent I'm not sure what the right code to show is, so I leave that to the developer of libtorrent/rtorrent, he is CC'ed.

Quoted 2 lines

... or short of that, the output of "strace -e socket,bind" when starting rtorrent with the kernel patch not reverted?

Here it is :

socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP) = -1 EAFNOSUPPORT (Address family not supported by protocol)
socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) = 5
bind(5, {sa_family=AF_INET6, sin6_port=htons(6903), inet_pton(AF_INET6, "::", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, 28) = -1 EINVAL (Invalid argument)

[ 95 lines with only the number in parentheses after htons changing ]

bind(5, {sa_family=AF_INET6, sin6_port=htons(6999), inet_pton(AF_INET6, "::", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, 28) = -1 EINVAL (Invalid argument) socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP) = -1 EAFNOSUPPORT (Address family not supported by protocol)
socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) = 5
bind(5, {sa_family=AF_INET6, sin6_port=htons(6881), inet_pton(AF_INET6, "::", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, 28) = -1 EINVAL (Invalid argument)

[ 21 lines with only the number in parentheses after htons changing ]

bind(5, {sa_family=AF_INET6, sin6_port=htons(6903), inet_pton(AF_INET6, "::", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, 28) = -1 EINVAL (Invalid argument)

If I understand correctly, it is trying to bind an IPv6 address to a socket expecting an IPv4 address, so it's a bug in libtorrent/rtorrent, but it was not visible before because an INADDR_ANY bind is not a problem for rtorrent?

Fabienne

#4 lore raw
Quoted 1 line · Fabienne Ducroquet

If I understand correctly, it is trying to bind an IPv6 address to a socket expecting an IPv4 address, so it's a bug in libtorrent/rtorrent, but it was not visible before because an INADDR_ANY bind is not a problem for rtorrent?

Yes, exactly.

cu
Reinhard

#5 lore raw
Quoted 8 lines · On Wed, 22 Jun 2011 16:58:24 +0200 (CEST) Reinhard Max <[email protected]> wrote:
Quoted 4 lines · Fabienne Ducroquet

If I understand correctly, it is trying to bind an IPv6 address to a socket expecting an IPv4 address, so it's a bug in libtorrent/rtorrent, but it was not visible before because an INADDR_ANY bind is not a problem for rtorrent?

Quoted 5 lines

Yes, exactly.

cu
Reinhard

You can find code here http://libtorrent.rakshasa.no/
but it is in C++ so there is an abnormally high indirection factor between reality of the bug and the code as written.

Did you try contacting the developer?

#6 lore raw
Quoted 3 lines · Stephen Hemminger

You can find code here http://libtorrent.rakshasa.no/
but it is in C++ so there is an abnormally high indirection factor between reality of the bug and the code as written.

I had a look at the code, I found where bind is called, but it does not
help: it is in libtorrent/src/net/socket_fd.cc:

	bool
	SocketFd::bind(const rak::socket_address& sa) {
	  check_valid();
	
	  return !::bind(m_fd, sa.c_sockaddr(), sa.length());
	}

check_valid() checks the validity of the socket FD. It is called by the function:

	bool
	Listen::open(uint16_t first, uint16_t last, const rak::socket_address* bindAddress) {
	  close();

	  [ Checks that the range of the ports is OK, that the address 
	  is an inet or inet6 address, that the socket can be 
	  allocated.]

	  rak::socket_address sa;
	  sa.copy(*bindAddress, bindAddress->length());

	  for (uint16_t i = first; i <= last; ++i) {
	  sa.set_port(i);

	  if (get_fd().bind(sa) && get_fd().listen(50)) {
	     ...

in libtorrent/src/net/listen.cc. That function was called by:

	bool
	ConnectionManager::listen_open(port_type begin, port_type end) {
	  if (!m_listen->open(begin, end, rak::socket_address::cast_from(m_bindAddress)))
	    return false;
	
	  m_listenPort = m_listen->port();
	
	  return true;
	}

in libtorrent/src/torrent/connection_manager.cc, and it was itself called by Manager::listen_open() in rtorrent/core/manager.cc, which throws the error message I got because the call to

	torrent::connection_manager()->listen_open(portFirst, portLast)

fails.

So the question now is to find how the m_bindAddress used in ConnectionManager::listen_open is set, but I prefer not to do that right now.

Quoted 1 line

Did you try contacting the developer?

I've put him in the Cc: since the first message.

Fabienne