mirror of
				https://github.com/GrapheneOS/hardened_malloc.git
				synced 2025-11-04 01:36: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