From 616119ee22fec0f0db7a4c89a6a8f649d5926891 Mon Sep 17 00:00:00 2001 From: Dirk Engling Date: Tue, 20 Apr 2021 03:48:50 +0200 Subject: Turn random() to nrand48 in inner loop where it is not cryptographically relevant to avoid futex storm. Thanks and credits to Bart Smienk --- opentracker.c | 3 +++ trackerlogic.c | 14 +++++++------- trackerlogic.h | 7 ++++++- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/opentracker.c b/opentracker.c index aed8374..d2c0635 100644 --- a/opentracker.c +++ b/opentracker.c @@ -258,6 +258,9 @@ static void * server_mainloop( void * args ) { #endif if( !ws.inbuf || !ws.outbuf ) panic( "Initializing worker failed" ); + ws.rand48_state[0] = (uint16_t)random(); + ws.rand48_state[1] = (uint16_t)random(); + ws.rand48_state[2] = (uint16_t)random(); for( ; ; ) { int64 sock; diff --git a/trackerlogic.c b/trackerlogic.c index 21bd790..ea4b489 100644 --- a/trackerlogic.c +++ b/trackerlogic.c @@ -29,7 +29,7 @@ #include "ot_livesync.h" /* Forward declaration */ -size_t return_peers_for_torrent( ot_torrent *torrent, size_t amount, char *reply, PROTO_FLAG proto ); +size_t return_peers_for_torrent( struct ot_workstruct * ws, ot_torrent *torrent, size_t amount, char *reply, PROTO_FLAG proto ); void free_peerlist( ot_peerlist *peer_list ) { if( peer_list->peers.data ) { @@ -178,7 +178,7 @@ size_t add_peer_to_torrent_and_return_peers( PROTO_FLAG proto, struct ot_workstr } #endif - ws->reply_size = return_peers_for_torrent( torrent, amount, ws->reply, proto ); + ws->reply_size = return_peers_for_torrent( ws, torrent, amount, ws->reply, proto ); mutex_bucket_unlock_by_hash( *ws->hash, delta_torrentcount ); return ws->reply_size; } @@ -210,7 +210,7 @@ static size_t return_peers_all( ot_peerlist *peer_list, char *reply ) { return result; } -static size_t return_peers_selection( ot_peerlist *peer_list, size_t amount, char *reply ) { +static size_t return_peers_selection( struct ot_workstruct *ws, ot_peerlist *peer_list, size_t amount, char *reply ) { unsigned int bucket_offset, bucket_index = 0, num_buckets = 1; ot_vector * bucket_list = &peer_list->peers; unsigned int shifted_pc = peer_list->peer_count; @@ -232,7 +232,7 @@ static size_t return_peers_selection( ot_peerlist *peer_list, size_t amount, cha /* Initialize somewhere in the middle of peers so that fixpoint's aliasing doesn't alway miss the same peers */ - bucket_offset = random() % peer_list->peer_count; + bucket_offset = nrand48(ws->rand48_state) % peer_list->peer_count; while( amount-- ) { ot_peer * peer; @@ -240,7 +240,7 @@ static size_t return_peers_selection( ot_peerlist *peer_list, size_t amount, cha /* This is the aliased, non shifted range, next value may fall into */ unsigned int diff = ( ( ( amount + 1 ) * shifted_step ) >> shift ) - ( ( amount * shifted_step ) >> shift ); - bucket_offset += 1 + random() % diff; + bucket_offset += 1 + nrand48(ws->rand48_state) % diff; while( bucket_offset >= bucket_list[bucket_index].size ) { bucket_offset -= bucket_list[bucket_index].size; @@ -262,7 +262,7 @@ static size_t return_peers_selection( ot_peerlist *peer_list, size_t amount, cha * reply must have enough space to hold 92+6*amount bytes * does not yet check not to return self */ -size_t return_peers_for_torrent( ot_torrent *torrent, size_t amount, char *reply, PROTO_FLAG proto ) { +size_t return_peers_for_torrent( struct ot_workstruct * ws, ot_torrent *torrent, size_t amount, char *reply, PROTO_FLAG proto ) { ot_peerlist *peer_list = torrent->peer_list; char *r = reply; @@ -283,7 +283,7 @@ size_t return_peers_for_torrent( ot_torrent *torrent, size_t amount, char *reply if( amount == peer_list->peer_count ) r += return_peers_all( peer_list, r ); else - r += return_peers_selection( peer_list, amount, r ); + r += return_peers_selection( ws, peer_list, amount, r ); } if( proto == FLAG_TCP ) diff --git a/trackerlogic.h b/trackerlogic.h index 721ba6e..33dccbe 100644 --- a/trackerlogic.h +++ b/trackerlogic.h @@ -10,6 +10,7 @@ #include #include #include +#include typedef uint8_t ot_hash[20]; typedef time_t ot_time; @@ -34,7 +35,7 @@ typedef struct { ot_ip6 address; int bits; } #define OT_TORRENT_TIMEOUT_HOURS 24 #define OT_TORRENT_TIMEOUT (60*OT_TORRENT_TIMEOUT_HOURS) -#define OT_CLIENT_REQUEST_INTERVAL_RANDOM ( OT_CLIENT_REQUEST_INTERVAL - OT_CLIENT_REQUEST_VARIATION/2 + (int)( random( ) % OT_CLIENT_REQUEST_VARIATION ) ) +#define OT_CLIENT_REQUEST_INTERVAL_RANDOM ( OT_CLIENT_REQUEST_INTERVAL - OT_CLIENT_REQUEST_VARIATION/2 + (int)( nrand48(ws->rand48_state) % OT_CLIENT_REQUEST_VARIATION ) ) /* If WANT_MODEST_FULLSCRAPES is on, ip addresses may not fullscrape more frequently than this amount in seconds */ @@ -131,6 +132,10 @@ struct ot_workstruct { ssize_t header_size; char *reply; ssize_t reply_size; + + /* Entropy state for rand48 function so that threads don't need to acquire mutexes for + global random() or arc4random() state, which causes heavy load on linuxes */ + uint16_t rand48_state[3]; }; /* -- cgit v1.2.3