Opened 4 years ago

Closed 3 years ago

Last modified 3 years ago

#5002 closed Bug (fixed)

crash in UTP_ProcessIncoming()

Reported by: davidak Owned by: jordan
Priority: Highest Milestone: 2.74
Component: libtransmission Version: 2.61
Severity: Critical Keywords: crash, os x, mac
Cc: thomas_reardon@…

Description

Transmission crashes after some time downloading and seeding (188 Torrents, not all active). also after update to 2.6.1

here is the os x crash report, hope that helps: http://pastebay.net/1069667

not found a related ticket, merge if there is one.

Attachments (2)

libutp.diff (797 bytes) - added by reardon 3 years ago.
RESENDS_MAX_COUNT.diff (2.0 KB) - added by cfpp2p 3 years ago.

Download all attachments as: .zip

Change History (36)

comment:1 Changed 4 years ago by jordan

Thread 2 Crashed:
0   libSystem.B.dylib                   0x00007fff861969ce __semwait_signal_nocancel + 10
1   libSystem.B.dylib                   0x00007fff861968d0 nanosleep$NOCANCEL + 129
2   libSystem.B.dylib                   0x00007fff861f33ce usleep$NOCANCEL + 57
3   libSystem.B.dylib                   0x00007fff862129a1 __abort + 113
4   libSystem.B.dylib                   0x00007fff861f6ff8 release_file_streams_for_task + 0
5   org.m0k.transmission                0x00000001000abc35 0x100000000 + 703541
6   ???                                 0x0000b14d0000b14e 0 + 194944270643534

I'm not sure what to do with this, the last waypoint before the crash appears to be release_file_streams_for_task(), which Google hints is a Mac system call. There don't seem to be any Transmission calls in this crash trace to indicate where in Transmission's code the crash occurred.

BMW, any ideas on release_file_streams_for_task()?

comment:2 Changed 4 years ago by davidak

it repeats every time i start. the most crash reports are identical to the first, this one has some more rows on thread 2:

Thread 2 Crashed:
0   libSystem.B.dylib                   0x00007fff861969ce __semwait_signal_nocancel + 10
1   libSystem.B.dylib                   0x00007fff861968d0 nanosleep$NOCANCEL + 129
2   libSystem.B.dylib                   0x00007fff861f33ce usleep$NOCANCEL + 57
3   libSystem.B.dylib                   0x00007fff862129a1 __abort + 113
4   libSystem.B.dylib                   0x00007fff861f6ff8 release_file_streams_for_task + 0
5   org.m0k.transmission                0x00000001000abc35 0x100000000 + 703541
6   org.m0k.transmission                0x00000001000ac4f5 0x100000000 + 705781
7   org.m0k.transmission                0x00000001000ad121 0x100000000 + 708897
8   org.m0k.transmission                0x000000010008bb43 0x100000000 + 572227
9   org.m0k.transmission                0x000000010008b986 0x100000000 + 571782
10  org.m0k.transmission                0x0000000100099cb3 0x100000000 + 629939
11  org.m0k.transmission                0x000000010006f527 0x100000000 + 455975
12  org.m0k.transmission                0x0000000100065b40 0x100000000 + 416576
13  libSystem.B.dylib                   0x00007fff8615cfd6 _pthread_start + 331
14  libSystem.B.dylib                   0x00007fff8615ce89 thread_start + 13

http://pastebay.net/1069671
http://pastebay.net/1069673

are these 0x* numbers adresses on the ram?

i couldn't use it any more. where can i download a previous version that works? 2.42 seams me to old.

here a version for snow leopard: https://trac.transmissionbt.com/wiki/PreviousReleases

i send the reports to apple, so if there is a problem on there side it should be fixed after some month or years :D

comment:3 follow-up: Changed 4 years ago by x190

davidak: Please test using the latest nightly and post the CR if you get one.

https://build.transmissionbt.com/job/trunk-mac/

comment:4 in reply to: ↑ 3 Changed 4 years ago by davidak

Replying to x190: thanks for your answer.

this seams to have more information: http://pastebay.net/1069690

comment:5 Changed 4 years ago by jordan

  • Component changed from Mac Client to libtransmission
  • Owner changed from livings124 to jordan
  • Status changed from new to assigned
Thread 2 Crashed:
0   libSystem.B.dylib                   0x00007fff861969ce __semwait_signal_nocancel + 10
1   libSystem.B.dylib                   0x00007fff861968d0 nanosleep$NOCANCEL + 129
2   libSystem.B.dylib                   0x00007fff861f33ce usleep$NOCANCEL + 57
3   libSystem.B.dylib                   0x00007fff862129a1 __abort + 113
4   libSystem.B.dylib                   0x00007fff861f6ff8 release_file_streams_for_task + 0
5   org.m0k.transmission                0x00000001000c2986 UTPSocket::selective_ack(unsigned int, unsigned char const*, unsigned char) + 724
6   org.m0k.transmission                0x00000001000c333d UTP_ProcessIncoming(UTPSocket*, unsigned char const*, unsigned long, bool) + 1689
7   org.m0k.transmission                0x00000001000c4300 UTP_IsIncomingUTP + 488
8   org.m0k.transmission                0x0000000100099b05 tr_utpPacket + 142
9   org.m0k.transmission                0x000000010009990a event_callback + 330
10  org.m0k.transmission                0x00000001000aa1b5 event_base_loop + 1149
11  org.m0k.transmission                0x00000001000780ca libeventThreadFunc + 145
12  org.m0k.transmission                0x000000010006d7ba ThreadFunc + 15
13  libSystem.B.dylib                   0x00007fff8615cfd6 _pthread_start + 331
14  libSystem.B.dylib                   0x00007fff8615ce89 thread_start + 13

x190, thanks for the suggestion :)

davidak, short-term workaround: disable uTP in the Preferences dialog

comment:6 Changed 4 years ago by x190

See also #4935 and #4960.

comment:7 Changed 4 years ago by jordan

  • Summary changed from crash after some minutes on OS X 10.6.8 to crash in UTP_ProcessIncoming()

comment:8 Changed 4 years ago by livings124

#5044 appears to be a duplicate, and has more information.

comment:9 Changed 4 years ago by reardon

Agree, is likely a dup, though not certain. Should add that I was on debian/linux, so this is not platform specific. Also in my case: 800+ torrents, ~10 active.

comment:10 Changed 4 years ago by reardon

  • Cc thomas_reardon@… added

comment:11 Changed 4 years ago by livings124

#5062 appears to be a duplicate of this as well.

comment:12 Changed 4 years ago by hohum

This is happening to me too on FreeBSD 9.0-RELEASE

UTP_ProcessIncoming (conn=0xc4420000c443, packet=0xc43e0000c43f <Error reading address 0xc43e0000c43f: Bad address>, len=Variable "len" is not available. ) at utp.cpp:2111 2111 if (conn->state == CS_CONNECTED_FULL && conn->is_writable(conn->get_packet_size())) {

comment:13 Changed 4 years ago by x190

"Bad address>, len=Variable "len" is not available. ) at utp.cpp:2111 2111 if (conn->state == CS_CONNECTED_FULL && conn->is_writable(conn->get_packet_size())) { "

if( !len )

return 0;


Last edited 4 years ago by x190 (previous) (diff)

comment:14 Changed 4 years ago by reardon

Hmm, a bit more info this time. 'nr' got corrupted somehow, it now holds a sequence number instead of the resends index. Judging from the code and where I'm guess 'nr' sits on the stack, a prior write to resends[nr] actually went past array limit and overwrote 'nr' with bogus value. I can't see how there is any protection against this in the code--'nr' is incremented without any checks.

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffff6082700 (LWP 24793)]
0x000000000045578e in UTPSocket::selective_ack (this=0x7ffff01a5ea0, base=31488, mask=0x7ffff6080de6 "", len=10 '\n') at utp.cpp:157
5
1575                            resends[nr++] = v;
(gdb) bt
#0  0x000000000045578e in UTPSocket::selective_ack (this=0x7ffff01a5ea0, base=31488, mask=0x7ffff6080de6 "", len=10 '\n') at utp.cpp
:1575
#1  0x0000000000456ad6 in UTP_ProcessIncoming (conn=0x7ffff01a5ea0, packet=0x7ffff6080dd0 "!\001\225a\025\020dT\223\233\302\371\006?
\"\252\362\365z\376", len=32, syn=false) at utp.cpp:2120
#2  0x0000000000457ede in UTP_IsIncomingUTP (incoming_proc=0x41e600 <incoming>, send_to_proc=0x41e6e0 <tr_utpSendTo>, send_to_userda
ta=0x6780f0, buffer=0x7ffff6080dd0 "!\001\225a\025\020dT\223\233\302\371\006?\"\252\362\365z\376", len=32, to=0x7ffff6080d50, tolen=
tolen@entry=16) at utp.cpp:2601
#3  0x000000000041e784 in tr_utpPacket (buf=buf@entry=0x7ffff6080dd0 "!\001\225a\025\020dT\223\233\302\371\006?\"\252\362\365z\376",
 buflen=buflen@entry=32, from=from@entry=0x7ffff6080d50, fromlen=16, ss=ss@entry=0x6780f0) at tr-utp.c:179
#4  0x000000000041dcf4 in event_callback (s=<optimized out>, type=<optimized out>, sv=0x6780f0) at tr-udp.c:225
#5  0x00007ffff799f0c4 in event_process_active_single_queue (activeq=0x67a760, base=0x678930) at event.c:1346
#6  event_process_active (base=<optimized out>) at event.c:1416
#7  event_base_loop (base=base@entry=0x678930, flags=flags@entry=0) at event.c:1617
#8  0x00007ffff79a0187 in event_base_dispatch (event_base=event_base@entry=0x678930) at event.c:1446
#9  0x000000000041efa0 in libeventThreadFunc (veh=0x678770) at trevent.c:248
#10 0x000000000041028a in ThreadFunc (_t=0x6787f0) at platform.c:118
#11 0x00007ffff6a58b50 in start_thread () from /lib/x86_64-linux-gnu/libpthread.so.0
#12 0x00007ffff67a370d in clone () from /lib/x86_64-linux-gnu/libc.so.6
#13 0x0000000000000000 in ?? ()

(gdb) p len
$1 = 10 '\n'
(gdb) p nr
$2 = 31515
(gdb) p v
$3 = 31513

(gdb) p base
$17 = 31488
(gdb) p *mask
$18 = 0 '\000'
(gdb) p len
$19 = 10 '\n'
(gdb) p bits
$20 = 25
(gdb) p cur_window_packets
$21 = 123
(gdb) p count
$22 = 8
(gdb) p fast_resend_seq_nr
$23 = 31487

(gdb) p seq_nr
$26 = 31610
(gdb) p bit_set
$27 = false
(gdb) p pkt
$28 = (OutgoingPacket *) 0x7ffff01930e0
(gdb) p *pkt
$29 = {length = 1402, payload = 1382, time_sent = 3128907897081, transmissions = 1, need_resend = false, data = "\001"}

(gdb) p duplicate_ack
$31 = 2 '\002'
(gdb) p resends
$32 = {31561, 31560, 31559, 31558, 31557, 31556, 31555, 31554, 31553, 31552, 31551, 31550, 31549, 31548, 31546, 31545, 31544, 31543, 31542, 31541, 31540, 31539, 31538, 31537, 31536, 31535, 31534, 31533, 31532, 31531, 31530, 31529}

comment:15 follow-up: Changed 4 years ago by reardon

Minutes later I got this one

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffff6082700 (LWP 610)]
0x0000000000455822 in UTPSocket::selective_ack (this=0x7ffff3f5d530, base=62562, mask=0x7ffff6080de6 "", len=6 '\006') at utp.cpp:1598
1598                    uint v = resends[--nr];
(gdb) bt
#0  0x0000000000455822 in UTPSocket::selective_ack (this=0x7ffff3f5d530, base=62562, mask=0x7ffff6080de6 "", len=6 '\006') at utp.cpp:1598
#1  0x0000000000456ad6 in UTP_ProcessIncoming (conn=0x7ffff3f5d530, packet=0x7ffff6080dd0 "!\001\004\233\200O\002\037\223\242f\251\006>?\356eV\364`", len=28, syn=false) at utp.cpp:2120
#2  0x0000000000457ede in UTP_IsIncomingUTP (incoming_proc=0x41e600 <incoming>, send_to_proc=0x41e6e0 <tr_utpSendTo>, send_to_userdata=0x6780f0, buffer=0x7ffff6080dd0 "!\001\004\233\200O\002\037\223\242f\251\006>?\356eV\364`", len=28, to=0x7ffff6080d50, tolen=tolen@entry=16) at utp.cpp:2601
#3  0x000000000041e784 in tr_utpPacket (buf=buf@entry=0x7ffff6080dd0 "!\001\004\233\200O\002\037\223\242f\251\006>?\356eV\364`", buflen=buflen@entry=28, from=from@entry=0x7ffff6080d50, fromlen=16, ss=ss@entry=0x6780f0) at tr-utp.c:179
#4  0x000000000041dcf4 in event_callback (s=<optimized out>, type=<optimized out>, sv=0x6780f0) at tr-udp.c:225
#5  0x00007ffff799f0c4 in event_process_active_single_queue (activeq=0x67a760, base=0x678930) at event.c:1346
#6  event_process_active (base=<optimized out>) at event.c:1416
#7  event_base_loop (base=base@entry=0x678930, flags=flags@entry=0) at event.c:1617
#8  0x00007ffff79a0187 in event_base_dispatch (event_base=event_base@entry=0x678930) at event.c:1446
#9  0x000000000041efa0 in libeventThreadFunc (veh=0x678770) at trevent.c:248
#10 0x000000000041028a in ThreadFunc (_t=0x6787f0) at platform.c:118
#11 0x00007ffff6a58b50 in start_thread () from /lib/x86_64-linux-gnu/libpthread.so.0
#12 0x00007ffff67a370d in clone () from /lib/x86_64-linux-gnu/libc.so.6
#13 0x0000000000000000 in ?? ()
(gdb) p nr
$33 = 62561
(gdb) p resends
$34 = {62606, 62605, 62604, 62603, 62602, 62601, 62600, 62599, 62598, 62597, 62596, 62595, 62594, 62593, 62592, 62591, 62590, 62589, 62588, 62587, 62586, 62585, 62584, 62583, 62582, 62581, 62580, 62579, 62578, 62577, 62576, 62575}
(gdb) p count
$35 = 3

comment:16 Changed 4 years ago by x190

Q:Who's responsible for libutp? Shouldn't someone pass on this information?

A:libutp - The uTorrent Transport Protocol library. Copyright (c) 2010 BitTorrent?, Inc.

Quote of the Day:The libutp API is considered unstable, and probably always will be.

Last edited 4 years ago by x190 (previous) (diff)

comment:17 in reply to: ↑ 15 Changed 4 years ago by reardon

Another one, with slightly more info. I set an abort() if nr>31, which it is here. I can't unravel this code, it's quite ugly, but just seems wrong to have an unchecked constant (32) for the array size of resends[]. Why hard-coded?? Almost seems intentional, as this can be exploited by some clever seq number to corrupt the stack and lead to code execution (ie, this is a serious bug).

Program received signal SIGINT, Interrupt.
[Switching to Thread 0x7ffff6082700 (LWP 23874)]
0x00007ffff6a60efb in raise () from /lib/x86_64-linux-gnu/libpthread.so.0
(gdb) n
Single stepping until exit from function raise,
which has no line number information.
UTPSocket::selective_ack (this=this@entry=0x7fffe81f0a70, base=base@entry=38753, mask=mask@entry=0x7ffff6080de6 "\002", len=<optimized out>) at utp.cpp:1577
1577                            resends[nr++] = v;
(gdb) p nr
$1 = 32
(gdb) p count
$2 = 6
(gdb) p bits
$3 = 19
(gdb) p len
$4 = <optimized out>
(gdb) p resends
$5 = {38804, 38803, 38802, 38801, 38800, 38799, 38798, 38797, 38796, 38795, 38794, 38793, 38792, 38791, 38790, 38789, 38788, 38787, 38786, 38785, 38784, 38783, 38782, 38781, 38780, 38779, 38778, 38777, 38776, 38775, 38774, 38773}
(gdb) p v
$6 = 38772
(gdb) p bit_set
$7 = <optimized out>
(gdb) p base
$8 = 38753
(gdb) p seq_nr
$9 = 38812
(gdb) p cur_window_packets
$10 = 60
(gdb) p pkt
$11 = (OutgoingPacket *) 0x0
(gdb) p *pkt
Cannot access memory at address 0x0
(gdb) p mask[0]
$12 = 2 '\002'
(gdb) p mask[1]
$13 = 0 '\000'
(gdb) p mask[2]
$15 = 0 '\000'
(gdb) p fast_resend_seq_nr
$16 = 38752
(gdb) p duplicate_ack
$17 = 0 '\000'

Changed 3 years ago by reardon

comment:18 Changed 3 years ago by reardon

I posted this on #5052, reposting here:

As I've said elsewhere, the libutp code is, um, dense, and I don't have the time to pull it apart. I made one change which seems to isolate the problem, which is in the resend acknowledgement logic. There is a hard-coded resend ack window, which seems awfully fishy.

Anyone with sufficient hacking skills will see how trivial it is to exploit this. It is seriously dangerous.

The attachment just throws a signal whenever the situation arises. You can "set nr=0" and continue, which just corrupts the ack packets, but so be it.

Wish we could get the libutp folks to maintain...

comment:19 follow-up: Changed 3 years ago by cfpp2p

attachment libutp.diff Download added

Thanks reardon !

good work (.around->set nr=0). I'll try to take a look at the dense code (i.e. Wish we could get the libutp folks to maintain... ). With your help so far (appreciated ) and what we have already, maybe a fix can be attained in due time, I'll try but it will take time...

comment:20 in reply to: ↑ 19 Changed 3 years ago by x190

Replying to cfpp2p:

Wish we could get the libutp folks to maintain...

For the love of Pete, nobody's reported the issue to them! Here's where and how.

https://github.com/bittorrent/libutp/issues/37

comment:21 Changed 3 years ago by cfpp2p

here is another UTPSocket::selective_ack crash

https://forum.transmissionbt.com/viewtopic.php?f=4&t=13894&hilit=%5Bthe+and%5D&sid=fd157648563da175d9dd1c7ae06b3723#p62712

Thread 2 Crashed:
0 org.m0k.transmission 0x000ca4c2 UTPSocket::send_packet(OutgoingPacket*) + 12
1 org.m0k.transmission 0x000cb394 UTPSocket::selective_ack(unsigned int, unsigned char const*, unsigned char) + 504
2 ??? 0x00000794 0 + 1940

Resend overflow in selective_ack() by reardonia November 29, 2012 https://github.com/bittorrent/libutp/issues/38

Last edited 3 years ago by cfpp2p (previous) (diff)

comment:22 Changed 3 years ago by reardon

Ok, I've spent a few hours in the code. There are several problems. Most importantly, selective_ack() seems only designed to handle 32 acks, or 4 bytes of ack mask bits. You will note that in every crash, the selective_ack data is more than 4 bytes.

A close reading of BEP29 says the mask must be a multiple of 4 bytes, but is not limited to 4 bytes. Real traffic, ie uTorrent, seems to send whatever size it wants. *BUT* the spec only has one byte for extension length, which limits the effective size of the mask to 255 bytes, or 252 in the modulo-4 case. This yields an upper limit of 2040 mask bits.

The overkill solution (I'm testing) just increases the size to resends[2040] on the stack. That will stop crashes for now. It needs a better solution. Seems like the resends[] buffer should be allocated in struct UTPSocket, as I don't think there is any chance of re-entrance to selective_ack()

comment:23 Changed 3 years ago by x190

Thanks for all your research, reardon. It might be wise to link your libutp issue report to this discussion.

comment:24 Changed 3 years ago by rsd

One more backtrace if you need.

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffff41ee700 (LWP 4012)]
0x000000000047b1e7 in UTPSocket::selective_ack (this=0xe9b7d0, base=53564,
    mask=0x7ffff41ecd76 "\377", len=7 '\a') at utp.cpp:1575
1575                            resends[nr++] = v;

Thread 3 (Thread 0x7ffff39ed700 (LWP 18012)):
#0  0x00007ffff67f73e3 in select () from /lib/libc.so.6
No symbol table info available.
#1  0x0000000000432dc7 in tr_select (nfds=0, r_fd_set=0x7ffff39ecd50, w_fd_set=0x7ffff39eccd0, 
    c_fd_set=0x7ffff39ecc50, t=0x7ffff39ecdf0) at web.c:307
No locals.
#2  0x000000000043320a in tr_webThreadFunc (vsession=0x6ae5c0) at web.c:397
        usec = 1000000
        r_fd_set = {__fds_bits = {0 <repeats 16 times>}}
        max_fd = -1
        t = {tv_sec = 0, tv_usec = 229697}
        w_fd_set = {__fds_bits = {0 <repeats 16 times>}}
        c_fd_set = {__fds_bits = {0 <repeats 16 times>}}
        msec = 1000
        unused = 0
        msg = 0x0
        mcode = CURLM_OK
        multi = 0x6c71c0
        web = 0x6c7100
        taskCount = 0
        task = 0x79f760
        session = 0x6ae5c0
#3  0x0000000000415f61 in ThreadFunc (_t=0x6afd10) at platform.c:118
        t = 0x6afd10
#4  0x00007ffff6a968ca in start_thread () from /lib/libpthread.so.0
No symbol table info available.
#5  0x00007ffff67fdb6d in clone () from /lib/libc.so.6
No symbol table info available.
#6  0x0000000000000000 in ?? ()
No symbol table info available.

Thread 2 (Thread 0x7ffff41ee700 (LWP 18011)):
#0  0x000000000047b1e7 in UTPSocket::selective_ack (this=0x1432610, base=9431, 
    mask=0x7ffff41ecd76 "", len=8 '\b') at utp.cpp:1575
        v = 9486
        bit_set = false
        pkt = 0x959e20
        bits = 55
        count = 9488
        nr = 9488
        __PRETTY_FUNCTION__ = "void UTPSocket::selective_ack(uint, const byte*, byte)"
        i = 100000
        resends = {9466, 9465, 9464, 9463, 9462, 9461, 9460, 9459, 9458, 9457, 9456, 9455, 9454, 
          9453, 9452, 9451, 9450, 9449, 9448, 9447, 9446, 9445, 9444, 9443, 9442, 9441, 9440, 
          9439, 9438, 9437, 9436, 9435}
        back_off = false
#1  0x000000000047c4ef in UTP_ProcessIncoming (conn=0x1432610, 
    packet=0x7ffff41ecd60 "!\001!{\343>`\265z]%\242", len=30, syn=false) at utp.cpp:2099
        packet_end = 0x7ffff41ecd7e "6\361 }"
        __PRETTY_FUNCTION__ = "size_t UTP_ProcessIncoming(UTPSocket*, const byte*, size_t, bool)"
        min_rtt = 130506
        prev_delay_base = 2052924856
        pk_ack_nr = 9429
        time = 17104319494362
        their_delay = 2242172965
        pf = 0x7ffff41ecd60
        pf1 = 0x7ffff41ecd60
        selack_ptr = 0x7ffff41ecd76 ""
        data = 0x7ffff41ecd7e "6\361 }"
        extension = 0
        seqnr = 0
        acks = 0
        actual_delay = 2052924834
        pk_seq_nr = 52838
        pk_flags = 2 '\002'
        acked_bytes = 1382
        p = 3812516021
#2  0x000000000047d915 in UTP_IsIncomingUTP (incoming_proc=0x42cad4 <incoming>, 
    send_to_proc=0x42cbfc <tr_utpSendTo>, send_to_userdata=0x6ae5c0, 
    buffer=0x7ffff41ecd60 "!\001!{\343>`\265z]%\242", len=30, to=0x7ffff41ecce0, tolen=16)
    at utp.cpp:2580
        read = 1400
        conn = 0x1432610
        i = 7
        pf = 0x7ffff41ecd60
        pf1 = 0x7ffff41ecd60
        flags = 2 '\002'
        seq_nr = 0
        addr = {_in = {
            _in6 = "\000\000\000\000\000\000\000\000\000\000\377\377l\355\304", <incomplete sequence \351>, _in6w = {0, 0, 0, 0, 0, 65535, 60780, 59844}, _in6d = {0, 0, 4294901760, 3921997164}, 
            _in6addr = {__in6_u = {
                __u6_addr8 = "\000\000\000\000\000\000\000\000\000\000\377\377l\355\304", <incomplete sequence \351>, __u6_addr16 = {0, 0, 0, 0, 0, 65535, 60780, 59844}, __u6_addr32 = {0, 0, 
                  4294901760, 3921997164}}}}, _port = 21992}
        p = 0x7ffff41ecd60
        p1 = 0x7ffff41ecd60
        version = 1 '\001'
        id = 8571
#3  0x000000000042ce07 in tr_utpPacket (buf=0x7ffff41ecd60 "!\001!{\343>`\265z]%\242", buflen=30, 
    from=0x7ffff41ecce0, fromlen=16, ss=0x6ae5c0) at tr-utp.c:179
No locals.
#4  0x000000000042c5cd in event_callback (s=16, type=2, sv=0x6ae5c0) at tr-udp.c:225
        rc = 30
        fromlen = 16
        buf = "!\001!{\343>`\265z]%\242\000\002\000\000\316f$\325\000\b\000\000\000\000p\000\000\000\066\361 }\000\213op6\244\344\343\305\303\302\215k#\r\273\227\t\204\067|\205\065\206\000ќzZ\236\221\")\273\215\347\310V\257f\377Q\312\340\017\261\004\337\004r\022\373\211\276\205\231\001$xzM,\031\224\\\275i\305\337\356@\255\t\263\r&\240\316\063f\326\065\267\003\372\016XfR\301\063\f\265;&\242\212\333:\345\255}\246c\tZ\314\360\327Z}\326\355\316\066\373Y\265%\276\221ظ\037\303Q\352\r\243\035\352\224\026̡\237=\354\345P\365W\243\340\375\236\231U\202+,\254\373\364\376B\375\337\375I\345\253\360\261j\376\356\226\027\030\005dy\267\212\021h0\274\222\242\201{IQvI\362,{\203P\f\323י\357`\255S\330\366w\252\001g3\332\000{jݣx\016\272H)\226\343\342\002\061\314\374y\274S\265\237\017\311wx\206)\362\211\260RX\030[\211\363\263\330\311.\263\334\341\332\327\267\024\200E%\372!ޞ\246\242/!iQ\031ޙ\247{\300\020\332\310z\363 YhӔ[ÁSG:q\336\034\364\343f]\347\000&]nO\332GYX\322\070\021\321-\261\200\315\322\330rA\222\323/'\353\275\327\320-\362d\331[\031b\034"...
        from = {ss_family = 2, __ss_align = 0, 
          __ss_padding = "@\276\250\366\377\177\000\000 \000\000\000\000\000\000\000@\276\250\366\377\177\000\000\020\000\000\000\000\000\000\000\250\210\307\000\000\000\000\000H\276\250\366\377\177\000\000\200\211\307\000\000\000\000\000pLz\366\377\177\000\000\243B(\367\377\177\000\000\020\000\000\000\000\000\000\000@\276\250\366\377\177\000\000\020\000\000\000\000\000\000\000\340\305!\001\000\000\000\000\200\033\355\000\000\000\000"}
        ss = 0x6ae5c0
        __PRETTY_FUNCTION__ = "event_callback"
#5  0x00007ffff79ac799 in event_base_loop () from /usr/local/lib/libevent-2.0.so.5
No symbol table info available.
#6  0x000000000042dac2 in libeventThreadFunc (veh=0x6aeb90) at trevent.c:248
        base = 0x6aed60
        eh = 0x6aeb90
#7  0x0000000000415f61 in ThreadFunc (_t=0x6aec10) at platform.c:118
        t = 0x6aec10
#8  0x00007ffff6a968ca in start_thread () from /lib/libpthread.so.0
No symbol table info available.
#9  0x00007ffff67fdb6d in clone () from /lib/libc.so.6
No symbol table info available.
#10 0x0000000000000000 in ?? ()
No symbol table info available.

Thread 1 (Thread 0x7ffff7fe1720 (LWP 18008)):
#0  0x00007ffff6a9e86d in nanosleep () from /lib/libpthread.so.0
No symbol table info available.
#1  0x000000000042f8d3 in tr_wait_msec (msec=1000) at utils.c:862
        ts = {tv_sec = 1, tv_nsec = 0}
#2  0x0000000000407609 in main (argc=2, argv=0x7fffffffe758) at daemon.c:577
        c = 0
        optarg = 0x0
        settings = {val = {b = 176 '\260', d = 3.4592105006704045e-317, i = 7001520, s = {
              len = 7001520, str = {
                buf = "\200\000\000\000\000\000\000\000\200\000\000\000\000\000\000", 
                ptr = 0x80 <Address 0x80 out of bounds>}}, l = {vals = 0x6ad5b0, alloc = 128, 
              count = 128}}, type = 8 '\b'}
        boolVal = false
        loaded = true
        foreground = true
        dumpSettings = false
        configDir = 0x6ac0f0 "/home/ixz/.config/transmission-daemon"
        pid_filename = 0x6adc98 "ciao.pid"
        watchdir = 0x0
        pidfile_created = true
        session = 0x6ae5c0
#0  0x000000000047b1e7 in UTPSocket::selective_ack (this=0x1432610, base=9431, 
    mask=0x7ffff41ecd76 "", len=8 '\b') at utp.cpp:1575
#1  0x000000000047c4ef in UTP_ProcessIncoming (conn=0x1432610, 
    packet=0x7ffff41ecd60 "!\001!{\343>`\265z]%\242", len=30, syn=false) at utp.cpp:2099
#2  0x000000000047d915 in UTP_IsIncomingUTP (incoming_proc=0x42cad4 <incoming>, 
    send_to_proc=0x42cbfc <tr_utpSendTo>, send_to_userdata=0x6ae5c0, 
    buffer=0x7ffff41ecd60 "!\001!{\343>`\265z]%\242", len=30, to=0x7ffff41ecce0, tolen=16)
    at utp.cpp:2580
#3  0x000000000042ce07 in tr_utpPacket (buf=0x7ffff41ecd60 "!\001!{\343>`\265z]%\242", buflen=30, 
    from=0x7ffff41ecce0, fromlen=16, ss=0x6ae5c0) at tr-utp.c:179
#4  0x000000000042c5cd in event_callback (s=16, type=2, sv=0x6ae5c0) at tr-udp.c:225
#5  0x00007ffff79ac799 in event_base_loop () from /usr/local/lib/libevent-2.0.so.5
#6  0x000000000042dac2 in libeventThreadFunc (veh=0x6aeb90) at trevent.c:248
#7  0x0000000000415f61 in ThreadFunc (_t=0x6aec10) at platform.c:118
#8  0x00007ffff6a968ca in start_thread () from /lib/libpthread.so.0
#9  0x00007ffff67fdb6d in clone () from /lib/libc.so.6
#10 0x0000000000000000 in ?? ()
A debugging session is active.

	Inferior 1 [process 18008] will be killed.

Quit anyway? (y or n) $1 = 53607
$2 = {53607, 53606, 53605, 53604, 53603, 53602, 53601, 53600, 53599, 53598, 53597, 53596, 53595, 
  53594, 53593, 53592, 53591, 53590, 53589, 53588, 53587, 53586, 53585, 53584, 53583, 53582, 
  53581, 53580, 53579, 53578, 53577, 53576}
$3 = 53607
#0  0x000000000047b1e7 in UTPSocket::selective_ack (this=0xe9b7d0, base=53564, 
    mask=0x7ffff41ecd76 "\377", len=7 '\a') at utp.cpp:1575
        v = 53605
        bit_set = false
        pkt = 0x7d6b20
        bits = 41
        count = 53607
        nr = 53607
        __PRETTY_FUNCTION__ = "void UTPSocket::selective_ack(uint, const byte*, byte)"
        i = 100000
        resends = {53607, 53606, 53605, 53604, 53603, 53602, 53601, 53600, 53599, 53598, 53597, 
          53596, 53595, 53594, 53593, 53592, 53591, 53590, 53589, 53588, 53587, 53586, 53585, 
          53584, 53583, 53582, 53581, 53580, 53579, 53578, 53577, 53576}
        back_off = false
#1  0x000000000047c4ef in UTP_ProcessIncoming (conn=0xe9b7d0, 
    packet=0x7ffff41ecd60 "!\001\070\062։a\231\177\070\202\351\006?\236ԓ\317\321:", len=29, 
    syn=false) at utp.cpp:2099
        packet_end = 0x7ffff41ecd7d "\332\344\023e1:q4:ping1:t2:\005\005\061:v4:LT"
        __PRETTY_FUNCTION__ = "size_t UTP_ProcessIncoming(UTPSocket*, const byte*, size_t, bool)"
        min_rtt = 243642
        prev_delay_base = 2134399898
        pk_ack_nr = 53562
        time = 17473392121445
        their_delay = 2160800972
        pf = 0x7ffff41ecd60
        pf1 = 0x7ffff41ecd60
        selack_ptr = 0x7ffff41ecd76 "\377"
        data = 0x7ffff41ecd7d "\332\344\023e1:q4:ping1:t2:\005\005\061:v4:LT"
        extension = 0
        seqnr = 0
        acks = 1
        actual_delay = 2134409961
        pk_seq_nr = 37839
        pk_flags = 2 '\002'
        acked_bytes = 1382
        p = 3599327641
#2  0x000000000047d915 in UTP_IsIncomingUTP (incoming_proc=0x42cad4 <incoming>, 
    send_to_proc=0x42cbfc <tr_utpSendTo>, send_to_userdata=0x6ae5c0, 
    buffer=0x7ffff41ecd60 "!\001\070\062։a\231\177\070\202\351\006?\236ԓ\317\321:", len=29, 
    to=0x7ffff41ecce0, tolen=16) at utp.cpp:2580
        read = 0
        conn = 0xe9b7d0
        i = 14
        pf = 0x7ffff41ecd60
        pf1 = 0x7ffff41ecd60
        flags = 2 '\002'
        seq_nr = 32767
        addr = {_in = {_in6 = "\000\000\000\000\000\000\000\000\000\000\377\377]\266\243\262", 
            _in6w = {0, 0, 0, 0, 0, 65535, 46685, 45731}, _in6d = {0, 0, 4294901760, 2997073501}, 
            _in6addr = {__in6_u = {
                __u6_addr8 = "\000\000\000\000\000\000\000\000\000\000\377\377]\266\243\262", 
                __u6_addr16 = {0, 0, 0, 0, 0, 65535, 46685, 45731}, __u6_addr32 = {0, 0, 
                  4294901760, 2997073501}}}}, _port = 44689}
        p = 0x7ffff41ecd60
        p1 = 0x7ffff41ecd60
        version = 1 '\001'
        id = 14386
#3  0x000000000042ce07 in tr_utpPacket (
    buf=0x7ffff41ecd60 "!\001\070\062։a\231\177\070\202\351\006?\236ԓ\317\321:", buflen=29, 
    from=0x7ffff41ecce0, fromlen=16, ss=0x6ae5c0) at tr-utp.c:179
No locals.
#4  0x000000000042c5cd in event_callback (s=16, type=2, sv=0x6ae5c0) at tr-udp.c:225
        rc = 29
        fromlen = 16
        buf = "!\001\070\062։a\231\177\070\202\351\006?\236ԓ\317\321:\000\a\377\000\000\000\000\360?\332\344\023e1:q4:ping1:t2:\005\005\061:v4:LT\000\017\061:y1:qe\000\066:noseedi1e6:scrapei1e4:wantl2:n6ee1:q9:get_peers1:t2:\005c1:v4:Zo\000\006\061:y1:qe\000\201t\327f\315T)m\371℠\215\065\066\214b\343\260~ٷ2|\372٦\030\205\224\032\206,\352dyi\350\332_7WS*\016{]6\314<\017\034\257_\a\276բ\374(r\363\300\227\017h\037\254\342\026\255\345-3+?H2o\256w\236\332|\326\307\334#\336\320\346s\244:G\336\065;\367\016Gy\177ޣ\347\360\066\237\365{\031\324q\206܊\345\230;\354GU%.\274\277\245_1\260"...
        from = {ss_family = 2, __ss_align = 0, 
          __ss_padding = "\024\366%6O\214\276\021\000\000\000\000\000\000\000\000@\276\250\366\377\177\000\000\020\000\000\000\000\000\000\000\270\301\302\000\000\000\000\000H\276\250\366\377\177\000\000\220\302\302\000\000\000\000\000pLz\366\377\177\000\000\243B(\367\377\177\000\000\020\000\000\000\000\000\000\000@\276\250\366\377\177\000\000\020\000\000\000\000\000\000\000p\250\340\000\000\000\000\000\020\354y\000\000\000\000"}
        ss = 0x6ae5c0
        __PRETTY_FUNCTION__ = "event_callback"
#5  0x00007ffff79ac799 in event_base_loop () from /usr/local/lib/libevent-2.0.so.5
No symbol table info available.
#6  0x000000000042dac2 in libeventThreadFunc (veh=0x6aeb90) at trevent.c:248
        base = 0x6aed60
        eh = 0x6aeb90
#7  0x0000000000415f61 in ThreadFunc (_t=0x6aec10) at platform.c:118
        t = 0x6aec10
#8  0x00007ffff6a968ca in start_thread () from /lib/libpthread.so.0
No symbol table info available.
#9  0x00007ffff67fdb6d in clone () from /lib/libc.so.6
No symbol table info available.
#10 0x0000000000000000 in ?? ()
No symbol table info available.
A debugging session is active.

Changed 3 years ago by cfpp2p

comment:25 Changed 3 years ago by cfpp2p

RESENDS_MAX_COUNT.diff is a patch that takes into account all of the insight that reardon has contributed. I don't know whether to call it a test, fix or workaround, but it is an alternative to reardon's overkill solution:

The overkill solution (I'm testing) just increases the size to resends[2040] on the stack

RESENDS_MAX_COUNT.diff keeps the resends[32] array size.

I can't see how there is any protection against this in the code--'nr' is incremented without any checks.

There isn't any protection. The code relied on decrementing the bits variable which as stated previously can be as large as 2040. There are a few other variables involved in whether nr is actually incremented. Unless there is a large enough extension length ( len ) and the other variables conditionals allow nr to be incremented as well it took somewhat unusual (i.e. rare) circumstances for nr to exceed 32.

but just seems wrong to have an unchecked constant (32) for the array size of resends[]. Why hard-coded?? Almost seems intentional...

I think it was intentional because there really is no way to know how large nr can be incremented to other than it might possibly reach the 2040 maximum. But it takes a rare situation for nr to exceed 32, ???something the libutp developers erred on apparently.

Line 1495 in utp.cpp allows for up to 2040 iterations and therefor nr can and does exceed 32 under the correct circumstances.

int bits = len * 8 - 1;

Controlling the value of len either somewhere in utp.cpp or tr-udp.c simply doesn't make sense because we never really know when a re-send is warranted and whether nr will be incremented anyway.

RESENDS_MAX_COUNT.diff patches the conditionals that increment nr so that nr will never exceeds the defined RESENDS_MAX_COUNT value.

Ultimately either the libutp or transmission developers will have to decide what to do with this situation. Tests with RESENDS_MAX_COUNT.diff are stable and RESENDS_MAX_COUNT defines a stable array size for the code. 2040 may very well be fine for this value but the original coded value of 32 is stable with RESENDS_MAX_COUNT.diff. Why 32, needs to be answered by the libutp developers.

Last edited 3 years ago by cfpp2p (previous) (diff)

comment:26 follow-up: Changed 3 years ago by ghazel

I would like to mimic x190's shock that no one reported this to the libutp project on Github. We already had a fix in the works, and could have addressed it much sooner and helped greatly reduce the debugging process. We're here to help!

comment:27 in reply to: ↑ 26 Changed 3 years ago by reardon

Replying to ghazel:

I would like to mimic x190's shock that no one reported this to the libutp project on Github. We already had a fix in the works, and could have addressed it much sooner and helped greatly reduce the debugging process. We're here to help!

Honestly, there hadn't been any activity at github for quite a while, so I thought the project was orphaned. Glad to see that it is alive and that you have a fix proposed fix.

comment:28 Changed 3 years ago by cfpp2p

from libutp:

We encourage you to test with the version of libutp you have, and be mindful when
upgrading. For this reason, it is probably also a good idea to bundle libutp
with your application.

https://github.com/bittorrent/libutp#packaging-and-api

'Selective ACK' is the ability to acknowledge individual packets in the event of packet loss.

In my humble opinion there should be something done with this ticket for transmission users. I might not assume that at libutp we'll see a resolution committed anytime soon and the issue will stagnate there. A couple of worthy patches are available at libutp and with uTP already bundled with transmission, maybe give transmission users one of the available patches.

comment:29 Changed 3 years ago by x190

  • Priority changed from High to Highest
  • Severity changed from Normal to Critical

comment:30 Changed 3 years ago by x190

Upgrading this ticket due to the security implications. Crash reports are coming in regularly now on the forum suggesting someone may have figured out how to force a crash.

https://forum.transmissionbt.com/viewtopic.php?f=2&t=14180#p62864

Github (libutp) has a patch available.

https://gist.github.com/ef69847aaa2482f14ddb

Last edited 3 years ago by x190 (previous) (diff)

comment:31 Changed 3 years ago by reardon

I recommend taking the patch posted in #comment:30 (from ghazel), even if it is not yet formally pulled to github. This is a net-exploitable bug. The patch is not perfect but it does avert the exploit. I have run it in stress for several days.

cfpp2p also has a workable patch if the preference is for something from a local owner, as it were.

Last edited 3 years ago by reardon (previous) (diff)

comment:32 Changed 3 years ago by jordan

Ideally I'd like to pull an "official" fix from libutp's repo, and I can't tell the context of this patch wrt it being experimental, proposed, etc... but regardless, it looks like an improvement over trunk, so I've landed it in r13646 for 2.74.

When an official fix comes out, Transmission will sync with it instead.

comment:33 Changed 3 years ago by jordan

  • Milestone changed from None Set to 2.75
  • Resolution set to fixed
  • Status changed from assigned to closed

comment:34 Changed 3 years ago by jordan

  • Milestone changed from 2.75 to 2.74
Note: See TracTickets for help on using tickets.