mem_sec.c 20 KB

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