Index | Thread | Search

From:
Jan Stary <hans@stare.cz>
Subject:
Re: rtorrent crashes
To:
"Thomas L." <tom.longshine@web.de>
Cc:
Klemens Nanni <kn@openbsd.org>, "Anthony J. Bentley" <bentley@openbsd.org>, ports@openbsd.org
Date:
Mon, 25 Aug 2025 19:27:17 +0200

Download raw body.

Thread
Thank you, this makes rtorrent no longer crash on my amd64

Jan

On Aug 25 16:42:52, tom.longshine@web.de wrote:
> i recently hit the same bug, did a ktrace(1) and found the following
> 
>  61086 rtorrent CALL  socket(AF_INET6,0x2<SOCK_DGRAM>,0)
>  61086 rtorrent RET   socket 16/0x10
>  61086 rtorrent CALL  setsockopt(16,41<ipv6>,27,0x71f9b0bf3e24,4)
>  61086 rtorrent RET   setsockopt -1 errno 22 Invalid argument
>  61086 rtorrent CALL  kbind(0x71f9b0bf3d30,24,0xa7ad56a04777c55)
>  61086 rtorrent RET   kbind 0
>  61086 rtorrent CALL  close(16)
>  61086 rtorrent RET   close 0
>  61086 rtorrent CALL  close(16)
>  61086 rtorrent RET   close -1 errno 9 Bad file descriptor
> 
> so i set a breakpoint on setsockopt(2) and found in libtorrents
> src/net/socket_fd.cc
> 
> bool
> SocketFd::set_ipv6_v6only(bool state) {
>   check_valid();
> 
>   if (!m_ipv6_socket)
>     return false;
> 
>   int opt = state;
>   return setsockopt(m_fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)) == 0;
> }
> 
> bool
> SocketFd::open_datagram() {
>   m_fd = socket(rak::socket_address::pf_inet6, SOCK_DGRAM, 0);
> 
>   if (m_fd == -1) {
>     m_ipv6_socket = false;
>     return (m_fd = socket(rak::socket_address::pf_inet, SOCK_DGRAM, 0)) != -1;
>   }
> 
>   m_ipv6_socket = true;
> 
>   if (!set_ipv6_v6only(false)) {
>     close();
>     return false;
>   }
> 
>   return true;
> }
> 
> OpenBSD does not support dualstack sockets, so setting IPV6_V6ONLY to
> false fails. instead of using two sockets or at least falling back to
> IPv4-only, libtorrent gives up completely and closes the socket.
> however, m_fd is not set to -1, so later in TrackerUdp::close_directly()
> SocketFd::is_valid() returns true and SocketFd::close() is called again,
> which leads to the crash.
> 
> the patch below changes SocketFd::open_datagram() to fall back to IPv4,
> like already done for SocketFd::open_stream(). proper dualstack support
> would need a bigger refactoring.
> 
> diff --git net/libtorrent/Makefile net/libtorrent/Makefile
> index 7bd433cd6b5..880218060e1 100644
> --- net/libtorrent/Makefile
> +++ net/libtorrent/Makefile
> @@ -7,7 +7,7 @@ BROKEN-sh =		undefined references to __sync atomic ops
>  NOT_FOR_ARCHS=		${GCC3_ARCHS}
>  
>  DISTNAME=		libtorrent-0.14.0
> -REVISION=		1
> +REVISION=		2
>  EPOCH=			0
>  SHARED_LIBS +=  	torrent 22.1	# .18.0
>  CATEGORIES=		net devel
> diff --git net/libtorrent/patches/patch-src_net_socket_fd_cc net/libtorrent/patches/patch-src_net_socket_fd_cc
> index 7f0b78aa71f..ad7dc8c1350 100644
> --- net/libtorrent/patches/patch-src_net_socket_fd_cc
> +++ net/libtorrent/patches/patch-src_net_socket_fd_cc
> @@ -1,7 +1,7 @@
>  Index: src/net/socket_fd.cc
>  --- src/net/socket_fd.cc.orig
>  +++ src/net/socket_fd.cc
> -@@ -126,21 +126,8 @@ SocketFd::get_error() const {
> +@@ -126,40 +126,14 @@ SocketFd::get_error() const {
>   
>   bool
>   SocketFd::open_stream() {
> @@ -25,3 +25,24 @@ Index: src/net/socket_fd.cc
>   }
>   
>   bool
> + SocketFd::open_datagram() {
> +-  m_fd = socket(rak::socket_address::pf_inet6, SOCK_DGRAM, 0);
> +-
> +-  if (m_fd == -1) {
> +-    m_ipv6_socket = false;
> +-    return (m_fd = socket(rak::socket_address::pf_inet, SOCK_DGRAM, 0)) != -1;
> +-  }
> +-
> +-  m_ipv6_socket = true;
> +-
> +-  if (!set_ipv6_v6only(false)) {
> +-    close();
> +-    return false;
> +-  }
> +-
> +-  return true;
> ++  m_ipv6_socket = false;
> ++  return (m_fd = socket(rak::socket_address::pf_inet, SOCK_DGRAM, 0)) != -1;
> + }
> + 
> + bool
> 
>