1#include "jemalloc/internal/jemalloc_preamble.h"
2#include "jemalloc/internal/jemalloc_internal_includes.h"
3
4#include "jemalloc/internal/san_bump.h"
5#include "jemalloc/internal/pac.h"
6#include "jemalloc/internal/san.h"
7#include "jemalloc/internal/ehooks.h"
8#include "jemalloc/internal/edata_cache.h"
9
10static bool
11san_bump_grow_locked(tsdn_t *tsdn, san_bump_alloc_t *sba, pac_t *pac,
12 ehooks_t *ehooks, size_t size);
13
14edata_t *
15san_bump_alloc(tsdn_t *tsdn, san_bump_alloc_t* sba, pac_t *pac,
16 ehooks_t *ehooks, size_t size, bool zero) {
17 assert(san_bump_enabled());
18
19 edata_t* to_destroy;
20 size_t guarded_size = san_one_side_guarded_sz(size);
21
22 malloc_mutex_lock(tsdn, &sba->mtx);
23
24 if (sba->curr_reg == NULL ||
25 edata_size_get(sba->curr_reg) < guarded_size) {
26 /*
27 * If the current region can't accommodate the allocation,
28 * try replacing it with a larger one and destroy current if the
29 * replacement succeeds.
30 */
31 to_destroy = sba->curr_reg;
32 bool err = san_bump_grow_locked(tsdn, sba, pac, ehooks,
33 guarded_size);
34 if (err) {
35 goto label_err;
36 }
37 } else {
38 to_destroy = NULL;
39 }
40 assert(guarded_size <= edata_size_get(sba->curr_reg));
41 size_t trail_size = edata_size_get(sba->curr_reg) - guarded_size;
42
43 edata_t* edata;
44 if (trail_size != 0) {
45 edata_t* curr_reg_trail = extent_split_wrapper(tsdn, pac,
46 ehooks, sba->curr_reg, guarded_size, trail_size,
47 /* holding_core_locks */ true);
48 if (curr_reg_trail == NULL) {
49 goto label_err;
50 }
51 edata = sba->curr_reg;
52 sba->curr_reg = curr_reg_trail;
53 } else {
54 edata = sba->curr_reg;
55 sba->curr_reg = NULL;
56 }
57
58 malloc_mutex_unlock(tsdn, &sba->mtx);
59
60 assert(!edata_guarded_get(edata));
61 assert(sba->curr_reg == NULL || !edata_guarded_get(sba->curr_reg));
62 assert(to_destroy == NULL || !edata_guarded_get(to_destroy));
63
64 if (to_destroy != NULL) {
65 extent_destroy_wrapper(tsdn, pac, ehooks, to_destroy);
66 }
67
68 san_guard_pages(tsdn, ehooks, edata, pac->emap, /* left */ false,
69 /* right */ true, /* remap */ true);
70
71 if (extent_commit_zero(tsdn, ehooks, edata, /* commit */ true, zero,
72 /* growing_retained */ false)) {
73 extent_record(tsdn, pac, ehooks, &pac->ecache_retained,
74 edata);
75 return NULL;
76 }
77
78 if (config_prof) {
79 extent_gdump_add(tsdn, edata);
80 }
81
82 return edata;
83label_err:
84 malloc_mutex_unlock(tsdn, &sba->mtx);
85 return NULL;
86}
87
88static bool
89san_bump_grow_locked(tsdn_t *tsdn, san_bump_alloc_t *sba, pac_t *pac,
90 ehooks_t *ehooks, size_t size) {
91 malloc_mutex_assert_owner(tsdn, &sba->mtx);
92
93 bool committed = false, zeroed = false;
94 size_t alloc_size = size > SBA_RETAINED_ALLOC_SIZE ? size :
95 SBA_RETAINED_ALLOC_SIZE;
96 assert((alloc_size & PAGE_MASK) == 0);
97 sba->curr_reg = extent_alloc_wrapper(tsdn, pac, ehooks, NULL,
98 alloc_size, PAGE, zeroed, &committed,
99 /* growing_retained */ true);
100 if (sba->curr_reg == NULL) {
101 return true;
102 }
103 return false;
104}
105