diff --git a/NEWS b/NEWS index 93ac8f5da..675520ddc 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,8 @@ +=== Transmission 2.83 (2014/xx/yy) === +[http://trac.transmissionbt.com/query?milestone=2.84&group=component&order=severity All tickets closed by this release] +==== All Platforms ==== + * Fix peer communication vulnerability (no known exploits) reported by Ben Hawkes + === Transmission 2.83 (2014/05/18) === [http://trac.transmissionbt.com/query?milestone=2.83&group=component&order=severity All tickets closed by this release] ==== All Platforms ==== diff --git a/libtransmission/bitfield.c b/libtransmission/bitfield.c index 11320ff49..bed09aec5 100644 --- a/libtransmission/bitfield.c +++ b/libtransmission/bitfield.c @@ -167,7 +167,7 @@ tr_bitfieldCountTrueBits (const tr_bitfield * b) static size_t get_bytes_needed (size_t bit_count) { - return (bit_count + 7u) / 8u; + return (bit_count >> 3) + (bit_count & 7 ? 1 : 0); } static void @@ -228,11 +228,16 @@ tr_bitfieldEnsureBitsAlloced (tr_bitfield * b, size_t n) } } -static void +static bool tr_bitfieldEnsureNthBitAlloced (tr_bitfield * b, size_t nth) { /* count is zero-based, so we need to allocate nth+1 bits before setting the nth */ + + if (nth == SIZE_MAX) + return false; + tr_bitfieldEnsureBitsAlloced (b, nth + 1); + return true; } static void @@ -365,9 +370,8 @@ tr_bitfieldSetFromFlags (tr_bitfield * b, const bool * flags, size_t n) void tr_bitfieldAdd (tr_bitfield * b, size_t nth) { - if (!tr_bitfieldHas (b, nth)) + if (!tr_bitfieldHas (b, nth) && tr_bitfieldEnsureNthBitAlloced (b, nth)) { - tr_bitfieldEnsureNthBitAlloced (b, nth); b->bits[nth >> 3u] |= (0x80 >> (nth & 7u)); tr_bitfieldIncTrueCount (b, 1); } @@ -393,7 +397,9 @@ tr_bitfieldAddRange (tr_bitfield * b, size_t begin, size_t end) eb = end >> 3; em = 0xff << (7 - (end & 7)); - tr_bitfieldEnsureNthBitAlloced (b, end); + if (!tr_bitfieldEnsureNthBitAlloced (b, end)) + return; + if (sb == eb) { b->bits[sb] |= (sm & em); @@ -414,9 +420,8 @@ tr_bitfieldRem (tr_bitfield * b, size_t nth) { assert (tr_bitfieldIsValid (b)); - if (!tr_bitfieldHas (b, nth)) + if (!tr_bitfieldHas (b, nth) && tr_bitfieldEnsureNthBitAlloced (b, nth)) { - tr_bitfieldEnsureNthBitAlloced (b, nth); b->bits[nth >> 3u] &= (0xff7f >> (nth & 7u)); tr_bitfieldIncTrueCount (b, -1); } @@ -443,7 +448,9 @@ tr_bitfieldRemRange (tr_bitfield * b, size_t begin, size_t end) eb = end >> 3; em = ~ (0xff << (7 - (end & 7))); - tr_bitfieldEnsureNthBitAlloced (b, end); + if (!tr_bitfieldEnsureNthBitAlloced (b, end)) + return; + if (sb == eb) { b->bits[sb] &= (sm | em); diff --git a/libtransmission/peer-msgs.c b/libtransmission/peer-msgs.c index 84646f73b..8644644c9 100644 --- a/libtransmission/peer-msgs.c +++ b/libtransmission/peer-msgs.c @@ -33,6 +33,10 @@ #include "variant.h" #include "version.h" +#ifndef EBADMSG + #define EBADMSG EINVAL +#endif + /** *** **/ @@ -1693,6 +1697,12 @@ clientGotBlock (tr_peerMsgs * msgs, assert (msgs); assert (req); + if (!requestIsValid (msgs, req)) { + dbgmsg (msgs, "dropping invalid block %u:%u->%u", + req->index, req->offset, req->length); + return EBADMSG; + } + if (req->length != tr_torBlockCountBytes (msgs->torrent, block)) { dbgmsg (msgs, "wrong block size -- expected %u, got %d", tr_torBlockCountBytes (msgs->torrent, block), req->length);