diff options
author | Dirk Engling <erdgeist@erdgeist.org> | 2021-04-20 03:48:50 +0200 |
---|---|---|
committer | Dirk Engling <erdgeist@erdgeist.org> | 2021-04-20 03:48:50 +0200 |
commit | 616119ee22fec0f0db7a4c89a6a8f649d5926891 (patch) | |
tree | 0b32171a1f16b389d80f050838aa52b5e38f0cce | |
parent | 0695b488708f3beaa17456c2b132b211a6fb5332 (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.c | 3 | ||||
-rw-r--r-- | trackerlogic.c | 14 | ||||
-rw-r--r-- | 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 ) { | |||
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 */ |
32 | size_t return_peers_for_torrent( ot_torrent *torrent, size_t amount, char *reply, PROTO_FLAG proto ); | 32 | size_t return_peers_for_torrent( struct ot_workstruct * ws, ot_torrent *torrent, size_t amount, char *reply, PROTO_FLAG proto ); |
33 | 33 | ||
34 | void free_peerlist( ot_peerlist *peer_list ) { | 34 | void 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 | ||
213 | static size_t return_peers_selection( ot_peerlist *peer_list, size_t amount, char *reply ) { | 213 | static 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 | */ |
265 | size_t return_peers_for_torrent( ot_torrent *torrent, size_t amount, char *reply, PROTO_FLAG proto ) { | 265 | size_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 | ||
14 | typedef uint8_t ot_hash[20]; | 15 | typedef uint8_t ot_hash[20]; |
15 | typedef time_t ot_time; | 16 | typedef 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 | /* |