mirror of
https://github.com/Divested-Mobile/DivestOS-Build.git
synced 2025-04-06 21:03:53 -04:00
Add bionic hardening patchsets from GrapheneOS
11b3a0c2c5db
115412c37195
#explicit zero 1131456ac632
#brk 1158ebc243ea
#random 115323b39f7e
#undefined 116a91d9dddb
#merge 11a042b5a0ba
#vla formatting 119ec639de1b
#pthread 1149571a0a49
#read only 11149cc5ccb8
#zero 112e613ccbe7
#fork mmap 11e239c7dff8
#memprot pthread 110b03d92b7f
#xor 11de08419b82
#junk 11897d4903e2
#guard 11648cd68ca3
#ptrhread guard 110bc4dbcbd2
#stack rand 10aa9cc05d07
10a8cdbb6352
#explicit zero 10b28302c668
#brk 109f8be7d07c
#random 10cb91a7ee3a
#undefined 1008279e2fdd
#merge 106a18bd565d
#vla formatting 102f392c2d08
#pthread 108bbce1bc50
#read only 10725f61db82
#zero 104cd257135f
#fork mmap 109220cf622b
#memprot pthread 108ef71d1ffd
#memprot exit 100eaef1abbd
#xor 1064f1cc2148
#junk 105c42a527cf
#guard 105cc8c34e60
#pthread guard 107f61cc8a1c
#stack rand 9abdf523d26
9e4b9b31e6f
#explicit zero 9a3a22a63d2
#brk 97444dbc3cf
#random 9dcd3b72ac9
#undefined 9543e1df342
#merge 9611e5691f7
#vla formatting 98de97ce864
#pthread 9a475717042
#read only 97f0947cc0e
#zero 9e9751d3370
#fork mmap 983cd86d0d5
#memprot pthread 91ebb165455
#memprot exit 9488ba483cf
#xor 9f9351d884b
#junk 985e5bca0a5
#move Signed-off-by: Tad <tad@spotco.us>
This commit is contained in:
parent
1878cd19ab
commit
181519cf38
@ -0,0 +1,163 @@
|
||||
From e4b9b31e6f9ff7eb9d168db6a99a775bf4f669c1 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Micay <danielmicay@gmail.com>
|
||||
Date: Thu, 5 Feb 2015 21:53:16 -0500
|
||||
Subject: [PATCH] add a real explicit_bzero implementation
|
||||
|
||||
Clang, GCC and other compilers special-case standard C functions like
|
||||
memset. Calls to memset will be optimized out.
|
||||
|
||||
OpenBSD provides explicit_bzero to work around this but Android simply
|
||||
defines it as memset so nothing prevents it from being optimized away.
|
||||
|
||||
This implementation uses a memory read constraint via empty inline
|
||||
assembly rather than something that may be broken via link-time
|
||||
optimization in the future.
|
||||
---
|
||||
libc/Android.bp | 1 +
|
||||
libc/bionic/explicit_bzero.cpp | 7 +++++++
|
||||
libc/include/string.h | 1 +
|
||||
libc/libc.arm.map | 1 +
|
||||
libc/libc.arm64.map | 1 +
|
||||
libc/libc.map.txt | 1 +
|
||||
libc/libc.mips.map | 1 +
|
||||
libc/libc.mips64.map | 1 +
|
||||
libc/libc.x86.map | 1 +
|
||||
libc/libc.x86_64.map | 1 +
|
||||
libc/upstream-openbsd/android/include/openbsd-compat.h | 2 --
|
||||
11 files changed, 16 insertions(+), 2 deletions(-)
|
||||
create mode 100644 libc/bionic/explicit_bzero.cpp
|
||||
|
||||
diff --git a/libc/Android.bp b/libc/Android.bp
|
||||
index 26ffc73b66..85a739e4e9 100644
|
||||
--- a/libc/Android.bp
|
||||
+++ b/libc/Android.bp
|
||||
@@ -1329,6 +1329,7 @@ cc_library_static {
|
||||
"bionic/eventfd_read.cpp",
|
||||
"bionic/eventfd_write.cpp",
|
||||
"bionic/exec.cpp",
|
||||
+ "bionic/explicit_bzero.cpp",
|
||||
"bionic/faccessat.cpp",
|
||||
"bionic/fchmod.cpp",
|
||||
"bionic/fchmodat.cpp",
|
||||
diff --git a/libc/bionic/explicit_bzero.cpp b/libc/bionic/explicit_bzero.cpp
|
||||
new file mode 100644
|
||||
index 0000000000..b06daa1386
|
||||
--- /dev/null
|
||||
+++ b/libc/bionic/explicit_bzero.cpp
|
||||
@@ -0,0 +1,7 @@
|
||||
+#include <string.h>
|
||||
+
|
||||
+void* explicit_bzero(void* s, size_t n) {
|
||||
+ void *ptr = memset(s, 0, n);
|
||||
+ __asm__ __volatile__("" : : "r"(ptr) : "memory");
|
||||
+ return ptr;
|
||||
+}
|
||||
diff --git a/libc/include/string.h b/libc/include/string.h
|
||||
index 54d5e1c800..5336777773 100644
|
||||
--- a/libc/include/string.h
|
||||
+++ b/libc/include/string.h
|
||||
@@ -56,6 +56,7 @@ void* mempcpy(void* __dst, const void* __src, size_t __n) __INTRODUCED_IN(23);
|
||||
#endif
|
||||
void* memmove(void* __dst, const void* __src, size_t __n);
|
||||
void* memset(void* __dst, int __ch, size_t __n);
|
||||
+void* explicit_bzero(void *s, size_t n);
|
||||
void* memmem(const void* __haystack, size_t __haystack_size, const void* __needle, size_t __needle_size) __attribute_pure__;
|
||||
|
||||
char* strchr(const char* __s, int __ch) __attribute_pure__;
|
||||
diff --git a/libc/libc.arm.map b/libc/libc.arm.map
|
||||
index b0f96a9ffc..28ad4913f6 100644
|
||||
--- a/libc/libc.arm.map
|
||||
+++ b/libc/libc.arm.map
|
||||
@@ -330,6 +330,7 @@ LIBC {
|
||||
execvp;
|
||||
execvpe; # introduced=21
|
||||
exit;
|
||||
+ explicit_bzero;
|
||||
faccessat; # introduced-arm=16 introduced-arm64=21 introduced-mips=16 introduced-mips64=21 introduced-x86=16 introduced-x86_64=21
|
||||
fallocate; # introduced=21
|
||||
fallocate64; # introduced=21
|
||||
diff --git a/libc/libc.arm64.map b/libc/libc.arm64.map
|
||||
index 6b0e415494..ee20108901 100644
|
||||
--- a/libc/libc.arm64.map
|
||||
+++ b/libc/libc.arm64.map
|
||||
@@ -260,6 +260,7 @@ LIBC {
|
||||
execvp;
|
||||
execvpe; # introduced=21
|
||||
exit;
|
||||
+ explicit_bzero;
|
||||
faccessat; # introduced-arm=16 introduced-arm64=21 introduced-mips=16 introduced-mips64=21 introduced-x86=16 introduced-x86_64=21
|
||||
fallocate; # introduced=21
|
||||
fallocate64; # introduced=21
|
||||
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
|
||||
index 85c9a581cb..6c7e3eb368 100644
|
||||
--- a/libc/libc.map.txt
|
||||
+++ b/libc/libc.map.txt
|
||||
@@ -332,6 +332,7 @@ LIBC {
|
||||
execvp;
|
||||
execvpe; # introduced=21
|
||||
exit;
|
||||
+ explicit_bzero;
|
||||
faccessat; # introduced-arm=16 introduced-arm64=21 introduced-mips=16 introduced-mips64=21 introduced-x86=16 introduced-x86_64=21
|
||||
fallocate; # introduced=21
|
||||
fallocate64; # introduced=21
|
||||
diff --git a/libc/libc.mips.map b/libc/libc.mips.map
|
||||
index 9e760c2422..12faa5d86b 100644
|
||||
--- a/libc/libc.mips.map
|
||||
+++ b/libc/libc.mips.map
|
||||
@@ -328,6 +328,7 @@ LIBC {
|
||||
execvp;
|
||||
execvpe; # introduced=21
|
||||
exit;
|
||||
+ explicit_bzero;
|
||||
faccessat; # introduced-arm=16 introduced-arm64=21 introduced-mips=16 introduced-mips64=21 introduced-x86=16 introduced-x86_64=21
|
||||
fallocate; # introduced=21
|
||||
fallocate64; # introduced=21
|
||||
diff --git a/libc/libc.mips64.map b/libc/libc.mips64.map
|
||||
index 6b0e415494..ee20108901 100644
|
||||
--- a/libc/libc.mips64.map
|
||||
+++ b/libc/libc.mips64.map
|
||||
@@ -260,6 +260,7 @@ LIBC {
|
||||
execvp;
|
||||
execvpe; # introduced=21
|
||||
exit;
|
||||
+ explicit_bzero;
|
||||
faccessat; # introduced-arm=16 introduced-arm64=21 introduced-mips=16 introduced-mips64=21 introduced-x86=16 introduced-x86_64=21
|
||||
fallocate; # introduced=21
|
||||
fallocate64; # introduced=21
|
||||
diff --git a/libc/libc.x86.map b/libc/libc.x86.map
|
||||
index 2855f9e22d..8be30d8424 100644
|
||||
--- a/libc/libc.x86.map
|
||||
+++ b/libc/libc.x86.map
|
||||
@@ -326,6 +326,7 @@ LIBC {
|
||||
execvp;
|
||||
execvpe; # introduced=21
|
||||
exit;
|
||||
+ explicit_bzero;
|
||||
faccessat; # introduced-arm=16 introduced-arm64=21 introduced-mips=16 introduced-mips64=21 introduced-x86=16 introduced-x86_64=21
|
||||
fallocate; # introduced=21
|
||||
fallocate64; # introduced=21
|
||||
diff --git a/libc/libc.x86_64.map b/libc/libc.x86_64.map
|
||||
index 6b0e415494..ee20108901 100644
|
||||
--- a/libc/libc.x86_64.map
|
||||
+++ b/libc/libc.x86_64.map
|
||||
@@ -260,6 +260,7 @@ LIBC {
|
||||
execvp;
|
||||
execvpe; # introduced=21
|
||||
exit;
|
||||
+ explicit_bzero;
|
||||
faccessat; # introduced-arm=16 introduced-arm64=21 introduced-mips=16 introduced-mips64=21 introduced-x86=16 introduced-x86_64=21
|
||||
fallocate; # introduced=21
|
||||
fallocate64; # introduced=21
|
||||
diff --git a/libc/upstream-openbsd/android/include/openbsd-compat.h b/libc/upstream-openbsd/android/include/openbsd-compat.h
|
||||
index f178149311..929e61eeda 100644
|
||||
--- a/libc/upstream-openbsd/android/include/openbsd-compat.h
|
||||
+++ b/libc/upstream-openbsd/android/include/openbsd-compat.h
|
||||
@@ -65,8 +65,6 @@ extern const char* __progname;
|
||||
/* OpenBSD has this, but we can't really implement it correctly on Linux. */
|
||||
#define issetugid() 0
|
||||
|
||||
-#define explicit_bzero(p, s) memset(p, 0, s)
|
||||
-
|
||||
/* OpenBSD has these in <sys/param.h>, but "ALIGN" isn't something we want to reserve. */
|
||||
#define ALIGNBYTES (sizeof(uintptr_t) - 1)
|
||||
#define ALIGN(p) (((uintptr_t)(p) + ALIGNBYTES) &~ ALIGNBYTES)
|
@ -0,0 +1,85 @@
|
||||
From e9751d3370aa44e6ca77843f7c7a7aac67e5bcc0 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Micay <danielmicay@gmail.com>
|
||||
Date: Wed, 2 Dec 2015 23:37:28 -0500
|
||||
Subject: [PATCH] switch pthread_atfork handler allocation to mmap
|
||||
|
||||
---
|
||||
libc/bionic/pthread_atfork.cpp | 35 ++++++++++++++++++++++++++++------
|
||||
1 file changed, 29 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/libc/bionic/pthread_atfork.cpp b/libc/bionic/pthread_atfork.cpp
|
||||
index 84e511c2e8..651c026df5 100644
|
||||
--- a/libc/bionic/pthread_atfork.cpp
|
||||
+++ b/libc/bionic/pthread_atfork.cpp
|
||||
@@ -29,8 +29,11 @@
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
+#include <sys/mman.h>
|
||||
+#include <unistd.h>
|
||||
|
||||
#include "private/bionic_macros.h"
|
||||
+#include "private/bionic_prctl.h"
|
||||
|
||||
struct atfork_t {
|
||||
atfork_t* next;
|
||||
@@ -43,6 +46,8 @@ struct atfork_t {
|
||||
void* dso_handle;
|
||||
};
|
||||
|
||||
+static atfork_t* pool;
|
||||
+
|
||||
class atfork_list_t {
|
||||
public:
|
||||
constexpr atfork_list_t() : first_(nullptr), last_(nullptr) {}
|
||||
@@ -101,7 +106,8 @@ class atfork_list_t {
|
||||
last_ = entry->prev;
|
||||
}
|
||||
|
||||
- free(entry);
|
||||
+ entry->next = pool;
|
||||
+ pool = entry;
|
||||
}
|
||||
|
||||
atfork_t* first_;
|
||||
@@ -154,18 +160,35 @@ void __bionic_atfork_run_parent() {
|
||||
// __register_atfork is the name used by glibc
|
||||
extern "C" int __register_atfork(void (*prepare)(void), void (*parent)(void),
|
||||
void(*child)(void), void* dso) {
|
||||
- atfork_t* entry = reinterpret_cast<atfork_t*>(malloc(sizeof(atfork_t)));
|
||||
- if (entry == nullptr) {
|
||||
- return ENOMEM;
|
||||
+ pthread_mutex_lock(&g_atfork_list_mutex);
|
||||
+
|
||||
+ if (!pool) {
|
||||
+ size_t page_size = getpagesize();
|
||||
+ char* page = static_cast<char*>(mmap(NULL, page_size, PROT_READ|PROT_WRITE,
|
||||
+ MAP_ANONYMOUS|MAP_PRIVATE, -1, 0));
|
||||
+ if (page == MAP_FAILED) {
|
||||
+ pthread_mutex_unlock(&g_atfork_list_mutex);
|
||||
+ return ENOMEM;
|
||||
+ }
|
||||
+
|
||||
+ prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, page, page_size,
|
||||
+ "atfork handlers");
|
||||
+
|
||||
+ for (char* it = page; it < page + page_size - sizeof(atfork_t); it += sizeof(atfork_t)) {
|
||||
+ atfork_t* node = reinterpret_cast<atfork_t*>(it);
|
||||
+ node->next = pool;
|
||||
+ pool = node;
|
||||
+ }
|
||||
}
|
||||
|
||||
+ atfork_t* entry = pool;
|
||||
+ pool = entry->next;
|
||||
+
|
||||
entry->prepare = prepare;
|
||||
entry->parent = parent;
|
||||
entry->child = child;
|
||||
entry->dso_handle = dso;
|
||||
|
||||
- pthread_mutex_lock(&g_atfork_list_mutex);
|
||||
-
|
||||
g_atfork_list.push_back(entry);
|
||||
|
||||
pthread_mutex_unlock(&g_atfork_list_mutex);
|
@ -0,0 +1,95 @@
|
||||
From 83cd86d0d522c64726dac41614c00f2534044f73 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Micay <danielmicay@gmail.com>
|
||||
Date: Thu, 3 Dec 2015 12:58:31 -0500
|
||||
Subject: [PATCH] add memory protection for pthread_atfork handlers
|
||||
|
||||
---
|
||||
libc/bionic/pthread_atfork.cpp | 34 ++++++++++++++++++++++++++++++++--
|
||||
1 file changed, 32 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/libc/bionic/pthread_atfork.cpp b/libc/bionic/pthread_atfork.cpp
|
||||
index 651c026df5..91c5233f73 100644
|
||||
--- a/libc/bionic/pthread_atfork.cpp
|
||||
+++ b/libc/bionic/pthread_atfork.cpp
|
||||
@@ -47,6 +47,7 @@ struct atfork_t {
|
||||
};
|
||||
|
||||
static atfork_t* pool;
|
||||
+static atfork_t* page_list;
|
||||
|
||||
class atfork_list_t {
|
||||
public:
|
||||
@@ -160,13 +161,22 @@ void __bionic_atfork_run_parent() {
|
||||
// __register_atfork is the name used by glibc
|
||||
extern "C" int __register_atfork(void (*prepare)(void), void (*parent)(void),
|
||||
void(*child)(void), void* dso) {
|
||||
+ size_t page_size = getpagesize();
|
||||
+
|
||||
pthread_mutex_lock(&g_atfork_list_mutex);
|
||||
|
||||
+ for (atfork_t* page_it = page_list; page_it; page_it = page_it->next) {
|
||||
+ mprotect(page_it, page_size, PROT_READ|PROT_WRITE);
|
||||
+ }
|
||||
+
|
||||
if (!pool) {
|
||||
- size_t page_size = getpagesize();
|
||||
char* page = static_cast<char*>(mmap(NULL, page_size, PROT_READ|PROT_WRITE,
|
||||
MAP_ANONYMOUS|MAP_PRIVATE, -1, 0));
|
||||
if (page == MAP_FAILED) {
|
||||
+ for (atfork_t* page_it = page_list; page_it; page_it = page_it->next) {
|
||||
+ mprotect(page_it, page_size, PROT_READ);
|
||||
+ }
|
||||
+
|
||||
pthread_mutex_unlock(&g_atfork_list_mutex);
|
||||
return ENOMEM;
|
||||
}
|
||||
@@ -174,11 +184,15 @@ extern "C" int __register_atfork(void (*prepare)(void), void (*parent)(void),
|
||||
prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, page, page_size,
|
||||
"atfork handlers");
|
||||
|
||||
- for (char* it = page; it < page + page_size - sizeof(atfork_t); it += sizeof(atfork_t)) {
|
||||
+ for (char* it = page + sizeof(atfork_t); it < page + page_size - sizeof(atfork_t); it += sizeof(atfork_t)) {
|
||||
atfork_t* node = reinterpret_cast<atfork_t*>(it);
|
||||
node->next = pool;
|
||||
pool = node;
|
||||
}
|
||||
+
|
||||
+ atfork_t* page_node = reinterpret_cast<atfork_t*>(page);
|
||||
+ page_node->next = page_list;
|
||||
+ page_list = page_node;
|
||||
}
|
||||
|
||||
atfork_t* entry = pool;
|
||||
@@ -191,6 +205,10 @@ extern "C" int __register_atfork(void (*prepare)(void), void (*parent)(void),
|
||||
|
||||
g_atfork_list.push_back(entry);
|
||||
|
||||
+ for (atfork_t* page_it = page_list; page_it; page_it = page_it->next) {
|
||||
+ mprotect(page_it, page_size, PROT_READ);
|
||||
+ }
|
||||
+
|
||||
pthread_mutex_unlock(&g_atfork_list_mutex);
|
||||
|
||||
return 0;
|
||||
@@ -198,9 +216,21 @@ extern "C" int __register_atfork(void (*prepare)(void), void (*parent)(void),
|
||||
|
||||
extern "C" __LIBC_HIDDEN__ void __unregister_atfork(void* dso) {
|
||||
pthread_mutex_lock(&g_atfork_list_mutex);
|
||||
+
|
||||
+ size_t page_size = getpagesize();
|
||||
+
|
||||
+ for (atfork_t* page_it = page_list; page_it; page_it = page_it->next) {
|
||||
+ mprotect(page_it, page_size, PROT_READ|PROT_WRITE);
|
||||
+ }
|
||||
+
|
||||
g_atfork_list.remove_if([&](const atfork_t* entry) {
|
||||
return entry->dso_handle == dso;
|
||||
});
|
||||
+
|
||||
+ for (atfork_t* page_it = page_list; page_it; page_it = page_it->next) {
|
||||
+ mprotect(page_it, page_size, PROT_READ);
|
||||
+ }
|
||||
+
|
||||
pthread_mutex_unlock(&g_atfork_list_mutex);
|
||||
}
|
||||
|
@ -0,0 +1,80 @@
|
||||
From 1ebb1654556ed74d63e43fe7dbbceae5b20f569f Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Micay <danielmicay@gmail.com>
|
||||
Date: Sat, 7 Feb 2015 20:14:24 -0500
|
||||
Subject: [PATCH] add memory protection for at_quick_exit
|
||||
|
||||
---
|
||||
.../lib/libc/stdlib/quick_exit.c | 41 ++++++++++++++++---
|
||||
1 file changed, 36 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/libc/upstream-freebsd/lib/libc/stdlib/quick_exit.c b/libc/upstream-freebsd/lib/libc/stdlib/quick_exit.c
|
||||
index ef8cdb1b40..b23d8642ae 100644
|
||||
--- a/libc/upstream-freebsd/lib/libc/stdlib/quick_exit.c
|
||||
+++ b/libc/upstream-freebsd/lib/libc/stdlib/quick_exit.c
|
||||
@@ -28,6 +28,10 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
+#include <sys/mman.h>
|
||||
+#include <unistd.h>
|
||||
+
|
||||
+#include "private/bionic_prctl.h"
|
||||
|
||||
/**
|
||||
* Linked list of quick exit handlers. This is simpler than the atexit()
|
||||
@@ -39,6 +43,10 @@ struct quick_exit_handler {
|
||||
void (*cleanup)(void);
|
||||
};
|
||||
|
||||
+static struct quick_exit_handler *pool_page;
|
||||
+static struct quick_exit_handler *pool;
|
||||
+static size_t pool_size;
|
||||
+
|
||||
/**
|
||||
* Lock protecting the handlers list.
|
||||
*/
|
||||
@@ -51,16 +59,39 @@ static struct quick_exit_handler *handlers;
|
||||
int
|
||||
at_quick_exit(void (*func)(void))
|
||||
{
|
||||
+ size_t page_size = getpagesize();
|
||||
struct quick_exit_handler *h;
|
||||
-
|
||||
- h = malloc(sizeof(*h));
|
||||
|
||||
- if (NULL == h)
|
||||
- return (1);
|
||||
- h->cleanup = func;
|
||||
pthread_mutex_lock(&atexit_mutex);
|
||||
+
|
||||
+ if (pool_size < sizeof(*h)) {
|
||||
+ void *ptr = mmap(NULL, page_size, PROT_READ|PROT_WRITE,
|
||||
+ MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
|
||||
+ if (ptr == MAP_FAILED) {
|
||||
+ pthread_mutex_unlock(&atexit_mutex);
|
||||
+ return (1);
|
||||
+ }
|
||||
+ prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, ptr, page_size,
|
||||
+ "at_quick_exit handlers");
|
||||
+ pool_page = pool = ptr;
|
||||
+ pool_size = page_size;
|
||||
+ } else {
|
||||
+ if (mprotect(pool_page, page_size, PROT_READ|PROT_WRITE)) {
|
||||
+ pthread_mutex_unlock(&atexit_mutex);
|
||||
+ return (1);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ h = pool++;
|
||||
+ pool_size -= sizeof(*h);
|
||||
+
|
||||
+ h->cleanup = func;
|
||||
+
|
||||
h->next = handlers;
|
||||
handlers = h;
|
||||
+
|
||||
+ mprotect(pool_page, page_size, PROT_READ);
|
||||
+
|
||||
pthread_mutex_unlock(&atexit_mutex);
|
||||
return (0);
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
From 488ba483cf9ad195fda33b3250115a308bf03f75 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Micay <danielmicay@gmail.com>
|
||||
Date: Wed, 27 Jan 2016 18:02:15 -0500
|
||||
Subject: [PATCH] add XOR mangling mitigation for thread-local dtors
|
||||
|
||||
---
|
||||
libc/bionic/__cxa_thread_atexit_impl.cpp | 8 +++++---
|
||||
libc/bionic/libc_init_common.cpp | 2 ++
|
||||
libc/private/bionic_globals.h | 1 +
|
||||
3 files changed, 8 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/libc/bionic/__cxa_thread_atexit_impl.cpp b/libc/bionic/__cxa_thread_atexit_impl.cpp
|
||||
index 99077c101d..74608513ef 100644
|
||||
--- a/libc/bionic/__cxa_thread_atexit_impl.cpp
|
||||
+++ b/libc/bionic/__cxa_thread_atexit_impl.cpp
|
||||
@@ -13,15 +13,17 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
+#include <stdint.h>
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
#include <private/bionic_defs.h>
|
||||
+#include <private/bionic_globals.h>
|
||||
|
||||
#include "pthread_internal.h"
|
||||
|
||||
class thread_local_dtor {
|
||||
public:
|
||||
- void (*func) (void *);
|
||||
+ uintptr_t func;
|
||||
void *arg;
|
||||
void *dso_handle; // unused...
|
||||
thread_local_dtor* next;
|
||||
@@ -35,7 +37,7 @@ __BIONIC_WEAK_FOR_NATIVE_BRIDGE
|
||||
int __cxa_thread_atexit_impl(void (*func) (void *), void *arg, void *dso_handle) {
|
||||
thread_local_dtor* dtor = new thread_local_dtor();
|
||||
|
||||
- dtor->func = func;
|
||||
+ dtor->func = __libc_globals->dtor_cookie ^ reinterpret_cast<uintptr_t>(func);
|
||||
dtor->arg = arg;
|
||||
dtor->dso_handle = dso_handle;
|
||||
|
||||
@@ -54,7 +56,7 @@ extern "C" __LIBC_HIDDEN__ void __cxa_thread_finalize() {
|
||||
thread_local_dtor* current = thread->thread_local_dtors;
|
||||
thread->thread_local_dtors = current->next;
|
||||
|
||||
- current->func(current->arg);
|
||||
+ (reinterpret_cast<void (*)(void*)>(__libc_globals->dtor_cookie ^ current->func))(current->arg);
|
||||
if (__loader_remove_thread_local_dtor != nullptr) {
|
||||
__loader_remove_thread_local_dtor(current->dso_handle);
|
||||
}
|
||||
diff --git a/libc/bionic/libc_init_common.cpp b/libc/bionic/libc_init_common.cpp
|
||||
index 2396c36782..47555c598a 100644
|
||||
--- a/libc/bionic/libc_init_common.cpp
|
||||
+++ b/libc/bionic/libc_init_common.cpp
|
||||
@@ -45,6 +45,7 @@
|
||||
|
||||
#include "private/KernelArgumentBlock.h"
|
||||
#include "private/WriteProtected.h"
|
||||
+#include "private/bionic_arc4random.h"
|
||||
#include "private/bionic_auxv.h"
|
||||
#include "private/bionic_defs.h"
|
||||
#include "private/bionic_globals.h"
|
||||
@@ -91,6 +92,7 @@ void __libc_init_globals(KernelArgumentBlock& args) {
|
||||
__libc_globals.mutate([&args](libc_globals* globals) {
|
||||
__libc_init_vdso(globals, args);
|
||||
__libc_init_setjmp_cookie(globals, args);
|
||||
+ arc4random_buf(&globals->dtor_cookie, sizeof(globals->dtor_cookie));
|
||||
});
|
||||
}
|
||||
|
||||
diff --git a/libc/private/bionic_globals.h b/libc/private/bionic_globals.h
|
||||
index 94dd7e8590..0361f4ed72 100644
|
||||
--- a/libc/private/bionic_globals.h
|
||||
+++ b/libc/private/bionic_globals.h
|
||||
@@ -37,6 +37,7 @@
|
||||
|
||||
struct libc_globals {
|
||||
vdso_entry vdso[VDSO_END];
|
||||
+ long dtor_cookie;
|
||||
long setjmp_cookie;
|
||||
MallocDispatch malloc_dispatch;
|
||||
};
|
@ -0,0 +1,23 @@
|
||||
From f9351d884bddaf126a8fc45c8cb14e7ca2cf463b Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Micay <danielmicay@gmail.com>
|
||||
Date: Fri, 29 Jan 2016 20:20:09 -0500
|
||||
Subject: [PATCH] use a better pthread_attr junk filling pattern
|
||||
|
||||
Guarantee that junk filled pointers will fault, at least on pure 64-bit.
|
||||
---
|
||||
libc/bionic/pthread_attr.cpp | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/libc/bionic/pthread_attr.cpp b/libc/bionic/pthread_attr.cpp
|
||||
index 93177f15c8..692bcf162b 100644
|
||||
--- a/libc/bionic/pthread_attr.cpp
|
||||
+++ b/libc/bionic/pthread_attr.cpp
|
||||
@@ -53,7 +53,7 @@ int pthread_attr_init(pthread_attr_t* attr) {
|
||||
|
||||
__BIONIC_WEAK_FOR_NATIVE_BRIDGE
|
||||
int pthread_attr_destroy(pthread_attr_t* attr) {
|
||||
- memset(attr, 0x42, sizeof(pthread_attr_t));
|
||||
+ memset(attr, 0xdf, sizeof(pthread_attr_t));
|
||||
return 0;
|
||||
}
|
||||
|
@ -0,0 +1,101 @@
|
||||
From 85e5bca0a525a1cb8142aa092286ae3424983dd5 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Micay <danielmicay@gmail.com>
|
||||
Date: Fri, 11 Dec 2015 01:52:08 -0500
|
||||
Subject: [PATCH] move pthread_internal_t out of the stack mapping
|
||||
|
||||
[TODO: guard pages]
|
||||
---
|
||||
libc/bionic/pthread_create.cpp | 20 +++++++++++---------
|
||||
libc/bionic/pthread_exit.cpp | 7 +++++--
|
||||
libc/bionic/pthread_internal.cpp | 1 +
|
||||
3 files changed, 17 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
|
||||
index 8825c6f240..e70af04094 100644
|
||||
--- a/libc/bionic/pthread_create.cpp
|
||||
+++ b/libc/bionic/pthread_create.cpp
|
||||
@@ -191,7 +191,6 @@ static int __allocate_thread(pthread_attr_t* attr, pthread_internal_t** threadp,
|
||||
// The caller didn't provide a stack, so allocate one.
|
||||
// Make sure the stack size and guard size are multiples of PAGE_SIZE.
|
||||
if (__builtin_add_overflow(attr->stack_size, attr->guard_size, &mmap_size)) return EAGAIN;
|
||||
- if (__builtin_add_overflow(mmap_size, sizeof(pthread_internal_t), &mmap_size)) return EAGAIN;
|
||||
mmap_size = __BIONIC_ALIGN(mmap_size, PAGE_SIZE);
|
||||
attr->guard_size = __BIONIC_ALIGN(attr->guard_size, PAGE_SIZE);
|
||||
attr->stack_base = __create_thread_mapped_space(mmap_size, attr->guard_size);
|
||||
@@ -210,21 +209,23 @@ static int __allocate_thread(pthread_attr_t* attr, pthread_internal_t** threadp,
|
||||
// thread stack (including guard)
|
||||
|
||||
// To safely access the pthread_internal_t and thread stack, we need to find a 16-byte aligned boundary.
|
||||
- stack_top = reinterpret_cast<uint8_t*>(
|
||||
- (reinterpret_cast<uintptr_t>(stack_top) - sizeof(pthread_internal_t)) & ~0xf);
|
||||
-
|
||||
- pthread_internal_t* thread = reinterpret_cast<pthread_internal_t*>(stack_top);
|
||||
- if (mmap_size == 0) {
|
||||
- // If thread was not allocated by mmap(), it may not have been cleared to zero.
|
||||
- // So assume the worst and zero it.
|
||||
- memset(thread, 0, sizeof(pthread_internal_t));
|
||||
+ stack_top = reinterpret_cast<uint8_t*>(reinterpret_cast<uintptr_t>(stack_top) & ~0xf);
|
||||
+
|
||||
+ pthread_internal_t* thread = static_cast<pthread_internal_t*>(
|
||||
+ mmap(nullptr, sizeof(pthread_internal_t), PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS,
|
||||
+ -1, 0));
|
||||
+ if (thread == MAP_FAILED) {
|
||||
+ if (thread->mmap_size != 0) munmap(thread->attr.stack_base, thread->mmap_size);
|
||||
+ return EAGAIN;
|
||||
}
|
||||
+ prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, thread, sizeof(pthread_internal_t), "pthread_internal_t");
|
||||
attr->stack_size = stack_top - reinterpret_cast<uint8_t*>(attr->stack_base);
|
||||
|
||||
thread->mmap_size = mmap_size;
|
||||
thread->attr = *attr;
|
||||
if (!__init_tls(thread)) {
|
||||
if (thread->mmap_size != 0) munmap(thread->attr.stack_base, thread->mmap_size);
|
||||
+ munmap(thread, sizeof(pthread_internal_t));
|
||||
return EAGAIN;
|
||||
}
|
||||
__init_thread_stack_guard(thread);
|
||||
@@ -313,6 +314,7 @@ int pthread_create(pthread_t* thread_out, pthread_attr_t const* attr,
|
||||
if (thread->mmap_size != 0) {
|
||||
munmap(thread->attr.stack_base, thread->mmap_size);
|
||||
}
|
||||
+ munmap(thread, sizeof(pthread_internal_t));
|
||||
async_safe_format_log(ANDROID_LOG_WARN, "libc", "pthread_create failed: clone failed: %s",
|
||||
strerror(clone_errno));
|
||||
return clone_errno;
|
||||
diff --git a/libc/bionic/pthread_exit.cpp b/libc/bionic/pthread_exit.cpp
|
||||
index f1b65fdf7a..fe26696baf 100644
|
||||
--- a/libc/bionic/pthread_exit.cpp
|
||||
+++ b/libc/bionic/pthread_exit.cpp
|
||||
@@ -118,7 +118,8 @@ void pthread_exit(void* return_value) {
|
||||
// pthread_internal_t is freed below with stack, not here.
|
||||
__pthread_internal_remove(thread);
|
||||
|
||||
- if (thread->mmap_size != 0) {
|
||||
+ size_t mmap_size = thread->mmap_size;
|
||||
+ if (mmap_size != 0) {
|
||||
// We need to free mapped space for detached threads when they exit.
|
||||
// That's not something we can do in C.
|
||||
|
||||
@@ -126,7 +127,9 @@ void pthread_exit(void* return_value) {
|
||||
// That's one last thing we can do before dropping to assembler.
|
||||
ScopedSignalBlocker ssb;
|
||||
__pthread_unmap_tls(thread);
|
||||
- _exit_with_stack_teardown(thread->attr.stack_base, thread->mmap_size);
|
||||
+ void* stack_base = thread->attr.stack_base;
|
||||
+ munmap(thread, sizeof(pthread_internal_t));
|
||||
+ _exit_with_stack_teardown(stack_base, mmap_size);
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/libc/bionic/pthread_internal.cpp b/libc/bionic/pthread_internal.cpp
|
||||
index 829194cc71..b5de202487 100644
|
||||
--- a/libc/bionic/pthread_internal.cpp
|
||||
+++ b/libc/bionic/pthread_internal.cpp
|
||||
@@ -91,6 +91,7 @@ static void __pthread_internal_free(pthread_internal_t* thread) {
|
||||
// Free mapped space, including thread stack and pthread_internal_t.
|
||||
munmap(thread->attr.stack_base, thread->mmap_size);
|
||||
}
|
||||
+ munmap(thread, sizeof(pthread_internal_t));
|
||||
}
|
||||
|
||||
void __pthread_internal_remove_and_free(pthread_internal_t* thread) {
|
@ -0,0 +1,74 @@
|
||||
From a3a22a63d2cf265d5edc8cf613484e13fd03e19d Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Micay <danielmicay@gmail.com>
|
||||
Date: Sun, 8 Feb 2015 01:18:54 -0500
|
||||
Subject: [PATCH] replace brk and sbrk with stubs
|
||||
|
||||
Pretend that there is never room to grow the heap in order to prevent
|
||||
usage of these unsafe legacy functions. There are likely no users of
|
||||
these in practice as it is inherently broken to use them outside of
|
||||
malloc.
|
||||
---
|
||||
libc/bionic/brk.cpp | 48 ++++++++-------------------------------------
|
||||
1 file changed, 8 insertions(+), 40 deletions(-)
|
||||
|
||||
diff --git a/libc/bionic/brk.cpp b/libc/bionic/brk.cpp
|
||||
index e1a4b05345..ef93055139 100644
|
||||
--- a/libc/bionic/brk.cpp
|
||||
+++ b/libc/bionic/brk.cpp
|
||||
@@ -29,48 +29,16 @@
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
-#if defined(__LP64__)
|
||||
-static void* __bionic_brk;
|
||||
-#else
|
||||
-void* __bionic_brk; // Accidentally exported by the NDK.
|
||||
+#if !defined(__LP64__)
|
||||
+void* __bionic_brk = reinterpret_cast<void*>(-1); // Accidentally exported by the NDK.
|
||||
#endif
|
||||
|
||||
-extern "C" void* __brk(void* __addr);
|
||||
-
|
||||
-int brk(void* end_data) {
|
||||
- __bionic_brk = __brk(end_data);
|
||||
- if (__bionic_brk < end_data) {
|
||||
- errno = ENOMEM;
|
||||
- return -1;
|
||||
- }
|
||||
- return 0;
|
||||
+int brk(void*) {
|
||||
+ errno = ENOMEM;
|
||||
+ return -1;
|
||||
}
|
||||
|
||||
-void* sbrk(ptrdiff_t increment) {
|
||||
- // Initialize __bionic_brk if necessary.
|
||||
- if (__bionic_brk == NULL) {
|
||||
- __bionic_brk = __brk(NULL);
|
||||
- }
|
||||
-
|
||||
- // Don't ask the kernel if we already know the answer.
|
||||
- if (increment == 0) {
|
||||
- return __bionic_brk;
|
||||
- }
|
||||
-
|
||||
- // Avoid overflow.
|
||||
- uintptr_t old_brk = reinterpret_cast<uintptr_t>(__bionic_brk);
|
||||
- if ((increment > 0 && static_cast<uintptr_t>(increment) > (UINTPTR_MAX - old_brk)) ||
|
||||
- (increment < 0 && static_cast<uintptr_t>(-increment) > old_brk)) {
|
||||
- errno = ENOMEM;
|
||||
- return reinterpret_cast<void*>(-1);
|
||||
- }
|
||||
-
|
||||
- void* desired_brk = reinterpret_cast<void*>(old_brk + increment);
|
||||
- __bionic_brk = __brk(desired_brk);
|
||||
- if (__bionic_brk < desired_brk) {
|
||||
- errno = ENOMEM;
|
||||
- return reinterpret_cast<void*>(-1);
|
||||
- }
|
||||
-
|
||||
- return reinterpret_cast<void*>(old_brk);
|
||||
+void* sbrk(ptrdiff_t) {
|
||||
+ errno = ENOMEM;
|
||||
+ return reinterpret_cast<void*>(-1);
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
From 7444dbc3cf11285fb94d5d00913016afd7b0dff2 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Micay <danielmicay@gmail.com>
|
||||
Date: Mon, 4 Mar 2019 04:26:04 -0500
|
||||
Subject: [PATCH] use blocking getrandom and avoid urandom fallback
|
||||
|
||||
---
|
||||
libc/bionic/getentropy.cpp | 30 ++----------------------------
|
||||
1 file changed, 2 insertions(+), 28 deletions(-)
|
||||
|
||||
diff --git a/libc/bionic/getentropy.cpp b/libc/bionic/getentropy.cpp
|
||||
index 2c6e417b87..ad49039af1 100644
|
||||
--- a/libc/bionic/getentropy.cpp
|
||||
+++ b/libc/bionic/getentropy.cpp
|
||||
@@ -31,26 +31,6 @@
|
||||
#include <sys/random.h>
|
||||
#include <unistd.h>
|
||||
|
||||
-static int getentropy_urandom(void* buffer, size_t buffer_size, int saved_errno) {
|
||||
- int fd = TEMP_FAILURE_RETRY(open("/dev/urandom", O_RDONLY | O_NOFOLLOW | O_CLOEXEC, 0));
|
||||
- if (fd == -1) return -1;
|
||||
-
|
||||
- size_t collected = 0;
|
||||
- while (collected < buffer_size) {
|
||||
- ssize_t count = TEMP_FAILURE_RETRY(read(fd, static_cast<char*>(buffer) + collected,
|
||||
- buffer_size - collected));
|
||||
- if (count == -1) {
|
||||
- close(fd);
|
||||
- return -1;
|
||||
- }
|
||||
- collected += count;
|
||||
- }
|
||||
-
|
||||
- close(fd);
|
||||
- errno = saved_errno;
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
int getentropy(void* buffer, size_t buffer_size) {
|
||||
if (buffer_size > 256) {
|
||||
errno = EIO;
|
||||
@@ -62,15 +42,9 @@ int getentropy(void* buffer, size_t buffer_size) {
|
||||
size_t collected = 0;
|
||||
while (collected < buffer_size) {
|
||||
long count = TEMP_FAILURE_RETRY(getrandom(static_cast<char*>(buffer) + collected,
|
||||
- buffer_size - collected, GRND_NONBLOCK));
|
||||
+ buffer_size - collected, 0));
|
||||
if (count == -1) {
|
||||
- // EAGAIN: there isn't enough entropy right now.
|
||||
- // ENOSYS/EINVAL: getrandom(2) or GRND_NONBLOCK isn't supported.
|
||||
- // EFAULT: `buffer` is invalid.
|
||||
- // Try /dev/urandom regardless because it can't hurt,
|
||||
- // and we don't need to optimize the EFAULT case.
|
||||
- // See http://b/33059407 and http://b/67015565.
|
||||
- return getentropy_urandom(buffer, buffer_size, saved_errno);
|
||||
+ return -1;
|
||||
}
|
||||
collected += count;
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
From dcd3b72ac9cac79d4322a17be150c46f65ffb3cd Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Micay <danielmicay@gmail.com>
|
||||
Date: Mon, 19 Sep 2016 07:57:43 -0400
|
||||
Subject: [PATCH] fix undefined out-of-bounds accesses in sched.h
|
||||
|
||||
---
|
||||
libc/include/sched.h | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/libc/include/sched.h b/libc/include/sched.h
|
||||
index de6969f863..fd333a023a 100644
|
||||
--- a/libc/include/sched.h
|
||||
+++ b/libc/include/sched.h
|
||||
@@ -71,7 +71,10 @@ int setns(int __fd, int __ns_type) __INTRODUCED_IN(21);
|
||||
#define __CPU_MASK(x) ((__CPU_BITTYPE)1 << ((x) & (__CPU_BITS - 1)))
|
||||
|
||||
typedef struct {
|
||||
- __CPU_BITTYPE __bits[ CPU_SETSIZE / __CPU_BITS ];
|
||||
+ union {
|
||||
+ __CPU_BITTYPE __bits_minimum[ CPU_SETSIZE / __CPU_BITS ];
|
||||
+ __CPU_BITTYPE __bits[0];
|
||||
+ };
|
||||
} cpu_set_t;
|
||||
|
||||
int sched_setaffinity(pid_t __pid, size_t __set_size, const cpu_set_t* __set) __INTRODUCED_IN(12);
|
@ -0,0 +1,46 @@
|
||||
From 543e1df342cdd8720ce967d990ca28a2b9c26af2 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Micay <danielmicay@gmail.com>
|
||||
Date: Sat, 19 Nov 2016 09:56:14 -0500
|
||||
Subject: [PATCH] stop implicitly marking mappings as mergeable
|
||||
|
||||
---
|
||||
libc/bionic/mmap.cpp | 19 +------------------
|
||||
1 file changed, 1 insertion(+), 18 deletions(-)
|
||||
|
||||
diff --git a/libc/bionic/mmap.cpp b/libc/bionic/mmap.cpp
|
||||
index 35033199ae..c081068928 100644
|
||||
--- a/libc/bionic/mmap.cpp
|
||||
+++ b/libc/bionic/mmap.cpp
|
||||
@@ -39,8 +39,6 @@ extern "C" void* __mmap2(void*, size_t, int, int, int, size_t);
|
||||
|
||||
#define MMAP2_SHIFT 12 // 2**12 == 4096
|
||||
|
||||
-static bool kernel_has_MADV_MERGEABLE = true;
|
||||
-
|
||||
void* mmap64(void* addr, size_t size, int prot, int flags, int fd, off64_t offset) {
|
||||
if (offset < 0 || (offset & ((1UL << MMAP2_SHIFT)-1)) != 0) {
|
||||
errno = EINVAL;
|
||||
@@ -54,22 +52,7 @@ void* mmap64(void* addr, size_t size, int prot, int flags, int fd, off64_t offse
|
||||
return MAP_FAILED;
|
||||
}
|
||||
|
||||
- bool is_private_anonymous =
|
||||
- (flags & (MAP_PRIVATE | MAP_ANONYMOUS)) == (MAP_PRIVATE | MAP_ANONYMOUS);
|
||||
- bool is_stack_or_grows_down = (flags & (MAP_STACK | MAP_GROWSDOWN)) != 0;
|
||||
-
|
||||
- void* result = __mmap2(addr, size, prot, flags, fd, offset >> MMAP2_SHIFT);
|
||||
-
|
||||
- if (result != MAP_FAILED && kernel_has_MADV_MERGEABLE &&
|
||||
- is_private_anonymous && !is_stack_or_grows_down) {
|
||||
- ErrnoRestorer errno_restorer;
|
||||
- int rc = madvise(result, size, MADV_MERGEABLE);
|
||||
- if (rc == -1 && errno == EINVAL) {
|
||||
- kernel_has_MADV_MERGEABLE = false;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- return result;
|
||||
+ return __mmap2(addr, size, prot, flags, fd, offset >> MMAP2_SHIFT);
|
||||
}
|
||||
|
||||
void* mmap(void* addr, size_t size, int prot, int flags, int fd, off_t offset) {
|
@ -0,0 +1,39 @@
|
||||
From 611e5691f7e48aba8529e49b22885021f322b31e Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Micay <danielmicay@gmail.com>
|
||||
Date: Sat, 16 Jul 2016 23:55:16 -0400
|
||||
Subject: [PATCH] replace VLA formatting buffer with dprintf
|
||||
|
||||
---
|
||||
libc/bionic/bionic_systrace.cpp | 10 +---------
|
||||
1 file changed, 1 insertion(+), 9 deletions(-)
|
||||
|
||||
diff --git a/libc/bionic/bionic_systrace.cpp b/libc/bionic/bionic_systrace.cpp
|
||||
index bac3d88021..076e10dbfb 100644
|
||||
--- a/libc/bionic/bionic_systrace.cpp
|
||||
+++ b/libc/bionic/bionic_systrace.cpp
|
||||
@@ -26,8 +26,6 @@
|
||||
|
||||
#include <cutils/trace.h> // For ATRACE_TAG_BIONIC.
|
||||
|
||||
-#define WRITE_OFFSET 32
|
||||
-
|
||||
static Lock g_lock;
|
||||
static CachedProperty g_debug_atrace_tags_enableflags("debug.atrace.tags.enableflags");
|
||||
static uint64_t g_tags;
|
||||
@@ -61,15 +59,9 @@ void bionic_trace_begin(const char* message) {
|
||||
return;
|
||||
}
|
||||
|
||||
- // If bionic tracing has been enabled, then write the message to the
|
||||
- // kernel trace_marker.
|
||||
- int length = strlen(message);
|
||||
- char buf[length + WRITE_OFFSET];
|
||||
- size_t len = snprintf(buf, length + WRITE_OFFSET, "B|%d|%s", getpid(), message);
|
||||
-
|
||||
// Tracing may stop just after checking property and before writing the message.
|
||||
// So the write is acceptable to fail. See b/20666100.
|
||||
- TEMP_FAILURE_RETRY(write(trace_marker_fd, buf, len));
|
||||
+ dprintf(trace_marker_fd, "B|%d|%s", getpid(), message);
|
||||
}
|
||||
|
||||
void bionic_trace_end() {
|
@ -0,0 +1,25 @@
|
||||
From 8de97ce864cc781d077160a8efd4902d4338078c Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Micay <danielmicay@gmail.com>
|
||||
Date: Fri, 17 Jul 2015 21:32:05 -0400
|
||||
Subject: [PATCH] increase default pthread stack to 8MiB on 64-bit
|
||||
|
||||
---
|
||||
libc/bionic/pthread_internal.h | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/libc/bionic/pthread_internal.h b/libc/bionic/pthread_internal.h
|
||||
index 9bdf9cdf0c..d59a545459 100644
|
||||
--- a/libc/bionic/pthread_internal.h
|
||||
+++ b/libc/bionic/pthread_internal.h
|
||||
@@ -164,7 +164,11 @@ __LIBC_HIDDEN__ void pthread_key_clean_all(void);
|
||||
// stack overflows, we subtracted the same amount we were using there
|
||||
// from the default thread stack size. This should keep memory usage
|
||||
// roughly constant.
|
||||
+#ifdef __LP64__
|
||||
+#define PTHREAD_STACK_SIZE_DEFAULT ((8 * 1024 * 1024) - SIGNAL_STACK_SIZE_WITHOUT_GUARD)
|
||||
+#else
|
||||
#define PTHREAD_STACK_SIZE_DEFAULT ((1 * 1024 * 1024) - SIGNAL_STACK_SIZE_WITHOUT_GUARD)
|
||||
+#endif
|
||||
|
||||
// Leave room for a guard page in the internally created signal stacks.
|
||||
#define SIGNAL_STACK_SIZE (SIGNAL_STACK_SIZE_WITHOUT_GUARD + PTHREAD_GUARD_SIZE)
|
@ -0,0 +1,47 @@
|
||||
From a47571704245e5514795f35bbcffdb8a533e738a Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Micay <danielmicay@gmail.com>
|
||||
Date: Sat, 1 Oct 2016 05:11:44 -0400
|
||||
Subject: [PATCH] make __stack_chk_guard read-only at runtime
|
||||
|
||||
---
|
||||
libc/bionic/__libc_init_main_thread.cpp | 14 +++++++++++---
|
||||
1 file changed, 11 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/libc/bionic/__libc_init_main_thread.cpp b/libc/bionic/__libc_init_main_thread.cpp
|
||||
index efa7dee57b..78d25fd977 100644
|
||||
--- a/libc/bionic/__libc_init_main_thread.cpp
|
||||
+++ b/libc/bionic/__libc_init_main_thread.cpp
|
||||
@@ -28,22 +28,30 @@
|
||||
|
||||
#include "libc_init_common.h"
|
||||
|
||||
+#include <limits.h>
|
||||
+#include <sys/mman.h>
|
||||
+
|
||||
+#include <async_safe/log.h>
|
||||
+
|
||||
#include "private/KernelArgumentBlock.h"
|
||||
#include "private/bionic_arc4random.h"
|
||||
#include "private/bionic_auxv.h"
|
||||
#include "private/bionic_defs.h"
|
||||
#include "private/bionic_globals.h"
|
||||
-#include "private/bionic_ssp.h"
|
||||
#include "pthread_internal.h"
|
||||
|
||||
extern "C" int __set_tls(void* ptr);
|
||||
extern "C" int __set_tid_address(int* tid_address);
|
||||
|
||||
// Declared in "private/bionic_ssp.h".
|
||||
-uintptr_t __stack_chk_guard = 0;
|
||||
+__attribute__((aligned(PAGE_SIZE)))
|
||||
+uintptr_t __stack_chk_guard[PAGE_SIZE / sizeof(uintptr_t)] = {0};
|
||||
|
||||
void __libc_init_global_stack_chk_guard(KernelArgumentBlock& args) {
|
||||
- __libc_safe_arc4random_buf(&__stack_chk_guard, sizeof(__stack_chk_guard), args);
|
||||
+ __libc_safe_arc4random_buf(&__stack_chk_guard[0], sizeof(__stack_chk_guard[0]), args);
|
||||
+ if (mprotect(__stack_chk_guard, sizeof(__stack_chk_guard), PROT_READ) == -1) {
|
||||
+ async_safe_fatal("mprotect __stack_chk_guard: %s", strerror(errno));
|
||||
+ }
|
||||
}
|
||||
|
||||
// Setup for the main thread. For dynamic executables, this is called by the
|
@ -0,0 +1,34 @@
|
||||
From 7f0947cc0e4fc52a41ef8ecfba892f5534e1fee5 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Micay <danielmicay@gmail.com>
|
||||
Date: Sun, 12 Mar 2017 17:49:13 -0400
|
||||
Subject: [PATCH] on 64-bit, zero the leading stack canary byte
|
||||
|
||||
This reduces entropy of the canary from 64-bit to 56-bit in exchange for
|
||||
mitigating non-terminated C string overflows.
|
||||
---
|
||||
libc/bionic/__libc_init_main_thread.cpp | 10 ++++++++++
|
||||
1 file changed, 10 insertions(+)
|
||||
|
||||
diff --git a/libc/bionic/__libc_init_main_thread.cpp b/libc/bionic/__libc_init_main_thread.cpp
|
||||
index 78d25fd977..ae2245829d 100644
|
||||
--- a/libc/bionic/__libc_init_main_thread.cpp
|
||||
+++ b/libc/bionic/__libc_init_main_thread.cpp
|
||||
@@ -47,8 +47,18 @@ extern "C" int __set_tid_address(int* tid_address);
|
||||
__attribute__((aligned(PAGE_SIZE)))
|
||||
uintptr_t __stack_chk_guard[PAGE_SIZE / sizeof(uintptr_t)] = {0};
|
||||
|
||||
+#if __LP64__
|
||||
+static const uintptr_t canary_mask = __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ ?
|
||||
+ 0xffffffffffffff00UL :
|
||||
+ 0x00ffffffffffffffUL;
|
||||
+#endif
|
||||
+
|
||||
void __libc_init_global_stack_chk_guard(KernelArgumentBlock& args) {
|
||||
__libc_safe_arc4random_buf(&__stack_chk_guard[0], sizeof(__stack_chk_guard[0]), args);
|
||||
+#if __LP64__
|
||||
+ // Sacrifice 8 bits of entropy on 64-bit to mitigate non-terminated C string overflows
|
||||
+ __stack_chk_guard[0] &= canary_mask;
|
||||
+#endif
|
||||
if (mprotect(__stack_chk_guard, sizeof(__stack_chk_guard), PROT_READ) == -1) {
|
||||
async_safe_fatal("mprotect __stack_chk_guard: %s", strerror(errno));
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
From abdf523d26450814fc3f5c211f3baa643c48bae3 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Micay <danielmicay@gmail.com>
|
||||
Date: Fri, 6 Feb 2015 11:41:57 -0500
|
||||
Subject: [PATCH] zero sensitive information with explicit_bzero
|
||||
|
||||
---
|
||||
init/security.cpp | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/init/security.cpp b/init/security.cpp
|
||||
index a3494a280bd..4b6c918ab30 100644
|
||||
--- a/init/security.cpp
|
||||
+++ b/init/security.cpp
|
||||
@@ -73,6 +73,7 @@ Result<Success> MixHwrngIntoLinuxRngAction(const BuiltinArguments&) {
|
||||
}
|
||||
|
||||
chunk_size = TEMP_FAILURE_RETRY(write(urandom_fd, buf, chunk_size));
|
||||
+ explicit_bzero(buf, chunk_size);
|
||||
if (chunk_size == -1) {
|
||||
return ErrnoError() << "Failed to write to /dev/urandom";
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
From a8cdbb6352e4ff708b791c7f3a976de8a6383105 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Micay <danielmicay@gmail.com>
|
||||
Date: Thu, 5 Feb 2015 21:53:16 -0500
|
||||
Subject: [PATCH] add a real explicit_bzero implementation
|
||||
|
||||
Clang, GCC and other compilers special-case standard C functions like
|
||||
memset. Calls to memset will be optimized out.
|
||||
|
||||
OpenBSD provides explicit_bzero to work around this but Android simply
|
||||
defines it as memset so nothing prevents it from being optimized away.
|
||||
|
||||
This implementation uses a memory read constraint via empty inline
|
||||
assembly rather than something that may be broken via link-time
|
||||
optimization in the future.
|
||||
---
|
||||
libc/Android.bp | 1 +
|
||||
libc/bionic/explicit_bzero.cpp | 7 +++++++
|
||||
libc/include/string.h | 1 +
|
||||
libc/libc.map.txt | 1 +
|
||||
libc/upstream-openbsd/android/include/openbsd-compat.h | 2 --
|
||||
5 files changed, 10 insertions(+), 2 deletions(-)
|
||||
create mode 100644 libc/bionic/explicit_bzero.cpp
|
||||
|
||||
diff --git a/libc/Android.bp b/libc/Android.bp
|
||||
index a5990288d2..47fccde7e7 100644
|
||||
--- a/libc/Android.bp
|
||||
+++ b/libc/Android.bp
|
||||
@@ -1041,6 +1041,7 @@ cc_library_static {
|
||||
"bionic/eventfd_read.cpp",
|
||||
"bionic/eventfd_write.cpp",
|
||||
"bionic/exec.cpp",
|
||||
+ "bionic/explicit_bzero.cpp",
|
||||
"bionic/faccessat.cpp",
|
||||
"bionic/fchmod.cpp",
|
||||
"bionic/fchmodat.cpp",
|
||||
diff --git a/libc/bionic/explicit_bzero.cpp b/libc/bionic/explicit_bzero.cpp
|
||||
new file mode 100644
|
||||
index 0000000000..b06daa1386
|
||||
--- /dev/null
|
||||
+++ b/libc/bionic/explicit_bzero.cpp
|
||||
@@ -0,0 +1,7 @@
|
||||
+#include <string.h>
|
||||
+
|
||||
+void* explicit_bzero(void* s, size_t n) {
|
||||
+ void *ptr = memset(s, 0, n);
|
||||
+ __asm__ __volatile__("" : : "r"(ptr) : "memory");
|
||||
+ return ptr;
|
||||
+}
|
||||
diff --git a/libc/include/string.h b/libc/include/string.h
|
||||
index 25f6673a99..6c7b4eba0f 100644
|
||||
--- a/libc/include/string.h
|
||||
+++ b/libc/include/string.h
|
||||
@@ -56,6 +56,7 @@ void* mempcpy(void* __dst, const void* __src, size_t __n) __INTRODUCED_IN(23);
|
||||
#endif
|
||||
void* memmove(void* __dst, const void* __src, size_t __n);
|
||||
void* memset(void* __dst, int __ch, size_t __n);
|
||||
+void* explicit_bzero(void *s, size_t n);
|
||||
void* memmem(const void* __haystack, size_t __haystack_size, const void* __needle, size_t __needle_size) __attribute_pure__;
|
||||
|
||||
char* strchr(const char* __s, int __ch) __attribute_pure__;
|
||||
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
|
||||
index 88192239a1..0ec519b9c8 100644
|
||||
--- a/libc/libc.map.txt
|
||||
+++ b/libc/libc.map.txt
|
||||
@@ -332,6 +332,7 @@ LIBC {
|
||||
execvp;
|
||||
execvpe; # introduced=21
|
||||
exit;
|
||||
+ explicit_bzero;
|
||||
faccessat; # introduced-arm=16 introduced-arm64=21 introduced-mips=16 introduced-mips64=21 introduced-x86=16 introduced-x86_64=21
|
||||
fallocate; # introduced=21
|
||||
fallocate64; # introduced=21
|
||||
diff --git a/libc/upstream-openbsd/android/include/openbsd-compat.h b/libc/upstream-openbsd/android/include/openbsd-compat.h
|
||||
index c99e2ce9df..62cb51e9fc 100644
|
||||
--- a/libc/upstream-openbsd/android/include/openbsd-compat.h
|
||||
+++ b/libc/upstream-openbsd/android/include/openbsd-compat.h
|
||||
@@ -65,8 +65,6 @@ extern const char* __progname;
|
||||
/* OpenBSD has this, but we can't really implement it correctly on Linux. */
|
||||
#define issetugid() 0
|
||||
|
||||
-#define explicit_bzero(p, s) memset(p, 0, s)
|
||||
-
|
||||
/* OpenBSD has these in <sys/param.h>, but "ALIGN" isn't something we want to reserve. */
|
||||
#define ALIGNBYTES (sizeof(uintptr_t) - 1)
|
||||
#define ALIGN(p) (((uintptr_t)(p) + ALIGNBYTES) &~ ALIGNBYTES)
|
@ -0,0 +1,83 @@
|
||||
From 4cd257135f72ceb7ddd32538d2ba579736bf7a12 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Micay <danielmicay@gmail.com>
|
||||
Date: Wed, 2 Dec 2015 23:37:28 -0500
|
||||
Subject: [PATCH] switch pthread_atfork handler allocation to mmap
|
||||
|
||||
---
|
||||
libc/bionic/pthread_atfork.cpp | 35 ++++++++++++++++++++++++++++------
|
||||
1 file changed, 29 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/libc/bionic/pthread_atfork.cpp b/libc/bionic/pthread_atfork.cpp
|
||||
index fb12a3ba74..cc3657f126 100644
|
||||
--- a/libc/bionic/pthread_atfork.cpp
|
||||
+++ b/libc/bionic/pthread_atfork.cpp
|
||||
@@ -29,6 +29,9 @@
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
+#include <sys/mman.h>
|
||||
+#include <sys/prctl.h>
|
||||
+#include <unistd.h>
|
||||
|
||||
#include "private/bionic_macros.h"
|
||||
|
||||
@@ -43,6 +46,8 @@ struct atfork_t {
|
||||
void* dso_handle;
|
||||
};
|
||||
|
||||
+static atfork_t* pool;
|
||||
+
|
||||
class atfork_list_t {
|
||||
public:
|
||||
constexpr atfork_list_t() : first_(nullptr), last_(nullptr) {}
|
||||
@@ -101,7 +106,8 @@ class atfork_list_t {
|
||||
last_ = entry->prev;
|
||||
}
|
||||
|
||||
- free(entry);
|
||||
+ entry->next = pool;
|
||||
+ pool = entry;
|
||||
}
|
||||
|
||||
atfork_t* first_;
|
||||
@@ -154,18 +160,35 @@ void __bionic_atfork_run_parent() {
|
||||
// __register_atfork is the name used by glibc
|
||||
extern "C" int __register_atfork(void (*prepare)(void), void (*parent)(void),
|
||||
void(*child)(void), void* dso) {
|
||||
- atfork_t* entry = reinterpret_cast<atfork_t*>(malloc(sizeof(atfork_t)));
|
||||
- if (entry == nullptr) {
|
||||
- return ENOMEM;
|
||||
+ pthread_mutex_lock(&g_atfork_list_mutex);
|
||||
+
|
||||
+ if (!pool) {
|
||||
+ size_t page_size = getpagesize();
|
||||
+ char* page = static_cast<char*>(mmap(NULL, page_size, PROT_READ|PROT_WRITE,
|
||||
+ MAP_ANONYMOUS|MAP_PRIVATE, -1, 0));
|
||||
+ if (page == MAP_FAILED) {
|
||||
+ pthread_mutex_unlock(&g_atfork_list_mutex);
|
||||
+ return ENOMEM;
|
||||
+ }
|
||||
+
|
||||
+ prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, page, page_size,
|
||||
+ "atfork handlers");
|
||||
+
|
||||
+ for (char* it = page; it < page + page_size - sizeof(atfork_t); it += sizeof(atfork_t)) {
|
||||
+ atfork_t* node = reinterpret_cast<atfork_t*>(it);
|
||||
+ node->next = pool;
|
||||
+ pool = node;
|
||||
+ }
|
||||
}
|
||||
|
||||
+ atfork_t* entry = pool;
|
||||
+ pool = entry->next;
|
||||
+
|
||||
entry->prepare = prepare;
|
||||
entry->parent = parent;
|
||||
entry->child = child;
|
||||
entry->dso_handle = dso;
|
||||
|
||||
- pthread_mutex_lock(&g_atfork_list_mutex);
|
||||
-
|
||||
g_atfork_list.push_back(entry);
|
||||
|
||||
pthread_mutex_unlock(&g_atfork_list_mutex);
|
@ -0,0 +1,94 @@
|
||||
From 9220cf622bab1099cbff937d88aa7ce2809bb9d4 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Micay <danielmicay@gmail.com>
|
||||
Date: Thu, 3 Dec 2015 12:58:31 -0500
|
||||
Subject: [PATCH] add memory protection for pthread_atfork handlers
|
||||
|
||||
---
|
||||
libc/bionic/pthread_atfork.cpp | 34 ++++++++++++++++++++++++++++++++--
|
||||
1 file changed, 32 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/libc/bionic/pthread_atfork.cpp b/libc/bionic/pthread_atfork.cpp
|
||||
index cc3657f126..d11dab84a7 100644
|
||||
--- a/libc/bionic/pthread_atfork.cpp
|
||||
+++ b/libc/bionic/pthread_atfork.cpp
|
||||
@@ -47,6 +47,7 @@ struct atfork_t {
|
||||
};
|
||||
|
||||
static atfork_t* pool;
|
||||
+static atfork_t* page_list;
|
||||
|
||||
class atfork_list_t {
|
||||
public:
|
||||
@@ -160,13 +161,22 @@ void __bionic_atfork_run_parent() {
|
||||
// __register_atfork is the name used by glibc
|
||||
extern "C" int __register_atfork(void (*prepare)(void), void (*parent)(void),
|
||||
void(*child)(void), void* dso) {
|
||||
+ size_t page_size = getpagesize();
|
||||
+
|
||||
pthread_mutex_lock(&g_atfork_list_mutex);
|
||||
|
||||
+ for (atfork_t* page_it = page_list; page_it; page_it = page_it->next) {
|
||||
+ mprotect(page_it, page_size, PROT_READ|PROT_WRITE);
|
||||
+ }
|
||||
+
|
||||
if (!pool) {
|
||||
- size_t page_size = getpagesize();
|
||||
char* page = static_cast<char*>(mmap(NULL, page_size, PROT_READ|PROT_WRITE,
|
||||
MAP_ANONYMOUS|MAP_PRIVATE, -1, 0));
|
||||
if (page == MAP_FAILED) {
|
||||
+ for (atfork_t* page_it = page_list; page_it; page_it = page_it->next) {
|
||||
+ mprotect(page_it, page_size, PROT_READ);
|
||||
+ }
|
||||
+
|
||||
pthread_mutex_unlock(&g_atfork_list_mutex);
|
||||
return ENOMEM;
|
||||
}
|
||||
@@ -174,11 +184,15 @@ extern "C" int __register_atfork(void (*prepare)(void), void (*parent)(void),
|
||||
prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, page, page_size,
|
||||
"atfork handlers");
|
||||
|
||||
- for (char* it = page; it < page + page_size - sizeof(atfork_t); it += sizeof(atfork_t)) {
|
||||
+ for (char* it = page + sizeof(atfork_t); it < page + page_size - sizeof(atfork_t); it += sizeof(atfork_t)) {
|
||||
atfork_t* node = reinterpret_cast<atfork_t*>(it);
|
||||
node->next = pool;
|
||||
pool = node;
|
||||
}
|
||||
+
|
||||
+ atfork_t* page_node = reinterpret_cast<atfork_t*>(page);
|
||||
+ page_node->next = page_list;
|
||||
+ page_list = page_node;
|
||||
}
|
||||
|
||||
atfork_t* entry = pool;
|
||||
@@ -191,6 +205,10 @@ extern "C" int __register_atfork(void (*prepare)(void), void (*parent)(void),
|
||||
|
||||
g_atfork_list.push_back(entry);
|
||||
|
||||
+ for (atfork_t* page_it = page_list; page_it; page_it = page_it->next) {
|
||||
+ mprotect(page_it, page_size, PROT_READ);
|
||||
+ }
|
||||
+
|
||||
pthread_mutex_unlock(&g_atfork_list_mutex);
|
||||
|
||||
return 0;
|
||||
@@ -198,8 +216,20 @@ extern "C" int __register_atfork(void (*prepare)(void), void (*parent)(void),
|
||||
|
||||
extern "C" __LIBC_HIDDEN__ void __unregister_atfork(void* dso) {
|
||||
pthread_mutex_lock(&g_atfork_list_mutex);
|
||||
+
|
||||
+ size_t page_size = getpagesize();
|
||||
+
|
||||
+ for (atfork_t* page_it = page_list; page_it; page_it = page_it->next) {
|
||||
+ mprotect(page_it, page_size, PROT_READ|PROT_WRITE);
|
||||
+ }
|
||||
+
|
||||
g_atfork_list.remove_if([&](const atfork_t* entry) {
|
||||
return entry->dso_handle == dso;
|
||||
});
|
||||
+
|
||||
+ for (atfork_t* page_it = page_list; page_it; page_it = page_it->next) {
|
||||
+ mprotect(page_it, page_size, PROT_READ);
|
||||
+ }
|
||||
+
|
||||
pthread_mutex_unlock(&g_atfork_list_mutex);
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
From 8ef71d1ffd51664bc8d61fd029efa899a87ddc30 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Micay <danielmicay@gmail.com>
|
||||
Date: Sat, 7 Feb 2015 20:14:24 -0500
|
||||
Subject: [PATCH] add memory protection for at_quick_exit
|
||||
|
||||
---
|
||||
.../lib/libc/stdlib/quick_exit.c | 40 ++++++++++++++++---
|
||||
1 file changed, 35 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/libc/upstream-freebsd/lib/libc/stdlib/quick_exit.c b/libc/upstream-freebsd/lib/libc/stdlib/quick_exit.c
|
||||
index ef8cdb1b40..63b54e3fb8 100644
|
||||
--- a/libc/upstream-freebsd/lib/libc/stdlib/quick_exit.c
|
||||
+++ b/libc/upstream-freebsd/lib/libc/stdlib/quick_exit.c
|
||||
@@ -28,6 +28,9 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
+#include <sys/mman.h>
|
||||
+#include <sys/prctl.h>
|
||||
+#include <unistd.h>
|
||||
|
||||
/**
|
||||
* Linked list of quick exit handlers. This is simpler than the atexit()
|
||||
@@ -39,6 +42,10 @@ struct quick_exit_handler {
|
||||
void (*cleanup)(void);
|
||||
};
|
||||
|
||||
+static struct quick_exit_handler *pool_page;
|
||||
+static struct quick_exit_handler *pool;
|
||||
+static size_t pool_size;
|
||||
+
|
||||
/**
|
||||
* Lock protecting the handlers list.
|
||||
*/
|
||||
@@ -51,16 +58,39 @@ static struct quick_exit_handler *handlers;
|
||||
int
|
||||
at_quick_exit(void (*func)(void))
|
||||
{
|
||||
+ size_t page_size = getpagesize();
|
||||
struct quick_exit_handler *h;
|
||||
-
|
||||
- h = malloc(sizeof(*h));
|
||||
|
||||
- if (NULL == h)
|
||||
- return (1);
|
||||
- h->cleanup = func;
|
||||
pthread_mutex_lock(&atexit_mutex);
|
||||
+
|
||||
+ if (pool_size < sizeof(*h)) {
|
||||
+ void *ptr = mmap(NULL, page_size, PROT_READ|PROT_WRITE,
|
||||
+ MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
|
||||
+ if (ptr == MAP_FAILED) {
|
||||
+ pthread_mutex_unlock(&atexit_mutex);
|
||||
+ return (1);
|
||||
+ }
|
||||
+ prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, ptr, page_size,
|
||||
+ "at_quick_exit handlers");
|
||||
+ pool_page = pool = ptr;
|
||||
+ pool_size = page_size;
|
||||
+ } else {
|
||||
+ if (mprotect(pool_page, page_size, PROT_READ|PROT_WRITE)) {
|
||||
+ pthread_mutex_unlock(&atexit_mutex);
|
||||
+ return (1);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ h = pool++;
|
||||
+ pool_size -= sizeof(*h);
|
||||
+
|
||||
+ h->cleanup = func;
|
||||
+
|
||||
h->next = handlers;
|
||||
handlers = h;
|
||||
+
|
||||
+ mprotect(pool_page, page_size, PROT_READ);
|
||||
+
|
||||
pthread_mutex_unlock(&atexit_mutex);
|
||||
return (0);
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
From 0eaef1abbdcbf40c990fcba1bd91401bdd38a9c5 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Micay <danielmicay@gmail.com>
|
||||
Date: Wed, 27 Jan 2016 18:02:15 -0500
|
||||
Subject: [PATCH] add XOR mangling mitigation for thread-local dtors
|
||||
|
||||
---
|
||||
libc/bionic/__cxa_thread_atexit_impl.cpp | 8 +++++---
|
||||
libc/bionic/libc_init_common.cpp | 2 ++
|
||||
libc/private/bionic_globals.h | 1 +
|
||||
3 files changed, 8 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/libc/bionic/__cxa_thread_atexit_impl.cpp b/libc/bionic/__cxa_thread_atexit_impl.cpp
|
||||
index 99077c101d..74608513ef 100644
|
||||
--- a/libc/bionic/__cxa_thread_atexit_impl.cpp
|
||||
+++ b/libc/bionic/__cxa_thread_atexit_impl.cpp
|
||||
@@ -13,15 +13,17 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
+#include <stdint.h>
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
#include <private/bionic_defs.h>
|
||||
+#include <private/bionic_globals.h>
|
||||
|
||||
#include "pthread_internal.h"
|
||||
|
||||
class thread_local_dtor {
|
||||
public:
|
||||
- void (*func) (void *);
|
||||
+ uintptr_t func;
|
||||
void *arg;
|
||||
void *dso_handle; // unused...
|
||||
thread_local_dtor* next;
|
||||
@@ -35,7 +37,7 @@ __BIONIC_WEAK_FOR_NATIVE_BRIDGE
|
||||
int __cxa_thread_atexit_impl(void (*func) (void *), void *arg, void *dso_handle) {
|
||||
thread_local_dtor* dtor = new thread_local_dtor();
|
||||
|
||||
- dtor->func = func;
|
||||
+ dtor->func = __libc_globals->dtor_cookie ^ reinterpret_cast<uintptr_t>(func);
|
||||
dtor->arg = arg;
|
||||
dtor->dso_handle = dso_handle;
|
||||
|
||||
@@ -54,7 +56,7 @@ extern "C" __LIBC_HIDDEN__ void __cxa_thread_finalize() {
|
||||
thread_local_dtor* current = thread->thread_local_dtors;
|
||||
thread->thread_local_dtors = current->next;
|
||||
|
||||
- current->func(current->arg);
|
||||
+ (reinterpret_cast<void (*)(void*)>(__libc_globals->dtor_cookie ^ current->func))(current->arg);
|
||||
if (__loader_remove_thread_local_dtor != nullptr) {
|
||||
__loader_remove_thread_local_dtor(current->dso_handle);
|
||||
}
|
||||
diff --git a/libc/bionic/libc_init_common.cpp b/libc/bionic/libc_init_common.cpp
|
||||
index b229cda2fd..e928c02f1b 100644
|
||||
--- a/libc/bionic/libc_init_common.cpp
|
||||
+++ b/libc/bionic/libc_init_common.cpp
|
||||
@@ -44,6 +44,7 @@
|
||||
#include <async_safe/log.h>
|
||||
|
||||
#include "private/WriteProtected.h"
|
||||
+#include "private/bionic_arc4random.h"
|
||||
#include "private/bionic_defs.h"
|
||||
#include "private/bionic_globals.h"
|
||||
#include "private/bionic_tls.h"
|
||||
@@ -65,6 +66,7 @@ void __libc_init_globals() {
|
||||
__libc_globals.mutate([](libc_globals* globals) {
|
||||
__libc_init_vdso(globals);
|
||||
__libc_init_setjmp_cookie(globals);
|
||||
+ arc4random_buf(&globals->dtor_cookie, sizeof(globals->dtor_cookie));
|
||||
});
|
||||
}
|
||||
|
||||
diff --git a/libc/private/bionic_globals.h b/libc/private/bionic_globals.h
|
||||
index d73079e33d..4c296037b1 100644
|
||||
--- a/libc/private/bionic_globals.h
|
||||
+++ b/libc/private/bionic_globals.h
|
||||
@@ -43,6 +43,7 @@
|
||||
|
||||
struct libc_globals {
|
||||
vdso_entry vdso[VDSO_END];
|
||||
+ long dtor_cookie;
|
||||
long setjmp_cookie;
|
||||
|
||||
// In order to allow a complete switch between dispatch tables without
|
@ -0,0 +1,23 @@
|
||||
From 64f1cc2148c1834212f6704ba08b626696501271 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Micay <danielmicay@gmail.com>
|
||||
Date: Fri, 29 Jan 2016 20:20:09 -0500
|
||||
Subject: [PATCH] use a better pthread_attr junk filling pattern
|
||||
|
||||
Guarantee that junk filled pointers will fault, at least on pure 64-bit.
|
||||
---
|
||||
libc/bionic/pthread_attr.cpp | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/libc/bionic/pthread_attr.cpp b/libc/bionic/pthread_attr.cpp
|
||||
index 3c4b169eed..a27201706e 100644
|
||||
--- a/libc/bionic/pthread_attr.cpp
|
||||
+++ b/libc/bionic/pthread_attr.cpp
|
||||
@@ -53,7 +53,7 @@ int pthread_attr_init(pthread_attr_t* attr) {
|
||||
|
||||
__BIONIC_WEAK_FOR_NATIVE_BRIDGE
|
||||
int pthread_attr_destroy(pthread_attr_t* attr) {
|
||||
- memset(attr, 0x42, sizeof(pthread_attr_t));
|
||||
+ memset(attr, 0xdf, sizeof(pthread_attr_t));
|
||||
return 0;
|
||||
}
|
||||
|
@ -0,0 +1,75 @@
|
||||
From 5c42a527cf958ca3c81613178618d452e806994f Mon Sep 17 00:00:00 2001
|
||||
From: Renlord <me@renlord.com>
|
||||
Date: Thu, 12 Sep 2019 14:51:51 +1000
|
||||
Subject: [PATCH] add guard page(s) between static_tls and stack
|
||||
|
||||
---
|
||||
libc/bionic/pthread_create.cpp | 29 +++++++++++++++++++----------
|
||||
1 file changed, 19 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
|
||||
index 4cf14ad72b..6bbf970a0b 100644
|
||||
--- a/libc/bionic/pthread_create.cpp
|
||||
+++ b/libc/bionic/pthread_create.cpp
|
||||
@@ -218,9 +218,10 @@ int __init_thread(pthread_internal_t* thread) {
|
||||
ThreadMapping __allocate_thread_mapping(size_t stack_size, size_t stack_guard_size) {
|
||||
const StaticTlsLayout& layout = __libc_shared_globals()->static_tls_layout;
|
||||
|
||||
- // Allocate in order: stack guard, stack, static TLS, guard page.
|
||||
+ // Allocate in order: stack guard, stack, guard page, static TLS, guard page.
|
||||
size_t mmap_size;
|
||||
if (__builtin_add_overflow(stack_size, stack_guard_size, &mmap_size)) return {};
|
||||
+ if (__builtin_add_overflow(mmap_size, PTHREAD_GUARD_SIZE, &mmap_size)) return {};
|
||||
if (__builtin_add_overflow(mmap_size, layout.size(), &mmap_size)) return {};
|
||||
if (__builtin_add_overflow(mmap_size, PTHREAD_GUARD_SIZE, &mmap_size)) return {};
|
||||
|
||||
@@ -229,8 +230,8 @@ ThreadMapping __allocate_thread_mapping(size_t stack_size, size_t stack_guard_si
|
||||
mmap_size = __BIONIC_ALIGN(mmap_size, PAGE_SIZE);
|
||||
if (mmap_size < unaligned_size) return {};
|
||||
|
||||
- // Create a new private anonymous map. Make the entire mapping PROT_NONE, then carve out a
|
||||
- // read+write area in the middle.
|
||||
+ // Create a new private anonymous map. Make the entire mapping PROT_NONE, then carve out
|
||||
+ // read+write areas for the stack and static TLS
|
||||
const int flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE;
|
||||
char* const space = static_cast<char*>(mmap(nullptr, mmap_size, PROT_NONE, flags, -1, 0));
|
||||
if (space == MAP_FAILED) {
|
||||
@@ -240,13 +241,21 @@ ThreadMapping __allocate_thread_mapping(size_t stack_size, size_t stack_guard_si
|
||||
mmap_size, strerror(errno));
|
||||
return {};
|
||||
}
|
||||
- const size_t writable_size = mmap_size - stack_guard_size - PTHREAD_GUARD_SIZE;
|
||||
- if (mprotect(space + stack_guard_size,
|
||||
- writable_size,
|
||||
- PROT_READ | PROT_WRITE) != 0) {
|
||||
+
|
||||
+ if (mprotect(space + stack_guard_size, stack_size, PROT_READ | PROT_WRITE) != 0) {
|
||||
async_safe_format_log(ANDROID_LOG_WARN, "libc",
|
||||
"pthread_create failed: couldn't mprotect R+W %zu-byte thread mapping region: %s",
|
||||
- writable_size, strerror(errno));
|
||||
+ stack_size, strerror(errno));
|
||||
+ munmap(space, mmap_size);
|
||||
+ return {};
|
||||
+ }
|
||||
+
|
||||
+ char* const static_tls_space = space + stack_guard_size + stack_size + PTHREAD_GUARD_SIZE;
|
||||
+
|
||||
+ if (mprotect(static_tls_space, layout.size(), PROT_READ | PROT_WRITE) != 0) {
|
||||
+ async_safe_format_log(ANDROID_LOG_WARN, "libc",
|
||||
+ "pthread_create failed: couldn't mprotect R+W %zu-byte static TLS mapping region: %s",
|
||||
+ layout.size(), strerror(errno));
|
||||
munmap(space, mmap_size);
|
||||
return {};
|
||||
}
|
||||
@@ -254,9 +263,9 @@ ThreadMapping __allocate_thread_mapping(size_t stack_size, size_t stack_guard_si
|
||||
ThreadMapping result = {};
|
||||
result.mmap_base = space;
|
||||
result.mmap_size = mmap_size;
|
||||
- result.static_tls = space + mmap_size - PTHREAD_GUARD_SIZE - layout.size();
|
||||
+ result.static_tls = static_tls_space;
|
||||
result.stack_base = space;
|
||||
- result.stack_top = result.static_tls;
|
||||
+ result.stack_top = space + stack_guard_size + stack_size;
|
||||
return result;
|
||||
}
|
||||
|
@ -0,0 +1,57 @@
|
||||
From 5cc8c34e60dbfeb1fd996bf83bb01a0443d93a8a Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Micay <danielmicay@gmail.com>
|
||||
Date: Thu, 10 Oct 2019 22:52:49 -0400
|
||||
Subject: [PATCH] move pthread_internal_t behind guard page
|
||||
|
||||
---
|
||||
libc/bionic/pthread_create.cpp | 19 +++++++++----------
|
||||
1 file changed, 9 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
|
||||
index 6bbf970a0b..b4a044db18 100644
|
||||
--- a/libc/bionic/pthread_create.cpp
|
||||
+++ b/libc/bionic/pthread_create.cpp
|
||||
@@ -218,10 +218,13 @@ int __init_thread(pthread_internal_t* thread) {
|
||||
ThreadMapping __allocate_thread_mapping(size_t stack_size, size_t stack_guard_size) {
|
||||
const StaticTlsLayout& layout = __libc_shared_globals()->static_tls_layout;
|
||||
|
||||
- // Allocate in order: stack guard, stack, guard page, static TLS, guard page.
|
||||
+ size_t thread_page_size = __BIONIC_ALIGN(sizeof(pthread_internal_t), PAGE_SIZE);
|
||||
+
|
||||
+ // Allocate in order: stack guard, stack, guard page, pthread_internal_t, static TLS, guard page.
|
||||
size_t mmap_size;
|
||||
if (__builtin_add_overflow(stack_size, stack_guard_size, &mmap_size)) return {};
|
||||
if (__builtin_add_overflow(mmap_size, PTHREAD_GUARD_SIZE, &mmap_size)) return {};
|
||||
+ if (__builtin_add_overflow(mmap_size, thread_page_size, &mmap_size)) return {};
|
||||
if (__builtin_add_overflow(mmap_size, layout.size(), &mmap_size)) return {};
|
||||
if (__builtin_add_overflow(mmap_size, PTHREAD_GUARD_SIZE, &mmap_size)) return {};
|
||||
|
||||
@@ -250,9 +253,10 @@ ThreadMapping __allocate_thread_mapping(size_t stack_size, size_t stack_guard_si
|
||||
return {};
|
||||
}
|
||||
|
||||
- char* const static_tls_space = space + stack_guard_size + stack_size + PTHREAD_GUARD_SIZE;
|
||||
+ char* const thread = space + stack_guard_size + stack_size + PTHREAD_GUARD_SIZE;
|
||||
+ char* const static_tls_space = thread + thread_page_size;
|
||||
|
||||
- if (mprotect(static_tls_space, layout.size(), PROT_READ | PROT_WRITE) != 0) {
|
||||
+ if (mprotect(thread, thread_page_size + layout.size(), PROT_READ | PROT_WRITE) != 0) {
|
||||
async_safe_format_log(ANDROID_LOG_WARN, "libc",
|
||||
"pthread_create failed: couldn't mprotect R+W %zu-byte static TLS mapping region: %s",
|
||||
layout.size(), strerror(errno));
|
||||
@@ -295,13 +299,8 @@ static int __allocate_thread(pthread_attr_t* attr, bionic_tcb** tcbp, void** chi
|
||||
stack_top = static_cast<char*>(attr->stack_base) + attr->stack_size;
|
||||
}
|
||||
|
||||
- // Carve out space from the stack for the thread's pthread_internal_t. This
|
||||
- // memory isn't counted in pthread_attr_getstacksize.
|
||||
-
|
||||
- // To safely access the pthread_internal_t and thread stack, we need to find a 16-byte aligned boundary.
|
||||
- stack_top = align_down(stack_top - sizeof(pthread_internal_t), 16);
|
||||
-
|
||||
- pthread_internal_t* thread = reinterpret_cast<pthread_internal_t*>(stack_top);
|
||||
+ pthread_internal_t* thread = reinterpret_cast<pthread_internal_t*>(
|
||||
+ mapping.static_tls - __BIONIC_ALIGN(sizeof(pthread_internal_t), PAGE_SIZE));
|
||||
if (!stack_clean) {
|
||||
// If thread was not allocated by mmap(), it may not have been cleared to zero.
|
||||
// So assume the worst and zero it.
|
@ -0,0 +1,97 @@
|
||||
From 7f61cc8a1c9abd04094a96959f242b7906fa3127 Mon Sep 17 00:00:00 2001
|
||||
From: Renlord <me@renlord.com>
|
||||
Date: Sun, 20 Oct 2019 08:17:11 +1100
|
||||
Subject: [PATCH] add secondary stack randomization
|
||||
|
||||
---
|
||||
libc/bionic/pthread_create.cpp | 32 +++++++++++++++++++++++++++-----
|
||||
libc/include/sys/cdefs.h | 1 +
|
||||
2 files changed, 28 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
|
||||
index b4a044db18..c2b61a2171 100644
|
||||
--- a/libc/bionic/pthread_create.cpp
|
||||
+++ b/libc/bionic/pthread_create.cpp
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <pthread.h>
|
||||
|
||||
#include <errno.h>
|
||||
+#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/prctl.h>
|
||||
@@ -218,12 +219,24 @@ int __init_thread(pthread_internal_t* thread) {
|
||||
ThreadMapping __allocate_thread_mapping(size_t stack_size, size_t stack_guard_size) {
|
||||
const StaticTlsLayout& layout = __libc_shared_globals()->static_tls_layout;
|
||||
|
||||
+ // round up if the given stack size is not in multiples of PAGE_SIZE
|
||||
+ stack_size = __BIONIC_ALIGN(stack_size, PAGE_SIZE);
|
||||
size_t thread_page_size = __BIONIC_ALIGN(sizeof(pthread_internal_t), PAGE_SIZE);
|
||||
|
||||
- // Allocate in order: stack guard, stack, guard page, pthread_internal_t, static TLS, guard page.
|
||||
+ // Place a randomly sized gap above the stack, up to 10% as large as the stack
|
||||
+ // on 32-bit and 50% on 64-bit where virtual memory is plentiful.
|
||||
+#if __LP64__
|
||||
+ size_t max_gap_size = stack_size / 2;
|
||||
+#else
|
||||
+ size_t max_gap_size = stack_size / 10;
|
||||
+#endif
|
||||
+ // Make sure random stack top guard size are multiples of PAGE_SIZE.
|
||||
+ size_t gap_size = __BIONIC_ALIGN(arc4random_uniform(max_gap_size), PAGE_SIZE);
|
||||
+
|
||||
+ // Allocate in order: stack guard, stack, (random) guard page(s), pthread_internal_t, static TLS, guard page.
|
||||
size_t mmap_size;
|
||||
if (__builtin_add_overflow(stack_size, stack_guard_size, &mmap_size)) return {};
|
||||
- if (__builtin_add_overflow(mmap_size, PTHREAD_GUARD_SIZE, &mmap_size)) return {};
|
||||
+ if (__builtin_add_overflow(mmap_size, gap_size, &mmap_size)) return {};
|
||||
if (__builtin_add_overflow(mmap_size, thread_page_size, &mmap_size)) return {};
|
||||
if (__builtin_add_overflow(mmap_size, layout.size(), &mmap_size)) return {};
|
||||
if (__builtin_add_overflow(mmap_size, PTHREAD_GUARD_SIZE, &mmap_size)) return {};
|
||||
@@ -245,15 +258,21 @@ ThreadMapping __allocate_thread_mapping(size_t stack_size, size_t stack_guard_si
|
||||
return {};
|
||||
}
|
||||
|
||||
- if (mprotect(space + stack_guard_size, stack_size, PROT_READ | PROT_WRITE) != 0) {
|
||||
+ // Stack is at the lower end of mapped space, stack guard region is at the lower end of stack.
|
||||
+ // Make the usable portion of the stack between the guard region and random gap readable and
|
||||
+ // writable.
|
||||
+ if (mprotect((space + stack_guard_size), stack_size, PROT_READ | PROT_WRITE) == -1) {
|
||||
async_safe_format_log(ANDROID_LOG_WARN, "libc",
|
||||
"pthread_create failed: couldn't mprotect R+W %zu-byte thread mapping region: %s",
|
||||
stack_size, strerror(errno));
|
||||
munmap(space, mmap_size);
|
||||
return {};
|
||||
}
|
||||
+ prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, space, stack_guard_size, "stack guard");
|
||||
+ char* const stack_top_guard = space + stack_guard_size + stack_size;
|
||||
+ prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, stack_top_guard, gap_size, "stack top guard");
|
||||
|
||||
- char* const thread = space + stack_guard_size + stack_size + PTHREAD_GUARD_SIZE;
|
||||
+ char* const thread = space + stack_guard_size + stack_size + gap_size;
|
||||
char* const static_tls_space = thread + thread_page_size;
|
||||
|
||||
if (mprotect(thread, thread_page_size + layout.size(), PROT_READ | PROT_WRITE) != 0) {
|
||||
@@ -269,7 +288,10 @@ ThreadMapping __allocate_thread_mapping(size_t stack_size, size_t stack_guard_si
|
||||
result.mmap_size = mmap_size;
|
||||
result.static_tls = static_tls_space;
|
||||
result.stack_base = space;
|
||||
- result.stack_top = space + stack_guard_size + stack_size;
|
||||
+ // Choose a random base within the first page of the stack. Waste no more
|
||||
+ // than the space originally wasted by pthread_internal_t for compatibility.
|
||||
+ result.stack_top = space + stack_guard_size + stack_size - arc4random_uniform(sizeof(pthread_internal_t));
|
||||
+ result.stack_top = reinterpret_cast<char*>(__BIONIC_ALIGN_DOWN(reinterpret_cast<size_t>(result.stack_top), 16));
|
||||
return result;
|
||||
}
|
||||
|
||||
diff --git a/libc/include/sys/cdefs.h b/libc/include/sys/cdefs.h
|
||||
index a919a79224..d223f7f871 100644
|
||||
--- a/libc/include/sys/cdefs.h
|
||||
+++ b/libc/include/sys/cdefs.h
|
||||
@@ -57,6 +57,7 @@
|
||||
#endif
|
||||
|
||||
#define __BIONIC_ALIGN(__value, __alignment) (((__value) + (__alignment)-1) & ~((__alignment)-1))
|
||||
+#define __BIONIC_ALIGN_DOWN(value, alignment) ((value) & ~((alignment) - 1))
|
||||
|
||||
/*
|
||||
* The __CONCAT macro is used to concatenate parts of symbol names, e.g.
|
@ -0,0 +1,74 @@
|
||||
From b28302c668013a5588a6939f0bbced0b7b288cc2 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Micay <danielmicay@gmail.com>
|
||||
Date: Sun, 8 Feb 2015 01:18:54 -0500
|
||||
Subject: [PATCH] replace brk and sbrk with stubs
|
||||
|
||||
Pretend that there is never room to grow the heap in order to prevent
|
||||
usage of these unsafe legacy functions. There are likely no users of
|
||||
these in practice as it is inherently broken to use them outside of
|
||||
malloc.
|
||||
---
|
||||
libc/bionic/brk.cpp | 48 ++++++++-------------------------------------
|
||||
1 file changed, 8 insertions(+), 40 deletions(-)
|
||||
|
||||
diff --git a/libc/bionic/brk.cpp b/libc/bionic/brk.cpp
|
||||
index 566c33a7a6..ef93055139 100644
|
||||
--- a/libc/bionic/brk.cpp
|
||||
+++ b/libc/bionic/brk.cpp
|
||||
@@ -29,48 +29,16 @@
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
-#if defined(__LP64__)
|
||||
-static void* __bionic_brk;
|
||||
-#else
|
||||
-void* __bionic_brk; // Accidentally exported by the NDK.
|
||||
+#if !defined(__LP64__)
|
||||
+void* __bionic_brk = reinterpret_cast<void*>(-1); // Accidentally exported by the NDK.
|
||||
#endif
|
||||
|
||||
-extern "C" void* __brk(void* __addr);
|
||||
-
|
||||
-int brk(void* end_data) {
|
||||
- __bionic_brk = __brk(end_data);
|
||||
- if (__bionic_brk < end_data) {
|
||||
- errno = ENOMEM;
|
||||
- return -1;
|
||||
- }
|
||||
- return 0;
|
||||
+int brk(void*) {
|
||||
+ errno = ENOMEM;
|
||||
+ return -1;
|
||||
}
|
||||
|
||||
-void* sbrk(ptrdiff_t increment) {
|
||||
- // Initialize __bionic_brk if necessary.
|
||||
- if (__bionic_brk == nullptr) {
|
||||
- __bionic_brk = __brk(nullptr);
|
||||
- }
|
||||
-
|
||||
- // Don't ask the kernel if we already know the answer.
|
||||
- if (increment == 0) {
|
||||
- return __bionic_brk;
|
||||
- }
|
||||
-
|
||||
- // Avoid overflow.
|
||||
- uintptr_t old_brk = reinterpret_cast<uintptr_t>(__bionic_brk);
|
||||
- if ((increment > 0 && static_cast<uintptr_t>(increment) > (UINTPTR_MAX - old_brk)) ||
|
||||
- (increment < 0 && static_cast<uintptr_t>(-increment) > old_brk)) {
|
||||
- errno = ENOMEM;
|
||||
- return reinterpret_cast<void*>(-1);
|
||||
- }
|
||||
-
|
||||
- void* desired_brk = reinterpret_cast<void*>(old_brk + increment);
|
||||
- __bionic_brk = __brk(desired_brk);
|
||||
- if (__bionic_brk < desired_brk) {
|
||||
- errno = ENOMEM;
|
||||
- return reinterpret_cast<void*>(-1);
|
||||
- }
|
||||
-
|
||||
- return reinterpret_cast<void*>(old_brk);
|
||||
+void* sbrk(ptrdiff_t) {
|
||||
+ errno = ENOMEM;
|
||||
+ return reinterpret_cast<void*>(-1);
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
From 9f8be7d07cc063933f8def97672c7671dd4fc360 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Micay <danielmicay@gmail.com>
|
||||
Date: Mon, 4 Mar 2019 04:26:04 -0500
|
||||
Subject: [PATCH] use blocking getrandom and avoid urandom fallback
|
||||
|
||||
---
|
||||
libc/bionic/getentropy.cpp | 30 ++----------------------------
|
||||
1 file changed, 2 insertions(+), 28 deletions(-)
|
||||
|
||||
diff --git a/libc/bionic/getentropy.cpp b/libc/bionic/getentropy.cpp
|
||||
index 2c6e417b87..ad49039af1 100644
|
||||
--- a/libc/bionic/getentropy.cpp
|
||||
+++ b/libc/bionic/getentropy.cpp
|
||||
@@ -31,26 +31,6 @@
|
||||
#include <sys/random.h>
|
||||
#include <unistd.h>
|
||||
|
||||
-static int getentropy_urandom(void* buffer, size_t buffer_size, int saved_errno) {
|
||||
- int fd = TEMP_FAILURE_RETRY(open("/dev/urandom", O_RDONLY | O_NOFOLLOW | O_CLOEXEC, 0));
|
||||
- if (fd == -1) return -1;
|
||||
-
|
||||
- size_t collected = 0;
|
||||
- while (collected < buffer_size) {
|
||||
- ssize_t count = TEMP_FAILURE_RETRY(read(fd, static_cast<char*>(buffer) + collected,
|
||||
- buffer_size - collected));
|
||||
- if (count == -1) {
|
||||
- close(fd);
|
||||
- return -1;
|
||||
- }
|
||||
- collected += count;
|
||||
- }
|
||||
-
|
||||
- close(fd);
|
||||
- errno = saved_errno;
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
int getentropy(void* buffer, size_t buffer_size) {
|
||||
if (buffer_size > 256) {
|
||||
errno = EIO;
|
||||
@@ -62,15 +42,9 @@ int getentropy(void* buffer, size_t buffer_size) {
|
||||
size_t collected = 0;
|
||||
while (collected < buffer_size) {
|
||||
long count = TEMP_FAILURE_RETRY(getrandom(static_cast<char*>(buffer) + collected,
|
||||
- buffer_size - collected, GRND_NONBLOCK));
|
||||
+ buffer_size - collected, 0));
|
||||
if (count == -1) {
|
||||
- // EAGAIN: there isn't enough entropy right now.
|
||||
- // ENOSYS/EINVAL: getrandom(2) or GRND_NONBLOCK isn't supported.
|
||||
- // EFAULT: `buffer` is invalid.
|
||||
- // Try /dev/urandom regardless because it can't hurt,
|
||||
- // and we don't need to optimize the EFAULT case.
|
||||
- // See http://b/33059407 and http://b/67015565.
|
||||
- return getentropy_urandom(buffer, buffer_size, saved_errno);
|
||||
+ return -1;
|
||||
}
|
||||
collected += count;
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
From cb91a7ee3aed607dab2d89f2f6b823bf28ea34a0 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Micay <danielmicay@gmail.com>
|
||||
Date: Mon, 19 Sep 2016 07:57:43 -0400
|
||||
Subject: [PATCH] fix undefined out-of-bounds accesses in sched.h
|
||||
|
||||
---
|
||||
libc/include/sched.h | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/libc/include/sched.h b/libc/include/sched.h
|
||||
index 1f5036677a..fc622cbd76 100644
|
||||
--- a/libc/include/sched.h
|
||||
+++ b/libc/include/sched.h
|
||||
@@ -71,7 +71,10 @@ int setns(int __fd, int __ns_type) __INTRODUCED_IN(21);
|
||||
#define __CPU_MASK(x) ((__CPU_BITTYPE)1 << ((x) & (__CPU_BITS - 1)))
|
||||
|
||||
typedef struct {
|
||||
- __CPU_BITTYPE __bits[ CPU_SETSIZE / __CPU_BITS ];
|
||||
+ union {
|
||||
+ __CPU_BITTYPE __bits_minimum[ CPU_SETSIZE / __CPU_BITS ];
|
||||
+ __CPU_BITTYPE __bits[0];
|
||||
+ };
|
||||
} cpu_set_t;
|
||||
|
||||
int sched_setaffinity(pid_t __pid, size_t __set_size, const cpu_set_t* __set) __INTRODUCED_IN(12);
|
@ -0,0 +1,46 @@
|
||||
From 08279e2fdd75d20ede2a56c326604f426557cea4 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Micay <danielmicay@gmail.com>
|
||||
Date: Sat, 19 Nov 2016 09:56:14 -0500
|
||||
Subject: [PATCH] stop implicitly marking mappings as mergeable
|
||||
|
||||
---
|
||||
libc/bionic/mmap.cpp | 19 +------------------
|
||||
1 file changed, 1 insertion(+), 18 deletions(-)
|
||||
|
||||
diff --git a/libc/bionic/mmap.cpp b/libc/bionic/mmap.cpp
|
||||
index 35033199ae..c081068928 100644
|
||||
--- a/libc/bionic/mmap.cpp
|
||||
+++ b/libc/bionic/mmap.cpp
|
||||
@@ -39,8 +39,6 @@ extern "C" void* __mmap2(void*, size_t, int, int, int, size_t);
|
||||
|
||||
#define MMAP2_SHIFT 12 // 2**12 == 4096
|
||||
|
||||
-static bool kernel_has_MADV_MERGEABLE = true;
|
||||
-
|
||||
void* mmap64(void* addr, size_t size, int prot, int flags, int fd, off64_t offset) {
|
||||
if (offset < 0 || (offset & ((1UL << MMAP2_SHIFT)-1)) != 0) {
|
||||
errno = EINVAL;
|
||||
@@ -54,22 +52,7 @@ void* mmap64(void* addr, size_t size, int prot, int flags, int fd, off64_t offse
|
||||
return MAP_FAILED;
|
||||
}
|
||||
|
||||
- bool is_private_anonymous =
|
||||
- (flags & (MAP_PRIVATE | MAP_ANONYMOUS)) == (MAP_PRIVATE | MAP_ANONYMOUS);
|
||||
- bool is_stack_or_grows_down = (flags & (MAP_STACK | MAP_GROWSDOWN)) != 0;
|
||||
-
|
||||
- void* result = __mmap2(addr, size, prot, flags, fd, offset >> MMAP2_SHIFT);
|
||||
-
|
||||
- if (result != MAP_FAILED && kernel_has_MADV_MERGEABLE &&
|
||||
- is_private_anonymous && !is_stack_or_grows_down) {
|
||||
- ErrnoRestorer errno_restorer;
|
||||
- int rc = madvise(result, size, MADV_MERGEABLE);
|
||||
- if (rc == -1 && errno == EINVAL) {
|
||||
- kernel_has_MADV_MERGEABLE = false;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- return result;
|
||||
+ return __mmap2(addr, size, prot, flags, fd, offset >> MMAP2_SHIFT);
|
||||
}
|
||||
|
||||
void* mmap(void* addr, size_t size, int prot, int flags, int fd, off_t offset) {
|
@ -0,0 +1,39 @@
|
||||
From 6a18bd565d9344db5f46f2bb423309dcb134be6e Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Micay <danielmicay@gmail.com>
|
||||
Date: Sat, 16 Jul 2016 23:55:16 -0400
|
||||
Subject: [PATCH] replace VLA formatting buffer with dprintf
|
||||
|
||||
---
|
||||
libc/bionic/bionic_systrace.cpp | 10 +---------
|
||||
1 file changed, 1 insertion(+), 9 deletions(-)
|
||||
|
||||
diff --git a/libc/bionic/bionic_systrace.cpp b/libc/bionic/bionic_systrace.cpp
|
||||
index 6182ed801c..ccb15a9959 100644
|
||||
--- a/libc/bionic/bionic_systrace.cpp
|
||||
+++ b/libc/bionic/bionic_systrace.cpp
|
||||
@@ -26,8 +26,6 @@
|
||||
|
||||
#include <cutils/trace.h> // For ATRACE_TAG_BIONIC.
|
||||
|
||||
-#define WRITE_OFFSET 32
|
||||
-
|
||||
static Lock g_lock;
|
||||
static CachedProperty g_debug_atrace_tags_enableflags("debug.atrace.tags.enableflags");
|
||||
static uint64_t g_tags;
|
||||
@@ -61,15 +59,9 @@ void bionic_trace_begin(const char* message) {
|
||||
return;
|
||||
}
|
||||
|
||||
- // If bionic tracing has been enabled, then write the message to the
|
||||
- // kernel trace_marker.
|
||||
- int length = strlen(message);
|
||||
- char buf[length + WRITE_OFFSET];
|
||||
- size_t len = snprintf(buf, length + WRITE_OFFSET, "B|%d|%s", getpid(), message);
|
||||
-
|
||||
// Tracing may stop just after checking property and before writing the message.
|
||||
// So the write is acceptable to fail. See b/20666100.
|
||||
- TEMP_FAILURE_RETRY(write(trace_marker_fd, buf, len));
|
||||
+ dprintf(trace_marker_fd, "B|%d|%s", getpid(), message);
|
||||
}
|
||||
|
||||
void bionic_trace_end() {
|
@ -0,0 +1,25 @@
|
||||
From 2f392c2d081fad13f61164ab07841818b972f950 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Micay <danielmicay@gmail.com>
|
||||
Date: Fri, 17 Jul 2015 21:32:05 -0400
|
||||
Subject: [PATCH] increase default pthread stack to 8MiB on 64-bit
|
||||
|
||||
---
|
||||
libc/bionic/pthread_internal.h | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/libc/bionic/pthread_internal.h b/libc/bionic/pthread_internal.h
|
||||
index e720c046d9..4f7c80e1b9 100644
|
||||
--- a/libc/bionic/pthread_internal.h
|
||||
+++ b/libc/bionic/pthread_internal.h
|
||||
@@ -218,7 +218,11 @@ __LIBC_HIDDEN__ void pthread_key_clean_all(void);
|
||||
// stack overflows, we subtracted the same amount we were using there
|
||||
// from the default thread stack size. This should keep memory usage
|
||||
// roughly constant.
|
||||
+#ifdef __LP64__
|
||||
+#define PTHREAD_STACK_SIZE_DEFAULT ((8 * 1024 * 1024) - SIGNAL_STACK_SIZE_WITHOUT_GUARD)
|
||||
+#else
|
||||
#define PTHREAD_STACK_SIZE_DEFAULT ((1 * 1024 * 1024) - SIGNAL_STACK_SIZE_WITHOUT_GUARD)
|
||||
+#endif
|
||||
|
||||
// Leave room for a guard page in the internally created signal stacks.
|
||||
#define SIGNAL_STACK_SIZE (SIGNAL_STACK_SIZE_WITHOUT_GUARD + PTHREAD_GUARD_SIZE)
|
@ -0,0 +1,58 @@
|
||||
From 8bbce1bc50f7b0fb210de3ef160542bbb08cdcc0 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Micay <danielmicay@gmail.com>
|
||||
Date: Sat, 1 Oct 2016 05:11:44 -0400
|
||||
Subject: [PATCH] make __stack_chk_guard read-only at runtime
|
||||
|
||||
---
|
||||
libc/bionic/__libc_init_main_thread.cpp | 15 ++++++++++++---
|
||||
1 file changed, 12 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/libc/bionic/__libc_init_main_thread.cpp b/libc/bionic/__libc_init_main_thread.cpp
|
||||
index 4984e38a13..2e3967daab 100644
|
||||
--- a/libc/bionic/__libc_init_main_thread.cpp
|
||||
+++ b/libc/bionic/__libc_init_main_thread.cpp
|
||||
@@ -28,6 +28,9 @@
|
||||
|
||||
#include "libc_init_common.h"
|
||||
|
||||
+#include <limits.h>
|
||||
+#include <sys/mman.h>
|
||||
+
|
||||
#include <async_safe/log.h>
|
||||
|
||||
#include "private/KernelArgumentBlock.h"
|
||||
@@ -35,17 +38,20 @@
|
||||
#include "private/bionic_defs.h"
|
||||
#include "private/bionic_elf_tls.h"
|
||||
#include "private/bionic_globals.h"
|
||||
-#include "private/bionic_ssp.h"
|
||||
#include "pthread_internal.h"
|
||||
|
||||
extern "C" pid_t __getpid();
|
||||
extern "C" int __set_tid_address(int* tid_address);
|
||||
|
||||
// Declared in "private/bionic_ssp.h".
|
||||
-uintptr_t __stack_chk_guard = 0;
|
||||
+__attribute__((aligned(PAGE_SIZE)))
|
||||
+uintptr_t __stack_chk_guard[PAGE_SIZE / sizeof(uintptr_t)] = {0};
|
||||
|
||||
static pthread_internal_t main_thread;
|
||||
|
||||
+void __libc_init_global_stack_chk_guard(KernelArgumentBlock& args) {
|
||||
+}
|
||||
+
|
||||
// Setup for the main thread. For dynamic executables, this is called by the
|
||||
// linker _before_ libc is mapped in memory. This means that all writes to
|
||||
// globals from this function will apply to linker-private copies and will not
|
||||
@@ -101,7 +107,10 @@ extern "C" void __libc_init_main_thread_late() {
|
||||
// The TLS stack guard is set from the global, so ensure that we've initialized the global
|
||||
// before we initialize the TLS. Dynamic executables will initialize their copy of the global
|
||||
// stack protector from the one in the main thread's TLS.
|
||||
- __libc_safe_arc4random_buf(&__stack_chk_guard, sizeof(__stack_chk_guard));
|
||||
+ __libc_safe_arc4random_buf(&__stack_chk_guard[0], sizeof(__stack_chk_guard[0]));
|
||||
+ if (mprotect(__stack_chk_guard, sizeof(__stack_chk_guard), PROT_READ) == -1) {
|
||||
+ async_safe_fatal("mprotect __stack_chk_guard: %s", strerror(errno));
|
||||
+ }
|
||||
__init_tcb_stack_guard(__get_bionic_tcb());
|
||||
|
||||
__init_thread(&main_thread);
|
@ -0,0 +1,40 @@
|
||||
From 725f61db82eb41098291ce06445ccfbf5d5b3581 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Micay <danielmicay@gmail.com>
|
||||
Date: Sun, 12 Mar 2017 17:49:13 -0400
|
||||
Subject: [PATCH] on 64-bit, zero the leading stack canary byte
|
||||
|
||||
This reduces entropy of the canary from 64-bit to 56-bit in exchange for
|
||||
mitigating non-terminated C string overflows.
|
||||
---
|
||||
libc/bionic/__libc_init_main_thread.cpp | 11 +++++++++--
|
||||
1 file changed, 9 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/libc/bionic/__libc_init_main_thread.cpp b/libc/bionic/__libc_init_main_thread.cpp
|
||||
index 2e3967daab..f5128de9ec 100644
|
||||
--- a/libc/bionic/__libc_init_main_thread.cpp
|
||||
+++ b/libc/bionic/__libc_init_main_thread.cpp
|
||||
@@ -49,8 +49,11 @@ uintptr_t __stack_chk_guard[PAGE_SIZE / sizeof(uintptr_t)] = {0};
|
||||
|
||||
static pthread_internal_t main_thread;
|
||||
|
||||
-void __libc_init_global_stack_chk_guard(KernelArgumentBlock& args) {
|
||||
-}
|
||||
+#if __LP64__
|
||||
+static const uintptr_t canary_mask = __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ ?
|
||||
+ 0xffffffffffffff00UL :
|
||||
+ 0x00ffffffffffffffUL;
|
||||
+#endif
|
||||
|
||||
// Setup for the main thread. For dynamic executables, this is called by the
|
||||
// linker _before_ libc is mapped in memory. This means that all writes to
|
||||
@@ -108,6 +111,10 @@ extern "C" void __libc_init_main_thread_late() {
|
||||
// before we initialize the TLS. Dynamic executables will initialize their copy of the global
|
||||
// stack protector from the one in the main thread's TLS.
|
||||
__libc_safe_arc4random_buf(&__stack_chk_guard[0], sizeof(__stack_chk_guard[0]));
|
||||
+#if __LP64__
|
||||
+ // Sacrifice 8 bits of entropy on 64-bit to mitigate non-terminated C string overflows
|
||||
+ __stack_chk_guard[0] &= canary_mask;
|
||||
+#endif
|
||||
if (mprotect(__stack_chk_guard, sizeof(__stack_chk_guard), PROT_READ) == -1) {
|
||||
async_safe_fatal("mprotect __stack_chk_guard: %s", strerror(errno));
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
From aa9cc05d07a5855fcae2d9f21dd9672543eafbb3 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Micay <danielmicay@gmail.com>
|
||||
Date: Fri, 6 Feb 2015 11:41:57 -0500
|
||||
Subject: [PATCH] zero sensitive information with explicit_bzero
|
||||
|
||||
---
|
||||
init/security.cpp | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/init/security.cpp b/init/security.cpp
|
||||
index a3494a280bd..4b6c918ab30 100644
|
||||
--- a/init/security.cpp
|
||||
+++ b/init/security.cpp
|
||||
@@ -73,6 +73,7 @@ Result<Success> MixHwrngIntoLinuxRngAction(const BuiltinArguments&) {
|
||||
}
|
||||
|
||||
chunk_size = TEMP_FAILURE_RETRY(write(urandom_fd, buf, chunk_size));
|
||||
+ explicit_bzero(buf, chunk_size);
|
||||
if (chunk_size == -1) {
|
||||
return ErrnoError() << "Failed to write to /dev/urandom";
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
From 5412c371955014eee8b2246b386ae7f539bac09e Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Micay <danielmicay@gmail.com>
|
||||
Date: Thu, 5 Feb 2015 21:53:16 -0500
|
||||
Subject: [PATCH] add a real explicit_bzero implementation
|
||||
|
||||
Clang, GCC and other compilers special-case standard C functions like
|
||||
memset. Calls to memset will be optimized out.
|
||||
|
||||
OpenBSD provides explicit_bzero to work around this but Android simply
|
||||
defines it as memset so nothing prevents it from being optimized away.
|
||||
|
||||
This implementation uses a memory read constraint via empty inline
|
||||
assembly rather than something that may be broken via link-time
|
||||
optimization in the future.
|
||||
---
|
||||
libc/Android.bp | 1 +
|
||||
libc/bionic/explicit_bzero.cpp | 7 +++++++
|
||||
libc/include/string.h | 1 +
|
||||
libc/libc.map.txt | 1 +
|
||||
libc/upstream-openbsd/android/include/openbsd-compat.h | 2 --
|
||||
5 files changed, 10 insertions(+), 2 deletions(-)
|
||||
create mode 100644 libc/bionic/explicit_bzero.cpp
|
||||
|
||||
diff --git a/libc/Android.bp b/libc/Android.bp
|
||||
index d3271ae919..043a03245d 100644
|
||||
--- a/libc/Android.bp
|
||||
+++ b/libc/Android.bp
|
||||
@@ -1028,6 +1028,7 @@ cc_library_static {
|
||||
"bionic/error.cpp",
|
||||
"bionic/eventfd.cpp",
|
||||
"bionic/exec.cpp",
|
||||
+ "bionic/explicit_bzero.cpp",
|
||||
"bionic/faccessat.cpp",
|
||||
"bionic/fchmod.cpp",
|
||||
"bionic/fchmodat.cpp",
|
||||
diff --git a/libc/bionic/explicit_bzero.cpp b/libc/bionic/explicit_bzero.cpp
|
||||
new file mode 100644
|
||||
index 0000000000..b06daa1386
|
||||
--- /dev/null
|
||||
+++ b/libc/bionic/explicit_bzero.cpp
|
||||
@@ -0,0 +1,7 @@
|
||||
+#include <string.h>
|
||||
+
|
||||
+void* explicit_bzero(void* s, size_t n) {
|
||||
+ void *ptr = memset(s, 0, n);
|
||||
+ __asm__ __volatile__("" : : "r"(ptr) : "memory");
|
||||
+ return ptr;
|
||||
+}
|
||||
diff --git a/libc/include/string.h b/libc/include/string.h
|
||||
index 0cc5611aa8..befffd0828 100644
|
||||
--- a/libc/include/string.h
|
||||
+++ b/libc/include/string.h
|
||||
@@ -56,6 +56,7 @@ void* mempcpy(void* __dst, const void* __src, size_t __n) __INTRODUCED_IN(23);
|
||||
#endif
|
||||
void* memmove(void* __dst, const void* __src, size_t __n);
|
||||
void* memset(void* __dst, int __ch, size_t __n);
|
||||
+void* explicit_bzero(void *s, size_t n);
|
||||
void* memmem(const void* __haystack, size_t __haystack_size, const void* __needle, size_t __needle_size) __attribute_pure__;
|
||||
|
||||
char* strchr(const char* __s, int __ch) __attribute_pure__;
|
||||
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
|
||||
index 4bfb8a2320..36803984e9 100644
|
||||
--- a/libc/libc.map.txt
|
||||
+++ b/libc/libc.map.txt
|
||||
@@ -332,6 +332,7 @@ LIBC {
|
||||
execvp;
|
||||
execvpe; # introduced=21
|
||||
exit;
|
||||
+ explicit_bzero; # introduced=30
|
||||
faccessat;
|
||||
fallocate; # introduced=21
|
||||
fallocate64; # introduced=21
|
||||
diff --git a/libc/upstream-openbsd/android/include/openbsd-compat.h b/libc/upstream-openbsd/android/include/openbsd-compat.h
|
||||
index 878f71cec6..79a2604259 100644
|
||||
--- a/libc/upstream-openbsd/android/include/openbsd-compat.h
|
||||
+++ b/libc/upstream-openbsd/android/include/openbsd-compat.h
|
||||
@@ -53,8 +53,6 @@ extern const char* __progname;
|
||||
/* OpenBSD has this, but we can't really implement it correctly on Linux. */
|
||||
#define issetugid() 0
|
||||
|
||||
-#define explicit_bzero(p, s) memset(p, 0, s)
|
||||
-
|
||||
/* OpenBSD has these in <sys/param.h>, but "ALIGN" isn't something we want to reserve. */
|
||||
#define ALIGNBYTES (sizeof(uintptr_t) - 1)
|
||||
#define ALIGN(p) (((uintptr_t)(p) + ALIGNBYTES) &~ ALIGNBYTES)
|
@ -0,0 +1,84 @@
|
||||
From 2e613ccbe7a6b2aa8f1688ed8493267d12c66d23 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Micay <danielmicay@gmail.com>
|
||||
Date: Wed, 2 Dec 2015 23:37:28 -0500
|
||||
Subject: [PATCH] switch pthread_atfork handler allocation to mmap
|
||||
|
||||
Signed-off-by: anupritaisno1 <www.anuprita804@gmail.com>
|
||||
---
|
||||
libc/bionic/pthread_atfork.cpp | 35 ++++++++++++++++++++++++++++------
|
||||
1 file changed, 29 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/libc/bionic/pthread_atfork.cpp b/libc/bionic/pthread_atfork.cpp
|
||||
index 0dcabdfb2d..6306052ee3 100644
|
||||
--- a/libc/bionic/pthread_atfork.cpp
|
||||
+++ b/libc/bionic/pthread_atfork.cpp
|
||||
@@ -29,6 +29,9 @@
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
+#include <sys/mman.h>
|
||||
+#include <sys/prctl.h>
|
||||
+#include <unistd.h>
|
||||
|
||||
#include "platform/bionic/macros.h"
|
||||
|
||||
@@ -43,6 +46,8 @@ struct atfork_t {
|
||||
void* dso_handle;
|
||||
};
|
||||
|
||||
+static atfork_t* pool;
|
||||
+
|
||||
class atfork_list_t {
|
||||
public:
|
||||
constexpr atfork_list_t() : first_(nullptr), last_(nullptr) {}
|
||||
@@ -101,7 +106,8 @@ class atfork_list_t {
|
||||
last_ = entry->prev;
|
||||
}
|
||||
|
||||
- free(entry);
|
||||
+ entry->next = pool;
|
||||
+ pool = entry;
|
||||
}
|
||||
|
||||
atfork_t* first_;
|
||||
@@ -154,18 +160,35 @@ void __bionic_atfork_run_parent() {
|
||||
// __register_atfork is the name used by glibc
|
||||
extern "C" int __register_atfork(void (*prepare)(void), void (*parent)(void),
|
||||
void(*child)(void), void* dso) {
|
||||
- atfork_t* entry = reinterpret_cast<atfork_t*>(malloc(sizeof(atfork_t)));
|
||||
- if (entry == nullptr) {
|
||||
- return ENOMEM;
|
||||
+ pthread_mutex_lock(&g_atfork_list_mutex);
|
||||
+
|
||||
+ if (!pool) {
|
||||
+ size_t page_size = getpagesize();
|
||||
+ char* page = static_cast<char*>(mmap(NULL, page_size, PROT_READ|PROT_WRITE,
|
||||
+ MAP_ANONYMOUS|MAP_PRIVATE, -1, 0));
|
||||
+ if (page == MAP_FAILED) {
|
||||
+ pthread_mutex_unlock(&g_atfork_list_mutex);
|
||||
+ return ENOMEM;
|
||||
+ }
|
||||
+
|
||||
+ prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, page, page_size,
|
||||
+ "atfork handlers");
|
||||
+
|
||||
+ for (char* it = page; it < page + page_size - sizeof(atfork_t); it += sizeof(atfork_t)) {
|
||||
+ atfork_t* node = reinterpret_cast<atfork_t*>(it);
|
||||
+ node->next = pool;
|
||||
+ pool = node;
|
||||
+ }
|
||||
}
|
||||
|
||||
+ atfork_t* entry = pool;
|
||||
+ pool = entry->next;
|
||||
+
|
||||
entry->prepare = prepare;
|
||||
entry->parent = parent;
|
||||
entry->child = child;
|
||||
entry->dso_handle = dso;
|
||||
|
||||
- pthread_mutex_lock(&g_atfork_list_mutex);
|
||||
-
|
||||
g_atfork_list.push_back(entry);
|
||||
|
||||
pthread_mutex_unlock(&g_atfork_list_mutex);
|
@ -0,0 +1,95 @@
|
||||
From e239c7dff88bbc37a3e902a695565fdbf6ed0b08 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Micay <danielmicay@gmail.com>
|
||||
Date: Thu, 3 Dec 2015 12:58:31 -0500
|
||||
Subject: [PATCH] add memory protection for pthread_atfork handlers
|
||||
|
||||
Signed-off-by: anupritaisno1 <www.anuprita804@gmail.com>
|
||||
---
|
||||
libc/bionic/pthread_atfork.cpp | 34 ++++++++++++++++++++++++++++++++--
|
||||
1 file changed, 32 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/libc/bionic/pthread_atfork.cpp b/libc/bionic/pthread_atfork.cpp
|
||||
index 6306052ee3..d59f3ae54b 100644
|
||||
--- a/libc/bionic/pthread_atfork.cpp
|
||||
+++ b/libc/bionic/pthread_atfork.cpp
|
||||
@@ -47,6 +47,7 @@ struct atfork_t {
|
||||
};
|
||||
|
||||
static atfork_t* pool;
|
||||
+static atfork_t* page_list;
|
||||
|
||||
class atfork_list_t {
|
||||
public:
|
||||
@@ -160,13 +161,22 @@ void __bionic_atfork_run_parent() {
|
||||
// __register_atfork is the name used by glibc
|
||||
extern "C" int __register_atfork(void (*prepare)(void), void (*parent)(void),
|
||||
void(*child)(void), void* dso) {
|
||||
+ size_t page_size = getpagesize();
|
||||
+
|
||||
pthread_mutex_lock(&g_atfork_list_mutex);
|
||||
|
||||
+ for (atfork_t* page_it = page_list; page_it; page_it = page_it->next) {
|
||||
+ mprotect(page_it, page_size, PROT_READ|PROT_WRITE);
|
||||
+ }
|
||||
+
|
||||
if (!pool) {
|
||||
- size_t page_size = getpagesize();
|
||||
char* page = static_cast<char*>(mmap(NULL, page_size, PROT_READ|PROT_WRITE,
|
||||
MAP_ANONYMOUS|MAP_PRIVATE, -1, 0));
|
||||
if (page == MAP_FAILED) {
|
||||
+ for (atfork_t* page_it = page_list; page_it; page_it = page_it->next) {
|
||||
+ mprotect(page_it, page_size, PROT_READ);
|
||||
+ }
|
||||
+
|
||||
pthread_mutex_unlock(&g_atfork_list_mutex);
|
||||
return ENOMEM;
|
||||
}
|
||||
@@ -174,11 +184,15 @@ extern "C" int __register_atfork(void (*prepare)(void), void (*parent)(void),
|
||||
prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, page, page_size,
|
||||
"atfork handlers");
|
||||
|
||||
- for (char* it = page; it < page + page_size - sizeof(atfork_t); it += sizeof(atfork_t)) {
|
||||
+ for (char* it = page + sizeof(atfork_t); it < page + page_size - sizeof(atfork_t); it += sizeof(atfork_t)) {
|
||||
atfork_t* node = reinterpret_cast<atfork_t*>(it);
|
||||
node->next = pool;
|
||||
pool = node;
|
||||
}
|
||||
+
|
||||
+ atfork_t* page_node = reinterpret_cast<atfork_t*>(page);
|
||||
+ page_node->next = page_list;
|
||||
+ page_list = page_node;
|
||||
}
|
||||
|
||||
atfork_t* entry = pool;
|
||||
@@ -191,6 +205,10 @@ extern "C" int __register_atfork(void (*prepare)(void), void (*parent)(void),
|
||||
|
||||
g_atfork_list.push_back(entry);
|
||||
|
||||
+ for (atfork_t* page_it = page_list; page_it; page_it = page_it->next) {
|
||||
+ mprotect(page_it, page_size, PROT_READ);
|
||||
+ }
|
||||
+
|
||||
pthread_mutex_unlock(&g_atfork_list_mutex);
|
||||
|
||||
return 0;
|
||||
@@ -198,8 +216,20 @@ extern "C" int __register_atfork(void (*prepare)(void), void (*parent)(void),
|
||||
|
||||
extern "C" __LIBC_HIDDEN__ void __unregister_atfork(void* dso) {
|
||||
pthread_mutex_lock(&g_atfork_list_mutex);
|
||||
+
|
||||
+ size_t page_size = getpagesize();
|
||||
+
|
||||
+ for (atfork_t* page_it = page_list; page_it; page_it = page_it->next) {
|
||||
+ mprotect(page_it, page_size, PROT_READ|PROT_WRITE);
|
||||
+ }
|
||||
+
|
||||
g_atfork_list.remove_if([&](const atfork_t* entry) {
|
||||
return entry->dso_handle == dso;
|
||||
});
|
||||
+
|
||||
+ for (atfork_t* page_it = page_list; page_it; page_it = page_it->next) {
|
||||
+ mprotect(page_it, page_size, PROT_READ);
|
||||
+ }
|
||||
+
|
||||
pthread_mutex_unlock(&g_atfork_list_mutex);
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
From 0b03d92b7f2dc5f12211037e99821ccead27a687 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Micay <danielmicay@gmail.com>
|
||||
Date: Wed, 27 Jan 2016 18:02:15 -0500
|
||||
Subject: [PATCH] add XOR mangling mitigation for thread-local dtors
|
||||
|
||||
Signed-off-by: anupritaisno1 <www.anuprita804@gmail.com>
|
||||
---
|
||||
libc/bionic/__cxa_thread_atexit_impl.cpp | 8 +++++---
|
||||
libc/bionic/libc_init_common.cpp | 2 ++
|
||||
libc/private/bionic_globals.h | 1 +
|
||||
3 files changed, 8 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/libc/bionic/__cxa_thread_atexit_impl.cpp b/libc/bionic/__cxa_thread_atexit_impl.cpp
|
||||
index 99077c101d..74608513ef 100644
|
||||
--- a/libc/bionic/__cxa_thread_atexit_impl.cpp
|
||||
+++ b/libc/bionic/__cxa_thread_atexit_impl.cpp
|
||||
@@ -13,15 +13,17 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
+#include <stdint.h>
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
#include <private/bionic_defs.h>
|
||||
+#include <private/bionic_globals.h>
|
||||
|
||||
#include "pthread_internal.h"
|
||||
|
||||
class thread_local_dtor {
|
||||
public:
|
||||
- void (*func) (void *);
|
||||
+ uintptr_t func;
|
||||
void *arg;
|
||||
void *dso_handle; // unused...
|
||||
thread_local_dtor* next;
|
||||
@@ -35,7 +37,7 @@ __BIONIC_WEAK_FOR_NATIVE_BRIDGE
|
||||
int __cxa_thread_atexit_impl(void (*func) (void *), void *arg, void *dso_handle) {
|
||||
thread_local_dtor* dtor = new thread_local_dtor();
|
||||
|
||||
- dtor->func = func;
|
||||
+ dtor->func = __libc_globals->dtor_cookie ^ reinterpret_cast<uintptr_t>(func);
|
||||
dtor->arg = arg;
|
||||
dtor->dso_handle = dso_handle;
|
||||
|
||||
@@ -54,7 +56,7 @@ extern "C" __LIBC_HIDDEN__ void __cxa_thread_finalize() {
|
||||
thread_local_dtor* current = thread->thread_local_dtors;
|
||||
thread->thread_local_dtors = current->next;
|
||||
|
||||
- current->func(current->arg);
|
||||
+ (reinterpret_cast<void (*)(void*)>(__libc_globals->dtor_cookie ^ current->func))(current->arg);
|
||||
if (__loader_remove_thread_local_dtor != nullptr) {
|
||||
__loader_remove_thread_local_dtor(current->dso_handle);
|
||||
}
|
||||
diff --git a/libc/bionic/libc_init_common.cpp b/libc/bionic/libc_init_common.cpp
|
||||
index a82ca50b69..2ad0b58c5a 100644
|
||||
--- a/libc/bionic/libc_init_common.cpp
|
||||
+++ b/libc/bionic/libc_init_common.cpp
|
||||
@@ -45,6 +45,7 @@
|
||||
#include <async_safe/log.h>
|
||||
|
||||
#include "private/WriteProtected.h"
|
||||
+#include "private/bionic_arc4random.h"
|
||||
#include "private/bionic_defs.h"
|
||||
#include "private/bionic_globals.h"
|
||||
#include "private/bionic_tls.h"
|
||||
@@ -66,6 +67,7 @@ void __libc_init_globals() {
|
||||
__libc_globals.mutate([](libc_globals* globals) {
|
||||
__libc_init_vdso(globals);
|
||||
__libc_init_setjmp_cookie(globals);
|
||||
+ arc4random_buf(&globals->dtor_cookie, sizeof(globals->dtor_cookie));
|
||||
});
|
||||
}
|
||||
|
||||
diff --git a/libc/private/bionic_globals.h b/libc/private/bionic_globals.h
|
||||
index 6e7eb76e40..1b75ca0ee6 100644
|
||||
--- a/libc/private/bionic_globals.h
|
||||
+++ b/libc/private/bionic_globals.h
|
||||
@@ -43,6 +43,7 @@
|
||||
|
||||
struct libc_globals {
|
||||
vdso_entry vdso[VDSO_END];
|
||||
+ long dtor_cookie;
|
||||
long setjmp_cookie;
|
||||
uintptr_t heap_pointer_tag;
|
||||
|
@ -0,0 +1,25 @@
|
||||
From de08419b8256ab7daf6ef7c7835348f9aaeb7478 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Micay <danielmicay@gmail.com>
|
||||
Date: Fri, 29 Jan 2016 20:20:09 -0500
|
||||
Subject: [PATCH] use a better pthread_attr junk filling pattern
|
||||
|
||||
Guarantee that junk filled pointers will fault, at least on pure 64-bit.
|
||||
|
||||
Signed-off-by: anupritaisno1 <www.anuprita804@gmail.com>
|
||||
---
|
||||
libc/bionic/pthread_attr.cpp | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/libc/bionic/pthread_attr.cpp b/libc/bionic/pthread_attr.cpp
|
||||
index 3c4b169eed..a27201706e 100644
|
||||
--- a/libc/bionic/pthread_attr.cpp
|
||||
+++ b/libc/bionic/pthread_attr.cpp
|
||||
@@ -53,7 +53,7 @@ int pthread_attr_init(pthread_attr_t* attr) {
|
||||
|
||||
__BIONIC_WEAK_FOR_NATIVE_BRIDGE
|
||||
int pthread_attr_destroy(pthread_attr_t* attr) {
|
||||
- memset(attr, 0x42, sizeof(pthread_attr_t));
|
||||
+ memset(attr, 0xdf, sizeof(pthread_attr_t));
|
||||
return 0;
|
||||
}
|
||||
|
@ -0,0 +1,76 @@
|
||||
From 897d4903e24c9f6b772539e9f8e0bf3520ed8838 Mon Sep 17 00:00:00 2001
|
||||
From: Renlord <me@renlord.com>
|
||||
Date: Thu, 12 Sep 2019 14:51:51 +1000
|
||||
Subject: [PATCH] add guard page(s) between static_tls and stack
|
||||
|
||||
Signed-off-by: anupritaisno1 <www.anuprita804@gmail.com>
|
||||
---
|
||||
libc/bionic/pthread_create.cpp | 29 +++++++++++++++++++----------
|
||||
1 file changed, 19 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
|
||||
index d4a8bef269..eac53cac85 100644
|
||||
--- a/libc/bionic/pthread_create.cpp
|
||||
+++ b/libc/bionic/pthread_create.cpp
|
||||
@@ -199,9 +199,10 @@ int __init_thread(pthread_internal_t* thread) {
|
||||
ThreadMapping __allocate_thread_mapping(size_t stack_size, size_t stack_guard_size) {
|
||||
const StaticTlsLayout& layout = __libc_shared_globals()->static_tls_layout;
|
||||
|
||||
- // Allocate in order: stack guard, stack, static TLS, guard page.
|
||||
+ // Allocate in order: stack guard, stack, guard page, static TLS, guard page.
|
||||
size_t mmap_size;
|
||||
if (__builtin_add_overflow(stack_size, stack_guard_size, &mmap_size)) return {};
|
||||
+ if (__builtin_add_overflow(mmap_size, PTHREAD_GUARD_SIZE, &mmap_size)) return {};
|
||||
if (__builtin_add_overflow(mmap_size, layout.size(), &mmap_size)) return {};
|
||||
if (__builtin_add_overflow(mmap_size, PTHREAD_GUARD_SIZE, &mmap_size)) return {};
|
||||
|
||||
@@ -210,8 +211,8 @@ ThreadMapping __allocate_thread_mapping(size_t stack_size, size_t stack_guard_si
|
||||
mmap_size = __BIONIC_ALIGN(mmap_size, PAGE_SIZE);
|
||||
if (mmap_size < unaligned_size) return {};
|
||||
|
||||
- // Create a new private anonymous map. Make the entire mapping PROT_NONE, then carve out a
|
||||
- // read+write area in the middle.
|
||||
+ // Create a new private anonymous map. Make the entire mapping PROT_NONE, then carve out
|
||||
+ // read+write areas for the stack and static TLS
|
||||
const int flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE;
|
||||
char* const space = static_cast<char*>(mmap(nullptr, mmap_size, PROT_NONE, flags, -1, 0));
|
||||
if (space == MAP_FAILED) {
|
||||
@@ -221,13 +222,21 @@ ThreadMapping __allocate_thread_mapping(size_t stack_size, size_t stack_guard_si
|
||||
mmap_size, strerror(errno));
|
||||
return {};
|
||||
}
|
||||
- const size_t writable_size = mmap_size - stack_guard_size - PTHREAD_GUARD_SIZE;
|
||||
- if (mprotect(space + stack_guard_size,
|
||||
- writable_size,
|
||||
- PROT_READ | PROT_WRITE) != 0) {
|
||||
+
|
||||
+ if (mprotect(space + stack_guard_size, stack_size, PROT_READ | PROT_WRITE) != 0) {
|
||||
async_safe_format_log(ANDROID_LOG_WARN, "libc",
|
||||
"pthread_create failed: couldn't mprotect R+W %zu-byte thread mapping region: %s",
|
||||
- writable_size, strerror(errno));
|
||||
+ stack_size, strerror(errno));
|
||||
+ munmap(space, mmap_size);
|
||||
+ return {};
|
||||
+ }
|
||||
+
|
||||
+ char* const static_tls_space = space + stack_guard_size + stack_size + PTHREAD_GUARD_SIZE;
|
||||
+
|
||||
+ if (mprotect(static_tls_space, layout.size(), PROT_READ | PROT_WRITE) != 0) {
|
||||
+ async_safe_format_log(ANDROID_LOG_WARN, "libc",
|
||||
+ "pthread_create failed: couldn't mprotect R+W %zu-byte static TLS mapping region: %s",
|
||||
+ layout.size(), strerror(errno));
|
||||
munmap(space, mmap_size);
|
||||
return {};
|
||||
}
|
||||
@@ -237,9 +246,9 @@ ThreadMapping __allocate_thread_mapping(size_t stack_size, size_t stack_guard_si
|
||||
result.mmap_size = mmap_size;
|
||||
result.mmap_base_unguarded = space + stack_guard_size;
|
||||
result.mmap_size_unguarded = mmap_size - stack_guard_size - PTHREAD_GUARD_SIZE;
|
||||
- result.static_tls = space + mmap_size - PTHREAD_GUARD_SIZE - layout.size();
|
||||
+ result.static_tls = static_tls_space;
|
||||
result.stack_base = space;
|
||||
- result.stack_top = result.static_tls;
|
||||
+ result.stack_top = space + stack_guard_size + stack_size;
|
||||
return result;
|
||||
}
|
||||
|
@ -0,0 +1,58 @@
|
||||
From 648cd68ca3ffefe685ae6acdae17171c8acfa75b Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Micay <danielmicay@gmail.com>
|
||||
Date: Thu, 10 Oct 2019 22:52:49 -0400
|
||||
Subject: [PATCH] move pthread_internal_t behind guard page
|
||||
|
||||
Signed-off-by: anupritaisno1 <www.anuprita804@gmail.com>
|
||||
---
|
||||
libc/bionic/pthread_create.cpp | 19 +++++++++----------
|
||||
1 file changed, 9 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
|
||||
index eac53cac85..336e69b597 100644
|
||||
--- a/libc/bionic/pthread_create.cpp
|
||||
+++ b/libc/bionic/pthread_create.cpp
|
||||
@@ -199,10 +199,13 @@ int __init_thread(pthread_internal_t* thread) {
|
||||
ThreadMapping __allocate_thread_mapping(size_t stack_size, size_t stack_guard_size) {
|
||||
const StaticTlsLayout& layout = __libc_shared_globals()->static_tls_layout;
|
||||
|
||||
- // Allocate in order: stack guard, stack, guard page, static TLS, guard page.
|
||||
+ size_t thread_page_size = __BIONIC_ALIGN(sizeof(pthread_internal_t), PAGE_SIZE);
|
||||
+
|
||||
+ // Allocate in order: stack guard, stack, guard page, pthread_internal_t, static TLS, guard page.
|
||||
size_t mmap_size;
|
||||
if (__builtin_add_overflow(stack_size, stack_guard_size, &mmap_size)) return {};
|
||||
if (__builtin_add_overflow(mmap_size, PTHREAD_GUARD_SIZE, &mmap_size)) return {};
|
||||
+ if (__builtin_add_overflow(mmap_size, thread_page_size, &mmap_size)) return {};
|
||||
if (__builtin_add_overflow(mmap_size, layout.size(), &mmap_size)) return {};
|
||||
if (__builtin_add_overflow(mmap_size, PTHREAD_GUARD_SIZE, &mmap_size)) return {};
|
||||
|
||||
@@ -231,9 +234,10 @@ ThreadMapping __allocate_thread_mapping(size_t stack_size, size_t stack_guard_si
|
||||
return {};
|
||||
}
|
||||
|
||||
- char* const static_tls_space = space + stack_guard_size + stack_size + PTHREAD_GUARD_SIZE;
|
||||
+ char* const thread = space + stack_guard_size + stack_size + PTHREAD_GUARD_SIZE;
|
||||
+ char* const static_tls_space = thread + thread_page_size;
|
||||
|
||||
- if (mprotect(static_tls_space, layout.size(), PROT_READ | PROT_WRITE) != 0) {
|
||||
+ if (mprotect(thread, thread_page_size + layout.size(), PROT_READ | PROT_WRITE) != 0) {
|
||||
async_safe_format_log(ANDROID_LOG_WARN, "libc",
|
||||
"pthread_create failed: couldn't mprotect R+W %zu-byte static TLS mapping region: %s",
|
||||
layout.size(), strerror(errno));
|
||||
@@ -278,13 +282,8 @@ static int __allocate_thread(pthread_attr_t* attr, bionic_tcb** tcbp, void** chi
|
||||
stack_top = static_cast<char*>(attr->stack_base) + attr->stack_size;
|
||||
}
|
||||
|
||||
- // Carve out space from the stack for the thread's pthread_internal_t. This
|
||||
- // memory isn't counted in pthread_attr_getstacksize.
|
||||
-
|
||||
- // To safely access the pthread_internal_t and thread stack, we need to find a 16-byte aligned boundary.
|
||||
- stack_top = align_down(stack_top - sizeof(pthread_internal_t), 16);
|
||||
-
|
||||
- pthread_internal_t* thread = reinterpret_cast<pthread_internal_t*>(stack_top);
|
||||
+ pthread_internal_t* thread = reinterpret_cast<pthread_internal_t*>(
|
||||
+ mapping.static_tls - __BIONIC_ALIGN(sizeof(pthread_internal_t), PAGE_SIZE));
|
||||
if (!stack_clean) {
|
||||
// If thread was not allocated by mmap(), it may not have been cleared to zero.
|
||||
// So assume the worst and zero it.
|
@ -0,0 +1,98 @@
|
||||
From 0bc4dbcbd27c7f48713913101fb3c868c215c1a3 Mon Sep 17 00:00:00 2001
|
||||
From: Renlord <me@renlord.com>
|
||||
Date: Sun, 20 Oct 2019 08:17:11 +1100
|
||||
Subject: [PATCH] add secondary stack randomization
|
||||
|
||||
Signed-off-by: anupritaisno1 <www.anuprita804@gmail.com>
|
||||
---
|
||||
libc/bionic/pthread_create.cpp | 32 +++++++++++++++++++++++++++-----
|
||||
libc/include/sys/cdefs.h | 1 +
|
||||
2 files changed, 28 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
|
||||
index 336e69b597..3008e3cd27 100644
|
||||
--- a/libc/bionic/pthread_create.cpp
|
||||
+++ b/libc/bionic/pthread_create.cpp
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <pthread.h>
|
||||
|
||||
#include <errno.h>
|
||||
+#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/prctl.h>
|
||||
@@ -199,12 +200,24 @@ int __init_thread(pthread_internal_t* thread) {
|
||||
ThreadMapping __allocate_thread_mapping(size_t stack_size, size_t stack_guard_size) {
|
||||
const StaticTlsLayout& layout = __libc_shared_globals()->static_tls_layout;
|
||||
|
||||
+ // round up if the given stack size is not in multiples of PAGE_SIZE
|
||||
+ stack_size = __BIONIC_ALIGN(stack_size, PAGE_SIZE);
|
||||
size_t thread_page_size = __BIONIC_ALIGN(sizeof(pthread_internal_t), PAGE_SIZE);
|
||||
|
||||
- // Allocate in order: stack guard, stack, guard page, pthread_internal_t, static TLS, guard page.
|
||||
+ // Place a randomly sized gap above the stack, up to 10% as large as the stack
|
||||
+ // on 32-bit and 50% on 64-bit where virtual memory is plentiful.
|
||||
+#if __LP64__
|
||||
+ size_t max_gap_size = stack_size / 2;
|
||||
+#else
|
||||
+ size_t max_gap_size = stack_size / 10;
|
||||
+#endif
|
||||
+ // Make sure random stack top guard size are multiples of PAGE_SIZE.
|
||||
+ size_t gap_size = __BIONIC_ALIGN(arc4random_uniform(max_gap_size), PAGE_SIZE);
|
||||
+
|
||||
+ // Allocate in order: stack guard, stack, (random) guard page(s), pthread_internal_t, static TLS, guard page.
|
||||
size_t mmap_size;
|
||||
if (__builtin_add_overflow(stack_size, stack_guard_size, &mmap_size)) return {};
|
||||
- if (__builtin_add_overflow(mmap_size, PTHREAD_GUARD_SIZE, &mmap_size)) return {};
|
||||
+ if (__builtin_add_overflow(mmap_size, gap_size, &mmap_size)) return {};
|
||||
if (__builtin_add_overflow(mmap_size, thread_page_size, &mmap_size)) return {};
|
||||
if (__builtin_add_overflow(mmap_size, layout.size(), &mmap_size)) return {};
|
||||
if (__builtin_add_overflow(mmap_size, PTHREAD_GUARD_SIZE, &mmap_size)) return {};
|
||||
@@ -226,15 +239,21 @@ ThreadMapping __allocate_thread_mapping(size_t stack_size, size_t stack_guard_si
|
||||
return {};
|
||||
}
|
||||
|
||||
- if (mprotect(space + stack_guard_size, stack_size, PROT_READ | PROT_WRITE) != 0) {
|
||||
+ // Stack is at the lower end of mapped space, stack guard region is at the lower end of stack.
|
||||
+ // Make the usable portion of the stack between the guard region and random gap readable and
|
||||
+ // writable.
|
||||
+ if (mprotect((space + stack_guard_size), stack_size, PROT_READ | PROT_WRITE) == -1) {
|
||||
async_safe_format_log(ANDROID_LOG_WARN, "libc",
|
||||
"pthread_create failed: couldn't mprotect R+W %zu-byte thread mapping region: %s",
|
||||
stack_size, strerror(errno));
|
||||
munmap(space, mmap_size);
|
||||
return {};
|
||||
}
|
||||
+ prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, space, stack_guard_size, "stack guard");
|
||||
+ char* const stack_top_guard = space + stack_guard_size + stack_size;
|
||||
+ prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, stack_top_guard, gap_size, "stack top guard");
|
||||
|
||||
- char* const thread = space + stack_guard_size + stack_size + PTHREAD_GUARD_SIZE;
|
||||
+ char* const thread = space + stack_guard_size + stack_size + gap_size;
|
||||
char* const static_tls_space = thread + thread_page_size;
|
||||
|
||||
if (mprotect(thread, thread_page_size + layout.size(), PROT_READ | PROT_WRITE) != 0) {
|
||||
@@ -252,7 +271,10 @@ ThreadMapping __allocate_thread_mapping(size_t stack_size, size_t stack_guard_si
|
||||
result.mmap_size_unguarded = mmap_size - stack_guard_size - PTHREAD_GUARD_SIZE;
|
||||
result.static_tls = static_tls_space;
|
||||
result.stack_base = space;
|
||||
- result.stack_top = space + stack_guard_size + stack_size;
|
||||
+ // Choose a random base within the first page of the stack. Waste no more
|
||||
+ // than the space originally wasted by pthread_internal_t for compatibility.
|
||||
+ result.stack_top = space + stack_guard_size + stack_size - arc4random_uniform(sizeof(pthread_internal_t));
|
||||
+ result.stack_top = reinterpret_cast<char*>(__BIONIC_ALIGN_DOWN(reinterpret_cast<size_t>(result.stack_top), 16));
|
||||
return result;
|
||||
}
|
||||
|
||||
diff --git a/libc/include/sys/cdefs.h b/libc/include/sys/cdefs.h
|
||||
index b4556a74e5..5b0b4fb097 100644
|
||||
--- a/libc/include/sys/cdefs.h
|
||||
+++ b/libc/include/sys/cdefs.h
|
||||
@@ -61,6 +61,7 @@
|
||||
#endif
|
||||
|
||||
#define __BIONIC_ALIGN(__value, __alignment) (((__value) + (__alignment)-1) & ~((__alignment)-1))
|
||||
+#define __BIONIC_ALIGN_DOWN(value, alignment) ((value) & ~((alignment) - 1))
|
||||
|
||||
/*
|
||||
* The __CONCAT macro is used to concatenate parts of symbol names, e.g.
|
@ -0,0 +1,76 @@
|
||||
From 31456ac632903235e14500af8b5d7dff2d25d724 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Micay <danielmicay@gmail.com>
|
||||
Date: Sun, 8 Feb 2015 01:18:54 -0500
|
||||
Subject: [PATCH] replace brk and sbrk with stubs
|
||||
|
||||
Pretend that there is never room to grow the heap in order to prevent
|
||||
usage of these unsafe legacy functions. There are likely no users of
|
||||
these in practice as it is inherently broken to use them outside of
|
||||
malloc.
|
||||
|
||||
Signed-off-by: anupritaisno1 <www.anuprita804@gmail.com>
|
||||
---
|
||||
libc/bionic/brk.cpp | 48 ++++++++-------------------------------------
|
||||
1 file changed, 8 insertions(+), 40 deletions(-)
|
||||
|
||||
diff --git a/libc/bionic/brk.cpp b/libc/bionic/brk.cpp
|
||||
index 566c33a7a6..ef93055139 100644
|
||||
--- a/libc/bionic/brk.cpp
|
||||
+++ b/libc/bionic/brk.cpp
|
||||
@@ -29,48 +29,16 @@
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
-#if defined(__LP64__)
|
||||
-static void* __bionic_brk;
|
||||
-#else
|
||||
-void* __bionic_brk; // Accidentally exported by the NDK.
|
||||
+#if !defined(__LP64__)
|
||||
+void* __bionic_brk = reinterpret_cast<void*>(-1); // Accidentally exported by the NDK.
|
||||
#endif
|
||||
|
||||
-extern "C" void* __brk(void* __addr);
|
||||
-
|
||||
-int brk(void* end_data) {
|
||||
- __bionic_brk = __brk(end_data);
|
||||
- if (__bionic_brk < end_data) {
|
||||
- errno = ENOMEM;
|
||||
- return -1;
|
||||
- }
|
||||
- return 0;
|
||||
+int brk(void*) {
|
||||
+ errno = ENOMEM;
|
||||
+ return -1;
|
||||
}
|
||||
|
||||
-void* sbrk(ptrdiff_t increment) {
|
||||
- // Initialize __bionic_brk if necessary.
|
||||
- if (__bionic_brk == nullptr) {
|
||||
- __bionic_brk = __brk(nullptr);
|
||||
- }
|
||||
-
|
||||
- // Don't ask the kernel if we already know the answer.
|
||||
- if (increment == 0) {
|
||||
- return __bionic_brk;
|
||||
- }
|
||||
-
|
||||
- // Avoid overflow.
|
||||
- uintptr_t old_brk = reinterpret_cast<uintptr_t>(__bionic_brk);
|
||||
- if ((increment > 0 && static_cast<uintptr_t>(increment) > (UINTPTR_MAX - old_brk)) ||
|
||||
- (increment < 0 && static_cast<uintptr_t>(-increment) > old_brk)) {
|
||||
- errno = ENOMEM;
|
||||
- return reinterpret_cast<void*>(-1);
|
||||
- }
|
||||
-
|
||||
- void* desired_brk = reinterpret_cast<void*>(old_brk + increment);
|
||||
- __bionic_brk = __brk(desired_brk);
|
||||
- if (__bionic_brk < desired_brk) {
|
||||
- errno = ENOMEM;
|
||||
- return reinterpret_cast<void*>(-1);
|
||||
- }
|
||||
-
|
||||
- return reinterpret_cast<void*>(old_brk);
|
||||
+void* sbrk(ptrdiff_t) {
|
||||
+ errno = ENOMEM;
|
||||
+ return reinterpret_cast<void*>(-1);
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
From 58ebc243ea3085056e6aba765d879807fa1a46d6 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Micay <danielmicay@gmail.com>
|
||||
Date: Mon, 4 Mar 2019 04:26:04 -0500
|
||||
Subject: [PATCH] use blocking getrandom and avoid urandom fallback
|
||||
|
||||
Signed-off-by: anupritaisno1 <www.anuprita804@gmail.com>
|
||||
---
|
||||
libc/bionic/getentropy.cpp | 26 ++------------------------
|
||||
1 file changed, 2 insertions(+), 24 deletions(-)
|
||||
|
||||
diff --git a/libc/bionic/getentropy.cpp b/libc/bionic/getentropy.cpp
|
||||
index 9c93e713b7..9b40852675 100644
|
||||
--- a/libc/bionic/getentropy.cpp
|
||||
+++ b/libc/bionic/getentropy.cpp
|
||||
@@ -33,22 +33,6 @@
|
||||
|
||||
#include "private/ScopedFd.h"
|
||||
|
||||
-static int getentropy_urandom(void* buffer, size_t buffer_size, int saved_errno) {
|
||||
- ScopedFd fd(TEMP_FAILURE_RETRY(open("/dev/urandom", O_RDONLY | O_NOFOLLOW | O_CLOEXEC, 0)));
|
||||
- if (fd.get() == -1) return -1;
|
||||
-
|
||||
- size_t collected = 0;
|
||||
- while (collected < buffer_size) {
|
||||
- ssize_t count = TEMP_FAILURE_RETRY(read(fd.get(), static_cast<char*>(buffer) + collected,
|
||||
- buffer_size - collected));
|
||||
- if (count == -1) return -1;
|
||||
- collected += count;
|
||||
- }
|
||||
-
|
||||
- errno = saved_errno;
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
int getentropy(void* buffer, size_t buffer_size) {
|
||||
if (buffer_size > 256) {
|
||||
errno = EIO;
|
||||
@@ -60,15 +44,9 @@ int getentropy(void* buffer, size_t buffer_size) {
|
||||
size_t collected = 0;
|
||||
while (collected < buffer_size) {
|
||||
long count = TEMP_FAILURE_RETRY(getrandom(static_cast<char*>(buffer) + collected,
|
||||
- buffer_size - collected, GRND_NONBLOCK));
|
||||
+ buffer_size - collected, 0));
|
||||
if (count == -1) {
|
||||
- // EAGAIN: there isn't enough entropy right now.
|
||||
- // ENOSYS/EINVAL: getrandom(2) or GRND_NONBLOCK isn't supported.
|
||||
- // EFAULT: `buffer` is invalid.
|
||||
- // Try /dev/urandom regardless because it can't hurt,
|
||||
- // and we don't need to optimize the EFAULT case.
|
||||
- // See http://b/33059407 and http://b/67015565.
|
||||
- return getentropy_urandom(buffer, buffer_size, saved_errno);
|
||||
+ return -1;
|
||||
}
|
||||
collected += count;
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
From 5323b39f7ec1fce2d788f1c8a2c28cfd32d5ccc4 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Micay <danielmicay@gmail.com>
|
||||
Date: Mon, 19 Sep 2016 07:57:43 -0400
|
||||
Subject: [PATCH] fix undefined out-of-bounds accesses in sched.h
|
||||
|
||||
Signed-off-by: anupritaisno1 <www.anuprita804@gmail.com>
|
||||
---
|
||||
libc/include/sched.h | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/libc/include/sched.h b/libc/include/sched.h
|
||||
index 3260231cf0..00c2a4a452 100644
|
||||
--- a/libc/include/sched.h
|
||||
+++ b/libc/include/sched.h
|
||||
@@ -70,7 +70,10 @@ int setns(int __fd, int __ns_type) __INTRODUCED_IN(21);
|
||||
#define __CPU_MASK(x) ((__CPU_BITTYPE)1 << ((x) & (__CPU_BITS - 1)))
|
||||
|
||||
typedef struct {
|
||||
- __CPU_BITTYPE __bits[ CPU_SETSIZE / __CPU_BITS ];
|
||||
+ union {
|
||||
+ __CPU_BITTYPE __bits_minimum[ CPU_SETSIZE / __CPU_BITS ];
|
||||
+ __CPU_BITTYPE __bits[0];
|
||||
+ };
|
||||
} cpu_set_t;
|
||||
|
||||
int sched_setaffinity(pid_t __pid, size_t __set_size, const cpu_set_t* __set);
|
@ -0,0 +1,47 @@
|
||||
From 6a91d9dddb01964134e50cc73f6f158706da800a Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Micay <danielmicay@gmail.com>
|
||||
Date: Sat, 19 Nov 2016 09:56:14 -0500
|
||||
Subject: [PATCH] stop implicitly marking mappings as mergeable
|
||||
|
||||
Signed-off-by: anupritaisno1 <www.anuprita804@gmail.com>
|
||||
---
|
||||
libc/bionic/mmap.cpp | 19 +------------------
|
||||
1 file changed, 1 insertion(+), 18 deletions(-)
|
||||
|
||||
diff --git a/libc/bionic/mmap.cpp b/libc/bionic/mmap.cpp
|
||||
index 9aad0b3156..6bf0ecfd16 100644
|
||||
--- a/libc/bionic/mmap.cpp
|
||||
+++ b/libc/bionic/mmap.cpp
|
||||
@@ -39,8 +39,6 @@ extern "C" void* __mmap2(void*, size_t, int, int, int, size_t);
|
||||
|
||||
#define MMAP2_SHIFT 12 // 2**12 == 4096
|
||||
|
||||
-static bool kernel_has_MADV_MERGEABLE = true;
|
||||
-
|
||||
void* mmap64(void* addr, size_t size, int prot, int flags, int fd, off64_t offset) {
|
||||
if (offset < 0 || (offset & ((1UL << MMAP2_SHIFT)-1)) != 0) {
|
||||
errno = EINVAL;
|
||||
@@ -54,22 +52,7 @@ void* mmap64(void* addr, size_t size, int prot, int flags, int fd, off64_t offse
|
||||
return MAP_FAILED;
|
||||
}
|
||||
|
||||
- bool is_private_anonymous =
|
||||
- (flags & (MAP_PRIVATE | MAP_ANONYMOUS)) == (MAP_PRIVATE | MAP_ANONYMOUS);
|
||||
- bool is_stack_or_grows_down = (flags & (MAP_STACK | MAP_GROWSDOWN)) != 0;
|
||||
-
|
||||
- void* result = __mmap2(addr, size, prot, flags, fd, offset >> MMAP2_SHIFT);
|
||||
-
|
||||
- if (result != MAP_FAILED && kernel_has_MADV_MERGEABLE &&
|
||||
- is_private_anonymous && !is_stack_or_grows_down) {
|
||||
- ErrnoRestorer errno_restorer;
|
||||
- int rc = madvise(result, size, MADV_MERGEABLE);
|
||||
- if (rc == -1 && errno == EINVAL) {
|
||||
- kernel_has_MADV_MERGEABLE = false;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- return result;
|
||||
+ return __mmap2(addr, size, prot, flags, fd, offset >> MMAP2_SHIFT);
|
||||
}
|
||||
|
||||
void* mmap(void* addr, size_t size, int prot, int flags, int fd, off_t offset) {
|
@ -0,0 +1,40 @@
|
||||
From a042b5a0bada9933b7c488003e8f9d8d0d195525 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Micay <danielmicay@gmail.com>
|
||||
Date: Sat, 16 Jul 2016 23:55:16 -0400
|
||||
Subject: [PATCH] replace VLA formatting with dprintf-like function
|
||||
|
||||
Signed-off-by: anupritaisno1 <www.anuprita804@gmail.com>
|
||||
---
|
||||
libc/bionic/bionic_systrace.cpp | 10 +---------
|
||||
1 file changed, 1 insertion(+), 9 deletions(-)
|
||||
|
||||
diff --git a/libc/bionic/bionic_systrace.cpp b/libc/bionic/bionic_systrace.cpp
|
||||
index fd97712982..acd9b76814 100644
|
||||
--- a/libc/bionic/bionic_systrace.cpp
|
||||
+++ b/libc/bionic/bionic_systrace.cpp
|
||||
@@ -27,8 +27,6 @@
|
||||
#include <async_safe/log.h>
|
||||
#include <cutils/trace.h> // For ATRACE_TAG_BIONIC.
|
||||
|
||||
-#define WRITE_OFFSET 32
|
||||
-
|
||||
static Lock g_lock;
|
||||
static CachedProperty g_debug_atrace_tags_enableflags("debug.atrace.tags.enableflags");
|
||||
static uint64_t g_tags;
|
||||
@@ -65,15 +63,9 @@ void bionic_trace_begin(const char* message) {
|
||||
return;
|
||||
}
|
||||
|
||||
- // If bionic tracing has been enabled, then write the message to the
|
||||
- // kernel trace_marker.
|
||||
- int length = strlen(message);
|
||||
- char buf[length + WRITE_OFFSET];
|
||||
- size_t len = async_safe_format_buffer(buf, length + WRITE_OFFSET, "B|%d|%s", getpid(), message);
|
||||
-
|
||||
// Tracing may stop just after checking property and before writing the message.
|
||||
// So the write is acceptable to fail. See b/20666100.
|
||||
- TEMP_FAILURE_RETRY(write(trace_marker_fd, buf, len));
|
||||
+ async_safe_format_fd(trace_marker_fd, "B|%d|%s", getpid(), message);
|
||||
}
|
||||
|
||||
void bionic_trace_end() {
|
@ -0,0 +1,26 @@
|
||||
From 9ec639de1bec2f655bdfc0750e363a6f8de31c4a Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Micay <danielmicay@gmail.com>
|
||||
Date: Fri, 17 Jul 2015 21:32:05 -0400
|
||||
Subject: [PATCH] increase default pthread stack to 8MiB on 64-bit
|
||||
|
||||
Signed-off-by: anupritaisno1 <www.anuprita804@gmail.com>
|
||||
---
|
||||
libc/bionic/pthread_internal.h | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/libc/bionic/pthread_internal.h b/libc/bionic/pthread_internal.h
|
||||
index d58725baf1..a108f5cc0d 100644
|
||||
--- a/libc/bionic/pthread_internal.h
|
||||
+++ b/libc/bionic/pthread_internal.h
|
||||
@@ -234,7 +234,11 @@ __LIBC_HIDDEN__ void pthread_key_clean_all(void);
|
||||
// stack overflows, we subtracted the same amount we were using there
|
||||
// from the default thread stack size. This should keep memory usage
|
||||
// roughly constant.
|
||||
+#ifdef __LP64__
|
||||
+#define PTHREAD_STACK_SIZE_DEFAULT ((8 * 1024 * 1024) - SIGNAL_STACK_SIZE_WITHOUT_GUARD)
|
||||
+#else
|
||||
#define PTHREAD_STACK_SIZE_DEFAULT ((1 * 1024 * 1024) - SIGNAL_STACK_SIZE_WITHOUT_GUARD)
|
||||
+#endif
|
||||
|
||||
// Leave room for a guard page in the internally created signal stacks.
|
||||
#define SIGNAL_STACK_SIZE (SIGNAL_STACK_SIZE_WITHOUT_GUARD + PTHREAD_GUARD_SIZE)
|
@ -0,0 +1,59 @@
|
||||
From 49571a0a496539b9af763b8ef30c5b5db57c8be7 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Micay <danielmicay@gmail.com>
|
||||
Date: Sat, 1 Oct 2016 05:11:44 -0400
|
||||
Subject: [PATCH] make __stack_chk_guard read-only at runtime
|
||||
|
||||
Signed-off-by: anupritaisno1 <www.anuprita804@gmail.com>
|
||||
---
|
||||
libc/bionic/__libc_init_main_thread.cpp | 15 ++++++++++++---
|
||||
1 file changed, 12 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/libc/bionic/__libc_init_main_thread.cpp b/libc/bionic/__libc_init_main_thread.cpp
|
||||
index 56a8488888..7c8256cd67 100644
|
||||
--- a/libc/bionic/__libc_init_main_thread.cpp
|
||||
+++ b/libc/bionic/__libc_init_main_thread.cpp
|
||||
@@ -28,6 +28,9 @@
|
||||
|
||||
#include "libc_init_common.h"
|
||||
|
||||
+#include <limits.h>
|
||||
+#include <sys/mman.h>
|
||||
+
|
||||
#include <async_safe/log.h>
|
||||
|
||||
#include "private/KernelArgumentBlock.h"
|
||||
@@ -35,17 +38,20 @@
|
||||
#include "private/bionic_defs.h"
|
||||
#include "private/bionic_elf_tls.h"
|
||||
#include "private/bionic_globals.h"
|
||||
-#include "private/bionic_ssp.h"
|
||||
#include "pthread_internal.h"
|
||||
|
||||
extern "C" pid_t __getpid();
|
||||
extern "C" int __set_tid_address(int* tid_address);
|
||||
|
||||
// Declared in "private/bionic_ssp.h".
|
||||
-uintptr_t __stack_chk_guard = 0;
|
||||
+__attribute__((aligned(PAGE_SIZE)))
|
||||
+uintptr_t __stack_chk_guard[PAGE_SIZE / sizeof(uintptr_t)] = {0};
|
||||
|
||||
static pthread_internal_t main_thread;
|
||||
|
||||
+void __libc_init_global_stack_chk_guard(KernelArgumentBlock& args) {
|
||||
+}
|
||||
+
|
||||
// Setup for the main thread. For dynamic executables, this is called by the
|
||||
// linker _before_ libc is mapped in memory. This means that all writes to
|
||||
// globals from this function will apply to linker-private copies and will not
|
||||
@@ -122,7 +128,10 @@ extern "C" void __libc_init_main_thread_late() {
|
||||
// The TLS stack guard is set from the global, so ensure that we've initialized the global
|
||||
// before we initialize the TLS. Dynamic executables will initialize their copy of the global
|
||||
// stack protector from the one in the main thread's TLS.
|
||||
- __libc_safe_arc4random_buf(&__stack_chk_guard, sizeof(__stack_chk_guard));
|
||||
+ __libc_safe_arc4random_buf(&__stack_chk_guard[0], sizeof(__stack_chk_guard[0]));
|
||||
+ if (mprotect(__stack_chk_guard, sizeof(__stack_chk_guard), PROT_READ) == -1) {
|
||||
+ async_safe_fatal("mprotect __stack_chk_guard: %s", strerror(errno));
|
||||
+ }
|
||||
__init_tcb_stack_guard(__get_bionic_tcb());
|
||||
|
||||
__init_thread(&main_thread);
|
@ -0,0 +1,42 @@
|
||||
From 149cc5ccb870640b2536b6bd5dfa1292f9dd6178 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Micay <danielmicay@gmail.com>
|
||||
Date: Sun, 12 Mar 2017 17:49:13 -0400
|
||||
Subject: [PATCH] on 64-bit, zero the leading stack canary byte
|
||||
|
||||
This reduces entropy of the canary from 64-bit to 56-bit in exchange for
|
||||
mitigating non-terminated C string overflows.
|
||||
|
||||
Signed-off-by: anupritaisno1 <www.anuprita804@gmail.com>
|
||||
---
|
||||
libc/bionic/__libc_init_main_thread.cpp | 11 +++++++++--
|
||||
1 file changed, 9 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/libc/bionic/__libc_init_main_thread.cpp b/libc/bionic/__libc_init_main_thread.cpp
|
||||
index 7c8256cd67..554477674a 100644
|
||||
--- a/libc/bionic/__libc_init_main_thread.cpp
|
||||
+++ b/libc/bionic/__libc_init_main_thread.cpp
|
||||
@@ -49,8 +49,11 @@ uintptr_t __stack_chk_guard[PAGE_SIZE / sizeof(uintptr_t)] = {0};
|
||||
|
||||
static pthread_internal_t main_thread;
|
||||
|
||||
-void __libc_init_global_stack_chk_guard(KernelArgumentBlock& args) {
|
||||
-}
|
||||
+#if __LP64__
|
||||
+static const uintptr_t canary_mask = __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ ?
|
||||
+ 0xffffffffffffff00UL :
|
||||
+ 0x00ffffffffffffffUL;
|
||||
+#endif
|
||||
|
||||
// Setup for the main thread. For dynamic executables, this is called by the
|
||||
// linker _before_ libc is mapped in memory. This means that all writes to
|
||||
@@ -129,6 +132,10 @@ extern "C" void __libc_init_main_thread_late() {
|
||||
// before we initialize the TLS. Dynamic executables will initialize their copy of the global
|
||||
// stack protector from the one in the main thread's TLS.
|
||||
__libc_safe_arc4random_buf(&__stack_chk_guard[0], sizeof(__stack_chk_guard[0]));
|
||||
+#if __LP64__
|
||||
+ // Sacrifice 8 bits of entropy on 64-bit to mitigate non-terminated C string overflows
|
||||
+ __stack_chk_guard[0] &= canary_mask;
|
||||
+#endif
|
||||
if (mprotect(__stack_chk_guard, sizeof(__stack_chk_guard), PROT_READ) == -1) {
|
||||
async_safe_fatal("mprotect __stack_chk_guard: %s", strerror(errno));
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
From b3a0c2c5db28852b6d485542c8a4f1649a256892 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Micay <danielmicay@gmail.com>
|
||||
Date: Fri, 6 Feb 2015 11:41:57 -0500
|
||||
Subject: [PATCH] zero sensitive information with explicit_bzero
|
||||
|
||||
---
|
||||
init/security.cpp | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/init/security.cpp b/init/security.cpp
|
||||
index 6cbe642c081..82fc8ca6413 100644
|
||||
--- a/init/security.cpp
|
||||
+++ b/init/security.cpp
|
||||
@@ -78,6 +78,7 @@ Result<void> MixHwrngIntoLinuxRngAction(const BuiltinArguments&) {
|
||||
}
|
||||
|
||||
chunk_size = TEMP_FAILURE_RETRY(write(urandom_fd, buf, chunk_size));
|
||||
+ explicit_bzero(buf, chunk_size);
|
||||
if (chunk_size == -1) {
|
||||
return ErrnoError() << "Failed to write to /dev/urandom";
|
||||
}
|
@ -61,6 +61,23 @@ fi;
|
||||
|
||||
if enterAndClear "bionic"; then
|
||||
if [ "$DOS_GRAPHENE_MALLOC" = true ]; then applyPatch "$DOS_PATCHES/android_bionic/0001-HM-Use_HM.patch"; fi; #(GrapheneOS)
|
||||
if [ "$DOS_GRAPHENE_BIONIC" = true ]; then
|
||||
applyPatch "$DOS_PATCHES/android_bionic/0002-Graphene_Bionic_Hardening-1.patch"; #Add a real explicit_bzero implementation #(GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_bionic/0002-Graphene_Bionic_Hardening-2.patch"; #Replace brk and sbrk with stubs #(GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_bionic/0002-Graphene_Bionic_Hardening-3.patch"; #Use blocking getrandom and avoid urandom fallback #(GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_bionic/0002-Graphene_Bionic_Hardening-4.patch"; #Fix undefined out-of-bounds accesses in sched.h #(GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_bionic/0002-Graphene_Bionic_Hardening-5.patch"; #Stop implicitly marking mappings as mergeable #(GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_bionic/0002-Graphene_Bionic_Hardening-6.patch"; #Replace VLA formatting buffer with dprintf #(GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_bionic/0002-Graphene_Bionic_Hardening-7.patch"; #Increase default pthread stack to 8MiB on 64-bit #(GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_bionic/0002-Graphene_Bionic_Hardening-8.patch"; #Make __stack_chk_guard read-only at runtime #(GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_bionic/0002-Graphene_Bionic_Hardening-9.patch"; #On 64-bit, zero the leading stack canary byte #(GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_bionic/0002-Graphene_Bionic_Hardening-10.patch"; #Switch pthread_atfork handler allocation to mmap #(GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_bionic/0002-Graphene_Bionic_Hardening-11.patch"; #Add memory protection for pthread_atfork handlers #(GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_bionic/0002-Graphene_Bionic_Hardening-12.patch"; #Add memory protection for at_quick_exit #(GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_bionic/0002-Graphene_Bionic_Hardening-13.patch"; #Add XOR mangling mitigation for thread-local dtors #(GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_bionic/0002-Graphene_Bionic_Hardening-14.patch"; #Use a better pthread_attr junk filling pattern #(GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_bionic/0002-Graphene_Bionic_Hardening-15.patch"; #Move pthread_internal_t out of the stack mapping #(GrapheneOS)
|
||||
fi;
|
||||
fi;
|
||||
|
||||
if enterAndClear "bootable/recovery"; then
|
||||
@ -302,6 +319,7 @@ if [ "$DOS_HOSTS_BLOCKING" = true ]; then cat "$DOS_HOSTS_FILE" >> rootdir/etc/h
|
||||
git revert --no-edit b3609d82999d23634c5e6db706a3ecbc5348309a; #Always update recovery
|
||||
applyPatch "$DOS_PATCHES/android_system_core/0001-Harden.patch"; #Harden mounts with nodev/noexec/nosuid + misc sysctl changes (GrapheneOS)
|
||||
if [ "$DOS_GRAPHENE_MALLOC" = true ]; then applyPatch "$DOS_PATCHES/android_system_core/0002-HM-Increase_vm_mmc.patch"; fi; #(GrapheneOS)
|
||||
if [ "$DOS_GRAPHENE_BIONIC" = true ]; then applyPatch "$DOS_PATCHES/android_system_core/0003-Zero_Sensitive_Info.patch"; fi; #Zero sensitive information with explicit_bzero (GrapheneOS)
|
||||
fi;
|
||||
|
||||
if enterAndClear "system/extras"; then
|
||||
|
@ -66,6 +66,25 @@ fi;
|
||||
if enterAndClear "bionic"; then
|
||||
if [ "$DOS_GRAPHENE_MALLOC" = true ]; then applyPatch "$DOS_PATCHES/android_bionic/0001-HM-Use_HM.patch"; fi; #(GrapheneOS)
|
||||
if [ "$DOS_GRAPHENE_MALLOC" = true ]; then applyPatch "$DOS_PATCHES/android_bionic/0002-Symbol_Ordering.patch"; fi; #(GrapheneOS)
|
||||
if [ "$DOS_GRAPHENE_BIONIC" = true ]; then
|
||||
applyPatch "$DOS_PATCHES/android_bionic/0003-Graphene_Bionic_Hardening-1.patch"; #Add a real explicit_bzero implementation (GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_bionic/0003-Graphene_Bionic_Hardening-2.patch"; #Replace brk and sbrk with stubs (GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_bionic/0003-Graphene_Bionic_Hardening-3.patch"; #Use blocking getrandom and avoid urandom fallback (GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_bionic/0003-Graphene_Bionic_Hardening-4.patch"; #Fix undefined out-of-bounds accesses in sched.h (GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_bionic/0003-Graphene_Bionic_Hardening-5.patch"; #Stop implicitly marking mappings as mergeable (GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_bionic/0003-Graphene_Bionic_Hardening-6.patch"; #Replace VLA formatting buffer with dprintf (GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_bionic/0003-Graphene_Bionic_Hardening-7.patch"; #Increase default pthread stack to 8MiB on 64-bit (GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_bionic/0003-Graphene_Bionic_Hardening-8.patch"; #Make __stack_chk_guard read-only at runtime (GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_bionic/0003-Graphene_Bionic_Hardening-9.patch"; #On 64-bit, zero the leading stack canary byte (GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_bionic/0003-Graphene_Bionic_Hardening-10.patch"; #Switch pthread_atfork handler allocation to mmap (GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_bionic/0003-Graphene_Bionic_Hardening-11.patch"; #Add memory protection for pthread_atfork handlers (GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_bionic/0003-Graphene_Bionic_Hardening-12.patch"; #Add memory protection for at_quick_exit (GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_bionic/0003-Graphene_Bionic_Hardening-13.patch"; #Add XOR mangling mitigation for thread-local dtors (GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_bionic/0003-Graphene_Bionic_Hardening-14.patch"; #Use a better pthread_attr junk filling pattern (GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_bionic/0003-Graphene_Bionic_Hardening-15.patch"; #Add guard page(s) between static_tls and stack (GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_bionic/0003-Graphene_Bionic_Hardening-16.patch"; #Move pthread_internal_t behind guard page (GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_bionic/0003-Graphene_Bionic_Hardening-17.patch"; #Add secondary stack randomization (GrapheneOS)
|
||||
fi;
|
||||
fi;
|
||||
|
||||
if enterAndClear "build/make"; then
|
||||
@ -308,6 +327,7 @@ git revert --no-edit 3032c7aa5ce90c0ae9c08fe271052c6e0304a1e7 01266f589e6deaef30
|
||||
git revert --no-edit bd4142eab8b3cead0c25a2e660b4b048d1315d3c; #Always update recovery
|
||||
applyPatch "$DOS_PATCHES/android_system_core/0001-Harden.patch"; #Harden mounts with nodev/noexec/nosuid + misc sysctl changes (GrapheneOS)
|
||||
if [ "$DOS_GRAPHENE_MALLOC" = true ]; then applyPatch "$DOS_PATCHES/android_system_core/0002-HM-Increase_vm_mmc.patch"; fi; #(GrapheneOS)
|
||||
if [ "$DOS_GRAPHENE_BIONIC" = true ]; then applyPatch "$DOS_PATCHES/android_system_core/0003-Zero_Sensitive_Info.patch"; fi; #Zero sensitive information with explicit_bzero (GrapheneOS)
|
||||
fi;
|
||||
|
||||
if enterAndClear "system/extras"; then
|
||||
|
@ -59,9 +59,27 @@ if enterAndClear "art"; then
|
||||
if [ "$DOS_GRAPHENE_CONSTIFY" = true ]; then applyPatch "$DOS_PATCHES/android_art/0001-constify_JNINativeMethod.patch"; fi; #Constify JNINativeMethod tables (GrapheneOS)
|
||||
fi;
|
||||
|
||||
#if enterAndClear "bionic"; then
|
||||
if enterAndClear "bionic"; then
|
||||
#if [ "$DOS_GRAPHENE_MALLOC" = true ]; then applyPatch "$DOS_PATCHES/android_bionic/0001-HM-Use_HM.patch"; fi; #(GrapheneOS) #XXX: needs to be verified
|
||||
#fi;
|
||||
if [ "$DOS_GRAPHENE_BIONIC" = true ]; then
|
||||
applyPatch "$DOS_PATCHES/android_bionic/0002-Graphene_Bionic_Hardening-1.patch"; #Add a real explicit_bzero implementation (GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_bionic/0002-Graphene_Bionic_Hardening-2.patch"; #Replace brk and sbrk with stubs (GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_bionic/0002-Graphene_Bionic_Hardening-3.patch"; #Use blocking getrandom and avoid urandom fallback (GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_bionic/0002-Graphene_Bionic_Hardening-4.patch"; #Fix undefined out-of-bounds accesses in sched.h (GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_bionic/0002-Graphene_Bionic_Hardening-5.patch"; #Stop implicitly marking mappings as mergeable (GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_bionic/0002-Graphene_Bionic_Hardening-6.patch"; #Replace VLA formatting with dprintf-like function (GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_bionic/0002-Graphene_Bionic_Hardening-7.patch"; #Increase default pthread stack to 8MiB on 64-bit (GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_bionic/0002-Graphene_Bionic_Hardening-8.patch"; #Make __stack_chk_guard read-only at runtime (GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_bionic/0002-Graphene_Bionic_Hardening-9.patch"; #On 64-bit, zero the leading stack canary byte (GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_bionic/0002-Graphene_Bionic_Hardening-10.patch"; #Switch pthread_atfork handler allocation to mmap (GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_bionic/0002-Graphene_Bionic_Hardening-11.patch"; #Add memory protection for pthread_atfork handlers (GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_bionic/0002-Graphene_Bionic_Hardening-12.patch"; #Add XOR mangling mitigation for thread-local dtors (GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_bionic/0002-Graphene_Bionic_Hardening-13.patch"; #Use a better pthread_attr junk filling pattern (GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_bionic/0002-Graphene_Bionic_Hardening-14.patch"; #Add guard page(s) between static_tls and stack (GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_bionic/0002-Graphene_Bionic_Hardening-15.patch"; #Move pthread_internal_t behind guard page (GrapheneOS)
|
||||
applyPatch "$DOS_PATCHES/android_bionic/0002-Graphene_Bionic_Hardening-16.patch"; #Add secondary stack randomization (GrapheneOS)
|
||||
fi;
|
||||
fi;
|
||||
|
||||
if enterAndClear "bootable/recovery"; then
|
||||
applyPatch "$DOS_PATCHES/android_bootable_recovery/0001-No_SerialNum_Restrictions.patch"; #Abort package installs if they are specific to a serial number (GrapheneOS)
|
||||
@ -323,6 +341,7 @@ git revert --no-edit e8dcabaf6b55ec55eb73c4585501ddbafc04fc9b 79f606ece6b74652d3
|
||||
applyPatch "$DOS_PATCHES/android_system_core/0001-Harden.patch"; #Harden mounts with nodev/noexec/nosuid + misc sysctl changes (GrapheneOS)
|
||||
if [ "$DOS_GRAPHENE_PTRACE_SCOPE" = true ]; then applyPatch "$DOS_PATCHES/android_system_core/0002-ptrace_scope.patch"; fi; #Add a property for controlling ptrace_scope (GrapheneOS)
|
||||
#if [ "$DOS_GRAPHENE_MALLOC" = true ]; then applyPatch "$DOS_PATCHES/android_system_core/0003-HM-Increase_vm_mmc.patch"; fi; #(GrapheneOS)
|
||||
if [ "$DOS_GRAPHENE_BIONIC" = true ]; then applyPatch "$DOS_PATCHES/android_system_core/0004-Zero_Sensitive_Info.patch"; fi; #Zero sensitive information with explicit_bzero (GrapheneOS)
|
||||
fi;
|
||||
|
||||
if enterAndClear "system/extras"; then
|
||||
|
@ -57,6 +57,7 @@ export DOS_DEBLOBBER_REPLACE_TIME=false; #Set true to replace Qualcomm Time Serv
|
||||
|
||||
#Features
|
||||
export DOS_GPS_GLONASS_FORCED=false; #Enables GLONASS on all devices
|
||||
export DOS_GRAPHENE_BIONIC=true; #Enables the bionic hardening patchset on 16.0+17.1+18.1
|
||||
export DOS_GRAPHENE_CONSTIFY=true; #Enables 'Constify JNINativeMethod tables' patchset on 16.0+17.1+18.1
|
||||
export DOS_GRAPHENE_MALLOC=true; #Enables use of GrapheneOS' hardened memory allocator on 64-bit platforms on 16.0+17.1+18.1
|
||||
export DOS_GRAPHENE_EXEC=false; #Enables use of GrapheneOS' exec spawning feature on 16.0+17.1+18.1 XXX: broken (just on 17.1?)
|
||||
|
Loading…
x
Reference in New Issue
Block a user