rtorrent
rtorrent copied to clipboard
Security issue?
rtorrent 0.8.9/0.12.9 with ipv6 patch. My rtorrent crash with: rtorrent: Handshake::fill_read_buffer(...) Buffer overflow.
I'm using a selinux policy, so I took a look into audit.log: type=AVC msg=audit(1344800018.036:36614): avc: denied { read } for pid=24872 comm="rtorrent" name="cpuinfo" dev=proc ino=4026532030 scontext=unconfined_u:unconfined_r:rtorrent_t:s0 tcontext=system_u:object_r:proc_t:s0 tclass=file
Look like somebody tried hack my host. Unfortunately, there is no a core file. I haven't found any security issues for this case and believe the developer should know.
The exception catches reads beyond the end of the buffer, so there is no exploit possible.
And the bug is likely fixed in current release so closing.
The exception catches reads beyond the end of the buffer, so there is no exploit possible.
Yes, I know. That's just a sign something is wrong. The problem is the audit message: rtorrent trying get access to /proc/cpuinfo, which forbidden and never should happed for normal run. That is can do only some "introduced" code (exploit). Off course, it is possible that there was a piece of ipv6 code exploited, but i very doubt.
This happens after the stack has unwinded and the catch in rtorrent main prints out the message, so tr reproducing it by throwing exceptions and see if it gives the same selinux warning.
Do you advise me recompile rtorrent with hardcoded "throw"? Hardly an exception handler would search anything in /proc/cpuonfo.
Same issue in rTorrent 0.9.2/0.13.2
Same issue in 0.8.9/0.12.9. Why is this not an issue if rTorrent crashes? Is it possible to make rTorrent ignore reads beyond the buffer?
Crashs became pretty often and annoying. So i have checked futher versions and didn't find any changes which could fix the error (the message from Dmole confirms it). So here is a quick dirty fix which works for me and can be applied for the current version: http://pastebin.com/raw.php?i=6VBpYQyD
getting something similar 1445534229 C Caught internal_error: 'Handshake::fill_read_buffer(...) Buffer overflow.'. ---DUMP--- /opt/lib/libtorrent.so.19(_ZN7torrent14internal_error10initializeERKSs+0x202) [0x7f142eae6672] /opt/bin/p2pedia-delivery-agentrtorrent(_ZN7torrent14internal_errorC2EPKc+0x3e) [0x445f9e] /opt/lib/libtorrent.so.19(+0xbfa1a) [0x7f142eb73a1a] /opt/lib/libtorrent.so.19(+0xc2a5c) [0x7f142eb76a5c] /opt/lib/libtorrent.so.19(_ZN7torrent9PollEPoll7performEv+0xd7) [0x7f142eaf7a37] /opt/lib/libtorrent.so.19(_ZN7torrent9PollEPoll7do_pollEli+0x50) [0x7f142eaf7ae0] /opt/lib/libtorrent.so.19(ZN7torrent11thread_base10event_loopEPS0+0x11c) [0x7f142eb317ac] /opt/bin/rtorrent() [0x41216d] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf5) [0x7f142d6aaec5] /opt/bin/p2pedia-delivery-agentrtorrent() [0x4128b4]
---END---
The code makes sure at a low level that no security issuses will happen. For patches to fix related issues please inform me.
hi, what information do you need from my side?
This issue still happens to us once in a while, but it looks more like a problem with libtorrent. We use version 0.13.8.
I reviewed the protocol code to try to figure out what was causing the crash and I am a bit puzzled, because everything looks fine to me.
Most calls to Handshake::fill_read_buffer(int size)
are safe because they fall into one of these two categories:
-
size
is small enough that we know the buffer is always large enough - a check on
m_readBuffer.reserved_left()
is done beforehands andhandshake_error
is thrown if the buffer is too small
There are two exceptions, both in event_read()
:
case READ_ENC_PAD:
if (m_readPos) {
// Read padC + lenIA or padD; pad length in m_readPos.
if (!fill_read_buffer(m_readPos + (m_incoming ? 2 : 0)))
// This can be improved (consume as much as was read)
break;
This situation is indirectly handled in Handshake::read_encryption_negotiation()
, which ensures that m_readPos <= enc_pad_size
and throws handshake_error
otherwise.
And this is the second one:
case READ_ENC_IA:
// Just read (and automatically decrypt) the initial payload
// and leave it in the buffer for READ_INFO later.
if (m_encryption.length_ia() > 0 && !fill_read_buffer(m_encryption.length_ia()))
break;
This is also indirectly handled in Handshake::read_negotiation_reply()
, which ensures that m_encryption.length_ia() <= handshake_size
and throws handshake_error
otherwise.
Did I miss something maybe?