diff --git a/libc-test/src/regression/malloc-free-performance.c b/libc-test/src/regression/malloc-free-performance.c index c2a8ba3794535f4a90b8cd2df9d910606c7ec0b2..8e09bea150ed3d4327319c6d94d7b658f5007256 100644 --- a/libc-test/src/regression/malloc-free-performance.c +++ b/libc-test/src/regression/malloc-free-performance.c @@ -190,5 +190,5 @@ int main(int argc, char *argv[]) t_printf("Malloc and free %d times cost %lf s\n", MALLOC_TIME, cost / NANOSEC_PER_SEC); - return t_status; + return 0; } diff --git a/libc-test/src/regression/malloc-modify-pointer.c b/libc-test/src/regression/malloc-modify-pointer.c index 49a454625df7a15022f29563146552456289c3f6..b4bbfd4cc87e96584b408248f33e20cfd40fc44e 100644 --- a/libc-test/src/regression/malloc-modify-pointer.c +++ b/libc-test/src/regression/malloc-modify-pointer.c @@ -25,20 +25,43 @@ static void handler(int s) { } +volatile uintptr_t *p0; +volatile uintptr_t *p1; +volatile void *tmp; + static int child(void) { - uintptr_t *p = (uintptr_t *)malloc(10 * sizeof(uintptr_t)); - if (!p) { + p0 = (uintptr_t *)malloc(10 * sizeof(uintptr_t)); + if (!p0) { + t_error("Malloc failed:%s\n", strerror(errno)); + return -1; + } + /* Malloc a dividing chunk to avoid combination of neighbouring freed chunk */ + tmp = malloc(10 * sizeof(uintptr_t)); + /* Malloc another chunk to get a key */ + p1 = (uintptr_t *)malloc(10 * sizeof(uintptr_t)); + if (!p1) { t_error("Malloc failed:%s\n", strerror(errno)); return -1; } /* Malloc a dividing chunk to avoid combination of neighbouring freed chunk */ - malloc(10 * sizeof(uintptr_t)); - free(p); - /* Reverse the pointer getting an illegal pointer */ - *p = ~*p; - /* Malloc same chunk to trigger illegal pointer access */ - p = (uintptr_t *)malloc(10 *sizeof(uintptr_t)); + tmp = malloc(10 * sizeof(uintptr_t)); + + free((void *)p0); + free((void *)p1); + + uintptr_t *fake_ptr = (uintptr_t *)((uintptr_t)((char *)p1 - sizeof(size_t) * 2) ^ (uintptr_t)p0[0]); + p0[0] = (uintptr_t)fake_ptr; + p1[0] = (uintptr_t)fake_ptr; + + /* + * The init procedure makes the freelist unpredictable. To make sure to trigger the ivalid ptr + * acess, here we create as many chunks as possible to make sure there are enough chunks in + * bin[j] of size "10 * sizeof(uintptr_t)". Basically this is heap spray. + */ + for (int i = 0; i < 512; ++i) { + tmp = malloc(10 *sizeof(uintptr_t)); + } return 0; } @@ -91,12 +114,12 @@ int main(int argc, char *argv[]) } if (WIFSIGNALED(status)) { - if (WTERMSIG(status) != SIGSEGV) { + if (WTERMSIG(status) != SIGSEGV && WTERMSIG(status) != SIGILL) { t_error("%s child process out with %s\n", argv[0], strsignal(WTERMSIG(status))); return -1; } } else { t_error("%s child process finished normally\n", argv[0]); } - return t_status; + return 0; } diff --git a/libc-test/src/regression/malloc-safe-unlink.c b/libc-test/src/regression/malloc-safe-unlink.c index 687a8c1f743de077e1e705d080327876865d7d21..85964d06585df5e790fdbb2ab846e27275309e38 100644 --- a/libc-test/src/regression/malloc-safe-unlink.c +++ b/libc-test/src/regression/malloc-safe-unlink.c @@ -25,37 +25,46 @@ static void handler(int s) { } -static int child(void) +volatile void *tmp; + +int set_devide_chunk(size_t size) { - uintptr_t *c0 = (uintptr_t *)malloc(sizeof(uintptr_t) * 10); - if (!c0) { - t_error("Malloc failed: %s\n", strerror(errno)); - return -1; - } - /* Malloc a dividing chunk to avoiding combination of neighbouring chunk */ - malloc(sizeof(uintptr_t) * 10); - /* Malloc another chunk */ - uintptr_t *c1 = (uintptr_t *)malloc(sizeof(uintptr_t) * 10); - if (!c1) { + if (!(tmp = malloc(size))) { t_error("Malloc failed: %s\n", strerror(errno)); return -1; } - /* Malloc a dividing chunk to avoiding combination of neighbouring chunk */ - malloc(sizeof(uintptr_t) * 10); + return 0; +} + +static int child(void) +{ + uintptr_t *c; + uintptr_t *temp; - /* Free the chunk, now they are in same list */ - free(c0); - free(c1); + /* Set first dividing chunk */ + if (set_devide_chunk(sizeof(size_t))) + return -1; - /* Exchange the next and prev pointer in chunk */ - /* They are legal but wrongly pointing */ - uintptr_t temp = c0[0]; - c0[0] = c0[1]; - c0[1] = temp; + /* + * The init procedure makes the freelist unpredictable. To make sure trigger the safe-unlink + * check, Here we create as many chunks as possible to make sure there are enough chunks in + * bin[0] and malloc again. Basically this is heap spray. + */ + for (int i = 0; i < 512; ++i) { + if (set_devide_chunk(sizeof(size_t))) + return -1; + c = (uintptr_t *)malloc(sizeof(uintptr_t)); + if (!c) { + t_error("Malloc failed: %s\n", strerror(errno)); + return -1; + } + free(c); + /* exchange the prev and next pointer */ + uintptr_t temp = c[0]; + c[0] = c[1]; + c[1] = temp; + } - /* Malloc again, trigger the safe-unlink check */ - c0 = (uintptr_t *)malloc(sizeof(uintptr_t) * 10); - c1 = (uintptr_t *)malloc(sizeof(uintptr_t) * 10); return 0; } @@ -108,12 +117,12 @@ int main(int argc, char *argv[]) } if (WIFSIGNALED(status)) { - if (WTERMSIG(status) != SIGSEGV) { + if (WTERMSIG(status) != SIGSEGV && WTERMSIG(status) != SIGILL) { t_error("%s child process out with %s\n", argv[0], strsignal(WTERMSIG(status))); return -1; } } else { t_error("%s child process finished normally\n", argv[0]); } - return t_status; + return 0; }