mirror of
				https://github.com/GrapheneOS/hardened_malloc.git
				synced 2025-10-31 00:06:33 +01:00 
			
		
		
		
	add real mallinfo implementation for Android
Android Q uses the mallinfo implementation in the ART GC:c220f981801575267302
This commit is contained in:
		
							parent
							
								
									7acebaa837
								
							
						
					
					
						commit
						350d0e5fd2
					
				
					 5 changed files with 96 additions and 4 deletions
				
			
		|  | @ -25,6 +25,7 @@ common_cflags = [ | ||||||
|     "-DFREE_SLABS_QUARANTINE_RANDOM_LENGTH=32", |     "-DFREE_SLABS_QUARANTINE_RANDOM_LENGTH=32", | ||||||
|     "-DCONFIG_CLASS_REGION_SIZE=1073741824", // 1GiB |     "-DCONFIG_CLASS_REGION_SIZE=1073741824", // 1GiB | ||||||
|     "-DN_ARENA=1", |     "-DN_ARENA=1", | ||||||
|  |     "-DSTATS=false", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
| cc_defaults { | cc_defaults { | ||||||
|  |  | ||||||
							
								
								
									
										6
									
								
								Makefile
									
										
									
									
									
								
							
							
						
						
									
										6
									
								
								Makefile
									
										
									
									
									
								
							|  | @ -15,7 +15,8 @@ CONFIG_REGION_QUARANTINE_QUEUE_LENGTH := 1024 | ||||||
| CONFIG_REGION_QUARANTINE_SKIP_THRESHOLD := 33554432 # 32MiB | CONFIG_REGION_QUARANTINE_SKIP_THRESHOLD := 33554432 # 32MiB | ||||||
| CONFIG_FREE_SLABS_QUARANTINE_RANDOM_LENGTH := 32 | CONFIG_FREE_SLABS_QUARANTINE_RANDOM_LENGTH := 32 | ||||||
| CONFIG_CLASS_REGION_SIZE := 137438953472 # 128GiB | CONFIG_CLASS_REGION_SIZE := 137438953472 # 128GiB | ||||||
| CONFIG_N_ARENA = 1 | CONFIG_N_ARENA := 1 | ||||||
|  | CONFIG_STATS := false | ||||||
| 
 | 
 | ||||||
| define safe_flag | define safe_flag | ||||||
| $(shell $(CC) -E $1 - </dev/null >/dev/null 2>&1 && echo $1 || echo $2) | $(shell $(CC) -E $1 - </dev/null >/dev/null 2>&1 && echo $1 || echo $2) | ||||||
|  | @ -81,7 +82,8 @@ CPPFLAGS += \ | ||||||
|     -DREGION_QUARANTINE_SKIP_THRESHOLD=$(CONFIG_REGION_QUARANTINE_SKIP_THRESHOLD) \
 |     -DREGION_QUARANTINE_SKIP_THRESHOLD=$(CONFIG_REGION_QUARANTINE_SKIP_THRESHOLD) \
 | ||||||
|     -DFREE_SLABS_QUARANTINE_RANDOM_LENGTH=$(CONFIG_FREE_SLABS_QUARANTINE_RANDOM_LENGTH) \
 |     -DFREE_SLABS_QUARANTINE_RANDOM_LENGTH=$(CONFIG_FREE_SLABS_QUARANTINE_RANDOM_LENGTH) \
 | ||||||
|     -DCONFIG_CLASS_REGION_SIZE=$(CONFIG_CLASS_REGION_SIZE) \
 |     -DCONFIG_CLASS_REGION_SIZE=$(CONFIG_CLASS_REGION_SIZE) \
 | ||||||
|     -DN_ARENA=$(CONFIG_N_ARENA) |     -DN_ARENA=$(CONFIG_N_ARENA) \
 | ||||||
|  |     -DSTATS=$(CONFIG_STATS) | ||||||
| 
 | 
 | ||||||
| libhardened_malloc.so: $(OBJECTS) | libhardened_malloc.so: $(OBJECTS) | ||||||
| 	$(CC) $(CFLAGS) $(LDFLAGS) -shared $^ $(LDLIBS) -o $@ | 	$(CC) $(CFLAGS) $(LDFLAGS) -shared $^ $(LDLIBS) -o $@ | ||||||
|  |  | ||||||
							
								
								
									
										69
									
								
								h_malloc.c
									
										
									
									
									
								
							
							
						
						
									
										69
									
								
								h_malloc.c
									
										
									
									
									
								
							|  | @ -240,6 +240,11 @@ struct __attribute__((aligned(CACHELINE_SIZE))) size_class { | ||||||
|     struct slab_metadata *free_slabs_tail; |     struct slab_metadata *free_slabs_tail; | ||||||
|     struct slab_metadata *free_slabs_quarantine[FREE_SLABS_QUARANTINE_RANDOM_LENGTH]; |     struct slab_metadata *free_slabs_quarantine[FREE_SLABS_QUARANTINE_RANDOM_LENGTH]; | ||||||
| 
 | 
 | ||||||
|  | #if STATS | ||||||
|  |     size_t allocated; | ||||||
|  |     size_t slab_allocated; | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|     struct random_state rng; |     struct random_state rng; | ||||||
|     size_t metadata_allocated; |     size_t metadata_allocated; | ||||||
|     size_t metadata_count; |     size_t metadata_count; | ||||||
|  | @ -478,6 +483,9 @@ static inline void *allocate_small(size_t requested_size) { | ||||||
|                 set_canary(metadata, p, size); |                 set_canary(metadata, p, size); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|  | #if STATS | ||||||
|  |             c->allocated += size; | ||||||
|  | #endif | ||||||
|             mutex_unlock(&c->lock); |             mutex_unlock(&c->lock); | ||||||
|             return p; |             return p; | ||||||
|         } |         } | ||||||
|  | @ -491,6 +499,9 @@ static inline void *allocate_small(size_t requested_size) { | ||||||
|                 mutex_unlock(&c->lock); |                 mutex_unlock(&c->lock); | ||||||
|                 return NULL; |                 return NULL; | ||||||
|             } |             } | ||||||
|  | #if STATS | ||||||
|  |             c->slab_allocated += slab_size; | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
|             c->free_slabs_head = c->free_slabs_head->next; |             c->free_slabs_head = c->free_slabs_head->next; | ||||||
|             if (c->free_slabs_head == NULL) { |             if (c->free_slabs_head == NULL) { | ||||||
|  | @ -509,6 +520,9 @@ static inline void *allocate_small(size_t requested_size) { | ||||||
|                 set_canary(metadata, p, size); |                 set_canary(metadata, p, size); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|  | #if STATS | ||||||
|  |             c->allocated += size; | ||||||
|  | #endif | ||||||
|             mutex_unlock(&c->lock); |             mutex_unlock(&c->lock); | ||||||
|             return p; |             return p; | ||||||
|         } |         } | ||||||
|  | @ -518,6 +532,9 @@ static inline void *allocate_small(size_t requested_size) { | ||||||
|             mutex_unlock(&c->lock); |             mutex_unlock(&c->lock); | ||||||
|             return NULL; |             return NULL; | ||||||
|         } |         } | ||||||
|  | #if STATS | ||||||
|  |         c->slab_allocated += slab_size; | ||||||
|  | #endif | ||||||
|         metadata->canary_value = get_random_canary(&c->rng); |         metadata->canary_value = get_random_canary(&c->rng); | ||||||
| 
 | 
 | ||||||
|         c->partial_slabs = metadata; |         c->partial_slabs = metadata; | ||||||
|  | @ -529,6 +546,9 @@ static inline void *allocate_small(size_t requested_size) { | ||||||
|             set_canary(metadata, p, size); |             set_canary(metadata, p, size); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | #if STATS | ||||||
|  |         c->allocated += size; | ||||||
|  | #endif | ||||||
|         mutex_unlock(&c->lock); |         mutex_unlock(&c->lock); | ||||||
|         return p; |         return p; | ||||||
|     } |     } | ||||||
|  | @ -551,6 +571,9 @@ static inline void *allocate_small(size_t requested_size) { | ||||||
|         set_canary(metadata, p, size); |         set_canary(metadata, p, size); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | #if STATS | ||||||
|  |     c->allocated += size; | ||||||
|  | #endif | ||||||
|     mutex_unlock(&c->lock); |     mutex_unlock(&c->lock); | ||||||
|     return p; |     return p; | ||||||
| } | } | ||||||
|  | @ -611,6 +634,9 @@ static inline void deallocate_small(void *p, const size_t *expected_size) { | ||||||
|     size_t slab_size = get_slab_size(slots, size); |     size_t slab_size = get_slab_size(slots, size); | ||||||
| 
 | 
 | ||||||
|     mutex_lock(&c->lock); |     mutex_lock(&c->lock); | ||||||
|  | #if STATS | ||||||
|  |     c->allocated -= size; | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
|     struct slab_metadata *metadata = get_metadata(c, p); |     struct slab_metadata *metadata = get_metadata(c, p); | ||||||
|     void *slab = get_slab(c, slab_size, metadata); |     void *slab = get_slab(c, slab_size, metadata); | ||||||
|  | @ -711,6 +737,9 @@ static inline void deallocate_small(void *p, const size_t *expected_size) { | ||||||
|         if (c->empty_slabs_total + slab_size > max_empty_slabs_total) { |         if (c->empty_slabs_total + slab_size > max_empty_slabs_total) { | ||||||
|             if (!memory_map_fixed(slab, slab_size)) { |             if (!memory_map_fixed(slab, slab_size)) { | ||||||
|                 memory_set_name(slab, slab_size, size_class_labels[class]); |                 memory_set_name(slab, slab_size, size_class_labels[class]); | ||||||
|  | #if STATS | ||||||
|  |                 c->slab_allocated -= slab_size; | ||||||
|  | #endif | ||||||
|                 enqueue_free_slab(c, metadata); |                 enqueue_free_slab(c, metadata); | ||||||
|                 mutex_unlock(&c->lock); |                 mutex_unlock(&c->lock); | ||||||
|                 return; |                 return; | ||||||
|  | @ -745,6 +774,9 @@ struct region_allocator { | ||||||
|     struct region_metadata *regions; |     struct region_metadata *regions; | ||||||
|     size_t total; |     size_t total; | ||||||
|     size_t free; |     size_t free; | ||||||
|  | #if STATS | ||||||
|  |     size_t allocated; | ||||||
|  | #endif | ||||||
|     struct quarantine_info quarantine_random[REGION_QUARANTINE_RANDOM_LENGTH]; |     struct quarantine_info quarantine_random[REGION_QUARANTINE_RANDOM_LENGTH]; | ||||||
|     struct quarantine_info quarantine_queue[REGION_QUARANTINE_QUEUE_LENGTH]; |     struct quarantine_info quarantine_queue[REGION_QUARANTINE_QUEUE_LENGTH]; | ||||||
|     size_t quarantine_queue_index; |     size_t quarantine_queue_index; | ||||||
|  | @ -1110,6 +1142,9 @@ static void *allocate(size_t size) { | ||||||
|         deallocate_pages(p, size, guard_size); |         deallocate_pages(p, size, guard_size); | ||||||
|         return NULL; |         return NULL; | ||||||
|     } |     } | ||||||
|  | #if STATS | ||||||
|  |     ra->allocated += size; | ||||||
|  | #endif | ||||||
|     mutex_unlock(&ra->lock); |     mutex_unlock(&ra->lock); | ||||||
| 
 | 
 | ||||||
|     return p; |     return p; | ||||||
|  | @ -1132,6 +1167,9 @@ static void deallocate_large(void *p, const size_t *expected_size) { | ||||||
|     } |     } | ||||||
|     size_t guard_size = region->guard_size; |     size_t guard_size = region->guard_size; | ||||||
|     regions_delete(region); |     regions_delete(region); | ||||||
|  | #if STATS | ||||||
|  |     ra->allocated -= size; | ||||||
|  | #endif | ||||||
|     mutex_unlock(&ra->lock); |     mutex_unlock(&ra->lock); | ||||||
| 
 | 
 | ||||||
|     regions_quarantine_deallocate_pages(p, size, guard_size); |     regions_quarantine_deallocate_pages(p, size, guard_size); | ||||||
|  | @ -1534,6 +1572,9 @@ EXPORT int h_malloc_trim(UNUSED size_t pad) { | ||||||
|                     break; |                     break; | ||||||
|                 } |                 } | ||||||
|                 memory_set_name(slab, slab_size, size_class_labels[class]); |                 memory_set_name(slab, slab_size, size_class_labels[class]); | ||||||
|  | #if STATS | ||||||
|  |                 c->slab_allocated -= slab_size; | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
|                 struct slab_metadata *trimmed = iterator; |                 struct slab_metadata *trimmed = iterator; | ||||||
|                 iterator = iterator->next; |                 iterator = iterator->next; | ||||||
|  | @ -1557,7 +1598,33 @@ EXPORT void h_malloc_stats(void) {} | ||||||
| 
 | 
 | ||||||
| #if defined(__GLIBC__) || defined(__ANDROID__) | #if defined(__GLIBC__) || defined(__ANDROID__) | ||||||
| EXPORT struct mallinfo h_mallinfo(void) { | EXPORT struct mallinfo h_mallinfo(void) { | ||||||
|     return (struct mallinfo){0}; |     struct mallinfo info = {0}; | ||||||
|  | 
 | ||||||
|  |     // glibc mallinfo type definition and implementation are both broken
 | ||||||
|  | #if STATS && !defined(__GLIBC__) | ||||||
|  |     struct region_allocator *ra = ro.region_allocator; | ||||||
|  |     mutex_lock(&ra->lock); | ||||||
|  |     info.hblkhd += ra->allocated; | ||||||
|  |     info.uordblks += ra->allocated; | ||||||
|  |     mutex_unlock(&ra->lock); | ||||||
|  | 
 | ||||||
|  |     for (unsigned arena = 0; arena < N_ARENA; arena++) { | ||||||
|  |         // skip zero byte size class
 | ||||||
|  |         for (unsigned class = 1; class < N_SIZE_CLASSES; class++) { | ||||||
|  |             struct size_class *c = &ro.size_class_metadata[arena][class]; | ||||||
|  | 
 | ||||||
|  |             mutex_lock(&c->lock); | ||||||
|  |             info.hblkhd += c->slab_allocated; | ||||||
|  |             info.uordblks += c->allocated; | ||||||
|  |             mutex_unlock(&c->lock); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     info.fordblks = info.hblkhd - info.uordblks; | ||||||
|  |     info.usmblks = info.hblkhd; | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  |     return info; | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -8,7 +8,8 @@ CPPFLAGS += \ | ||||||
|     -DSLAB_CANARY=$(CONFIG_SLAB_CANARY) |     -DSLAB_CANARY=$(CONFIG_SLAB_CANARY) | ||||||
| 
 | 
 | ||||||
| EXECUTABLES := \
 | EXECUTABLES := \
 | ||||||
|     offset |     offset \
 | ||||||
|  |     mallinfo | ||||||
| 
 | 
 | ||||||
| all: $(EXECUTABLES) | all: $(EXECUTABLES) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										21
									
								
								test/mallinfo.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								test/mallinfo.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,21 @@ | ||||||
|  | #include <malloc.h> | ||||||
|  | 
 | ||||||
|  | __attribute__((optimize(0))) | ||||||
|  | int main(void) { | ||||||
|  |     malloc(1024 * 1024 * 1024); | ||||||
|  |     malloc(16); | ||||||
|  |     malloc(32); | ||||||
|  |     malloc(64); | ||||||
|  | 
 | ||||||
|  |     struct mallinfo info = mallinfo(); | ||||||
|  |     printf("arena: %zu\n", info.arena); | ||||||
|  |     printf("ordblks: %zu\n", info.ordblks); | ||||||
|  |     printf("smblks: %zu\n", info.smblks); | ||||||
|  |     printf("hblks: %zu\n", info.hblks); | ||||||
|  |     printf("hblkhd: %zu\n", info.hblkhd); | ||||||
|  |     printf("usmblks: %zu\n", info.usmblks); | ||||||
|  |     printf("fsmblks: %zu\n", info.fsmblks); | ||||||
|  |     printf("uordblks: %zu\n", info.uordblks); | ||||||
|  |     printf("fordblks: %zu\n", info.fordblks); | ||||||
|  |     printf("keepcost: %zu\n", info.keepcost); | ||||||
|  | } | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue