OLD | NEW |
1 /* crypto/ex_data.c */ | 1 /* crypto/ex_data.c */ |
2 | 2 |
3 /* | 3 /* |
4 * Overhaul notes; | 4 * Overhaul notes; |
5 * | 5 * |
6 * This code is now *mostly* thread-safe. It is now easier to understand in what | 6 * This code is now *mostly* thread-safe. It is now easier to understand in what |
7 * ways it is safe and in what ways it is not, which is an improvement. Firstly, | 7 * ways it is safe and in what ways it is not, which is an improvement. Firstly, |
8 * all per-class stacks and index-counters for ex_data are stored in the same | 8 * all per-class stacks and index-counters for ex_data are stored in the same |
9 * global LHASH table (keyed by class). This hash table uses locking for all | 9 * global LHASH table (keyed by class). This hash table uses locking for all |
10 * access with the exception of CRYPTO_cleanup_all_ex_data(), which must only be | 10 * access with the exception of CRYPTO_cleanup_all_ex_data(), which must only be |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
238 typedef struct st_ex_class_item { | 238 typedef struct st_ex_class_item { |
239 int class_index; | 239 int class_index; |
240 STACK_OF(CRYPTO_EX_DATA_FUNCS) *meth; | 240 STACK_OF(CRYPTO_EX_DATA_FUNCS) *meth; |
241 int meth_num; | 241 int meth_num; |
242 } EX_CLASS_ITEM; | 242 } EX_CLASS_ITEM; |
243 | 243 |
244 /* When assigning new class indexes, this is our counter */ | 244 /* When assigning new class indexes, this is our counter */ |
245 static int ex_class = CRYPTO_EX_INDEX_USER; | 245 static int ex_class = CRYPTO_EX_INDEX_USER; |
246 | 246 |
247 /* The global hash table of EX_CLASS_ITEM items */ | 247 /* The global hash table of EX_CLASS_ITEM items */ |
248 static LHASH *ex_data = NULL; | 248 DECLARE_LHASH_OF(EX_CLASS_ITEM); |
| 249 static LHASH_OF(EX_CLASS_ITEM) *ex_data = NULL; |
249 | 250 |
250 /* The callbacks required in the "ex_data" hash table */ | 251 /* The callbacks required in the "ex_data" hash table */ |
251 static unsigned long ex_hash_cb(const void *a_void) | 252 static unsigned long ex_class_item_hash(const EX_CLASS_ITEM *a) |
252 { | 253 { |
253 » return ((const EX_CLASS_ITEM *)a_void)->class_index; | 254 » return a->class_index; |
254 } | 255 } |
255 static int ex_cmp_cb(const void *a_void, const void *b_void) | 256 static IMPLEMENT_LHASH_HASH_FN(ex_class_item, EX_CLASS_ITEM) |
| 257 |
| 258 static int ex_class_item_cmp(const EX_CLASS_ITEM *a, const EX_CLASS_ITEM *b) |
256 { | 259 { |
257 » return (((const EX_CLASS_ITEM *)a_void)->class_index - | 260 » return a->class_index - b->class_index; |
258 » » ((const EX_CLASS_ITEM *)b_void)->class_index); | |
259 } | 261 } |
| 262 static IMPLEMENT_LHASH_COMP_FN(ex_class_item, EX_CLASS_ITEM) |
260 | 263 |
261 /* Internal functions used by the "impl_default" implementation to access the | 264 /* Internal functions used by the "impl_default" implementation to access the |
262 * state */ | 265 * state */ |
263 | 266 |
264 static int ex_data_check(void) | 267 static int ex_data_check(void) |
265 { | 268 { |
266 int toret = 1; | 269 int toret = 1; |
267 CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA); | 270 CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA); |
268 » if(!ex_data && ((ex_data = lh_new(ex_hash_cb, ex_cmp_cb)) == NULL)) | 271 » if(!ex_data |
| 272 » && (ex_data = lh_EX_CLASS_ITEM_new()) == NULL) |
269 toret = 0; | 273 toret = 0; |
270 CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA); | 274 CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA); |
271 return toret; | 275 return toret; |
272 } | 276 } |
273 /* This macros helps reduce the locking from repeated checks because the | 277 /* This macros helps reduce the locking from repeated checks because the |
274 * ex_data_check() function checks ex_data again inside a lock. */ | 278 * ex_data_check() function checks ex_data again inside a lock. */ |
275 #define EX_DATA_CHECK(iffail) if(!ex_data && !ex_data_check()) {iffail} | 279 #define EX_DATA_CHECK(iffail) if(!ex_data && !ex_data_check()) {iffail} |
276 | 280 |
277 /* This "inner" callback is used by the callback function that follows it */ | 281 /* This "inner" callback is used by the callback function that follows it */ |
278 static void def_cleanup_util_cb(CRYPTO_EX_DATA_FUNCS *funcs) | 282 static void def_cleanup_util_cb(CRYPTO_EX_DATA_FUNCS *funcs) |
(...skipping 12 matching lines...) Expand all Loading... |
291 } | 295 } |
292 | 296 |
293 /* Return the EX_CLASS_ITEM from the "ex_data" hash table that corresponds to a | 297 /* Return the EX_CLASS_ITEM from the "ex_data" hash table that corresponds to a |
294 * given class. Handles locking. */ | 298 * given class. Handles locking. */ |
295 static EX_CLASS_ITEM *def_get_class(int class_index) | 299 static EX_CLASS_ITEM *def_get_class(int class_index) |
296 { | 300 { |
297 EX_CLASS_ITEM d, *p, *gen; | 301 EX_CLASS_ITEM d, *p, *gen; |
298 EX_DATA_CHECK(return NULL;) | 302 EX_DATA_CHECK(return NULL;) |
299 d.class_index = class_index; | 303 d.class_index = class_index; |
300 CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA); | 304 CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA); |
301 » p = lh_retrieve(ex_data, &d); | 305 » p = lh_EX_CLASS_ITEM_retrieve(ex_data, &d); |
302 if(!p) | 306 if(!p) |
303 { | 307 { |
304 gen = OPENSSL_malloc(sizeof(EX_CLASS_ITEM)); | 308 gen = OPENSSL_malloc(sizeof(EX_CLASS_ITEM)); |
305 if(gen) | 309 if(gen) |
306 { | 310 { |
307 gen->class_index = class_index; | 311 gen->class_index = class_index; |
308 gen->meth_num = 0; | 312 gen->meth_num = 0; |
309 gen->meth = sk_CRYPTO_EX_DATA_FUNCS_new_null(); | 313 gen->meth = sk_CRYPTO_EX_DATA_FUNCS_new_null(); |
310 if(!gen->meth) | 314 if(!gen->meth) |
311 OPENSSL_free(gen); | 315 OPENSSL_free(gen); |
312 else | 316 else |
313 { | 317 { |
314 /* Because we're inside the ex_data lock, the | 318 /* Because we're inside the ex_data lock, the |
315 * return value from the insert will be NULL */ | 319 * return value from the insert will be NULL */ |
316 » » » » lh_insert(ex_data, gen); | 320 » » » » (void)lh_EX_CLASS_ITEM_insert(ex_data, gen); |
317 p = gen; | 321 p = gen; |
318 } | 322 } |
319 } | 323 } |
320 } | 324 } |
321 CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA); | 325 CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA); |
322 if(!p) | 326 if(!p) |
323 CRYPTOerr(CRYPTO_F_DEF_GET_CLASS,ERR_R_MALLOC_FAILURE); | 327 CRYPTOerr(CRYPTO_F_DEF_GET_CLASS,ERR_R_MALLOC_FAILURE); |
324 return p; | 328 return p; |
325 } | 329 } |
326 | 330 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
368 int toret; | 372 int toret; |
369 CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA); | 373 CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA); |
370 toret = ex_class++; | 374 toret = ex_class++; |
371 CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA); | 375 CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA); |
372 return toret; | 376 return toret; |
373 } | 377 } |
374 | 378 |
375 static void int_cleanup(void) | 379 static void int_cleanup(void) |
376 { | 380 { |
377 EX_DATA_CHECK(return;) | 381 EX_DATA_CHECK(return;) |
378 » lh_doall(ex_data, def_cleanup_cb); | 382 » lh_EX_CLASS_ITEM_doall(ex_data, def_cleanup_cb); |
379 » lh_free(ex_data); | 383 » lh_EX_CLASS_ITEM_free(ex_data); |
380 ex_data = NULL; | 384 ex_data = NULL; |
381 impl = NULL; | 385 impl = NULL; |
382 } | 386 } |
383 | 387 |
384 static int int_get_new_index(int class_index, long argl, void *argp, | 388 static int int_get_new_index(int class_index, long argl, void *argp, |
385 CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func, | 389 CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func, |
386 CRYPTO_EX_free *free_func) | 390 CRYPTO_EX_free *free_func) |
387 { | 391 { |
388 EX_CLASS_ITEM *item = def_get_class(class_index); | 392 EX_CLASS_ITEM *item = def_get_class(class_index); |
389 if(!item) | 393 if(!item) |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
445 char *ptr; | 449 char *ptr; |
446 CRYPTO_EX_DATA_FUNCS **storage = NULL; | 450 CRYPTO_EX_DATA_FUNCS **storage = NULL; |
447 EX_CLASS_ITEM *item; | 451 EX_CLASS_ITEM *item; |
448 if(!from->sk) | 452 if(!from->sk) |
449 /* 'to' should be "blank" which *is* just like 'from' */ | 453 /* 'to' should be "blank" which *is* just like 'from' */ |
450 return 1; | 454 return 1; |
451 if((item = def_get_class(class_index)) == NULL) | 455 if((item = def_get_class(class_index)) == NULL) |
452 return 0; | 456 return 0; |
453 CRYPTO_r_lock(CRYPTO_LOCK_EX_DATA); | 457 CRYPTO_r_lock(CRYPTO_LOCK_EX_DATA); |
454 mx = sk_CRYPTO_EX_DATA_FUNCS_num(item->meth); | 458 mx = sk_CRYPTO_EX_DATA_FUNCS_num(item->meth); |
455 » j = sk_num(from->sk); | 459 » j = sk_void_num(from->sk); |
456 if(j < mx) | 460 if(j < mx) |
457 mx = j; | 461 mx = j; |
458 if(mx > 0) | 462 if(mx > 0) |
459 { | 463 { |
460 storage = OPENSSL_malloc(mx * sizeof(CRYPTO_EX_DATA_FUNCS*)); | 464 storage = OPENSSL_malloc(mx * sizeof(CRYPTO_EX_DATA_FUNCS*)); |
461 if(!storage) | 465 if(!storage) |
462 goto skip; | 466 goto skip; |
463 for(i = 0; i < mx; i++) | 467 for(i = 0; i < mx; i++) |
464 storage[i] = sk_CRYPTO_EX_DATA_FUNCS_value(item->meth,i)
; | 468 storage[i] = sk_CRYPTO_EX_DATA_FUNCS_value(item->meth,i)
; |
465 } | 469 } |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
516 { | 520 { |
517 ptr = CRYPTO_get_ex_data(ad,i); | 521 ptr = CRYPTO_get_ex_data(ad,i); |
518 storage[i]->free_func(obj,ptr,ad,i, | 522 storage[i]->free_func(obj,ptr,ad,i, |
519 storage[i]->argl,storage[i]->argp); | 523 storage[i]->argl,storage[i]->argp); |
520 } | 524 } |
521 } | 525 } |
522 if(storage) | 526 if(storage) |
523 OPENSSL_free(storage); | 527 OPENSSL_free(storage); |
524 if(ad->sk) | 528 if(ad->sk) |
525 { | 529 { |
526 » » sk_free(ad->sk); | 530 » » sk_void_free(ad->sk); |
527 ad->sk=NULL; | 531 ad->sk=NULL; |
528 } | 532 } |
529 } | 533 } |
530 | 534 |
531 /********************************************************************/ | 535 /********************************************************************/ |
532 /* API functions that defer all "state" operations to the "ex_data" | 536 /* API functions that defer all "state" operations to the "ex_data" |
533 * implementation we have set. */ | 537 * implementation we have set. */ |
534 | 538 |
535 /* Obtain an index for a new class (not the same as getting a new index within | 539 /* Obtain an index for a new class (not the same as getting a new index within |
536 * an existing class - this is actually getting a new *class*) */ | 540 * an existing class - this is actually getting a new *class*) */ |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
589 } | 593 } |
590 | 594 |
591 /* For a given CRYPTO_EX_DATA variable, set the value corresponding to a | 595 /* For a given CRYPTO_EX_DATA variable, set the value corresponding to a |
592 * particular index in the class used by this variable */ | 596 * particular index in the class used by this variable */ |
593 int CRYPTO_set_ex_data(CRYPTO_EX_DATA *ad, int idx, void *val) | 597 int CRYPTO_set_ex_data(CRYPTO_EX_DATA *ad, int idx, void *val) |
594 { | 598 { |
595 int i; | 599 int i; |
596 | 600 |
597 if (ad->sk == NULL) | 601 if (ad->sk == NULL) |
598 { | 602 { |
599 » » if ((ad->sk=sk_new_null()) == NULL) | 603 » » if ((ad->sk=sk_void_new_null()) == NULL) |
600 { | 604 { |
601 CRYPTOerr(CRYPTO_F_CRYPTO_SET_EX_DATA,ERR_R_MALLOC_FAILU
RE); | 605 CRYPTOerr(CRYPTO_F_CRYPTO_SET_EX_DATA,ERR_R_MALLOC_FAILU
RE); |
602 return(0); | 606 return(0); |
603 } | 607 } |
604 } | 608 } |
605 » i=sk_num(ad->sk); | 609 » i=sk_void_num(ad->sk); |
606 | 610 |
607 while (i <= idx) | 611 while (i <= idx) |
608 { | 612 { |
609 » » if (!sk_push(ad->sk,NULL)) | 613 » » if (!sk_void_push(ad->sk,NULL)) |
610 { | 614 { |
611 CRYPTOerr(CRYPTO_F_CRYPTO_SET_EX_DATA,ERR_R_MALLOC_FAILU
RE); | 615 CRYPTOerr(CRYPTO_F_CRYPTO_SET_EX_DATA,ERR_R_MALLOC_FAILU
RE); |
612 return(0); | 616 return(0); |
613 } | 617 } |
614 i++; | 618 i++; |
615 } | 619 } |
616 » sk_set(ad->sk,idx,val); | 620 » sk_void_set(ad->sk,idx,val); |
617 return(1); | 621 return(1); |
618 } | 622 } |
619 | 623 |
620 /* For a given CRYPTO_EX_DATA_ variable, get the value corresponding to a | 624 /* For a given CRYPTO_EX_DATA_ variable, get the value corresponding to a |
621 * particular index in the class used by this variable */ | 625 * particular index in the class used by this variable */ |
622 void *CRYPTO_get_ex_data(const CRYPTO_EX_DATA *ad, int idx) | 626 void *CRYPTO_get_ex_data(const CRYPTO_EX_DATA *ad, int idx) |
623 { | 627 { |
624 if (ad->sk == NULL) | 628 if (ad->sk == NULL) |
625 return(0); | 629 return(0); |
626 » else if (idx >= sk_num(ad->sk)) | 630 » else if (idx >= sk_void_num(ad->sk)) |
627 return(0); | 631 return(0); |
628 else | 632 else |
629 » » return(sk_value(ad->sk,idx)); | 633 » » return(sk_void_value(ad->sk,idx)); |
630 } | 634 } |
631 | 635 |
632 IMPLEMENT_STACK_OF(CRYPTO_EX_DATA_FUNCS) | 636 IMPLEMENT_STACK_OF(CRYPTO_EX_DATA_FUNCS) |
OLD | NEW |