Add bionic hardening patchsets from GrapheneOS

11 b3a0c2c5db
11 5412c37195 #explicit zero
11 31456ac632 #brk
11 58ebc243ea #random
11 5323b39f7e #undefined
11 6a91d9dddb #merge
11 a042b5a0ba #vla formatting
11 9ec639de1b #pthread
11 49571a0a49 #read only
11 149cc5ccb8 #zero
11 2e613ccbe7 #fork mmap
11 e239c7dff8 #memprot pthread
11 0b03d92b7f #xor
11 de08419b82 #junk
11 897d4903e2 #guard
11 648cd68ca3 #ptrhread guard
11 0bc4dbcbd2 #stack rand
10 aa9cc05d07
10 a8cdbb6352 #explicit zero
10 b28302c668 #brk
10 9f8be7d07c #random
10 cb91a7ee3a #undefined
10 08279e2fdd #merge
10 6a18bd565d #vla formatting
10 2f392c2d08 #pthread
10 8bbce1bc50 #read only
10 725f61db82 #zero
10 4cd257135f #fork mmap
10 9220cf622b #memprot pthread
10 8ef71d1ffd #memprot exit
10 0eaef1abbd #xor
10 64f1cc2148 #junk
10 5c42a527cf #guard
10 5cc8c34e60 #pthread guard
10 7f61cc8a1c #stack rand
9  abdf523d26
9  e4b9b31e6f #explicit zero
9  a3a22a63d2 #brk
9  7444dbc3cf #random
9  dcd3b72ac9 #undefined
9  543e1df342 #merge
9  611e5691f7 #vla formatting
9  8de97ce864 #pthread
9  a475717042 #read only
9  7f0947cc0e #zero
9  e9751d3370 #fork mmap
9  83cd86d0d5 #memprot pthread
9  1ebb165455 #memprot exit
9  488ba483cf #xor
9  f9351d884b #junk
9  85e5bca0a5 #move

Signed-off-by: Tad <tad@spotco.us>
This commit is contained in:
Tad 2022-03-15 16:34:57 -04:00
parent 1878cd19ab
commit 181519cf38
55 changed files with 3121 additions and 2 deletions

View File

@ -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)

View File

@ -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);

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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;
};

View File

@ -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;
}

View File

@ -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) {

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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) {

View File

@ -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() {

View File

@ -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)

View File

@ -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

View File

@ -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));
}

View File

@ -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";
}

View File

@ -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)

View File

@ -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);

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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.

View File

@ -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.

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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) {

View File

@ -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() {

View File

@ -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)

View File

@ -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);

View File

@ -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));
}

View File

@ -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";
}

View File

@ -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)

View File

@ -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);

View File

@ -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);
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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.

View File

@ -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.

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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) {

View File

@ -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() {

View File

@ -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)

View File

@ -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);

View File

@ -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));
}

View File

@ -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";
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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?)