summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDirk Engling <erdgeist@erdgeist.org>2021-04-20 03:48:50 +0200
committerDirk Engling <erdgeist@erdgeist.org>2021-04-20 03:48:50 +0200
commit616119ee22fec0f0db7a4c89a6a8f649d5926891 (patch)
tree0b32171a1f16b389d80f050838aa52b5e38f0cce
parent0695b488708f3beaa17456c2b132b211a6fb5332 (diff)
Turn random() to nrand48 in inner loop where it is not cryptographically relevant to avoid futex storm. Thanks and credits to Bart Smienk
-rw-r--r--opentracker.c3
-rw-r--r--trackerlogic.c14
-rw-r--r--trackerlogic.h7
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 ) {
258#endif 258#endif
259 if( !ws.inbuf || !ws.outbuf ) 259 if( !ws.inbuf || !ws.outbuf )
260 panic( "Initializing worker failed" ); 260 panic( "Initializing worker failed" );
261 ws.rand48_state[0] = (uint16_t)random();
262 ws.rand48_state[1] = (uint16_t)random();
263 ws.rand48_state[2] = (uint16_t)random();
261 264
262 for( ; ; ) { 265 for( ; ; ) {
263 int64 sock; 266 int64 sock;
diff --git a/trackerlogic.c b/trackerlogic.c
index 21bd790..ea4b489 100644
--- a/trackerlogic.c
+++ b/trackerlogic.c
@@ -29,7 +29,7 @@
29#include "ot_livesync.h" 29#include "ot_livesync.h"
30 30
31/* Forward declaration */ 31/* Forward declaration */
32size_t return_peers_for_torrent( ot_torrent *torrent, size_t amount, char *reply, PROTO_FLAG proto ); 32size_t return_peers_for_torrent( struct ot_workstruct * ws, ot_torrent *torrent, size_t amount, char *reply, PROTO_FLAG proto );
33 33
34void free_peerlist( ot_peerlist *peer_list ) { 34void free_peerlist( ot_peerlist *peer_list ) {
35 if( peer_list->peers.data ) { 35 if( peer_list->peers.data ) {
@@ -178,7 +178,7 @@ size_t add_peer_to_torrent_and_return_peers( PROTO_FLAG proto, struct ot_workstr
178 } 178 }
179#endif 179#endif
180 180
181 ws->reply_size = return_peers_for_torrent( torrent, amount, ws->reply, proto ); 181 ws->reply_size = return_peers_for_torrent( ws, torrent, amount, ws->reply, proto );
182 mutex_bucket_unlock_by_hash( *ws->hash, delta_torrentcount ); 182 mutex_bucket_unlock_by_hash( *ws->hash, delta_torrentcount );
183 return ws->reply_size; 183 return ws->reply_size;
184} 184}
@@ -210,7 +210,7 @@ static size_t return_peers_all( ot_peerlist *peer_list, char *reply ) {
210 return result; 210 return result;
211} 211}
212 212
213static size_t return_peers_selection( ot_peerlist *peer_list, size_t amount, char *reply ) { 213static size_t return_peers_selection( struct ot_workstruct *ws, ot_peerlist *peer_list, size_t amount, char *reply ) {
214 unsigned int bucket_offset, bucket_index = 0, num_buckets = 1; 214 unsigned int bucket_offset, bucket_index = 0, num_buckets = 1;
215 ot_vector * bucket_list = &peer_list->peers; 215 ot_vector * bucket_list = &peer_list->peers;
216 unsigned int shifted_pc = peer_list->peer_count; 216 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
232 232
233 /* Initialize somewhere in the middle of peers so that 233 /* Initialize somewhere in the middle of peers so that
234 fixpoint's aliasing doesn't alway miss the same peers */ 234 fixpoint's aliasing doesn't alway miss the same peers */
235 bucket_offset = random() % peer_list->peer_count; 235 bucket_offset = nrand48(ws->rand48_state) % peer_list->peer_count;
236 236
237 while( amount-- ) { 237 while( amount-- ) {
238 ot_peer * peer; 238 ot_peer * peer;
@@ -240,7 +240,7 @@ static size_t return_peers_selection( ot_peerlist *peer_list, size_t amount, cha
240 /* This is the aliased, non shifted range, next value may fall into */ 240 /* This is the aliased, non shifted range, next value may fall into */
241 unsigned int diff = ( ( ( amount + 1 ) * shifted_step ) >> shift ) - 241 unsigned int diff = ( ( ( amount + 1 ) * shifted_step ) >> shift ) -
242 ( ( amount * shifted_step ) >> shift ); 242 ( ( amount * shifted_step ) >> shift );
243 bucket_offset += 1 + random() % diff; 243 bucket_offset += 1 + nrand48(ws->rand48_state) % diff;
244 244
245 while( bucket_offset >= bucket_list[bucket_index].size ) { 245 while( bucket_offset >= bucket_list[bucket_index].size ) {
246 bucket_offset -= bucket_list[bucket_index].size; 246 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
262 * reply must have enough space to hold 92+6*amount bytes 262 * reply must have enough space to hold 92+6*amount bytes
263 * does not yet check not to return self 263 * does not yet check not to return self
264*/ 264*/
265size_t return_peers_for_torrent( ot_torrent *torrent, size_t amount, char *reply, PROTO_FLAG proto ) { 265size_t return_peers_for_torrent( struct ot_workstruct * ws, ot_torrent *torrent, size_t amount, char *reply, PROTO_FLAG proto ) {
266 ot_peerlist *peer_list = torrent->peer_list; 266 ot_peerlist *peer_list = torrent->peer_list;
267 char *r = reply; 267 char *r = reply;
268 268
@@ -283,7 +283,7 @@ size_t return_peers_for_torrent( ot_torrent *torrent, size_t amount, char *reply
283 if( amount == peer_list->peer_count ) 283 if( amount == peer_list->peer_count )
284 r += return_peers_all( peer_list, r ); 284 r += return_peers_all( peer_list, r );
285 else 285 else
286 r += return_peers_selection( peer_list, amount, r ); 286 r += return_peers_selection( ws, peer_list, amount, r );
287 } 287 }
288 288
289 if( proto == FLAG_TCP ) 289 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 @@
10#include <sys/time.h> 10#include <sys/time.h>
11#include <time.h> 11#include <time.h>
12#include <stdint.h> 12#include <stdint.h>
13#include <stdlib.h>
13 14
14typedef uint8_t ot_hash[20]; 15typedef uint8_t ot_hash[20];
15typedef time_t ot_time; 16typedef time_t ot_time;
@@ -34,7 +35,7 @@ typedef struct { ot_ip6 address; int bits; }
34#define OT_TORRENT_TIMEOUT_HOURS 24 35#define OT_TORRENT_TIMEOUT_HOURS 24
35#define OT_TORRENT_TIMEOUT (60*OT_TORRENT_TIMEOUT_HOURS) 36#define OT_TORRENT_TIMEOUT (60*OT_TORRENT_TIMEOUT_HOURS)
36 37
37#define OT_CLIENT_REQUEST_INTERVAL_RANDOM ( OT_CLIENT_REQUEST_INTERVAL - OT_CLIENT_REQUEST_VARIATION/2 + (int)( random( ) % OT_CLIENT_REQUEST_VARIATION ) ) 38#define OT_CLIENT_REQUEST_INTERVAL_RANDOM ( OT_CLIENT_REQUEST_INTERVAL - OT_CLIENT_REQUEST_VARIATION/2 + (int)( nrand48(ws->rand48_state) % OT_CLIENT_REQUEST_VARIATION ) )
38 39
39/* If WANT_MODEST_FULLSCRAPES is on, ip addresses may not 40/* If WANT_MODEST_FULLSCRAPES is on, ip addresses may not
40 fullscrape more frequently than this amount in seconds */ 41 fullscrape more frequently than this amount in seconds */
@@ -131,6 +132,10 @@ struct ot_workstruct {
131 ssize_t header_size; 132 ssize_t header_size;
132 char *reply; 133 char *reply;
133 ssize_t reply_size; 134 ssize_t reply_size;
135
136 /* Entropy state for rand48 function so that threads don't need to acquire mutexes for
137 global random() or arc4random() state, which causes heavy load on linuxes */
138 uint16_t rand48_state[3];
134}; 139};
135 140
136/* 141/*