2
0

mem_sec.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745
  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. #ifndef OPENSSL_NO_SECURE_MEMORY
  242. return secure_mem_used;
  243. #else
  244. return 0;
  245. #endif /* OPENSSL_NO_SECURE_MEMORY */
  246. }
  247. size_t CRYPTO_secure_actual_size(void *ptr)
  248. {
  249. #ifndef OPENSSL_NO_SECURE_MEMORY
  250. size_t actual_size;
  251. if (!CRYPTO_THREAD_write_lock(sec_malloc_lock))
  252. return 0;
  253. actual_size = sh_actual_size(ptr);
  254. CRYPTO_THREAD_unlock(sec_malloc_lock);
  255. return actual_size;
  256. #else
  257. return 0;
  258. #endif
  259. }
  260. /*
  261. * SECURE HEAP IMPLEMENTATION
  262. */
  263. #ifndef OPENSSL_NO_SECURE_MEMORY
  264. /*
  265. * The implementation provided here uses a fixed-sized mmap() heap,
  266. * which is locked into memory, not written to core files, and protected
  267. * on either side by an unmapped page, which will catch pointer overruns
  268. * (or underruns) and an attempt to read data out of the secure heap.
  269. * Free'd memory is zero'd or otherwise cleansed.
  270. *
  271. * This is a pretty standard buddy allocator. We keep areas in a multiple
  272. * of "sh.minsize" units. The freelist and bitmaps are kept separately,
  273. * so all (and only) data is kept in the mmap'd heap.
  274. *
  275. * This code assumes eight-bit bytes. The numbers 3 and 7 are all over the
  276. * place.
  277. */
  278. #define ONE ((size_t)1)
  279. # define TESTBIT(t, b) (t[(b) >> 3] & (ONE << ((b) & 7)))
  280. # define SETBIT(t, b) (t[(b) >> 3] |= (ONE << ((b) & 7)))
  281. # define CLEARBIT(t, b) (t[(b) >> 3] &= (0xFF & ~(ONE << ((b) & 7))))
  282. #define WITHIN_ARENA(p) \
  283. ((char*)(p) >= sh.arena && (char*)(p) < &sh.arena[sh.arena_size])
  284. #define WITHIN_FREELIST(p) \
  285. ((char*)(p) >= (char*)sh.freelist && (char*)(p) < (char*)&sh.freelist[sh.freelist_size])
  286. typedef struct sh_list_st
  287. {
  288. struct sh_list_st *next;
  289. struct sh_list_st **p_next;
  290. } SH_LIST;
  291. typedef struct sh_st
  292. {
  293. char* map_result;
  294. size_t map_size;
  295. char *arena;
  296. size_t arena_size;
  297. char **freelist;
  298. ossl_ssize_t freelist_size;
  299. size_t minsize;
  300. unsigned char *bittable;
  301. unsigned char *bitmalloc;
  302. size_t bittable_size; /* size in bits */
  303. } SH;
  304. static SH sh;
  305. static size_t sh_getlist(char *ptr)
  306. {
  307. ossl_ssize_t list = sh.freelist_size - 1;
  308. size_t bit = (sh.arena_size + ptr - sh.arena) / sh.minsize;
  309. for (; bit; bit >>= 1, list--) {
  310. if (TESTBIT(sh.bittable, bit))
  311. break;
  312. OPENSSL_assert((bit & 1) == 0);
  313. }
  314. return list;
  315. }
  316. static int sh_testbit(char *ptr, int list, unsigned char *table)
  317. {
  318. size_t bit;
  319. OPENSSL_assert(list >= 0 && list < sh.freelist_size);
  320. OPENSSL_assert(((ptr - sh.arena) & ((sh.arena_size >> list) - 1)) == 0);
  321. bit = (ONE << list) + ((ptr - sh.arena) / (sh.arena_size >> list));
  322. OPENSSL_assert(bit > 0 && bit < sh.bittable_size);
  323. return TESTBIT(table, bit);
  324. }
  325. static void sh_clearbit(char *ptr, int list, unsigned char *table)
  326. {
  327. size_t bit;
  328. OPENSSL_assert(list >= 0 && list < sh.freelist_size);
  329. OPENSSL_assert(((ptr - sh.arena) & ((sh.arena_size >> list) - 1)) == 0);
  330. bit = (ONE << list) + ((ptr - sh.arena) / (sh.arena_size >> list));
  331. OPENSSL_assert(bit > 0 && bit < sh.bittable_size);
  332. OPENSSL_assert(TESTBIT(table, bit));
  333. CLEARBIT(table, bit);
  334. }
  335. static void sh_setbit(char *ptr, int list, unsigned char *table)
  336. {
  337. size_t bit;
  338. OPENSSL_assert(list >= 0 && list < sh.freelist_size);
  339. OPENSSL_assert(((ptr - sh.arena) & ((sh.arena_size >> list) - 1)) == 0);
  340. bit = (ONE << list) + ((ptr - sh.arena) / (sh.arena_size >> list));
  341. OPENSSL_assert(bit > 0 && bit < sh.bittable_size);
  342. OPENSSL_assert(!TESTBIT(table, bit));
  343. SETBIT(table, bit);
  344. }
  345. static void sh_add_to_list(char **list, char *ptr)
  346. {
  347. SH_LIST *temp;
  348. OPENSSL_assert(WITHIN_FREELIST(list));
  349. OPENSSL_assert(WITHIN_ARENA(ptr));
  350. temp = (SH_LIST *)ptr;
  351. temp->next = *(SH_LIST **)list;
  352. OPENSSL_assert(temp->next == NULL || WITHIN_ARENA(temp->next));
  353. temp->p_next = (SH_LIST **)list;
  354. if (temp->next != NULL) {
  355. OPENSSL_assert((char **)temp->next->p_next == list);
  356. temp->next->p_next = &(temp->next);
  357. }
  358. *list = ptr;
  359. }
  360. static void sh_remove_from_list(char *ptr)
  361. {
  362. SH_LIST *temp, *temp2;
  363. temp = (SH_LIST *)ptr;
  364. if (temp->next != NULL)
  365. temp->next->p_next = temp->p_next;
  366. *temp->p_next = temp->next;
  367. if (temp->next == NULL)
  368. return;
  369. temp2 = temp->next;
  370. OPENSSL_assert(WITHIN_FREELIST(temp2->p_next) || WITHIN_ARENA(temp2->p_next));
  371. }
  372. static int sh_init(size_t size, size_t minsize)
  373. {
  374. int ret;
  375. size_t i;
  376. size_t pgsize;
  377. size_t aligned;
  378. #if defined(_WIN32)
  379. DWORD flOldProtect;
  380. SYSTEM_INFO systemInfo;
  381. #endif
  382. memset(&sh, 0, sizeof(sh));
  383. /* make sure size is a powers of 2 */
  384. OPENSSL_assert(size > 0);
  385. OPENSSL_assert((size & (size - 1)) == 0);
  386. if (size == 0 || (size & (size - 1)) != 0)
  387. goto err;
  388. if (minsize <= sizeof(SH_LIST)) {
  389. OPENSSL_assert(sizeof(SH_LIST) <= 65536);
  390. /*
  391. * Compute the minimum possible allocation size.
  392. * This must be a power of 2 and at least as large as the SH_LIST
  393. * structure.
  394. */
  395. minsize = sizeof(SH_LIST) - 1;
  396. minsize |= minsize >> 1;
  397. minsize |= minsize >> 2;
  398. if (sizeof(SH_LIST) > 16)
  399. minsize |= minsize >> 4;
  400. if (sizeof(SH_LIST) > 256)
  401. minsize |= minsize >> 8;
  402. minsize++;
  403. } else {
  404. /* make sure minsize is a powers of 2 */
  405. OPENSSL_assert((minsize & (minsize - 1)) == 0);
  406. if ((minsize & (minsize - 1)) != 0)
  407. goto err;
  408. }
  409. sh.arena_size = size;
  410. sh.minsize = minsize;
  411. sh.bittable_size = (sh.arena_size / sh.minsize) * 2;
  412. /* Prevent allocations of size 0 later on */
  413. if (sh.bittable_size >> 3 == 0)
  414. goto err;
  415. sh.freelist_size = -1;
  416. for (i = sh.bittable_size; i; i >>= 1)
  417. sh.freelist_size++;
  418. sh.freelist = OPENSSL_zalloc(sh.freelist_size * sizeof(char *));
  419. OPENSSL_assert(sh.freelist != NULL);
  420. if (sh.freelist == NULL)
  421. goto err;
  422. sh.bittable = OPENSSL_zalloc(sh.bittable_size >> 3);
  423. OPENSSL_assert(sh.bittable != NULL);
  424. if (sh.bittable == NULL)
  425. goto err;
  426. sh.bitmalloc = OPENSSL_zalloc(sh.bittable_size >> 3);
  427. OPENSSL_assert(sh.bitmalloc != NULL);
  428. if (sh.bitmalloc == NULL)
  429. goto err;
  430. /* Allocate space for heap, and two extra pages as guards */
  431. #if defined(_SC_PAGE_SIZE) || defined (_SC_PAGESIZE)
  432. {
  433. # if defined(_SC_PAGE_SIZE)
  434. long tmppgsize = sysconf(_SC_PAGE_SIZE);
  435. # else
  436. long tmppgsize = sysconf(_SC_PAGESIZE);
  437. # endif
  438. if (tmppgsize < 1)
  439. pgsize = PAGE_SIZE;
  440. else
  441. pgsize = (size_t)tmppgsize;
  442. }
  443. #elif defined(_WIN32)
  444. GetSystemInfo(&systemInfo);
  445. pgsize = (size_t)systemInfo.dwPageSize;
  446. #else
  447. pgsize = PAGE_SIZE;
  448. #endif
  449. sh.map_size = pgsize + sh.arena_size + pgsize;
  450. #if !defined(_WIN32)
  451. # ifdef MAP_ANON
  452. sh.map_result = mmap(NULL, sh.map_size,
  453. PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE|MAP_CONCEAL, -1, 0);
  454. # else
  455. {
  456. int fd;
  457. sh.map_result = MAP_FAILED;
  458. if ((fd = open("/dev/zero", O_RDWR)) >= 0) {
  459. sh.map_result = mmap(NULL, sh.map_size,
  460. PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
  461. close(fd);
  462. }
  463. }
  464. # endif
  465. if (sh.map_result == MAP_FAILED)
  466. goto err;
  467. #else
  468. sh.map_result = VirtualAlloc(NULL, sh.map_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
  469. if (sh.map_result == NULL)
  470. goto err;
  471. #endif
  472. sh.arena = (char *)(sh.map_result + pgsize);
  473. sh_setbit(sh.arena, 0, sh.bittable);
  474. sh_add_to_list(&sh.freelist[0], sh.arena);
  475. /* Now try to add guard pages and lock into memory. */
  476. ret = 1;
  477. #if !defined(_WIN32)
  478. /* Starting guard is already aligned from mmap. */
  479. if (mprotect(sh.map_result, pgsize, PROT_NONE) < 0)
  480. ret = 2;
  481. #else
  482. if (VirtualProtect(sh.map_result, pgsize, PAGE_NOACCESS, &flOldProtect) == FALSE)
  483. ret = 2;
  484. #endif
  485. /* Ending guard page - need to round up to page boundary */
  486. aligned = (pgsize + sh.arena_size + (pgsize - 1)) & ~(pgsize - 1);
  487. #if !defined(_WIN32)
  488. if (mprotect(sh.map_result + aligned, pgsize, PROT_NONE) < 0)
  489. ret = 2;
  490. #else
  491. if (VirtualProtect(sh.map_result + aligned, pgsize, PAGE_NOACCESS, &flOldProtect) == FALSE)
  492. ret = 2;
  493. #endif
  494. #if defined(OPENSSL_SYS_LINUX) && defined(MLOCK_ONFAULT) && defined(SYS_mlock2)
  495. if (syscall(SYS_mlock2, sh.arena, sh.arena_size, MLOCK_ONFAULT) < 0) {
  496. if (errno == ENOSYS) {
  497. if (mlock(sh.arena, sh.arena_size) < 0)
  498. ret = 2;
  499. } else {
  500. ret = 2;
  501. }
  502. }
  503. #elif defined(_WIN32)
  504. if (VirtualLock(sh.arena, sh.arena_size) == FALSE)
  505. ret = 2;
  506. #else
  507. if (mlock(sh.arena, sh.arena_size) < 0)
  508. ret = 2;
  509. #endif
  510. #ifndef NO_MADVISE
  511. if (madvise(sh.arena, sh.arena_size, MADV_DONTDUMP) < 0)
  512. ret = 2;
  513. #endif
  514. return ret;
  515. err:
  516. sh_done();
  517. return 0;
  518. }
  519. static void sh_done(void)
  520. {
  521. OPENSSL_free(sh.freelist);
  522. OPENSSL_free(sh.bittable);
  523. OPENSSL_free(sh.bitmalloc);
  524. #if !defined(_WIN32)
  525. if (sh.map_result != MAP_FAILED && sh.map_size)
  526. munmap(sh.map_result, sh.map_size);
  527. #else
  528. if (sh.map_result != NULL && sh.map_size)
  529. VirtualFree(sh.map_result, 0, MEM_RELEASE);
  530. #endif
  531. memset(&sh, 0, sizeof(sh));
  532. }
  533. static int sh_allocated(const char *ptr)
  534. {
  535. return WITHIN_ARENA(ptr) ? 1 : 0;
  536. }
  537. static char *sh_find_my_buddy(char *ptr, int list)
  538. {
  539. size_t bit;
  540. char *chunk = NULL;
  541. bit = (ONE << list) + (ptr - sh.arena) / (sh.arena_size >> list);
  542. bit ^= 1;
  543. if (TESTBIT(sh.bittable, bit) && !TESTBIT(sh.bitmalloc, bit))
  544. chunk = sh.arena + ((bit & ((ONE << list) - 1)) * (sh.arena_size >> list));
  545. return chunk;
  546. }
  547. static void *sh_malloc(size_t size)
  548. {
  549. ossl_ssize_t list, slist;
  550. size_t i;
  551. char *chunk;
  552. if (size > sh.arena_size)
  553. return NULL;
  554. list = sh.freelist_size - 1;
  555. for (i = sh.minsize; i < size; i <<= 1)
  556. list--;
  557. if (list < 0)
  558. return NULL;
  559. /* try to find a larger entry to split */
  560. for (slist = list; slist >= 0; slist--)
  561. if (sh.freelist[slist] != NULL)
  562. break;
  563. if (slist < 0)
  564. return NULL;
  565. /* split larger entry */
  566. while (slist != list) {
  567. char *temp = sh.freelist[slist];
  568. /* remove from bigger list */
  569. OPENSSL_assert(!sh_testbit(temp, slist, sh.bitmalloc));
  570. sh_clearbit(temp, slist, sh.bittable);
  571. sh_remove_from_list(temp);
  572. OPENSSL_assert(temp != sh.freelist[slist]);
  573. /* done with bigger list */
  574. slist++;
  575. /* add to smaller list */
  576. OPENSSL_assert(!sh_testbit(temp, slist, sh.bitmalloc));
  577. sh_setbit(temp, slist, sh.bittable);
  578. sh_add_to_list(&sh.freelist[slist], temp);
  579. OPENSSL_assert(sh.freelist[slist] == temp);
  580. /* split in 2 */
  581. temp += sh.arena_size >> slist;
  582. OPENSSL_assert(!sh_testbit(temp, slist, sh.bitmalloc));
  583. sh_setbit(temp, slist, sh.bittable);
  584. sh_add_to_list(&sh.freelist[slist], temp);
  585. OPENSSL_assert(sh.freelist[slist] == temp);
  586. OPENSSL_assert(temp-(sh.arena_size >> slist) == sh_find_my_buddy(temp, slist));
  587. }
  588. /* peel off memory to hand back */
  589. chunk = sh.freelist[list];
  590. OPENSSL_assert(sh_testbit(chunk, list, sh.bittable));
  591. sh_setbit(chunk, list, sh.bitmalloc);
  592. sh_remove_from_list(chunk);
  593. OPENSSL_assert(WITHIN_ARENA(chunk));
  594. /* zero the free list header as a precaution against information leakage */
  595. memset(chunk, 0, sizeof(SH_LIST));
  596. return chunk;
  597. }
  598. static void sh_free(void *ptr)
  599. {
  600. size_t list;
  601. void *buddy;
  602. if (ptr == NULL)
  603. return;
  604. OPENSSL_assert(WITHIN_ARENA(ptr));
  605. if (!WITHIN_ARENA(ptr))
  606. return;
  607. list = sh_getlist(ptr);
  608. OPENSSL_assert(sh_testbit(ptr, list, sh.bittable));
  609. sh_clearbit(ptr, list, sh.bitmalloc);
  610. sh_add_to_list(&sh.freelist[list], ptr);
  611. /* Try to coalesce two adjacent free areas. */
  612. while ((buddy = sh_find_my_buddy(ptr, list)) != NULL) {
  613. OPENSSL_assert(ptr == sh_find_my_buddy(buddy, list));
  614. OPENSSL_assert(ptr != NULL);
  615. OPENSSL_assert(!sh_testbit(ptr, list, sh.bitmalloc));
  616. sh_clearbit(ptr, list, sh.bittable);
  617. sh_remove_from_list(ptr);
  618. OPENSSL_assert(!sh_testbit(ptr, list, sh.bitmalloc));
  619. sh_clearbit(buddy, list, sh.bittable);
  620. sh_remove_from_list(buddy);
  621. list--;
  622. /* Zero the higher addressed block's free list pointers */
  623. memset(ptr > buddy ? ptr : buddy, 0, sizeof(SH_LIST));
  624. if (ptr > buddy)
  625. ptr = buddy;
  626. OPENSSL_assert(!sh_testbit(ptr, list, sh.bitmalloc));
  627. sh_setbit(ptr, list, sh.bittable);
  628. sh_add_to_list(&sh.freelist[list], ptr);
  629. OPENSSL_assert(sh.freelist[list] == ptr);
  630. }
  631. }
  632. static size_t sh_actual_size(char *ptr)
  633. {
  634. int list;
  635. OPENSSL_assert(WITHIN_ARENA(ptr));
  636. if (!WITHIN_ARENA(ptr))
  637. return 0;
  638. list = sh_getlist(ptr);
  639. OPENSSL_assert(sh_testbit(ptr, list, sh.bittable));
  640. return sh.arena_size / (ONE << list);
  641. }
  642. #endif /* OPENSSL_NO_SECURE_MEMORY */