Browse code

tls: the pointer of cfg structure

- synchronize when updating the list of tls configs and their reference
count
- with parts from patch by Ding Ma, FS#380, contributed under BSD
license
- backport of 208934d47ac1585d42029234267bcceab40ae218

Daniel-Constantin Mierla authored on 06/03/2014 10:57:23
Showing 8 changed files
... ...
@@ -74,7 +74,7 @@ struct cfg_group_tls default_tls_cfg = {
74 74
 	0 /* send_close_notify (off by default)*/
75 75
 };
76 76
 
77
-void* tls_cfg = &default_tls_cfg;
77
+volatile void* tls_cfg = &default_tls_cfg;
78 78
 
79 79
 
80 80
 /* if *to<0 to=default_val, else if to>max_val to=max_val */
... ...
@@ -101,7 +101,7 @@ struct cfg_group_tls {
101 101
 
102 102
 
103 103
 extern struct cfg_group_tls default_tls_cfg;
104
-extern void* tls_cfg;
104
+extern volatile void* tls_cfg;
105 105
 extern cfg_def_t tls_cfg_def[];
106 106
 
107 107
 
... ...
@@ -118,6 +118,7 @@ void tls_free_cfg(tls_domains_cfg_t* cfg)
118 118
 	}
119 119
 	if (cfg->srv_default) tls_free_domain(cfg->srv_default);
120 120
 	if (cfg->cli_default) tls_free_domain(cfg->cli_default);
121
+	shm_free(cfg);
121 122
 }
122 123
 
123 124
 
... ...
@@ -92,7 +92,7 @@ typedef struct tls_domains_cfg {
92 92
 	tls_domain_t* srv_list;    /**< Server domain list */
93 93
 	tls_domain_t* cli_list;    /**< Client domain list */
94 94
 	struct tls_domains_cfg* next; /**< Next element in the garbage list */
95
-	int ref_count;             /**< How many connections use this configuration */
95
+	volatile int ref_count;             /**< How many connections use this configuration */
96 96
 } tls_domains_cfg_t;
97 97
 
98 98
 
... ...
@@ -300,7 +300,7 @@ static int mod_init(void)
300 300
 	}
301 301
 	/* declare configuration */
302 302
 	if (cfg_declare("tls", tls_cfg_def, &default_tls_cfg,
303
-							cfg_sizeof(tls), &tls_cfg)) {
303
+							cfg_sizeof(tls), (void **)&tls_cfg)) {
304 304
 		ERR("failed to register the configuration\n");
305 305
 		return -1;
306 306
 	}
... ...
@@ -81,8 +81,10 @@ static void tls_reload(rpc_t* rpc, void* ctx)
81 81
 	}
82 82
 
83 83
 	DBG("TLS configuration successfuly loaded");
84
+	lock_get(tls_domains_cfg_lock);
84 85
 	cfg->next = (*tls_domains_cfg);
85 86
 	*tls_domains_cfg = cfg;
87
+	lock_release(tls_domains_cfg_lock);
86 88
 	return;
87 89
 
88 90
  error:
... ...
@@ -151,13 +151,9 @@ static int tls_complete_init(struct tcp_connection* c)
151 151
 		goto error2;
152 152
 	}
153 153
 	     /* Get current TLS configuration and increase reference
154
-	      * count immediately. There is no need to lock the structure
155
-	      * here, because it does not get deleted immediately. When
156
-	      * SER reloads TLS configuration it will put the old configuration
157
-	      * on a garbage queue and delete it later, so we know here that
158
-	      * the pointer we get from *tls_domains_cfg will be valid for a while,
159
-		  * at least by the time this function finishes
154
+	      * count immediately.
160 155
 	      */
156
+	lock_get(tls_domains_cfg_lock);
161 157
 	cfg = *tls_domains_cfg;
162 158
 
163 159
 	     /* Increment the reference count in the configuration structure, this
... ...
@@ -165,6 +161,7 @@ static int tls_complete_init(struct tcp_connection* c)
165 161
 	      * not get deleted if there are still connection referencing its SSL_CTX
166 162
 	      */
167 163
 	cfg->ref_count++;
164
+	lock_release(tls_domains_cfg_lock);
168 165
 
169 166
 	if (c->flags & F_CONN_PASSIVE) {
170 167
 		state=S_TLS_ACCEPTING;
... ...
@@ -74,7 +74,7 @@ int shm_asciiz_dup(char** dest, char* val)
74 74
  */
75 75
 void collect_garbage(void)
76 76
 {
77
-	tls_domains_cfg_t* prev, *cur;
77
+	tls_domains_cfg_t* prev, *cur, *next;
78 78
 
79 79
 	     /* Make sure we do not run two garbage collectors
80 80
 	      * at the same time
... ...
@@ -88,14 +88,17 @@ void collect_garbage(void)
88 88
 	cur = (*tls_domains_cfg)->next;
89 89
 
90 90
 	while(cur) {
91
+		next = cur->next;
91 92
 		if (cur->ref_count == 0) {
92
-			     /* Not referenced by any existing connection */
93
+			/* Not referenced by any existing connection */
93 94
 			prev->next = cur->next;
94 95
 			tls_free_cfg(cur);
96
+		} else {
97
+			/* Only update prev if we didn't remove cur */
98
+			prev = cur;
95 99
 		}
96 100
 
97
-		prev = cur;
98
-		cur = cur->next;
101
+		cur = next;
99 102
 	}
100 103
 
101 104
 	lock_release(tls_domains_cfg_lock);