Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

large chunk (with dangling pointer) is forgotten and can be reclaimed #1

Closed
setuid0x0 opened this issue Jun 18, 2020 · 1 comment
Closed

Comments

@setuid0x0
Copy link

The Bug

A large chunk (size >= 4080) is not handled correctly and can be reclaimed even if a dangling pointer exists.

In the PoC code, we allocate and free chunk a, and create memory pressure while keeping a dangling pointer to a. After that, memory for chunk a is reclaimed when we allocate chunk b.

MarkUs should have detected a reference to the chunk a in the stack and delayed it's free.

Proof of Concept

PoC Code:

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>

#define GC_CNT 31
void gc() {
	void *arr[GC_CNT];
	for (int i = 0; i < GC_CNT; ++i) {
		arr[i] = malloc(0x4000);
	}
	for (int i = 0; i < GC_CNT; ++i) {
		free(arr[i]);
	}
}

int main() {
	uint64_t *a = malloc(4080);
	a[0] = 0x41414141;
	printf("a = %p, a[0] = %lx\n", a, a[0]);
	free(a);
	puts("freed a");

	puts("gc...");
	gc();

	uint64_t *b = malloc(4080);
	b[0] = 0x42424242;
	printf("b = %p, b[0] = %lx\n", b, b[0]);
	printf("a = %p, a[0] = %lx\n", a, a[0]);

	return 0;
}

Output:

a = 0x563827e37000, a[0] = 41414141
freed a
gc...
b = 0x563827e37000, b[0] = 42424242
a = 0x563827e37000, a[0] = 42424242

PoC Code generated by Hardsheap:

// The number of actions: 5
// chunk 2 is reused to chunk 0 at a probability of 1.000000
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <malloc.h>
void* p[256];
uintptr_t buf[256];
int main() {
  p[0] = malloc(842373);
  p[1] = malloc(842389);
  free(p[1]);
  free(p[0]);
  p[2] = malloc(842373);
  return 0;
}
@SamAinsworth
Copy link
Owner

Thanks Jungwon! The bug was in the code for Munmapped regions, which shouldn't be walked for pointers because 1) it's unnecessary and 2) it would cause a segfault. That code mistakenly also caused the mark bit not to be set on the discovery of a pointer to such a region, which is now fixed.

That now prevents these two PoC, and I believe fixes the bug in general.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants