VirtualBox

source: vbox/trunk/src/libs/openssl-3.0.7/crypto/mem_sec.c@ 97371

Last change on this file since 97371 was 95238, checked in by vboxsync, 3 years ago

libs/openssl-3.0.3: Fix for building on OS/2, bugref:10128

File size: 19.4 KB
Line 
1/*
2 * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
3 * Copyright 2004-2014, Akamai Technologies. All Rights Reserved.
4 *
5 * Licensed under the Apache License 2.0 (the "License"). You may not use
6 * this file except in compliance with the License. You can obtain a copy
7 * in the file LICENSE in the source distribution or at
8 * https://www.openssl.org/source/license.html
9 */
10
11/*
12 * This file is in two halves. The first half implements the public API
13 * to be used by external consumers, and to be used by OpenSSL to store
14 * data in a "secure arena." The second half implements the secure arena.
15 * For details on that implementation, see below (look for uppercase
16 * "SECURE HEAP IMPLEMENTATION").
17 */
18#include "e_os.h"
19#include <openssl/crypto.h>
20
21#include <string.h>
22
23#if defined(VBOX)
24# include <iprt/memsafer.h>
25#else
26#ifndef OPENSSL_NO_SECURE_MEMORY
27# if defined(_WIN32)
28# include <windows.h>
29# endif
30# include <stdlib.h>
31# include <assert.h>
32# if defined(OPENSSL_SYS_UNIX)
33# include <unistd.h>
34# endif
35# include <sys/types.h>
36# if defined(OPENSSL_SYS_UNIX)
37# include <sys/mman.h>
38# if defined(__FreeBSD__)
39# define MADV_DONTDUMP MADV_NOCORE
40# endif
41# if !defined(MAP_CONCEAL)
42# define MAP_CONCEAL 0
43# endif
44# endif
45# if defined(OPENSSL_SYS_LINUX)
46# include <sys/syscall.h>
47# if defined(SYS_mlock2)
48# include <linux/mman.h>
49# include <errno.h>
50# endif
51# include <sys/param.h>
52# endif
53# include <sys/stat.h>
54# include <fcntl.h>
55#endif
56#endif /* !VBOX */
57
58#define CLEAR(p, s) OPENSSL_cleanse(p, s)
59#ifndef PAGE_SIZE
60# define PAGE_SIZE 4096
61#endif
62#if !defined(MAP_ANON) && defined(MAP_ANONYMOUS)
63# define MAP_ANON MAP_ANONYMOUS
64#endif
65
66#ifndef OPENSSL_NO_SECURE_MEMORY
67static size_t secure_mem_used;
68
69static int secure_mem_initialized;
70
71static CRYPTO_RWLOCK *sec_malloc_lock = NULL;
72
73/*
74 * These are the functions that must be implemented by a secure heap (sh).
75 */
76static int sh_init(size_t size, size_t minsize);
77static void *sh_malloc(size_t size);
78static void sh_free(void *ptr);
79static void sh_done(void);
80static size_t sh_actual_size(char *ptr);
81static int sh_allocated(const char *ptr);
82#endif
83
84int CRYPTO_secure_malloc_init(size_t size, size_t minsize)
85{
86#ifndef VBOX
87#ifndef OPENSSL_NO_SECURE_MEMORY
88 int ret = 0;
89
90 if (!secure_mem_initialized) {
91 sec_malloc_lock = CRYPTO_THREAD_lock_new();
92 if (sec_malloc_lock == NULL)
93 return 0;
94 if ((ret = sh_init(size, minsize)) != 0) {
95 secure_mem_initialized = 1;
96 } else {
97 CRYPTO_THREAD_lock_free(sec_malloc_lock);
98 sec_malloc_lock = NULL;
99 }
100 }
101
102 return ret;
103#else
104 return 0;
105#endif /* OPENSSL_NO_SECURE_MEMORY */
106#else
107 return 0;
108#endif /* VBOX */
109}
110
111int CRYPTO_secure_malloc_done(void)
112{
113#ifndef VBOX
114#ifndef OPENSSL_NO_SECURE_MEMORY
115 if (secure_mem_used == 0) {
116 sh_done();
117 secure_mem_initialized = 0;
118 CRYPTO_THREAD_lock_free(sec_malloc_lock);
119 sec_malloc_lock = NULL;
120 return 1;
121 }
122#endif /* OPENSSL_NO_SECURE_MEMORY */
123#endif /* VBOX */
124 return 0;
125}
126
127int CRYPTO_secure_malloc_initialized(void)
128{
129#ifndef VBOX
130#ifndef OPENSSL_NO_SECURE_MEMORY
131 return secure_mem_initialized;
132#else
133 return 0;
134#endif /* OPENSSL_NO_SECURE_MEMORY */
135#else
136 return 0;
137#endif /* VBOX */
138}
139
140void *CRYPTO_secure_malloc(size_t num, const char *file, int line)
141{
142#ifndef VBOX
143#ifndef OPENSSL_NO_SECURE_MEMORY
144 void *ret;
145 size_t actual_size;
146
147 if (!secure_mem_initialized) {
148 return CRYPTO_malloc(num, file, line);
149 }
150 if (!CRYPTO_THREAD_write_lock(sec_malloc_lock))
151 return NULL;
152 ret = sh_malloc(num);
153 actual_size = ret ? sh_actual_size(ret) : 0;
154 secure_mem_used += actual_size;
155 CRYPTO_THREAD_unlock(sec_malloc_lock);
156 return ret;
157#else
158 return CRYPTO_malloc(num, file, line);
159#endif /* OPENSSL_NO_SECURE_MEMORY */
160#else
161 RT_NOREF(line);
162 return RTMemSaferAllocZTag(num, file);
163#endif /* VBOX */
164}
165
166void *CRYPTO_secure_zalloc(size_t num, const char *file, int line)
167{
168#ifndef VBOX
169#ifndef OPENSSL_NO_SECURE_MEMORY
170 if (secure_mem_initialized)
171 /* CRYPTO_secure_malloc() zeroes allocations when it is implemented */
172 return CRYPTO_secure_malloc(num, file, line);
173#endif
174 return CRYPTO_zalloc(num, file, line);
175#else
176 RT_NOREF(line);
177 return RTMemSaferAllocZTag(num, file);
178#endif
179}
180
181void CRYPTO_secure_free(void *ptr, const char *file, int line)
182{
183#ifndef VBOX
184#ifndef OPENSSL_NO_SECURE_MEMORY
185 size_t actual_size;
186
187 if (ptr == NULL)
188 return;
189 if (!CRYPTO_secure_allocated(ptr)) {
190 CRYPTO_free(ptr, file, line);
191 return;
192 }
193 if (!CRYPTO_THREAD_write_lock(sec_malloc_lock))
194 return;
195 actual_size = sh_actual_size(ptr);
196 CLEAR(ptr, actual_size);
197 secure_mem_used -= actual_size;
198 sh_free(ptr);
199 CRYPTO_THREAD_unlock(sec_malloc_lock);
200#else
201 CRYPTO_free(ptr, file, line);
202#endif /* OPENSSL_NO_SECURE_MEMORY */
203#else
204 RT_NOREF(line);
205 RTMemSaferFree(ptr, 0);
206#endif /* VBOX */
207}
208
209void CRYPTO_secure_clear_free(void *ptr, size_t num,
210 const char *file, int line)
211{
212#ifndef VBOX
213#ifndef OPENSSL_NO_SECURE_MEMORY
214 size_t actual_size;
215
216 if (ptr == NULL)
217 return;
218 if (!CRYPTO_secure_allocated(ptr)) {
219 OPENSSL_cleanse(ptr, num);
220 CRYPTO_free(ptr, file, line);
221 return;
222 }
223 if (!CRYPTO_THREAD_write_lock(sec_malloc_lock))
224 return;
225 actual_size = sh_actual_size(ptr);
226 CLEAR(ptr, actual_size);
227 secure_mem_used -= actual_size;
228 sh_free(ptr);
229 CRYPTO_THREAD_unlock(sec_malloc_lock);
230#else
231 if (ptr == NULL)
232 return;
233 OPENSSL_cleanse(ptr, num);
234 CRYPTO_free(ptr, file, line);
235#endif /* OPENSSL_NO_SECURE_MEMORY */
236#else
237 RT_NOREF(line);
238 RTMemSaferFree(ptr, 0);
239#endif /* VBOX */
240}
241
242int CRYPTO_secure_allocated(const void *ptr)
243{
244#ifndef VBOX
245#ifndef OPENSSL_NO_SECURE_MEMORY
246 if (!secure_mem_initialized)
247 return 0;
248 /*
249 * Only read accesses to the arena take place in sh_allocated() and this
250 * is only changed by the sh_init() and sh_done() calls which are not
251 * locked. Hence, it is safe to make this check without a lock too.
252 */
253 return sh_allocated(ptr);
254#else
255 return 0;
256#endif /* OPENSSL_NO_SECURE_MEMORY */
257#else
258 return RTMemSaferGetSize((void *)ptr) > 0;
259#endif /* VBOX */
260}
261
262size_t CRYPTO_secure_used(void)
263{
264#ifndef VBOX
265#ifndef OPENSSL_NO_SECURE_MEMORY
266 return secure_mem_used;
267#else
268 return 0;
269#endif /* OPENSSL_NO_SECURE_MEMORY */
270#else
271 return 0;
272#endif /* VBOX */
273}
274
275size_t CRYPTO_secure_actual_size(void *ptr)
276{
277#ifndef VBOX
278#ifndef OPENSSL_NO_SECURE_MEMORY
279 size_t actual_size;
280
281 if (!CRYPTO_THREAD_write_lock(sec_malloc_lock))
282 return 0;
283 actual_size = sh_actual_size(ptr);
284 CRYPTO_THREAD_unlock(sec_malloc_lock);
285 return actual_size;
286#else
287 return 0;
288#endif
289#else
290 return RTMemSaferGetSize(ptr);
291#endif /* VBOX */
292}
293
294#ifndef VBOX
295/*
296 * SECURE HEAP IMPLEMENTATION
297 */
298#ifndef OPENSSL_NO_SECURE_MEMORY
299
300
301/*
302 * The implementation provided here uses a fixed-sized mmap() heap,
303 * which is locked into memory, not written to core files, and protected
304 * on either side by an unmapped page, which will catch pointer overruns
305 * (or underruns) and an attempt to read data out of the secure heap.
306 * Free'd memory is zero'd or otherwise cleansed.
307 *
308 * This is a pretty standard buddy allocator. We keep areas in a multiple
309 * of "sh.minsize" units. The freelist and bitmaps are kept separately,
310 * so all (and only) data is kept in the mmap'd heap.
311 *
312 * This code assumes eight-bit bytes. The numbers 3 and 7 are all over the
313 * place.
314 */
315
316#define ONE ((size_t)1)
317
318# define TESTBIT(t, b) (t[(b) >> 3] & (ONE << ((b) & 7)))
319# define SETBIT(t, b) (t[(b) >> 3] |= (ONE << ((b) & 7)))
320# define CLEARBIT(t, b) (t[(b) >> 3] &= (0xFF & ~(ONE << ((b) & 7))))
321
322#define WITHIN_ARENA(p) \
323 ((char*)(p) >= sh.arena && (char*)(p) < &sh.arena[sh.arena_size])
324#define WITHIN_FREELIST(p) \
325 ((char*)(p) >= (char*)sh.freelist && (char*)(p) < (char*)&sh.freelist[sh.freelist_size])
326
327
328typedef struct sh_list_st
329{
330 struct sh_list_st *next;
331 struct sh_list_st **p_next;
332} SH_LIST;
333
334typedef struct sh_st
335{
336 char* map_result;
337 size_t map_size;
338 char *arena;
339 size_t arena_size;
340 char **freelist;
341 ossl_ssize_t freelist_size;
342 size_t minsize;
343 unsigned char *bittable;
344 unsigned char *bitmalloc;
345 size_t bittable_size; /* size in bits */
346} SH;
347
348static SH sh;
349
350static size_t sh_getlist(char *ptr)
351{
352 ossl_ssize_t list = sh.freelist_size - 1;
353 size_t bit = (sh.arena_size + ptr - sh.arena) / sh.minsize;
354
355 for (; bit; bit >>= 1, list--) {
356 if (TESTBIT(sh.bittable, bit))
357 break;
358 OPENSSL_assert((bit & 1) == 0);
359 }
360
361 return list;
362}
363
364
365static int sh_testbit(char *ptr, int list, unsigned char *table)
366{
367 size_t bit;
368
369 OPENSSL_assert(list >= 0 && list < sh.freelist_size);
370 OPENSSL_assert(((ptr - sh.arena) & ((sh.arena_size >> list) - 1)) == 0);
371 bit = (ONE << list) + ((ptr - sh.arena) / (sh.arena_size >> list));
372 OPENSSL_assert(bit > 0 && bit < sh.bittable_size);
373 return TESTBIT(table, bit);
374}
375
376static void sh_clearbit(char *ptr, int list, unsigned char *table)
377{
378 size_t bit;
379
380 OPENSSL_assert(list >= 0 && list < sh.freelist_size);
381 OPENSSL_assert(((ptr - sh.arena) & ((sh.arena_size >> list) - 1)) == 0);
382 bit = (ONE << list) + ((ptr - sh.arena) / (sh.arena_size >> list));
383 OPENSSL_assert(bit > 0 && bit < sh.bittable_size);
384 OPENSSL_assert(TESTBIT(table, bit));
385 CLEARBIT(table, bit);
386}
387
388static void sh_setbit(char *ptr, int list, unsigned char *table)
389{
390 size_t bit;
391
392 OPENSSL_assert(list >= 0 && list < sh.freelist_size);
393 OPENSSL_assert(((ptr - sh.arena) & ((sh.arena_size >> list) - 1)) == 0);
394 bit = (ONE << list) + ((ptr - sh.arena) / (sh.arena_size >> list));
395 OPENSSL_assert(bit > 0 && bit < sh.bittable_size);
396 OPENSSL_assert(!TESTBIT(table, bit));
397 SETBIT(table, bit);
398}
399
400static void sh_add_to_list(char **list, char *ptr)
401{
402 SH_LIST *temp;
403
404 OPENSSL_assert(WITHIN_FREELIST(list));
405 OPENSSL_assert(WITHIN_ARENA(ptr));
406
407 temp = (SH_LIST *)ptr;
408 temp->next = *(SH_LIST **)list;
409 OPENSSL_assert(temp->next == NULL || WITHIN_ARENA(temp->next));
410 temp->p_next = (SH_LIST **)list;
411
412 if (temp->next != NULL) {
413 OPENSSL_assert((char **)temp->next->p_next == list);
414 temp->next->p_next = &(temp->next);
415 }
416
417 *list = ptr;
418}
419
420static void sh_remove_from_list(char *ptr)
421{
422 SH_LIST *temp, *temp2;
423
424 temp = (SH_LIST *)ptr;
425 if (temp->next != NULL)
426 temp->next->p_next = temp->p_next;
427 *temp->p_next = temp->next;
428 if (temp->next == NULL)
429 return;
430
431 temp2 = temp->next;
432 OPENSSL_assert(WITHIN_FREELIST(temp2->p_next) || WITHIN_ARENA(temp2->p_next));
433}
434
435
436static int sh_init(size_t size, size_t minsize)
437{
438 int ret;
439 size_t i;
440 size_t pgsize;
441 size_t aligned;
442#if defined(_WIN32)
443 DWORD flOldProtect;
444 SYSTEM_INFO systemInfo;
445#endif
446
447 memset(&sh, 0, sizeof(sh));
448
449 /* make sure size is a powers of 2 */
450 OPENSSL_assert(size > 0);
451 OPENSSL_assert((size & (size - 1)) == 0);
452 if (size == 0 || (size & (size - 1)) != 0)
453 goto err;
454
455 if (minsize <= sizeof(SH_LIST)) {
456 OPENSSL_assert(sizeof(SH_LIST) <= 65536);
457 /*
458 * Compute the minimum possible allocation size.
459 * This must be a power of 2 and at least as large as the SH_LIST
460 * structure.
461 */
462 minsize = sizeof(SH_LIST) - 1;
463 minsize |= minsize >> 1;
464 minsize |= minsize >> 2;
465 if (sizeof(SH_LIST) > 16)
466 minsize |= minsize >> 4;
467 if (sizeof(SH_LIST) > 256)
468 minsize |= minsize >> 8;
469 minsize++;
470 } else {
471 /* make sure minsize is a powers of 2 */
472 OPENSSL_assert((minsize & (minsize - 1)) == 0);
473 if ((minsize & (minsize - 1)) != 0)
474 goto err;
475 }
476
477 sh.arena_size = size;
478 sh.minsize = minsize;
479 sh.bittable_size = (sh.arena_size / sh.minsize) * 2;
480
481 /* Prevent allocations of size 0 later on */
482 if (sh.bittable_size >> 3 == 0)
483 goto err;
484
485 sh.freelist_size = -1;
486 for (i = sh.bittable_size; i; i >>= 1)
487 sh.freelist_size++;
488
489 sh.freelist = OPENSSL_zalloc(sh.freelist_size * sizeof(char *));
490 OPENSSL_assert(sh.freelist != NULL);
491 if (sh.freelist == NULL)
492 goto err;
493
494 sh.bittable = OPENSSL_zalloc(sh.bittable_size >> 3);
495 OPENSSL_assert(sh.bittable != NULL);
496 if (sh.bittable == NULL)
497 goto err;
498
499 sh.bitmalloc = OPENSSL_zalloc(sh.bittable_size >> 3);
500 OPENSSL_assert(sh.bitmalloc != NULL);
501 if (sh.bitmalloc == NULL)
502 goto err;
503
504 /* Allocate space for heap, and two extra pages as guards */
505#if defined(_SC_PAGE_SIZE) || defined (_SC_PAGESIZE)
506 {
507# if defined(_SC_PAGE_SIZE)
508 long tmppgsize = sysconf(_SC_PAGE_SIZE);
509# else
510 long tmppgsize = sysconf(_SC_PAGESIZE);
511# endif
512 if (tmppgsize < 1)
513 pgsize = PAGE_SIZE;
514 else
515 pgsize = (size_t)tmppgsize;
516 }
517#elif defined(_WIN32)
518 GetSystemInfo(&systemInfo);
519 pgsize = (size_t)systemInfo.dwPageSize;
520#else
521 pgsize = PAGE_SIZE;
522#endif
523 sh.map_size = pgsize + sh.arena_size + pgsize;
524
525#if !defined(_WIN32)
526# ifdef MAP_ANON
527 sh.map_result = mmap(NULL, sh.map_size,
528 PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE|MAP_CONCEAL, -1, 0);
529# else
530 {
531 int fd;
532
533 sh.map_result = MAP_FAILED;
534 if ((fd = open("/dev/zero", O_RDWR)) >= 0) {
535 sh.map_result = mmap(NULL, sh.map_size,
536 PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
537 close(fd);
538 }
539 }
540# endif
541 if (sh.map_result == MAP_FAILED)
542 goto err;
543#else
544 sh.map_result = VirtualAlloc(NULL, sh.map_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
545
546 if (sh.map_result == NULL)
547 goto err;
548#endif
549
550 sh.arena = (char *)(sh.map_result + pgsize);
551 sh_setbit(sh.arena, 0, sh.bittable);
552 sh_add_to_list(&sh.freelist[0], sh.arena);
553
554 /* Now try to add guard pages and lock into memory. */
555 ret = 1;
556
557#if !defined(_WIN32)
558 /* Starting guard is already aligned from mmap. */
559 if (mprotect(sh.map_result, pgsize, PROT_NONE) < 0)
560 ret = 2;
561#else
562 if (VirtualProtect(sh.map_result, pgsize, PAGE_NOACCESS, &flOldProtect) == FALSE)
563 ret = 2;
564#endif
565
566 /* Ending guard page - need to round up to page boundary */
567 aligned = (pgsize + sh.arena_size + (pgsize - 1)) & ~(pgsize - 1);
568#if !defined(_WIN32)
569 if (mprotect(sh.map_result + aligned, pgsize, PROT_NONE) < 0)
570 ret = 2;
571#else
572 if (VirtualProtect(sh.map_result + aligned, pgsize, PAGE_NOACCESS, &flOldProtect) == FALSE)
573 ret = 2;
574#endif
575
576#if defined(OPENSSL_SYS_LINUX) && defined(MLOCK_ONFAULT) && defined(SYS_mlock2)
577 if (syscall(SYS_mlock2, sh.arena, sh.arena_size, MLOCK_ONFAULT) < 0) {
578 if (errno == ENOSYS) {
579 if (mlock(sh.arena, sh.arena_size) < 0)
580 ret = 2;
581 } else {
582 ret = 2;
583 }
584 }
585#elif defined(_WIN32)
586 if (VirtualLock(sh.arena, sh.arena_size) == FALSE)
587 ret = 2;
588#else
589 if (mlock(sh.arena, sh.arena_size) < 0)
590 ret = 2;
591#endif
592#ifdef MADV_DONTDUMP
593 if (madvise(sh.arena, sh.arena_size, MADV_DONTDUMP) < 0)
594 ret = 2;
595#endif
596
597 return ret;
598
599 err:
600 sh_done();
601 return 0;
602}
603
604static void sh_done(void)
605{
606 OPENSSL_free(sh.freelist);
607 OPENSSL_free(sh.bittable);
608 OPENSSL_free(sh.bitmalloc);
609#if !defined(_WIN32)
610 if (sh.map_result != MAP_FAILED && sh.map_size)
611 munmap(sh.map_result, sh.map_size);
612#else
613 if (sh.map_result != NULL && sh.map_size)
614 VirtualFree(sh.map_result, 0, MEM_RELEASE);
615#endif
616 memset(&sh, 0, sizeof(sh));
617}
618
619static int sh_allocated(const char *ptr)
620{
621 return WITHIN_ARENA(ptr) ? 1 : 0;
622}
623
624static char *sh_find_my_buddy(char *ptr, int list)
625{
626 size_t bit;
627 char *chunk = NULL;
628
629 bit = (ONE << list) + (ptr - sh.arena) / (sh.arena_size >> list);
630 bit ^= 1;
631
632 if (TESTBIT(sh.bittable, bit) && !TESTBIT(sh.bitmalloc, bit))
633 chunk = sh.arena + ((bit & ((ONE << list) - 1)) * (sh.arena_size >> list));
634
635 return chunk;
636}
637
638static void *sh_malloc(size_t size)
639{
640 ossl_ssize_t list, slist;
641 size_t i;
642 char *chunk;
643
644 if (size > sh.arena_size)
645 return NULL;
646
647 list = sh.freelist_size - 1;
648 for (i = sh.minsize; i < size; i <<= 1)
649 list--;
650 if (list < 0)
651 return NULL;
652
653 /* try to find a larger entry to split */
654 for (slist = list; slist >= 0; slist--)
655 if (sh.freelist[slist] != NULL)
656 break;
657 if (slist < 0)
658 return NULL;
659
660 /* split larger entry */
661 while (slist != list) {
662 char *temp = sh.freelist[slist];
663
664 /* remove from bigger list */
665 OPENSSL_assert(!sh_testbit(temp, slist, sh.bitmalloc));
666 sh_clearbit(temp, slist, sh.bittable);
667 sh_remove_from_list(temp);
668 OPENSSL_assert(temp != sh.freelist[slist]);
669
670 /* done with bigger list */
671 slist++;
672
673 /* add to smaller list */
674 OPENSSL_assert(!sh_testbit(temp, slist, sh.bitmalloc));
675 sh_setbit(temp, slist, sh.bittable);
676 sh_add_to_list(&sh.freelist[slist], temp);
677 OPENSSL_assert(sh.freelist[slist] == temp);
678
679 /* split in 2 */
680 temp += sh.arena_size >> slist;
681 OPENSSL_assert(!sh_testbit(temp, slist, sh.bitmalloc));
682 sh_setbit(temp, slist, sh.bittable);
683 sh_add_to_list(&sh.freelist[slist], temp);
684 OPENSSL_assert(sh.freelist[slist] == temp);
685
686 OPENSSL_assert(temp-(sh.arena_size >> slist) == sh_find_my_buddy(temp, slist));
687 }
688
689 /* peel off memory to hand back */
690 chunk = sh.freelist[list];
691 OPENSSL_assert(sh_testbit(chunk, list, sh.bittable));
692 sh_setbit(chunk, list, sh.bitmalloc);
693 sh_remove_from_list(chunk);
694
695 OPENSSL_assert(WITHIN_ARENA(chunk));
696
697 /* zero the free list header as a precaution against information leakage */
698 memset(chunk, 0, sizeof(SH_LIST));
699
700 return chunk;
701}
702
703static void sh_free(void *ptr)
704{
705 size_t list;
706 void *buddy;
707
708 if (ptr == NULL)
709 return;
710 OPENSSL_assert(WITHIN_ARENA(ptr));
711 if (!WITHIN_ARENA(ptr))
712 return;
713
714 list = sh_getlist(ptr);
715 OPENSSL_assert(sh_testbit(ptr, list, sh.bittable));
716 sh_clearbit(ptr, list, sh.bitmalloc);
717 sh_add_to_list(&sh.freelist[list], ptr);
718
719 /* Try to coalesce two adjacent free areas. */
720 while ((buddy = sh_find_my_buddy(ptr, list)) != NULL) {
721 OPENSSL_assert(ptr == sh_find_my_buddy(buddy, list));
722 OPENSSL_assert(ptr != NULL);
723 OPENSSL_assert(!sh_testbit(ptr, list, sh.bitmalloc));
724 sh_clearbit(ptr, list, sh.bittable);
725 sh_remove_from_list(ptr);
726 OPENSSL_assert(!sh_testbit(ptr, list, sh.bitmalloc));
727 sh_clearbit(buddy, list, sh.bittable);
728 sh_remove_from_list(buddy);
729
730 list--;
731
732 /* Zero the higher addressed block's free list pointers */
733 memset(ptr > buddy ? ptr : buddy, 0, sizeof(SH_LIST));
734 if (ptr > buddy)
735 ptr = buddy;
736
737 OPENSSL_assert(!sh_testbit(ptr, list, sh.bitmalloc));
738 sh_setbit(ptr, list, sh.bittable);
739 sh_add_to_list(&sh.freelist[list], ptr);
740 OPENSSL_assert(sh.freelist[list] == ptr);
741 }
742}
743
744static size_t sh_actual_size(char *ptr)
745{
746 int list;
747
748 OPENSSL_assert(WITHIN_ARENA(ptr));
749 if (!WITHIN_ARENA(ptr))
750 return 0;
751 list = sh_getlist(ptr);
752 OPENSSL_assert(sh_testbit(ptr, list, sh.bittable));
753 return sh.arena_size / (ONE << list);
754}
755#endif /* OPENSSL_NO_SECURE_MEMORY */
756#endif /* VBOX */
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette