Loading...
--- libmalloc/libmalloc-792.60.6/src/pgm_malloc.c
+++ libmalloc/libmalloc-646.0.13/src/pgm_malloc.c
@@ -84,7 +84,6 @@
uint32_t max_allocations;
uint32_t max_metadata;
uint32_t sample_counter_range;
- uint32_t left_align_pct;
bool debug;
uint64_t debug_log_throttle_ms;
@@ -127,7 +126,7 @@
MALLOC_STATIC_ASSERT(sizeof(void *) >= sizeof(uint32_t), "Pointer is used as 32bit counter");
-#define TSD_GET_COUNTER() ((uint32_t)(uintptr_t)_pthread_getspecific_direct(__TSD_MALLOC_PROB_GUARD_SAMPLE_COUNTER))
+#define TSD_GET_COUNTER() ((uint32_t)_pthread_getspecific_direct(__TSD_MALLOC_PROB_GUARD_SAMPLE_COUNTER))
#define TSD_SET_COUNTER(val) _pthread_setspecific_direct(__TSD_MALLOC_PROB_GUARD_SAMPLE_COUNTER, (void *)(uintptr_t)val)
static const uint32_t k_no_sample = UINT32_MAX;
@@ -367,17 +366,12 @@
}
static uint16_t
-choose_offset_on_page(size_t size,
- size_t alignment,
- uint32_t left_align_pct,
- uint16_t page_size)
-{
+choose_offset_on_page(size_t size, size_t alignment, uint16_t page_size) {
MALLOC_ASSERT(size <= page_size);
MALLOC_ASSERT(alignment <= page_size && is_power_of_2(alignment));
MALLOC_ASSERT(is_power_of_2(page_size));
- MALLOC_ASSERT(left_align_pct <= 100);
-
- if (rand_uniform(100) < left_align_pct) {
+ boolean_t left_align = rand_uniform(2);
+ if (left_align) {
return 0;
}
size_t mask = ~(alignment - 1);
@@ -441,8 +435,7 @@
size = block_size(size);
uint32_t slot = choose_available_slot(zone);
uint32_t metadata = choose_metadata(zone, slot);
- uint16_t offset = choose_offset_on_page(
- size, alignment, zone->left_align_pct, PAGE_SIZE);
+ uint16_t offset = choose_offset_on_page(size, alignment, PAGE_SIZE);
// Mark page writable before updating metadata. Ensures metadata is correct
// whenever a fault could be triggered.
@@ -589,13 +582,6 @@
}
static void *
-pgm_malloc_type_malloc(pgm_zone_t *zone, size_t size, malloc_type_id_t type_id)
-{
- SAMPLED_ALLOCATE(size, k_min_alignment, malloc_type_malloc, size, type_id);
- return ptr;
-}
-
-static void *
pgm_calloc(pgm_zone_t *zone, size_t num_items, size_t size)
{
size_t total_size;
@@ -603,21 +589,7 @@
return DELEGATE(calloc, num_items, size);
}
SAMPLED_ALLOCATE(total_size, k_min_alignment, calloc, num_items, size);
- bzero(ptr, total_size);
- return ptr;
-}
-
-static void *
-pgm_malloc_type_calloc(pgm_zone_t *zone, size_t num_items, size_t size,
- malloc_type_id_t type_id)
-{
- size_t total_size;
- if (os_unlikely(os_mul_overflow(num_items, size, &total_size))) {
- return DELEGATE(malloc_type_calloc, num_items, size, type_id);
- }
- SAMPLED_ALLOCATE(total_size, k_min_alignment, malloc_type_calloc, num_items,
- size, type_id);
- bzero(ptr, total_size);
+ memset(ptr, 0, total_size);
return ptr;
}
@@ -650,23 +622,6 @@
return new_ptr;
}
-static void *
-pgm_malloc_type_realloc(pgm_zone_t *zone, void *ptr, size_t new_size,
- malloc_type_id_t type_id)
-{
- if (os_unlikely(!ptr)) {
- return pgm_malloc_type_malloc(zone, new_size, type_id);
- }
- boolean_t sample = should_sample(zone, new_size);
- if (os_likely(!sample)) {
- DELEGATE_UNGUARDED(ptr, malloc_type_realloc, ptr, new_size, type_id);
- }
- lock(zone);
- void *new_ptr = (void *)reallocate(zone, (vm_address_t)ptr, new_size, sample);
- unlock(zone);
- return new_ptr;
-}
-
static void my_vm_deallocate(vm_address_t addr, size_t size);
static void
pgm_destroy(pgm_zone_t *zone)
@@ -679,7 +634,8 @@
static void *
pgm_memalign(pgm_zone_t *zone, size_t alignment, size_t size)
{
- if (os_unlikely(alignment > PAGE_SIZE)) {
+ // Delegate for (alignment > page size) and invalid alignment sizes.
+ if (alignment > PAGE_SIZE || !is_power_of_2(alignment) || alignment < sizeof(void *)) {
return DELEGATE(memalign, alignment, size);
}
size_t adj_alignment = MAX(alignment, k_min_alignment);
@@ -687,19 +643,6 @@
return ptr;
}
-static void *
-pgm_malloc_type_memalign(pgm_zone_t *zone, size_t alignment, size_t size,
- malloc_type_id_t type_id)
-{
- if (os_unlikely(alignment > PAGE_SIZE)) {
- return DELEGATE(malloc_type_memalign, alignment, size, type_id);
- }
- size_t adj_alignment = MAX(alignment, k_min_alignment);
- SAMPLED_ALLOCATE(size, adj_alignment, malloc_type_memalign, alignment, size,
- type_id);
- return ptr;
-}
-
static void
pgm_free_definite_size(pgm_zone_t *zone, void *ptr, size_t size)
{
@@ -715,34 +658,37 @@
static void *
pgm_malloc_with_options(pgm_zone_t *zone, size_t align, size_t size,
- malloc_zone_malloc_options_t options)
-{
- if (os_unlikely(align > PAGE_SIZE)) {
+ uint64_t options)
+{
+ if (os_unlikely(should_sample(zone, size))) {
+ size_t adj_alignment = MAX(align, k_min_alignment);
+ lock(zone);
+ void *ptr = (void *)allocate(zone, size, adj_alignment);
+ unlock(zone);
+ if (ptr) {
+ if (options & MALLOC_NP_OPTION_CLEAR) {
+ bzero(ptr, size);
+ }
+ return ptr;
+ }
+ // If the allocation fails, fall back to the wrapped zone
+ }
+
+ // FIXME: calls wrapped_zone->malloc_with_options/memalign without NULL check
+ if (zone->wrapped_zone->version >= 15 &&
+ zone->wrapped_zone->malloc_with_options) {
return DELEGATE(malloc_with_options, align, size, options);
- }
- size_t adj_alignment = MAX(align, k_min_alignment);
- SAMPLED_ALLOCATE(size, adj_alignment, malloc_with_options, align, size, options);
- if (options & MALLOC_NP_OPTION_CLEAR) {
- bzero(ptr, size);
- }
- return ptr;
-}
-
-static void *
-pgm_malloc_type_malloc_with_options(pgm_zone_t *zone, size_t align, size_t size,
- malloc_zone_malloc_options_t options, malloc_type_id_t type_id)
-{
- if (os_unlikely(align > PAGE_SIZE)) {
- return DELEGATE(malloc_type_malloc_with_options, align, size, options,
- type_id);
- }
- size_t adj_alignment = MAX(align, k_min_alignment);
- SAMPLED_ALLOCATE(size, adj_alignment, malloc_type_malloc_with_options,
- align, size, options, type_id);
- if (options & MALLOC_NP_OPTION_CLEAR) {
- bzero(ptr, size);
- }
- return ptr;
+ } else if (align) {
+ void *ptr = DELEGATE(memalign, align, size);
+ if (ptr && (options & MALLOC_NP_OPTION_CLEAR)) {
+ bzero(ptr, size);
+ }
+ return ptr;
+ } else if (options & MALLOC_NP_OPTION_CLEAR) {
+ return DELEGATE(calloc, 1, size);
+ } else {
+ return DELEGATE(malloc, size);
+ }
}
#pragma mark -
@@ -758,8 +704,7 @@
(zone->max_allocations <= zone->max_metadata / 2) && // choose_metadata() relies on max_allocations << max_metadata
(zone->max_metadata <= zone->num_slots) &&
(zone->num_slots <= k_max_slots) &&
- (zone->sample_counter_range > 0) &&
- (0 <= zone->left_align_pct && zone->left_align_pct <= 100);
+ (zone->sample_counter_range > 0);
}
static bool
@@ -1038,8 +983,7 @@
#pragma mark -
#pragma mark Zone Templates
-#define PGM_ZONE_VERSION 16
-#define MIN_WRAPPED_ZONE_VERSION 16
+#define PGM_ZONE_VERSION 15
// Suppress warning: incompatible function pointer types
#define FN_PTR(fn) (void *)(&fn)
@@ -1111,14 +1055,6 @@
.claimed_address = FN_PTR(pgm_claimed_address),
.try_free_default = NULL,
.malloc_with_options = FN_PTR(pgm_malloc_with_options),
-
- // Typed entrypoints
- .malloc_type_malloc = FN_PTR(pgm_malloc_type_malloc),
- .malloc_type_calloc = FN_PTR(pgm_malloc_type_calloc),
- .malloc_type_realloc = FN_PTR(pgm_malloc_type_realloc),
- .malloc_type_memalign = FN_PTR(pgm_malloc_type_memalign),
- .malloc_type_malloc_with_options =
- FN_PTR(pgm_malloc_type_malloc_with_options),
};
@@ -1159,7 +1095,6 @@
bool internal_build;
bool MallocProbGuard_is_set;
bool MallocProbGuard;
- bool targeted_coverage;
} g_env;
void
@@ -1172,13 +1107,6 @@
if (env_var("MallocProbGuard")) {
g_env.MallocProbGuard_is_set = true;
g_env.MallocProbGuard = env_bool("MallocProbGuard");
- }
-
- const char *all_factors = env_var("__TRIFactors");
- const char *pgm_factor =
- "PROBABILISTIC_GUARD_MALLOC_TARGETED_COVERAGE:enable=1";
- if (all_factors && strstr(all_factors, pgm_factor)) {
- g_env.targeted_coverage = true;
}
}
@@ -1196,11 +1124,6 @@
static bool
should_activate(bool internal_build)
{
-#if CONFIG_MTE
- if (malloc_has_sec_transition) {
- return false;
- }
-#endif
if (!internal_build && !is_platform_binary()) {
return false;
}
@@ -1216,47 +1139,42 @@
#if TARGET_OS_WATCH || TARGET_OS_TV
static bool
-is_low_memory_device(void)
-{
- uint64_t low_memory = 1.2 * 1024 * 1024 * 1024; // 1.2 GB
- return platform_hw_memsize() <= low_memory;
+is_high_memory_device(void)
+{
+ uint64_t high_memory = 1.2 * 1024 * 1024 * 1024; // 1.2 GB
+ return platform_hw_memsize() > high_memory;
}
#endif
+
+#define PGM_ALLOW_NON_INTERNAL_ACTIVATION 0
+
bool
pgm_should_enable(void)
{
- // Env var override
if (g_env.MallocProbGuard_is_set) {
return g_env.MallocProbGuard;
}
-
- // Feature flags
- if (!FEATURE_FLAG(ProbGuard, true)) {
- return false;
+ bool internal_build = g_env.internal_build;
+ if (FEATURE_FLAG(ProbGuard, true) && should_activate(internal_build)) {
+#if TARGET_OS_OSX || TARGET_OS_IOS
+ return true;
+#elif TARGET_OS_WATCH || TARGET_OS_TV
+ if (is_high_memory_device()) {
+ return true;
+ }
+#elif PGM_ALLOW_NON_INTERNAL_ACTIVATION
+ return true;
+#else
+ if (internal_build) {
+ return true;
+ }
+#endif
}
if (FEATURE_FLAG(ProbGuardAllProcesses, false)) {
return true;
}
-
- // Excluded configurations
-#if TARGET_OS_WATCH || TARGET_OS_TV
- if (is_low_memory_device()) {
- return false;
- }
-#elif TARGET_OS_BRIDGE || TARGET_OS_DRIVERKIT
- if (!g_env.internal_build) {
- return false;
- }
-#endif
-
- // Targeted coverage via Trial
- if (g_env.targeted_coverage) {
- return true;
- }
-
- // Random activation
- return should_activate(g_env.internal_build);
+ return false;
}
static uint32_t
@@ -1304,7 +1222,6 @@
uint32_t sample_rate = env_uint("MallocProbGuardSampleRate", choose_sample_rate());
// Approximate a (1 / sample_rate) chance for sampling; 1 means "always sample".
zone->sample_counter_range = (sample_rate != 1) ? (2 * sample_rate) : 1;
- zone->left_align_pct = env_uint("MallocProbGuardLeftAlignPercentage", 10);
zone->debug = env_bool("MallocProbGuardDebug");
zone->debug_log_throttle_ms = env_uint("MallocProbGuardDebugLogThrottleInMillis", 1000);
@@ -1333,18 +1250,9 @@
disable_unsupported_apis(malloc_zone_t *pgm_zone, const malloc_zone_t *wrapped_zone)
{
#define DISABLE_UNSUPPORTED(api) if (!wrapped_zone->api) pgm_zone->api = NULL;
-
- // In practice, there are no zones we support wrapping right now that don't
- // have these entrypoints
DISABLE_UNSUPPORTED(memalign)
- DISABLE_UNSUPPORTED(malloc_type_memalign)
DISABLE_UNSUPPORTED(free_definite_size)
DISABLE_UNSUPPORTED(claimed_address)
-
- // These ones are actually load-bearing: the nano and scalable zones do not
- // implement these entrypoints
- DISABLE_UNSUPPORTED(malloc_with_options)
- DISABLE_UNSUPPORTED(malloc_type_malloc_with_options)
}
static void
@@ -1378,7 +1286,12 @@
malloc_zone_t *
pgm_create_zone(malloc_zone_t *wrapped_zone)
{
- MALLOC_ASSERT(wrapped_zone->version >= MIN_WRAPPED_ZONE_VERSION);
+ // The PGM zone includes the `malloc_introspection_t::zone_type` field
+ // (version 14) so we need to support the "malloc()/calloc() set errno to
+ // ENOMEM on failure" behavior (version 13). Require wrapped zone to be at
+ // least version 13.
+ MALLOC_STATIC_ASSERT(PGM_ZONE_VERSION == 15, "PGM zone version");
+ MALLOC_ASSERT(wrapped_zone->version >= 13);
pgm_zone_t *zone = (pgm_zone_t *)my_vm_map(sizeof(pgm_zone_t), VM_PROT_READ_WRITE, VM_MEMORY_MALLOC);
setup_zone(zone, wrapped_zone);