summaryrefslogtreecommitdiff
path: root/ot_accesslist.c
diff options
context:
space:
mode:
authorDirk Engling <erdgeist@erdgeist.org>2021-04-19 22:33:23 +0200
committerDirk Engling <erdgeist@erdgeist.org>2021-04-19 22:33:23 +0200
commit102ba9075b8df32627f38074a293d804e04139ba (patch)
treecce73c37a043055e37a6a52fc2c978110ebdaff3 /ot_accesslist.c
parentfde79836e6ebb339f67f99768b5b75dde619779e (diff)
Make accesslist reload thread safe. The last commit actually would make a free possible while another thread was bsearching that memory
Diffstat (limited to 'ot_accesslist.c')
-rw-r--r--ot_accesslist.c58
1 files changed, 40 insertions, 18 deletions
diff --git a/ot_accesslist.c b/ot_accesslist.c
index 12bd29e..2e3778f 100644
--- a/ot_accesslist.c
+++ b/ot_accesslist.c
@@ -25,19 +25,25 @@
25/* GLOBAL VARIABLES */ 25/* GLOBAL VARIABLES */
26#ifdef WANT_ACCESSLIST 26#ifdef WANT_ACCESSLIST
27 char *g_accesslist_filename; 27 char *g_accesslist_filename;
28static ot_hash *g_accesslist;
29static size_t g_accesslist_size;
30static pthread_mutex_t g_accesslist_mutex; 28static pthread_mutex_t g_accesslist_mutex;
31 29
30typedef struct {
31 ot_hash *list;
32 size_t size;
33} ot_accesslist;
34ot_accesslist * g_accesslist = NULL;
35ot_accesslist * g_accesslist_old = NULL;
36
32static int vector_compare_hash(const void *hash1, const void *hash2 ) { 37static int vector_compare_hash(const void *hash1, const void *hash2 ) {
33 return memcmp( hash1, hash2, OT_HASH_COMPARE_SIZE ); 38 return memcmp( hash1, hash2, OT_HASH_COMPARE_SIZE );
34} 39}
35 40
36/* Read initial access list */ 41/* Read initial access list */
37static void accesslist_readfile( void ) { 42static void accesslist_readfile( void ) {
38 ot_hash *info_hash, *accesslist_new = NULL, *accesslist_old; 43 ot_accesslist * accesslist_new = malloc(sizeof(ot_accesslist));
39 char *map, *map_end, *read_offs; 44 ot_hash *info_hash;
40 size_t maplen; 45 const char *map, *map_end, *read_offs;
46 size_t maplen;
41 47
42 if( ( map = mmap_read( g_accesslist_filename, &maplen ) ) == NULL ) { 48 if( ( map = mmap_read( g_accesslist_filename, &maplen ) ) == NULL ) {
43 char *wd = getcwd( NULL, 0 ); 49 char *wd = getcwd( NULL, 0 );
@@ -48,9 +54,11 @@ static void accesslist_readfile( void ) {
48 54
49 /* You need at least 41 bytes to pass an info_hash, make enough room 55 /* You need at least 41 bytes to pass an info_hash, make enough room
50 for the maximum amount of them */ 56 for the maximum amount of them */
51 info_hash = accesslist_new = malloc( ( maplen / 41 ) * 20 ); 57 accesslist_new->size = 0;
58 info_hash = accesslist_new->list = malloc( ( maplen / 41 ) * 20 );
52 if( !accesslist_new ) { 59 if( !accesslist_new ) {
53 fprintf( stderr, "Warning: Not enough memory to allocate %zd bytes for accesslist buffer. May succeed later.\n", ( maplen / 41 ) * 20 ); 60 fprintf( stderr, "Warning: Not enough memory to allocate %zd bytes for accesslist buffer. May succeed later.\n", ( maplen / 41 ) * 20 );
61 free(accesslist_new);
54 return; 62 return;
55 } 63 }
56 64
@@ -81,28 +89,33 @@ static void accesslist_readfile( void ) {
81 while( read_offs <= map_end && *(read_offs++) != '\n' ); 89 while( read_offs <= map_end && *(read_offs++) != '\n' );
82 } 90 }
83#ifdef _DEBUG 91#ifdef _DEBUG
84 fprintf( stderr, "Added %zd info_hashes to accesslist\n", (size_t)(info_hash - accesslist_new) ); 92 fprintf( stderr, "Added %zd info_hashes to accesslist\n", (size_t)(info_hash - accesslist_new->list) );
85#endif 93#endif
86 94
87 mmap_unmap( map, maplen); 95 mmap_unmap( map, maplen);
88 96
89 qsort( accesslist_new, info_hash - accesslist_new, sizeof( *info_hash ), vector_compare_hash ); 97 qsort( accesslist_new->list, info_hash - accesslist_new->list, sizeof( *info_hash ), vector_compare_hash );
98 accesslist_new->size = info_hash - accesslist_new->list;
90 99
91 /* Now exchange the accesslist vector in the least race condition prone way */ 100 /* Now exchange the accesslist vector in the least race condition prone way */
92 pthread_mutex_lock(&g_accesslist_mutex); 101 pthread_mutex_lock(&g_accesslist_mutex);
93 102
94 accesslist_old = g_accesslist; /* Keep a copy for later free */ 103 if (g_accesslist_old) {
95 g_accesslist_size = 0; /* Set size to 0 to prevent clients from searching through uninitialised memory */ 104 free(g_accesslist_old->list);
96 g_accesslist = accesslist_new; /* Only now set a new list */ 105 free(g_accesslist_old);
97 g_accesslist_size = info_hash - accesslist_new; /* And finally store it's size */ 106 }
98 free(g_accesslist_old); /* If new list is active, the old one can be destroyed */ 107
108 g_accesslist_old = g_accesslist; /* Keep a copy for later free */
109 g_accesslist = accesslist_new; /* Only now set a new list */
110
99 pthread_mutex_unlock(&g_accesslist_mutex); 111 pthread_mutex_unlock(&g_accesslist_mutex);
100} 112}
101 113
102int accesslist_hashisvalid( ot_hash hash ) { 114int accesslist_hashisvalid( ot_hash hash ) {
103 void *exactmatch; 115 /* Get working copy of current access list */
116 ot_accesslist * accesslist = g_accesslist;
104 117
105 exactmatch = bsearch( hash, g_accesslist, g_accesslist_size, OT_HASH_COMPARE_SIZE, vector_compare_hash ); 118 void * exactmatch = bsearch( hash, accesslist->list, accesslist->size, OT_HASH_COMPARE_SIZE, vector_compare_hash );
106 119
107#ifdef WANT_ACCESSLIST_BLACK 120#ifdef WANT_ACCESSLIST_BLACK
108 return exactmatch == NULL; 121 return exactmatch == NULL;
@@ -140,9 +153,18 @@ void accesslist_init( ) {
140void accesslist_deinit( void ) { 153void accesslist_deinit( void ) {
141 pthread_cancel( thread_id ); 154 pthread_cancel( thread_id );
142 pthread_mutex_destroy(&g_accesslist_mutex); 155 pthread_mutex_destroy(&g_accesslist_mutex);
143 free( g_accesslist ); 156
144 g_accesslist = 0; 157 if (g_accesslist_old) {
145 g_accesslist_size = 0; 158 free(g_accesslist_old->list);
159 free(g_accesslist_old);
160 g_accesslist_old = 0;
161 }
162
163 if (g_accesslist) {
164 free(g_accesslist->list);
165 free(g_accesslist);
166 g_accesslist = 0;
167 }
146} 168}
147#endif 169#endif
148 170