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