xref: /freebsd/contrib/jemalloc/src/san_bump.c (revision c43cad87172039ccf38172129c79755ea79e6102)
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