Merge "Fix fcntrl#tee test to use the same expected/actual buffer size."
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 7b533a4..f7c8fd7 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -1,2 +1,5 @@
[Hook Scripts]
notice = tools/update_notice.sh
+seccomp = tools/update_seccomp.sh
+syscalls = tools/update_syscalls.sh
+version_scripts = tools/update_version_scripts.sh
diff --git a/benchmarks/Android.bp b/benchmarks/Android.bp
index e8745a2..00c9560 100644
--- a/benchmarks/Android.bp
+++ b/benchmarks/Android.bp
@@ -73,7 +73,6 @@
cc_benchmark_host {
name: "bionic-benchmarks-glibc",
defaults: ["bionic-benchmarks-defaults"],
- host_ldlibs: ["-lrt"],
target: {
darwin: {
// Only supported on linux systems.
diff --git a/libc/Android.bp b/libc/Android.bp
index d126f2f..cd01efd 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -299,13 +299,14 @@
cc_library_static {
defaults: ["libc_defaults"],
srcs: [
+ "upstream-freebsd/lib/libc/gen/glob.c",
"upstream-freebsd/lib/libc/stdlib/realpath.c",
],
cflags: [
"-Wno-sign-compare",
"-include freebsd-compat.h",
- "-Wframe-larger-than=15000",
+ "-Wframe-larger-than=66000",
],
local_include_dirs: [
@@ -1825,7 +1826,6 @@
"bionic/dl_iterate_phdr_static.cpp",
"bionic/icu_static.cpp",
"bionic/malloc_common.cpp",
- "bionic/libc_init_static.cpp",
],
cflags: ["-DLIBC_STATIC"],
whole_static_libs: ["libc_init_static"],
diff --git a/libc/NOTICE b/libc/NOTICE
index feea29d..32980b7 100644
--- a/libc/NOTICE
+++ b/libc/NOTICE
@@ -1914,6 +1914,75 @@
The Regents of the University of California. All rights reserved.
This code is derived from software contributed to Berkeley by
+Guido van Rossum.
+
+Copyright (c) 2011 The FreeBSD Foundation
+All rights reserved.
+Portions of this software were developed by David Chisnall
+under sponsorship from the FreeBSD Foundation.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of the University nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1989, 1993
+ The Regents of the University of California. All rights reserved.
+
+This code is derived from software contributed to Berkeley by
+Guido van Rossum.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. Neither the name of the University nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1989, 1993
+ The Regents of the University of California. All rights reserved.
+
+This code is derived from software contributed to Berkeley by
Roger L. Snyder.
Redistribution and use in source and binary forms, with or without
diff --git a/libc/SECCOMP_WHITELIST.TXT b/libc/SECCOMP_WHITELIST.TXT
index 2c4767b..36a579b 100644
--- a/libc/SECCOMP_WHITELIST.TXT
+++ b/libc/SECCOMP_WHITELIST.TXT
@@ -35,7 +35,6 @@
int rt_sigreturn:rt_sigreturn(unsigned long __unused) all
int rt_tgsigqueueinfo:int rt_tgsigqueueinfo(pid_t tgid, pid_t tid, int sig, siginfo_t *uinfo) all
int restart_syscall:int restart_syscall() all
-int getrandom:int getrandom(void *buf, size_t buflen, unsigned int flags) all
int fstatat64|fstatat:newfstatat(int, const char*, struct stat*, int) mips64
int fstat64|fstat:fstat(int, struct stat*) mips64
int _flush_cache:cacheflush(char* addr, const int nbytes, const int op) mips64
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index a1d1af0..f8be0b0 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -353,3 +353,6 @@
# vdso stuff.
int __clock_gettime:clock_gettime(clockid_t, timespec*) all
int __gettimeofday:gettimeofday(timeval*, timezone*) all
+
+# <sys/random.h>
+ssize_t getrandom(void*, size_t, unsigned) all
diff --git a/libc/arch-arm/syscalls/getrandom.S b/libc/arch-arm/syscalls/getrandom.S
new file mode 100644
index 0000000..3f28af6
--- /dev/null
+++ b/libc/arch-arm/syscalls/getrandom.S
@@ -0,0 +1,16 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+ENTRY(getrandom)
+ mov ip, r7
+ .cfi_register r7, ip
+ ldr r7, =__NR_getrandom
+ swi #0
+ mov r7, ip
+ .cfi_restore r7
+ cmn r0, #(MAX_ERRNO + 1)
+ bxls lr
+ neg r0, r0
+ b __set_errno_internal
+END(getrandom)
diff --git a/libc/arch-arm64/syscalls/getrandom.S b/libc/arch-arm64/syscalls/getrandom.S
new file mode 100644
index 0000000..c8fe41f
--- /dev/null
+++ b/libc/arch-arm64/syscalls/getrandom.S
@@ -0,0 +1,14 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+ENTRY(getrandom)
+ mov x8, __NR_getrandom
+ svc #0
+
+ cmn x0, #(MAX_ERRNO + 1)
+ cneg x0, x0, hi
+ b.hi __set_errno_internal
+
+ ret
+END(getrandom)
diff --git a/libc/arch-mips/syscalls/getrandom.S b/libc/arch-mips/syscalls/getrandom.S
new file mode 100644
index 0000000..7a2f3b9
--- /dev/null
+++ b/libc/arch-mips/syscalls/getrandom.S
@@ -0,0 +1,19 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+ENTRY(getrandom)
+ .set noreorder
+ .cpload t9
+ li v0, __NR_getrandom
+ syscall
+ bnez a3, 1f
+ move a0, v0
+ j ra
+ nop
+1:
+ la t9,__set_errno_internal
+ j t9
+ nop
+ .set reorder
+END(getrandom)
diff --git a/libc/arch-mips64/syscalls/getrandom.S b/libc/arch-mips64/syscalls/getrandom.S
new file mode 100644
index 0000000..3c5b467
--- /dev/null
+++ b/libc/arch-mips64/syscalls/getrandom.S
@@ -0,0 +1,25 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+ENTRY(getrandom)
+ .set push
+ .set noreorder
+ li v0, __NR_getrandom
+ syscall
+ bnez a3, 1f
+ move a0, v0
+ j ra
+ nop
+1:
+ move t0, ra
+ bal 2f
+ nop
+2:
+ .cpsetup ra, t1, 2b
+ LA t9,__set_errno_internal
+ .cpreturn
+ j t9
+ move ra, t0
+ .set pop
+END(getrandom)
diff --git a/libc/arch-x86/syscalls/getrandom.S b/libc/arch-x86/syscalls/getrandom.S
new file mode 100644
index 0000000..2e8ebc9
--- /dev/null
+++ b/libc/arch-x86/syscalls/getrandom.S
@@ -0,0 +1,39 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+ENTRY(getrandom)
+ pushl %ebx
+ .cfi_def_cfa_offset 8
+ .cfi_rel_offset ebx, 0
+ pushl %ecx
+ .cfi_adjust_cfa_offset 4
+ .cfi_rel_offset ecx, 0
+ pushl %edx
+ .cfi_adjust_cfa_offset 4
+ .cfi_rel_offset edx, 0
+
+ call __kernel_syscall
+ pushl %eax
+ .cfi_adjust_cfa_offset 4
+ .cfi_rel_offset eax, 0
+
+ mov 20(%esp), %ebx
+ mov 24(%esp), %ecx
+ mov 28(%esp), %edx
+ movl $__NR_getrandom, %eax
+ call *(%esp)
+ addl $4, %esp
+
+ cmpl $-MAX_ERRNO, %eax
+ jb 1f
+ negl %eax
+ pushl %eax
+ call __set_errno_internal
+ addl $4, %esp
+1:
+ popl %edx
+ popl %ecx
+ popl %ebx
+ ret
+END(getrandom)
diff --git a/libc/arch-x86_64/syscalls/getrandom.S b/libc/arch-x86_64/syscalls/getrandom.S
new file mode 100644
index 0000000..c5e44a9
--- /dev/null
+++ b/libc/arch-x86_64/syscalls/getrandom.S
@@ -0,0 +1,15 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+ENTRY(getrandom)
+ movl $__NR_getrandom, %eax
+ syscall
+ cmpq $-MAX_ERRNO, %rax
+ jb 1f
+ negl %eax
+ movl %eax, %edi
+ call __set_errno_internal
+1:
+ ret
+END(getrandom)
diff --git a/libc/bionic/clone.cpp b/libc/bionic/clone.cpp
index d7ce37f..66ec503 100644
--- a/libc/bionic/clone.cpp
+++ b/libc/bionic/clone.cpp
@@ -34,11 +34,15 @@
#include "pthread_internal.h"
+#include "private/bionic_macros.h"
+
extern "C" pid_t __bionic_clone(uint32_t flags, void* child_stack, int* parent_tid, void* tls, int* child_tid, int (*fn)(void*), void* arg);
extern "C" __noreturn void __exit(int status);
// Called from the __bionic_clone assembler to call the thread function then exit.
extern "C" __LIBC_HIDDEN__ void __start_thread(int (*fn)(void*), void* arg) {
+ BIONIC_STOP_UNWIND;
+
pthread_internal_t* self = __get_thread();
if (self && self->tid == -1) {
self->tid = syscall(__NR_gettid);
diff --git a/libc/bionic/grp_pwd.cpp b/libc/bionic/grp_pwd.cpp
index 2823662..50fcbce 100644
--- a/libc/bionic/grp_pwd.cpp
+++ b/libc/bionic/grp_pwd.cpp
@@ -580,7 +580,7 @@
ErrnoRestorer errno_restorer;
*result = NULL;
char* p = reinterpret_cast<char*>(
- BIONIC_ALIGN(reinterpret_cast<uintptr_t>(buf), sizeof(uintptr_t)));
+ __BIONIC_ALIGN(reinterpret_cast<uintptr_t>(buf), sizeof(uintptr_t)));
if (p + sizeof(group_state_t) > buf + buflen) {
return ERANGE;
}
diff --git a/libc/bionic/jemalloc_wrapper.cpp b/libc/bionic/jemalloc_wrapper.cpp
index 266b966..19081a4 100644
--- a/libc/bionic/jemalloc_wrapper.cpp
+++ b/libc/bionic/jemalloc_wrapper.cpp
@@ -23,7 +23,7 @@
void* je_pvalloc(size_t bytes) {
size_t pagesize = getpagesize();
- size_t size = BIONIC_ALIGN(bytes, pagesize);
+ size_t size = __BIONIC_ALIGN(bytes, pagesize);
if (size < bytes) {
return NULL;
}
diff --git a/libc/bionic/libc_init_dynamic.cpp b/libc/bionic/libc_init_dynamic.cpp
index 7c73950..349d488 100644
--- a/libc/bionic/libc_init_dynamic.cpp
+++ b/libc/bionic/libc_init_dynamic.cpp
@@ -52,6 +52,7 @@
#include "libc_init_common.h"
#include "private/bionic_globals.h"
+#include "private/bionic_macros.h"
#include "private/bionic_ssp.h"
#include "private/bionic_tls.h"
#include "private/KernelArgumentBlock.h"
@@ -108,6 +109,7 @@
void (*onexit)(void) __unused,
int (*slingshot)(int, char**, char**),
structors_array_t const * const structors) {
+ BIONIC_STOP_UNWIND;
KernelArgumentBlock args(raw_args);
diff --git a/libc/bionic/libc_init_static.cpp b/libc/bionic/libc_init_static.cpp
index 5e06d39..93a63b5 100644
--- a/libc/bionic/libc_init_static.cpp
+++ b/libc/bionic/libc_init_static.cpp
@@ -40,6 +40,7 @@
#include "pthread_internal.h"
#include "private/bionic_globals.h"
+#include "private/bionic_macros.h"
#include "private/bionic_page.h"
#include "private/bionic_tls.h"
#include "private/KernelArgumentBlock.h"
@@ -82,6 +83,8 @@
void (*onexit)(void) __unused,
int (*slingshot)(int, char**, char**),
structors_array_t const * const structors) {
+ BIONIC_STOP_UNWIND;
+
KernelArgumentBlock args(raw_args);
__libc_init_main_thread(args);
diff --git a/libc/bionic/mmap.cpp b/libc/bionic/mmap.cpp
index 57a8cdf..3503319 100644
--- a/libc/bionic/mmap.cpp
+++ b/libc/bionic/mmap.cpp
@@ -48,7 +48,7 @@
}
// prevent allocations large enough for `end - start` to overflow
- size_t rounded = BIONIC_ALIGN(size, PAGE_SIZE);
+ size_t rounded = __BIONIC_ALIGN(size, PAGE_SIZE);
if (rounded < size || rounded > PTRDIFF_MAX) {
errno = ENOMEM;
return MAP_FAILED;
diff --git a/libc/bionic/mremap.cpp b/libc/bionic/mremap.cpp
index 6653d43..896ccef 100644
--- a/libc/bionic/mremap.cpp
+++ b/libc/bionic/mremap.cpp
@@ -38,7 +38,7 @@
void* mremap(void* old_address, size_t old_size, size_t new_size, int flags, ...) {
// prevent allocations large enough for `end - start` to overflow
- size_t rounded = BIONIC_ALIGN(new_size, PAGE_SIZE);
+ size_t rounded = __BIONIC_ALIGN(new_size, PAGE_SIZE);
if (rounded < new_size || rounded > PTRDIFF_MAX) {
errno = ENOMEM;
return MAP_FAILED;
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index 65ab92c..be0fd1b 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -172,8 +172,8 @@
// 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);
+ 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);
if (attr->stack_base == NULL) {
return EAGAIN;
diff --git a/libc/bionic/sysconf.cpp b/libc/bionic/sysconf.cpp
index 7325dbd..d45cb38 100644
--- a/libc/bionic/sysconf.cpp
+++ b/libc/bionic/sysconf.cpp
@@ -148,7 +148,7 @@
case _SC_THREAD_PRIO_INHERIT: return _POSIX_THREAD_PRIO_INHERIT;
case _SC_THREAD_PRIO_PROTECT: return _POSIX_THREAD_PRIO_PROTECT;
case _SC_THREAD_SAFE_FUNCTIONS: return _POSIX_THREAD_SAFE_FUNCTIONS;
- case _SC_MONOTONIC_CLOCK: return _POSIX_VERSION;
+ case _SC_MONOTONIC_CLOCK: return _POSIX_MONOTONIC_CLOCK;
case _SC_2_PBS: return -1; // Obsolescent in POSIX.1-2008.
case _SC_2_PBS_ACCOUNTING: return -1; // Obsolescent in POSIX.1-2008.
@@ -159,7 +159,7 @@
case _SC_ADVISORY_INFO: return _POSIX_ADVISORY_INFO;
case _SC_BARRIERS: return _POSIX_BARRIERS;
case _SC_CLOCK_SELECTION: return _POSIX_CLOCK_SELECTION;
- case _SC_CPUTIME: return _POSIX_VERSION;
+ case _SC_CPUTIME: return _POSIX_CPUTIME;
case _SC_HOST_NAME_MAX: return _POSIX_HOST_NAME_MAX; // Minimum requirement.
case _SC_IPV6: return _POSIX_IPV6;
@@ -172,7 +172,7 @@
case _SC_SPORADIC_SERVER: return _POSIX_SPORADIC_SERVER;
case _SC_SS_REPL_MAX: return -1;
case _SC_SYMLOOP_MAX: return _POSIX_SYMLOOP_MAX; // Minimum requirement.
- case _SC_THREAD_CPUTIME: return _POSIX_VERSION;
+ case _SC_THREAD_CPUTIME: return _POSIX_THREAD_CPUTIME;
case _SC_THREAD_PROCESS_SHARED: return _POSIX_THREAD_PROCESS_SHARED;
case _SC_THREAD_ROBUST_PRIO_INHERIT: return _POSIX_THREAD_ROBUST_PRIO_INHERIT;
diff --git a/libc/bionic/system_properties.cpp b/libc/bionic/system_properties.cpp
index c57cd9c..b781ea3 100644
--- a/libc/bionic/system_properties.cpp
+++ b/libc/bionic/system_properties.cpp
@@ -304,7 +304,7 @@
}
void* prop_area::allocate_obj(const size_t size, uint_least32_t* const off) {
- const size_t aligned = BIONIC_ALIGN(size, sizeof(uint_least32_t));
+ const size_t aligned = __BIONIC_ALIGN(size, sizeof(uint_least32_t));
if (bytes_used_ + aligned > pa_data_size) {
return nullptr;
}
diff --git a/libc/include/android/api-level.h b/libc/include/android/api-level.h
index 7e3aa99..18825e7 100644
--- a/libc/include/android/api-level.h
+++ b/libc/include/android/api-level.h
@@ -57,5 +57,6 @@
#define __ANDROID_API_N__ 24
#define __ANDROID_API_N_MR1__ 25
#define __ANDROID_API_O__ 26
+#define __ANDROID_API_O_MR1__ 27
#endif /* ANDROID_API_LEVEL_H */
diff --git a/libc/include/android/legacy_sys_mman_inlines.h b/libc/include/android/legacy_sys_mman_inlines.h
new file mode 100644
index 0000000..7eb537e
--- /dev/null
+++ b/libc/include/android/legacy_sys_mman_inlines.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <sys/cdefs.h>
+#include <sys/mman.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+
+#if __ANDROID_API__ < __ANDROID_API_L__
+
+__BEGIN_DECLS
+
+/*
+ * While this was never an inline, this function alone has caused most of the
+ * bug reports related to _FILE_OFFSET_BITS=64. Providing an inline for it
+ * should allow a lot more code to build with _FILE_OFFSET_BITS=64 when
+ * targeting pre-L.
+ */
+static __inline void* mmap64(void* __addr, size_t __size, int __prot, int __flags, int __fd,
+ off64_t __offset) __RENAME(mmap64);
+static __inline void* mmap64(void* __addr, size_t __size, int __prot, int __flags, int __fd,
+ off64_t __offset) {
+ const int __mmap2_shift = 12; // 2**12 == 4096
+ if (__offset < 0 || (__offset & ((1UL << __mmap2_shift) - 1)) != 0) {
+ errno = EINVAL;
+ return MAP_FAILED;
+ }
+
+ // prevent allocations large enough for `end - start` to overflow
+ size_t __rounded = __BIONIC_ALIGN(__size, PAGE_SIZE);
+ if (__rounded < __size || __rounded > PTRDIFF_MAX) {
+ errno = ENOMEM;
+ return MAP_FAILED;
+ }
+
+ extern void* __mmap2(void* __addr, size_t __size, int __prot, int __flags, int __fd,
+ size_t __offset);
+ return __mmap2(__addr, __size, __prot, __flags, __fd, __offset >> __mmap2_shift);
+}
+
+__END_DECLS
+
+#endif /* __ANDROID_API__ < __ANDROID_API_L__ */
diff --git a/libc/include/bits/posix_limits.h b/libc/include/bits/posix_limits.h
index cfc46f5..4038c3a 100644
--- a/libc/include/bits/posix_limits.h
+++ b/libc/include/bits/posix_limits.h
@@ -31,93 +31,67 @@
#include <sys/cdefs.h>
-#define __BIONIC_POSIX_FEATURE_SINCE(level) (((__ANDROID_API__) >= level) ? 200809L : -1)
+#define _POSIX_VERSION 200809L
+#define _POSIX2_VERSION _POSIX_VERSION
+#define _XOPEN_VERSION 700
-/* Any constant values here other than -1 or 200809L are explicitly specified by POSIX.1-2008. */
+#define __BIONIC_POSIX_FEATURE_MISSING (-1)
+#define __BIONIC_POSIX_FEATURE_SINCE(level) \
+ (((__ANDROID_API__) >= level) ? _POSIX_VERSION : __BIONIC_POSIX_FEATURE_MISSING)
+
+/* Availability macros. */
+/* See http://man7.org/linux/man-pages/man7/posixoptions.7.html for documentation. */
/* Keep this list sorted by name. */
#define _POSIX_ADVISORY_INFO __BIONIC_POSIX_FEATURE_SINCE(23) /* posix_memadvise arrived late. */
-#define _POSIX_AIO_LISTIO_MAX 2
-#define _POSIX_AIO_MAX 1
-#define _POSIX_ARG_MAX 4096
-#define _POSIX_ASYNCHRONOUS_IO -1 /* not implemented */
+#define _POSIX_ASYNCHRONOUS_IO __BIONIC_POSIX_FEATURE_MISSING
#define _POSIX_BARRIERS __BIONIC_POSIX_FEATURE_SINCE(24)
-#define _POSIX_CHILD_MAX 25
-#define _POSIX_CHOWN_RESTRICTED 1 /* yes, chown requires appropriate privileges */
-#define _POSIX_CLOCK_SELECTION 200809L
-#define _POSIX_CPUTIME 0 /* Use sysconf to detect support at runtime. */
-#define _POSIX_DELAYTIMER_MAX 32
-#define _POSIX_FSYNC 200809L
-#define _POSIX_HOST_NAME_MAX 255
-#define _POSIX_IPV6 200809L
-#define _POSIX_JOB_CONTROL 1 /* job control is a Linux feature */
-#define _POSIX_LINK_MAX 8
-#define _POSIX_LOGIN_NAME_MAX 9 /* includes trailing NUL */
-#define _POSIX_MAPPED_FILES 200809L /* mmap-ed files supported */
-#define _POSIX_MAX_CANON 255
-#define _POSIX_MAX_INPUT 255
-#define _POSIX_MEMLOCK __BIONIC_POSIX_FEATURE_SINCE(17) /* mlockall. */
-#define _POSIX_MEMLOCK_RANGE 200809L /* mlock. */
-#define _POSIX_MEMORY_PROTECTION 200809L
-#define _POSIX_MESSAGE_PASSING -1 /* not implemented */
-#define _POSIX_MONOTONIC_CLOCK 0 /* the monotonic clock may be available; ask sysconf */
-#define _POSIX_MQ_OPEN_MAX 8
-#define _POSIX_MQ_PRIO_MAX 32
-#define _POSIX_NAME_MAX 14
-#define _POSIX_NGROUPS_MAX 8
-#define _POSIX_NO_TRUNC 1 /* very long pathnames generate an error */
-#define _POSIX_OPEN_MAX 20
-#define _POSIX_PATH_MAX 256
-#define _POSIX_PIPE_BUF 512
-#define _POSIX_PRIORITY_SCHEDULING 200809L /* priority scheduling is a Linux feature */
-#define _POSIX_PRIORITIZED_IO -1 /* not implemented */
-#define _POSIX_RAW_SOCKETS 200809L
-#define _POSIX_READER_WRITER_LOCKS 200809L
-#define _POSIX_REALTIME_SIGNALS 200809L
-#define _POSIX_REGEXP 1
-#define _POSIX_RE_DUP_MAX 255
-#define _POSIX_SAVED_IDS 1 /* saved user ids is a Linux feature */
-#define _POSIX_SEMAPHORES 200809L
-#define _POSIX_SEM_NSEMS_MAX 256
-#define _POSIX_SEM_VALUE_MAX 32767
-#define _POSIX_SHARED_MEMORY_OBJECTS -1 /* shm_open()/shm_unlink() not implemented */
-#define _POSIX_SHELL 1 /* system() supported */
-#define _POSIX_SIGQUEUE_MAX 32
-#define _POSIX_SPAWN -1 /* not implemented */
-#define _POSIX_SPIN_LOCKS __BIONIC_POSIX_FEATURE_SINCE(24)
-#define _POSIX_SPORADIC_SERVER -1 /* not implemented */
-#define _POSIX_SSIZE_MAX 32767
-#define _POSIX_STREAM_MAX 8
-#define _POSIX_SYMLINK_MAX 255
-#define _POSIX_SYMLOOP_MAX 8
-#define _POSIX_SYNCHRONIZED_IO 200809L /* synchronized i/o supported */
-#define _POSIX_THREADS 200809L /* we support threads */
-#define _POSIX_THREAD_ATTR_STACKADDR 200809L
-#define _POSIX_THREAD_ATTR_STACKSIZE 200809L
-#define _POSIX_THREAD_CPUTIME 0 /* Use sysconf to detect support at runtime. */
-#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4
-#define _POSIX_THREAD_KEYS_MAX 128
-#define _POSIX_THREAD_PRIORITY_SCHEDULING 200809L
-#define _POSIX_THREAD_PRIO_INHERIT -1 /* not implemented */
-#define _POSIX_THREAD_PRIO_PROTECT -1 /* not implemented */
-#define _POSIX_THREAD_PROCESS_SHARED 200809L /* PTHREAD_PROCESS_SHARED supported. */
-#define _POSIX_THREAD_ROBUST_PRIO_INHERIT -1 /* not implemented */
-#define _POSIX_THREAD_ROBUST_PRIO_PROTECT -1 /* not implemented */
-#define _POSIX_THREAD_SAFE_FUNCTIONS 200809L
-#define _POSIX_THREAD_SPORADIC_SERVER -1 /* not implemented */
-#define _POSIX_THREAD_THREADS_MAX 64
+#define _POSIX_CHOWN_RESTRICTED 1 /* chown/fchown require appropriate privileges. */
+#define _POSIX_CLOCK_SELECTION __BIONIC_POSIX_FEATURE_SINCE(21) /* clock_nanosleep/pthread_condattr_getclock/pthread_condattr_setclock. */
+#define _POSIX_CPUTIME _POSIX_VERSION /* CLOCK_PROCESS_CPUTIME_ID. */
+#define _POSIX_FSYNC _POSIX_VERSION /* fsync. */
+#define _POSIX_IPV6 _POSIX_VERSION
+#define _POSIX_JOB_CONTROL __BIONIC_POSIX_FEATURE_SINCE(21) /* setpgid/tcdrain/tcflush/tcgetpgrp/tcsendbreak/tcsetattr/tcsetpgrp. */
+#define _POSIX_MAPPED_FILES _POSIX_VERSION /* mmap/msync/munmap. */
+#define _POSIX_MEMLOCK __BIONIC_POSIX_FEATURE_SINCE(17) /* mlockall/munlockall. */
+#define _POSIX_MEMLOCK_RANGE _POSIX_VERSION /* mlock/munlock. */
+#define _POSIX_MEMORY_PROTECTION _POSIX_VERSION /* mprotect. */
+#define _POSIX_MESSAGE_PASSING __BIONIC_POSIX_FEATURE_MISSING
+#define _POSIX_MONOTONIC_CLOCK _POSIX_VERSION /* CLOCK_MONOTONIC. */
+#define _POSIX_NO_TRUNC 1 /* Over-long pathnames return errors. */
+#define _POSIX_PRIORITIZED_IO __BIONIC_POSIX_FEATURE_MISSING
+#define _POSIX_PRIORITY_SCHEDULING _POSIX_VERSION /* sched_*. */
+#define _POSIX_RAW_SOCKETS _POSIX_VERSION
+#define _POSIX_READER_WRITER_LOCKS _POSIX_VERSION /* pthread_rwlock*. */
+#define _POSIX_REALTIME_SIGNALS __BIONIC_POSIX_FEATURE_SINCE(23) /* sigqueue/sigtimedwait/sigwaitinfo. */
+#define _POSIX_REGEXP 1
+#define _POSIX_SAVED_IDS 1
+#define _POSIX_SEMAPHORES _POSIX_VERSION /* sem_*. */
+#define _POSIX_SHARED_MEMORY_OBJECTS __BIONIC_POSIX_FEATURE_MISSING /* mmap/munmap are implemented, but shm_open/shm_unlink are not. */
+#define _POSIX_SHELL 1 /* system. */
+#define _POSIX_SPAWN __BIONIC_POSIX_FEATURE_MISSING /* <spawn.h> */
+#define _POSIX_SPIN_LOCKS __BIONIC_POSIX_FEATURE_SINCE(24) /* pthread_spin_*. */
+#define _POSIX_SPORADIC_SERVER _POSIX_VERSION /* sched_setparam/sched_setscheduler. */
+#define _POSIX_SYNCHRONIZED_IO _POSIX_VERSION
+#define _POSIX_THREAD_ATTR_STACKADDR _POSIX_VERSION /* Strictly, we're missing the deprecated pthread_attr_getstackaddr/pthread_attr_setstackaddr, but we do have pthread_attr_getstack/pthread_attr_setstack. */
+#define _POSIX_THREAD_ATTR_STACKSIZE _POSIX_VERSION /* pthread_attr_getstack/pthread_attr_getstacksize/pthread_attr_setstack/pthread_attr_setstacksize. */
+#define _POSIX_THREAD_CPUTIME _POSIX_VERSION /* CLOCK_THREAD_CPUTIME_ID. */
+#define _POSIX_THREAD_PRIO_INHERIT __BIONIC_POSIX_FEATURE_MISSING
+#define _POSIX_THREAD_PRIO_PROTECT __BIONIC_POSIX_FEATURE_MISSING
+#define _POSIX_THREAD_PRIORITY_SCHEDULING _POSIX_VERSION /* Strictly, pthread_attr_getinheritsched/pthread_attr_setinheritsched are missing. */
+#define _POSIX_THREAD_PROCESS_SHARED _POSIX_VERSION
+#define _POSIX_THREAD_ROBUST_PRIO_INHERIT __BIONIC_POSIX_FEATURE_MISSING
+#define _POSIX_THREAD_ROBUST_PRIO_PROTECT __BIONIC_POSIX_FEATURE_MISSING
+#define _POSIX_THREAD_SAFE_FUNCTIONS _POSIX_VERSION
+#define _POSIX_THREAD_SPORADIC_SERVER _POSIX_VERSION /* sched_setparam/sched_setscheduler. */
+#define _POSIX_THREADS _POSIX_VERSION /* Strictly, pthread_cancel/pthread_testcancel are missing. */
#define _POSIX_TIMEOUTS __BIONIC_POSIX_FEATURE_SINCE(21) /* pthread_mutex_timedlock arrived late. */
-#define _POSIX_TIMERS 200809L /* Posix timers are supported */
-#define _POSIX_TIMER_MAX 32
-#define _POSIX_TRACE -1 /* not implemented */
-#define _POSIX_TRACE_EVENT_FILTER -1 /* not implemented */
-#define _POSIX_TRACE_INHERIT -1 /* not implemented */
-#define _POSIX_TRACE_LOG -1 /* not implemented */
-#define _POSIX_TRACE_NAME_MAX 8
-#define _POSIX_TRACE_SYS_MAX 8
-#define _POSIX_TRACE_USER_EVENT_MAX 32
-#define _POSIX_TTY_NAME_MAX 9 /* includes trailing NUL */
-#define _POSIX_TYPED_MEMORY_OBJECTS -1 /* not implemented */
-#define _POSIX_TZNAME_MAX 6
+#define _POSIX_TIMERS _POSIX_VERSION /* clock_getres/clock_gettime/clock_settime/nanosleep/timer_create/timer_delete/timer_gettime/timer_getoverrun/timer_settime. */
+#define _POSIX_TRACE __BIONIC_POSIX_FEATURE_MISSING
+#define _POSIX_TRACE_EVENT_FILTER __BIONIC_POSIX_FEATURE_MISSING
+#define _POSIX_TRACE_INHERIT __BIONIC_POSIX_FEATURE_MISSING
+#define _POSIX_TRACE_LOG __BIONIC_POSIX_FEATURE_MISSING
+#define _POSIX_TYPED_MEMORY_OBJECTS __BIONIC_POSIX_FEATURE_MISSING
+
#define _POSIX_VDISABLE '\0'
#if defined(__LP64__)
@@ -132,6 +106,42 @@
#define _POSIX_V7_LPBIG_OFFBIG -1
#endif
+/* Minimum values for other maxima. These numbers are simply lower bounds mandated by POSIX. */
+/* Any constant values here other than -1 or 200809L are explicitly specified by POSIX.1-2008. */
+#define _POSIX_AIO_LISTIO_MAX 2
+#define _POSIX_AIO_MAX 1
+#define _POSIX_ARG_MAX 4096
+#define _POSIX_CHILD_MAX 25
+#define _POSIX_DELAYTIMER_MAX 32
+#define _POSIX_HOST_NAME_MAX 255
+#define _POSIX_LINK_MAX 8
+#define _POSIX_LOGIN_NAME_MAX 9 /* includes trailing NUL */
+#define _POSIX_MAX_CANON 255
+#define _POSIX_MAX_INPUT 255
+#define _POSIX_MQ_OPEN_MAX 8
+#define _POSIX_MQ_PRIO_MAX 32
+#define _POSIX_NAME_MAX 14
+#define _POSIX_NGROUPS_MAX 8
+#define _POSIX_OPEN_MAX 20
+#define _POSIX_PATH_MAX 256
+#define _POSIX_PIPE_BUF 512
+#define _POSIX_RE_DUP_MAX 255
+#define _POSIX_SEM_NSEMS_MAX 256
+#define _POSIX_SEM_VALUE_MAX 32767
+#define _POSIX_SIGQUEUE_MAX 32
+#define _POSIX_SSIZE_MAX 32767
+#define _POSIX_STREAM_MAX 8
+#define _POSIX_SYMLINK_MAX 255
+#define _POSIX_SYMLOOP_MAX 8
+#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4
+#define _POSIX_THREAD_KEYS_MAX 128
+#define _POSIX_THREAD_THREADS_MAX 64
+#define _POSIX_TIMER_MAX 32
+#define _POSIX_TRACE_NAME_MAX 8
+#define _POSIX_TRACE_SYS_MAX 8
+#define _POSIX_TRACE_USER_EVENT_MAX 32
+#define _POSIX_TTY_NAME_MAX 9 /* includes trailing NUL */
+#define _POSIX_TZNAME_MAX 6
#define _POSIX2_BC_BASE_MAX 99
#define _POSIX2_BC_DIM_MAX 2048
#define _POSIX2_BC_SCALE_MAX 99
diff --git a/libc/include/glob.h b/libc/include/glob.h
new file mode 100644
index 0000000..6ae8573
--- /dev/null
+++ b/libc/include/glob.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Guido van Rossum.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)glob.h 8.1 (Berkeley) 6/2/93
+ * $FreeBSD$
+ */
+
+#ifndef _GLOB_H_
+#define _GLOB_H_
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+struct dirent;
+struct stat;
+
+typedef struct {
+ size_t gl_pathc; /* Count of total paths so far. */
+ size_t gl_matchc; /* Count of paths matching pattern. */
+ size_t gl_offs; /* Reserved at beginning of gl_pathv. */
+ int gl_flags; /* Copy of flags parameter to glob. */
+ char** gl_pathv; /* List of paths matching pattern. */
+
+ /* Copy of `__error_callback` parameter to glob. */
+ int (*gl_errfunc)(const char* __failure_path, int __failure_errno);
+
+ /*
+ * Alternate filesystem access methods for glob; replacement
+ * versions of closedir(3), readdir(3), opendir(3), stat(2)
+ * and lstat(2).
+ */
+ void (*gl_closedir)(void*);
+ struct dirent* (*gl_readdir)(void*);
+ void* (*gl_opendir)(const char*);
+ int (*gl_lstat)(const char*, struct stat*);
+ int (*gl_stat)(const char*, struct stat*);
+} glob_t;
+
+/* Believed to have been introduced in 1003.2-1992 */
+#define GLOB_APPEND 0x0001 /* Append to output from previous call. */
+#define GLOB_DOOFFS 0x0002 /* Prepend `gl_offs` null pointers (leaving space for exec, say). */
+#define GLOB_ERR 0x0004 /* Return on error. */
+#define GLOB_MARK 0x0008 /* Append "/" to the names of returned directories. */
+#define GLOB_NOCHECK 0x0010 /* Return pattern itself if nothing matches. */
+#define GLOB_NOSORT 0x0020 /* Don't sort. */
+#define GLOB_NOESCAPE 0x2000 /* Disable backslash escaping. */
+
+/* Error values returned by glob(3) */
+#define GLOB_NOSPACE (-1) /* Malloc call failed. */
+#define GLOB_ABORTED (-2) /* Unignored error. */
+#define GLOB_NOMATCH (-3) /* No match and GLOB_NOCHECK was not set. */
+
+#if __USE_BSD
+#define GLOB_ALTDIRFUNC 0x0040 /* Use alternately specified directory funcs. */
+#define GLOB_BRACE 0x0080 /* Expand braces like csh. */
+#define GLOB_MAGCHAR 0x0100 /* Set in `gl_flags` if the pattern had globbing characters. */
+#define GLOB_NOMAGIC 0x0200 /* GLOB_NOCHECK without magic chars (csh). */
+#define GLOB_QUOTE 0x0400 /* Quote special chars with \. */
+#define GLOB_TILDE 0x0800 /* Expand tilde names from the passwd file. */
+#define GLOB_LIMIT 0x1000 /* limit number of returned paths */
+#endif
+
+__BEGIN_DECLS
+
+int glob(const char* __pattern, int __flags, int (*__error_callback)(const char* __failure_path, int __failure_errno), glob_t* __result_ptr) __INTRODUCED_IN_FUTURE;
+void globfree(glob_t* __result_ptr) __INTRODUCED_IN_FUTURE;
+
+__END_DECLS
+
+#endif
diff --git a/libc/include/limits.h b/libc/include/limits.h
index 51f4fad..4384f6f 100644
--- a/libc/include/limits.h
+++ b/libc/include/limits.h
@@ -140,10 +140,6 @@
#define LOGIN_NAME_MAX 256
#define TTY_NAME_MAX 32
-#define _POSIX_VERSION 200809L
-#define _POSIX2_VERSION _POSIX_VERSION
-#define _XOPEN_VERSION 700 /* by Posix definition */
-
/* >= _POSIX_THREAD_DESTRUCTOR_ITERATIONS */
#define PTHREAD_DESTRUCTOR_ITERATIONS 4
/* >= _POSIX_THREAD_KEYS_MAX */
diff --git a/libc/include/sys/cdefs.h b/libc/include/sys/cdefs.h
index 063b51d..3656733 100644
--- a/libc/include/sys/cdefs.h
+++ b/libc/include/sys/cdefs.h
@@ -79,6 +79,8 @@
#define __BIONIC_CAST(_k,_t,_v) ((_t) (_v))
#endif
+#define __BIONIC_ALIGN(__value, __alignment) (((__value) + (__alignment)-1) & ~((__alignment)-1))
+
/*
* The __CONCAT macro is used to concatenate parts of symbol names, e.g.
* with "#define OLD(foo) __CONCAT(old,foo)", OLD(foo) produces oldfoo.
diff --git a/libc/include/sys/mman.h b/libc/include/sys/mman.h
index 1e752c4..028b024 100644
--- a/libc/include/sys/mman.h
+++ b/libc/include/sys/mman.h
@@ -45,12 +45,30 @@
#define MREMAP_FIXED 2
#if defined(__USE_FILE_OFFSET64)
-void* mmap(void* __addr, size_t __size, int __prot, int __flags, int __fd, off_t __offset) __RENAME(mmap64) __INTRODUCED_IN(21);
+/*
+ * mmap64 wasn't really around until L, but we added an inline for it since it
+ * allows a lot more code to compile with _FILE_OFFSET_BITS=64.
+ *
+ * GCC removes the static inline unless it is explicitly used. We can get around
+ * this with __attribute__((used)), but that needlessly adds a definition of
+ * mmap64 to every translation unit that includes this header. Instead, just
+ * preserve the old behavior for GCC and emit a useful diagnostic.
+ */
+void* mmap(void* __addr, size_t __size, int __prot, int __flags, int __fd, off_t __offset)
+#if !defined(__clang__) && __ANDROID_API__ < __ANDROID_API_L__
+ __attribute__((error("mmap is not available with _FILE_OFFSET_BITS=64 when using GCC until "
+ "android-21. Either raise your minSdkVersion, disable "
+ "_FILE_OFFSET_BITS=64, or switch to Clang.")));
+#else
+ __RENAME(mmap64);
+#endif /* defined(__clang__) */
#else
void* mmap(void* __addr, size_t __size, int __prot, int __flags, int __fd, off_t __offset);
-#endif
+#endif /* defined(__USE_FILE_OFFSET64) */
+#if __ANDROID_API__ >= __ANDROID_API_L__
void* mmap64(void* __addr, size_t __size, int __prot, int __flags, int __fd, off64_t __offset) __INTRODUCED_IN(21);
+#endif
int munmap(void* __addr, size_t __size);
int msync(void* __addr, size_t __size, int __flags);
@@ -86,4 +104,6 @@
__END_DECLS
+#include <android/legacy_sys_mman_inlines.h>
+
#endif
diff --git a/libc/include/sys/random.h b/libc/include/sys/random.h
new file mode 100644
index 0000000..3475652
--- /dev/null
+++ b/libc/include/sys/random.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _SYS_RANDOM_H_
+#define _SYS_RANDOM_H_
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include <linux/random.h>
+
+__BEGIN_DECLS
+
+/* See also arc4random_buf in <stdlib.h>, which is available in all API levels. */
+
+int getentropy(void* __buffer, size_t __buffer_size) __wur __INTRODUCED_IN_FUTURE;
+
+ssize_t getrandom(void* __buffer, size_t __buffer_size, unsigned int __flags) __wur __INTRODUCED_IN_FUTURE;
+
+__END_DECLS
+
+#endif
diff --git a/libc/libc.arm.map b/libc/libc.arm.map
index 5018951..13c267a 100644
--- a/libc/libc.arm.map
+++ b/libc/libc.arm.map
@@ -1318,21 +1318,25 @@
wctrans_l; # introduced=26
} LIBC_N;
-LIBC_P {
+LIBC_P { # introduced=P
global:
- __freading; # future
- __fwriting; # future
- getlogin_r; # future
- hcreate; # future
- hcreate_r; # future
- hdestroy; # future
- hdestroy_r; # future
- hsearch; # future
- hsearch_r; # future
- iconv; # future
- iconv_close; # future
- iconv_open; # future
- syncfs; # future
+ __freading;
+ __fwriting;
+ getentropy;
+ getrandom;
+ getlogin_r;
+ glob;
+ globfree;
+ hcreate;
+ hcreate_r;
+ hdestroy;
+ hdestroy_r;
+ hsearch;
+ hsearch_r;
+ iconv;
+ iconv_close;
+ iconv_open;
+ syncfs;
} LIBC_O;
LIBC_PRIVATE {
diff --git a/libc/libc.arm64.map b/libc/libc.arm64.map
index 4ea5896..9d8c1b7 100644
--- a/libc/libc.arm64.map
+++ b/libc/libc.arm64.map
@@ -1238,21 +1238,25 @@
wctrans_l; # introduced=26
} LIBC_N;
-LIBC_P {
+LIBC_P { # introduced=P
global:
- __freading; # future
- __fwriting; # future
- getlogin_r; # future
- hcreate; # future
- hcreate_r; # future
- hdestroy; # future
- hdestroy_r; # future
- hsearch; # future
- hsearch_r; # future
- iconv; # future
- iconv_close; # future
- iconv_open; # future
- syncfs; # future
+ __freading;
+ __fwriting;
+ getentropy;
+ getrandom;
+ getlogin_r;
+ glob;
+ globfree;
+ hcreate;
+ hcreate_r;
+ hdestroy;
+ hdestroy_r;
+ hsearch;
+ hsearch_r;
+ iconv;
+ iconv_close;
+ iconv_open;
+ syncfs;
} LIBC_O;
LIBC_PRIVATE {
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
index a0ac50a..da462d3 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -1343,21 +1343,25 @@
wctrans_l; # introduced=26
} LIBC_N;
-LIBC_P {
+LIBC_P { # introduced=P
global:
- __freading; # future
- __fwriting; # future
- getlogin_r; # future
- hcreate; # future
- hcreate_r; # future
- hdestroy; # future
- hdestroy_r; # future
- hsearch; # future
- hsearch_r; # future
- iconv; # future
- iconv_close; # future
- iconv_open; # future
- syncfs; # future
+ __freading;
+ __fwriting;
+ getentropy;
+ getrandom;
+ getlogin_r;
+ glob;
+ globfree;
+ hcreate;
+ hcreate_r;
+ hdestroy;
+ hdestroy_r;
+ hsearch;
+ hsearch_r;
+ iconv;
+ iconv_close;
+ iconv_open;
+ syncfs;
} LIBC_O;
LIBC_PRIVATE {
diff --git a/libc/libc.mips.map b/libc/libc.mips.map
index 8970549..3e41f95 100644
--- a/libc/libc.mips.map
+++ b/libc/libc.mips.map
@@ -1302,21 +1302,25 @@
wctrans_l; # introduced=26
} LIBC_N;
-LIBC_P {
+LIBC_P { # introduced=P
global:
- __freading; # future
- __fwriting; # future
- getlogin_r; # future
- hcreate; # future
- hcreate_r; # future
- hdestroy; # future
- hdestroy_r; # future
- hsearch; # future
- hsearch_r; # future
- iconv; # future
- iconv_close; # future
- iconv_open; # future
- syncfs; # future
+ __freading;
+ __fwriting;
+ getentropy;
+ getrandom;
+ getlogin_r;
+ glob;
+ globfree;
+ hcreate;
+ hcreate_r;
+ hdestroy;
+ hdestroy_r;
+ hsearch;
+ hsearch_r;
+ iconv;
+ iconv_close;
+ iconv_open;
+ syncfs;
} LIBC_O;
LIBC_PRIVATE {
diff --git a/libc/libc.mips64.map b/libc/libc.mips64.map
index 4ea5896..9d8c1b7 100644
--- a/libc/libc.mips64.map
+++ b/libc/libc.mips64.map
@@ -1238,21 +1238,25 @@
wctrans_l; # introduced=26
} LIBC_N;
-LIBC_P {
+LIBC_P { # introduced=P
global:
- __freading; # future
- __fwriting; # future
- getlogin_r; # future
- hcreate; # future
- hcreate_r; # future
- hdestroy; # future
- hdestroy_r; # future
- hsearch; # future
- hsearch_r; # future
- iconv; # future
- iconv_close; # future
- iconv_open; # future
- syncfs; # future
+ __freading;
+ __fwriting;
+ getentropy;
+ getrandom;
+ getlogin_r;
+ glob;
+ globfree;
+ hcreate;
+ hcreate_r;
+ hdestroy;
+ hdestroy_r;
+ hsearch;
+ hsearch_r;
+ iconv;
+ iconv_close;
+ iconv_open;
+ syncfs;
} LIBC_O;
LIBC_PRIVATE {
diff --git a/libc/libc.x86.map b/libc/libc.x86.map
index 5439852..c3d678c 100644
--- a/libc/libc.x86.map
+++ b/libc/libc.x86.map
@@ -1300,21 +1300,25 @@
wctrans_l; # introduced=26
} LIBC_N;
-LIBC_P {
+LIBC_P { # introduced=P
global:
- __freading; # future
- __fwriting; # future
- getlogin_r; # future
- hcreate; # future
- hcreate_r; # future
- hdestroy; # future
- hdestroy_r; # future
- hsearch; # future
- hsearch_r; # future
- iconv; # future
- iconv_close; # future
- iconv_open; # future
- syncfs; # future
+ __freading;
+ __fwriting;
+ getentropy;
+ getrandom;
+ getlogin_r;
+ glob;
+ globfree;
+ hcreate;
+ hcreate_r;
+ hdestroy;
+ hdestroy_r;
+ hsearch;
+ hsearch_r;
+ iconv;
+ iconv_close;
+ iconv_open;
+ syncfs;
} LIBC_O;
LIBC_PRIVATE {
diff --git a/libc/libc.x86_64.map b/libc/libc.x86_64.map
index 4ea5896..9d8c1b7 100644
--- a/libc/libc.x86_64.map
+++ b/libc/libc.x86_64.map
@@ -1238,21 +1238,25 @@
wctrans_l; # introduced=26
} LIBC_N;
-LIBC_P {
+LIBC_P { # introduced=P
global:
- __freading; # future
- __fwriting; # future
- getlogin_r; # future
- hcreate; # future
- hcreate_r; # future
- hdestroy; # future
- hdestroy_r; # future
- hsearch; # future
- hsearch_r; # future
- iconv; # future
- iconv_close; # future
- iconv_open; # future
- syncfs; # future
+ __freading;
+ __fwriting;
+ getentropy;
+ getrandom;
+ getlogin_r;
+ glob;
+ globfree;
+ hcreate;
+ hcreate_r;
+ hdestroy;
+ hdestroy_r;
+ hsearch;
+ hsearch_r;
+ iconv;
+ iconv_close;
+ iconv_open;
+ syncfs;
} LIBC_O;
LIBC_PRIVATE {
diff --git a/libc/malloc_debug/BacktraceData.cpp b/libc/malloc_debug/BacktraceData.cpp
index 65ae6fa..d597280 100644
--- a/libc/malloc_debug/BacktraceData.cpp
+++ b/libc/malloc_debug/BacktraceData.cpp
@@ -53,7 +53,7 @@
: OptionData(debug_data) {
size_t hdr_len = sizeof(BacktraceHeader) + sizeof(uintptr_t) * config.backtrace_frames();
alloc_offset_ = *offset;
- *offset += BIONIC_ALIGN(hdr_len, MINIMUM_ALIGNMENT_BYTES);
+ *offset += __BIONIC_ALIGN(hdr_len, MINIMUM_ALIGNMENT_BYTES);
}
bool BacktraceData::Initialize(const Config& config) {
diff --git a/libc/malloc_debug/Config.cpp b/libc/malloc_debug/Config.cpp
index e3798ab..3cecf9b 100644
--- a/libc/malloc_debug/Config.cpp
+++ b/libc/malloc_debug/Config.cpp
@@ -191,7 +191,7 @@
// It's necessary to align the front guard to MINIMUM_ALIGNMENT_BYTES to
// make sure that the header is aligned properly.
- front_guard_bytes_ = BIONIC_ALIGN(rear_guard_bytes_, MINIMUM_ALIGNMENT_BYTES);
+ front_guard_bytes_ = __BIONIC_ALIGN(rear_guard_bytes_, MINIMUM_ALIGNMENT_BYTES);
return true;
}
@@ -201,7 +201,7 @@
}
// It's necessary to align the front guard to MINIMUM_ALIGNMENT_BYTES to
// make sure that the header is aligned properly.
- front_guard_bytes_ = BIONIC_ALIGN(front_guard_bytes_, MINIMUM_ALIGNMENT_BYTES);
+ front_guard_bytes_ = __BIONIC_ALIGN(front_guard_bytes_, MINIMUM_ALIGNMENT_BYTES);
return true;
}
diff --git a/libc/malloc_debug/DebugData.cpp b/libc/malloc_debug/DebugData.cpp
index e9974d7..d6ca998 100644
--- a/libc/malloc_debug/DebugData.cpp
+++ b/libc/malloc_debug/DebugData.cpp
@@ -47,7 +47,7 @@
need_header_ = true;
// Initialize all of the static header offsets.
- pointer_offset_ = BIONIC_ALIGN(sizeof(Header), MINIMUM_ALIGNMENT_BYTES);
+ pointer_offset_ = __BIONIC_ALIGN(sizeof(Header), MINIMUM_ALIGNMENT_BYTES);
if (config_.options() & BACKTRACE) {
backtrace.reset(new BacktraceData(this, config_, &pointer_offset_));
diff --git a/libc/malloc_debug/malloc_debug.cpp b/libc/malloc_debug/malloc_debug.cpp
index d890a1c..a2ada2f 100644
--- a/libc/malloc_debug/malloc_debug.cpp
+++ b/libc/malloc_debug/malloc_debug.cpp
@@ -767,7 +767,7 @@
}
size_t pagesize = getpagesize();
- size_t size = BIONIC_ALIGN(bytes, pagesize);
+ size_t size = __BIONIC_ALIGN(bytes, pagesize);
if (size < bytes) {
// Overflow
errno = ENOMEM;
diff --git a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
index 37d8057..d7ba379 100644
--- a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
+++ b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
@@ -74,9 +74,10 @@
constexpr uint32_t BACKTRACE_HEADER = 0x1;
static size_t get_tag_offset(uint32_t flags = 0, size_t backtrace_frames = 0) {
- size_t offset = BIONIC_ALIGN(sizeof(Header), MINIMUM_ALIGNMENT_BYTES);
+ size_t offset = __BIONIC_ALIGN(sizeof(Header), MINIMUM_ALIGNMENT_BYTES);
if (flags & BACKTRACE_HEADER) {
- offset += BIONIC_ALIGN(sizeof(BacktraceHeader) + sizeof(uintptr_t) * backtrace_frames, MINIMUM_ALIGNMENT_BYTES);
+ offset += __BIONIC_ALIGN(sizeof(BacktraceHeader) + sizeof(uintptr_t) * backtrace_frames,
+ MINIMUM_ALIGNMENT_BYTES);
}
return offset;
}
diff --git a/libc/private/bionic_macros.h b/libc/private/bionic_macros.h
index 303218e..c0df917 100644
--- a/libc/private/bionic_macros.h
+++ b/libc/private/bionic_macros.h
@@ -40,9 +40,6 @@
TypeName() = delete; \
DISALLOW_COPY_AND_ASSIGN(TypeName)
-#define BIONIC_ALIGN(value, alignment) \
- (((value) + (alignment) - 1) & ~((alignment) - 1))
-
#define BIONIC_ROUND_UP_POWER_OF_2(value) \
((sizeof(value) == 8) \
? (1UL << (64 - __builtin_clzl(static_cast<unsigned long>(value)))) \
@@ -66,4 +63,17 @@
return reinterpret_cast<T*>(align_up(reinterpret_cast<uintptr_t>(p), align));
}
+#if defined(__arm__)
+// Do not emit anything for arm, clang does not allow emiting an arm unwind
+// directive.
+// #define BIONIC_STOP_UNWIND asm volatile(".cantunwind")
+#define BIONIC_STOP_UNWIND
+#elif defined(__aarch64__)
+#define BIONIC_STOP_UNWIND asm volatile(".cfi_undefined x30")
+#elif defined(__i386__)
+#define BIONIC_STOP_UNWIND asm volatile(".cfi_undefined \%eip")
+#elif defined(__x86_64__)
+#define BIONIC_STOP_UNWIND asm volatile(".cfi_undefined \%rip")
+#endif
+
#endif // _BIONIC_MACROS_H_
diff --git a/libc/private/bionic_tls.h b/libc/private/bionic_tls.h
index 852b9ae..de086f2 100644
--- a/libc/private/bionic_tls.h
+++ b/libc/private/bionic_tls.h
@@ -102,7 +102,7 @@
passwd_state_t passwd;
};
-#define BIONIC_TLS_SIZE (BIONIC_ALIGN(sizeof(bionic_tls), PAGE_SIZE))
+#define BIONIC_TLS_SIZE (__BIONIC_ALIGN(sizeof(bionic_tls), PAGE_SIZE))
/*
* Bionic uses some pthread keys internally. All pthread keys used internally
diff --git a/libc/seccomp/Android.bp b/libc/seccomp/Android.bp
index a75aa65..b3707bc 100644
--- a/libc/seccomp/Android.bp
+++ b/libc/seccomp/Android.bp
@@ -16,6 +16,7 @@
"mips64_global_policy.cpp",
],
export_include_dirs: ["include"],
+ cflags: ["-Wall", "-Werror"],
shared: {
shared_libs: ["libbase"],
},
diff --git a/libc/seccomp/arm64_global_policy.cpp b/libc/seccomp/arm64_global_policy.cpp
index 1a138b7..e2c594e 100644
--- a/libc/seccomp/arm64_global_policy.cpp
+++ b/libc/seccomp/arm64_global_policy.cpp
@@ -5,12 +5,12 @@
#include "seccomp_bpfs.h"
const sock_filter arm64_global_filter[] = {
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5, 0, 32),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 0, 0, 32),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 219, 15, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 101, 7, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 43, 3, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 19, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 18, 27, 26), //setxattr|lsetxattr|fsetxattr|getxattr|lgetxattr|fgetxattr|listxattr|llistxattr|flistxattr|removexattr|lremovexattr|fremovexattr|getcwd
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 18, 27, 26), //io_setup|io_destroy|io_submit|io_cancel|io_getevents|setxattr|lsetxattr|fsetxattr|getxattr|lgetxattr|fgetxattr|listxattr|llistxattr|flistxattr|removexattr|lremovexattr|fremovexattr|getcwd
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 42, 26, 25), //eventfd2|epoll_create1|epoll_ctl|epoll_pwait|dup|dup3|fcntl|inotify_init1|inotify_add_watch|inotify_rm_watch|ioctl|ioprio_set|ioprio_get|flock|mknodat|mkdirat|unlinkat|symlinkat|linkat|renameat|umount2|mount|pivot_root
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 59, 1, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 58, 24, 23), //statfs|fstatfs|truncate|ftruncate|fallocate|faccessat|chdir|fchdir|chroot|fchmod|fchmodat|fchownat|fchown|openat|close
diff --git a/libc/seccomp/arm_global_policy.cpp b/libc/seccomp/arm_global_policy.cpp
index 2f9a122..d7b5d7e 100644
--- a/libc/seccomp/arm_global_policy.cpp
+++ b/libc/seccomp/arm_global_policy.cpp
@@ -5,7 +5,7 @@
#include "seccomp_bpfs.h"
const sock_filter arm_global_filter[] = {
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 0, 0, 132),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 0, 0, 130),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 168, 65, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 77, 33, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 45, 17, 0),
@@ -13,88 +13,86 @@
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 19, 5, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 10, 3, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 8, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 7, 124, 123), //restart_syscall|exit|fork|read|write|open|close
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 9, 123, 122), //creat
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 13, 122, 121), //unlink|execve|chdir
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 7, 122, 121), //restart_syscall|exit|fork|read|write|open|close
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 9, 121, 120), //creat
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 13, 120, 119), //unlink|execve|chdir
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 24, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 22, 120, 119), //lseek|getpid|mount
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 25, 119, 118), //getuid
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 22, 118, 117), //lseek|getpid|mount
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 25, 117, 116), //getuid
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 36, 3, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 33, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 27, 116, 115), //ptrace
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 34, 115, 114), //access
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 27, 114, 113), //ptrace
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 34, 113, 112), //access
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 41, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 40, 113, 112), //sync|kill|rename|mkdir
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 44, 112, 111), //dup|pipe|times
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 40, 111, 110), //sync|kill|rename|mkdir
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 44, 110, 109), //dup|pipe|times
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 60, 7, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 54, 3, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 51, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 46, 108, 107), //brk
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 53, 107, 106), //acct|umount2
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 46, 106, 105), //brk
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 53, 105, 104), //acct|umount2
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 57, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 56, 105, 104), //ioctl|fcntl
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 58, 104, 103), //setpgid
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 56, 103, 102), //ioctl|fcntl
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 58, 102, 101), //setpgid
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 66, 3, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 63, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 62, 101, 100), //umask|chroot
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 65, 100, 99), //dup2|getppid
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 62, 99, 98), //umask|chroot
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 65, 98, 97), //dup2|getppid
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 74, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 68, 98, 97), //setsid|sigaction
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 76, 97, 96), //sethostname|setrlimit
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 68, 96, 95), //setsid|sigaction
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 76, 95, 94), //sethostname|setrlimit
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 116, 15, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 94, 7, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 87, 3, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 85, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 80, 92, 91), //getrusage|gettimeofday|settimeofday
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 86, 91, 90), //readlink
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 80, 90, 89), //getrusage|gettimeofday|settimeofday
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 86, 89, 88), //readlink
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 91, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 89, 89, 88), //swapon|reboot
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 93, 88, 87), //munmap|truncate
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 89, 87, 86), //swapon|reboot
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 93, 86, 85), //munmap|truncate
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 103, 3, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 96, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 95, 85, 84), //fchmod
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 98, 84, 83), //getpriority|setpriority
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 95, 83, 82), //fchmod
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 98, 82, 81), //getpriority|setpriority
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 114, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 106, 82, 81), //syslog|setitimer|getitimer
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 115, 81, 80), //wait4
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 106, 80, 79), //syslog|setitimer|getitimer
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 115, 79, 78), //wait4
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 131, 7, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 124, 3, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 118, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 117, 77, 76), //sysinfo
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 123, 76, 75), //fsync|sigreturn|clone|setdomainname|uname
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 117, 75, 74), //sysinfo
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 123, 74, 73), //fsync|sigreturn|clone|setdomainname|uname
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 128, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 126, 74, 73), //adjtimex|mprotect
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 130, 73, 72), //init_module|delete_module
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 126, 72, 71), //adjtimex|mprotect
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 130, 71, 70), //init_module|delete_module
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 138, 3, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 136, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 134, 70, 69), //quotactl|getpgid|fchdir
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 137, 69, 68), //personality
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 134, 68, 67), //quotactl|getpgid|fchdir
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 137, 67, 66), //personality
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 150, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 149, 67, 66), //setfsuid|setfsgid|_llseek|getdents|_newselect|flock|msync|readv|writev|getsid|fdatasync
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 164, 66, 65), //mlock|munlock|mlockall|munlockall|sched_setparam|sched_getparam|sched_setscheduler|sched_getscheduler|sched_yield|sched_get_priority_max|sched_get_priority_min|sched_rr_get_interval|nanosleep|mremap
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 309, 33, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 248, 17, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 213, 9, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 190, 5, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 149, 65, 64), //setfsuid|setfsgid|_llseek|getdents|_newselect|flock|msync|readv|writev|getsid|fdatasync
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 164, 64, 63), //mlock|munlock|mlockall|munlockall|sched_setparam|sched_getparam|sched_setscheduler|sched_getscheduler|sched_yield|sched_get_priority_max|sched_get_priority_min|sched_rr_get_interval|nanosleep|mremap
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 309, 31, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 224, 15, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 199, 7, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 183, 3, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 172, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 169, 59, 58), //poll
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 182, 58, 57), //prctl|rt_sigreturn|rt_sigaction|rt_sigprocmask|rt_sigpending|rt_sigtimedwait|rt_sigqueueinfo|rt_sigsuspend|pread64|pwrite64
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 188, 57, 56), //getcwd|capget|capset|sigaltstack|sendfile
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 199, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 198, 55, 54), //vfork|ugetrlimit|mmap2|truncate64|ftruncate64|stat64|lstat64|fstat64
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 212, 54, 53), //getuid32|getgid32|geteuid32|getegid32|setreuid32|setregid32|getgroups32|setgroups32|fchown32|setresuid32|getresuid32|setresgid32|getresgid32
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 219, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 217, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 215, 51, 50), //setuid32|setgid32
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 218, 50, 49), //getdents64
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 224, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 222, 48, 47), //mincore|madvise|fcntl64
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 243, 47, 46), //gettid|readahead|setxattr|lsetxattr|fsetxattr|getxattr|lgetxattr|fgetxattr|listxattr|llistxattr|flistxattr|removexattr|lremovexattr|fremovexattr|tkill|sendfile64|futex|sched_setaffinity|sched_getaffinity
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 169, 58, 57), //poll
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 182, 57, 56), //prctl|rt_sigreturn|rt_sigaction|rt_sigprocmask|rt_sigpending|rt_sigtimedwait|rt_sigqueueinfo|rt_sigsuspend|pread64|pwrite64
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 190, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 188, 55, 54), //getcwd|capget|capset|sigaltstack|sendfile
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 198, 54, 53), //vfork|ugetrlimit|mmap2|truncate64|ftruncate64|stat64|lstat64|fstat64
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 217, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 213, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 212, 51, 50), //getuid32|getgid32|geteuid32|getegid32|setreuid32|setregid32|getgroups32|setgroups32|fchown32|setresuid32|getresuid32|setresgid32|getresgid32
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 215, 50, 49), //setuid32|setgid32
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 219, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 218, 48, 47), //getdents64
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 222, 47, 46), //mincore|madvise|fcntl64
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 280, 7, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 256, 3, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 250, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 249, 43, 42), //exit_group
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 249, 43, 42), //gettid|readahead|setxattr|lsetxattr|fsetxattr|getxattr|lgetxattr|fgetxattr|listxattr|llistxattr|flistxattr|removexattr|lremovexattr|fremovexattr|tkill|sendfile64|futex|sched_setaffinity|sched_getaffinity|io_setup|io_destroy|io_getevents|io_submit|io_cancel|exit_group
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 254, 42, 41), //epoll_create|epoll_ctl|epoll_wait|remap_file_pages
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 270, 1, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 269, 40, 39), //set_tid_address|timer_create|timer_settime|timer_gettime|timer_getoverrun|timer_delete|clock_settime|clock_gettime|clock_getres|clock_nanosleep|statfs64|fstatfs64|tgkill
diff --git a/libc/seccomp/mips64_global_policy.cpp b/libc/seccomp/mips64_global_policy.cpp
index 004eda2..04c13b3 100644
--- a/libc/seccomp/mips64_global_policy.cpp
+++ b/libc/seccomp/mips64_global_policy.cpp
@@ -59,9 +59,9 @@
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5173, 35, 34), //quotactl
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5193, 34, 33), //gettid|readahead|setxattr|lsetxattr|fsetxattr|getxattr|lgetxattr|fgetxattr|listxattr|llistxattr|flistxattr|removexattr|lremovexattr|fremovexattr|tkill
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5208, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5205, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5200, 1, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5198, 31, 30), //futex|sched_setaffinity|sched_getaffinity|cacheflush
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5206, 30, 29), //exit_group
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5206, 30, 29), //io_setup|io_destroy|io_getevents|io_submit|io_cancel|exit_group
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5209, 29, 28), //epoll_ctl
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5239, 5, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5237, 3, 0),
diff --git a/libc/seccomp/mips_global_policy.cpp b/libc/seccomp/mips_global_policy.cpp
index b4fa23d..103e544 100644
--- a/libc/seccomp/mips_global_policy.cpp
+++ b/libc/seccomp/mips_global_policy.cpp
@@ -5,93 +5,91 @@
#include "seccomp_bpfs.h"
const sock_filter mips_global_filter[] = {
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4001, 0, 114),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4136, 57, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4066, 29, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4041, 15, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4001, 0, 112),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4131, 55, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4063, 27, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4036, 13, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4023, 7, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4010, 3, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4008, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4007, 107, 106), //exit|fork|read|write|open|close
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4009, 106, 105), //creat
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4007, 105, 104), //exit|fork|read|write|open|close
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4009, 104, 103), //creat
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4019, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4013, 104, 103), //unlink|execve|chdir
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4022, 103, 102), //lseek|getpid|mount
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4013, 102, 101), //unlink|execve|chdir
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4022, 101, 100), //lseek|getpid|mount
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4033, 3, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4026, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4025, 100, 99), //setuid|getuid
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4027, 99, 98), //ptrace
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4036, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4034, 97, 96), //access
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4040, 96, 95), //sync|kill|rename|mkdir
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4057, 7, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4049, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4045, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4044, 92, 91), //dup|pipe|times
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4048, 91, 90), //brk|setgid|getgid
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4054, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4053, 89, 88), //geteuid|getegid|acct|umount2
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4056, 88, 87), //ioctl|fcntl
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4063, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4060, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4058, 85, 84), //setpgid
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4062, 84, 83), //umask|chroot
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4065, 83, 82), //dup2|getppid
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4103, 13, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4087, 7, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4074, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4070, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4068, 78, 77), //setsid|sigaction
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4072, 77, 76), //setreuid|setregid
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4085, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4082, 75, 74), //sethostname|setrlimit|getrlimit|getrusage|gettimeofday|settimeofday|getgroups|setgroups
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4086, 74, 73), //readlink
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4094, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4090, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4089, 71, 70), //swapon|reboot
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4093, 70, 69), //mmap|munmap|truncate
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4098, 69, 68), //fchmod|fchown|getpriority|setpriority
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4124, 7, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4116, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4114, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4106, 65, 64), //syslog|setitimer|getitimer
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4115, 64, 63), //wait4
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4118, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4117, 62, 61), //sysinfo
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4123, 61, 60), //fsync|sigreturn|clone|setdomainname|uname
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4131, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4128, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4126, 58, 57), //adjtimex|mprotect
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4130, 57, 56), //init_module|delete_module
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4134, 56, 55), //quotactl|getpgid|fchdir
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4025, 98, 97), //setuid|getuid
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4027, 97, 96), //ptrace
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4034, 96, 95), //access
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4054, 7, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4045, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4041, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4040, 92, 91), //sync|kill|rename|mkdir
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4044, 91, 90), //dup|pipe|times
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4049, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4048, 89, 88), //brk|setgid|getgid
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4053, 88, 87), //geteuid|getegid|acct|umount2
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4060, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4057, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4056, 85, 84), //ioctl|fcntl
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4058, 84, 83), //setpgid
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4062, 83, 82), //umask|chroot
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4094, 13, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4085, 7, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4070, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4066, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4065, 78, 77), //dup2|getppid
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4068, 77, 76), //setsid|sigaction
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4074, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4072, 75, 74), //setreuid|setregid
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4082, 74, 73), //sethostname|setrlimit|getrlimit|getrusage|gettimeofday|settimeofday|getgroups|setgroups
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4090, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4087, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4086, 71, 70), //readlink
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4089, 70, 69), //swapon|reboot
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4093, 69, 68), //mmap|munmap|truncate
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4118, 7, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4114, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4103, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4098, 65, 64), //fchmod|fchown|getpriority|setpriority
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4106, 64, 63), //syslog|setitimer|getitimer
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4116, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4115, 62, 61), //wait4
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4117, 61, 60), //sysinfo
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4128, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4124, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4123, 58, 57), //fsync|sigreturn|clone|setdomainname|uname
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4126, 57, 56), //adjtimex|mprotect
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4130, 56, 55), //init_module|delete_module
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4248, 27, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4188, 13, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4169, 7, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4151, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4138, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4137, 50, 49), //personality
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4148, 49, 48), //setfsuid|setfsgid|_llseek|getdents|_newselect|flock|msync|readv|writev|cacheflush
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4154, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4153, 47, 46), //getsid|fdatasync
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4168, 46, 45), //mlock|munlock|mlockall|munlockall|sched_setparam|sched_getparam|sched_setscheduler|sched_getscheduler|sched_yield|sched_get_priority_max|sched_get_priority_min|sched_rr_get_interval|nanosleep|mremap
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4179, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4176, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4175, 43, 42), //bind|connect|getpeername|getsockname|getsockopt|listen
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4178, 42, 41), //recvfrom|recvmsg
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4187, 41, 40), //sendmsg|sendto|setsockopt|shutdown|socket|socketpair|setresuid|getresuid
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4217, 7, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4203, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4190, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4189, 37, 36), //poll
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4202, 36, 35), //setresgid|getresgid|prctl|rt_sigreturn|rt_sigaction|rt_sigprocmask|rt_sigpending|rt_sigtimedwait|rt_sigqueueinfo|rt_sigsuspend|pread64|pwrite64
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4210, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4208, 34, 33), //getcwd|capget|capset|sigaltstack|sendfile
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4216, 33, 32), //mmap2|truncate64|ftruncate64|stat64|lstat64|fstat64
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4246, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4222, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4221, 30, 29), //mincore|madvise|getdents64|fcntl64
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4241, 29, 28), //gettid|readahead|setxattr|lsetxattr|fsetxattr|getxattr|lgetxattr|fgetxattr|listxattr|llistxattr|flistxattr|removexattr|lremovexattr|fremovexattr|tkill|sendfile64|futex|sched_setaffinity|sched_getaffinity
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4247, 28, 27), //exit_group
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4179, 13, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4154, 7, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4138, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4136, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4134, 50, 49), //quotactl|getpgid|fchdir
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4137, 49, 48), //personality
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4151, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4148, 47, 46), //setfsuid|setfsgid|_llseek|getdents|_newselect|flock|msync|readv|writev|cacheflush
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4153, 46, 45), //getsid|fdatasync
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4176, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4169, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4168, 43, 42), //mlock|munlock|mlockall|munlockall|sched_setparam|sched_getparam|sched_setscheduler|sched_getscheduler|sched_yield|sched_get_priority_max|sched_get_priority_min|sched_rr_get_interval|nanosleep|mremap
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4175, 42, 41), //bind|connect|getpeername|getsockname|getsockopt|listen
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4178, 41, 40), //recvfrom|recvmsg
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4210, 7, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4190, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4188, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4187, 37, 36), //sendmsg|sendto|setsockopt|shutdown|socket|socketpair|setresuid|getresuid
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4189, 36, 35), //poll
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4203, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4202, 34, 33), //setresgid|getresgid|prctl|rt_sigreturn|rt_sigaction|rt_sigprocmask|rt_sigpending|rt_sigtimedwait|rt_sigqueueinfo|rt_sigsuspend|pread64|pwrite64
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4208, 33, 32), //getcwd|capget|capset|sigaltstack|sendfile
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4222, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4217, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4216, 30, 29), //mmap2|truncate64|ftruncate64|stat64|lstat64|fstat64
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4221, 29, 28), //mincore|madvise|getdents64|fcntl64
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4247, 28, 27), //gettid|readahead|setxattr|lsetxattr|fsetxattr|getxattr|lgetxattr|fgetxattr|listxattr|llistxattr|flistxattr|removexattr|lremovexattr|fremovexattr|tkill|sendfile64|futex|sched_setaffinity|sched_getaffinity|io_setup|io_destroy|io_getevents|io_submit|io_cancel|exit_group
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4316, 13, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4288, 7, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4280, 3, 0),
diff --git a/libc/seccomp/x86_64_global_policy.cpp b/libc/seccomp/x86_64_global_policy.cpp
index 71be1c1..801d6c2 100644
--- a/libc/seccomp/x86_64_global_policy.cpp
+++ b/libc/seccomp/x86_64_global_policy.cpp
@@ -5,81 +5,83 @@
#include "seccomp_bpfs.h"
const sock_filter x86_64_global_filter[] = {
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 0, 0, 86),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 0, 0, 88),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 175, 43, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 79, 21, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 35, 11, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 8, 5, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 5, 3, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 3, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 2, 79, 78), //read|write
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4, 78, 77), //close
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 6, 77, 76), //fstat
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 2, 81, 80), //read|write
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 4, 80, 79), //close
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 6, 79, 78), //fstat
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 32, 3, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 24, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 21, 74, 73), //lseek|mmap|mprotect|munmap|brk|rt_sigaction|rt_sigprocmask|rt_sigreturn|ioctl|pread64|pwrite64|readv|writev
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 29, 73, 72), //sched_yield|mremap|msync|mincore|madvise
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 33, 72, 71), //dup
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 21, 76, 75), //lseek|mmap|mprotect|munmap|brk|rt_sigaction|rt_sigprocmask|rt_sigreturn|ioctl|pread64|pwrite64|readv|writev
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 29, 75, 74), //sched_yield|mremap|msync|mincore|madvise
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 33, 74, 73), //dup
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 58, 5, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 44, 3, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 38, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 37, 68, 67), //nanosleep|getitimer
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 43, 67, 66), //setitimer|getpid|sendfile|socket|connect
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 57, 66, 65), //sendto|recvfrom|sendmsg|recvmsg|shutdown|bind|listen|getsockname|getpeername|socketpair|setsockopt|getsockopt|clone
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 37, 70, 69), //nanosleep|getitimer
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 43, 69, 68), //setitimer|getpid|sendfile|socket|connect
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 57, 68, 67), //sendto|recvfrom|sendmsg|recvmsg|shutdown|bind|listen|getsockname|getpeername|socketpair|setsockopt|getsockopt|clone
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 72, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 64, 64, 63), //vfork|execve|exit|wait4|kill|uname
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 78, 63, 62), //fcntl|flock|fsync|fdatasync|truncate|ftruncate
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 64, 66, 65), //vfork|execve|exit|wait4|kill|uname
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 78, 65, 64), //fcntl|flock|fsync|fdatasync|truncate|ftruncate
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 137, 11, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 95, 5, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 93, 3, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 91, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 82, 58, 57), //getcwd|chdir|fchdir
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 92, 57, 56), //fchmod
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 94, 56, 55), //fchown
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 82, 60, 59), //getcwd|chdir|fchdir
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 92, 59, 58), //fchmod
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 94, 58, 57), //fchown
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 135, 3, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 112, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 111, 53, 52), //umask|gettimeofday|getrlimit|getrusage|sysinfo|times|ptrace|getuid|syslog|getgid|setuid|setgid|geteuid|getegid|setpgid|getppid
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 132, 52, 51), //setsid|setreuid|setregid|getgroups|setgroups|setresuid|getresuid|setresgid|getresgid|getpgid|setfsuid|setfsgid|getsid|capget|capset|rt_sigpending|rt_sigtimedwait|rt_sigqueueinfo|rt_sigsuspend|sigaltstack
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 136, 51, 50), //personality
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 111, 55, 54), //umask|gettimeofday|getrlimit|getrusage|sysinfo|times|ptrace|getuid|syslog|getgid|setuid|setgid|geteuid|getegid|setpgid|getppid
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 132, 54, 53), //setsid|setreuid|setregid|getgroups|setgroups|setresuid|getresuid|setresgid|getresgid|getpgid|setfsuid|setfsgid|getsid|capget|capset|rt_sigpending|rt_sigtimedwait|rt_sigqueueinfo|rt_sigsuspend|sigaltstack
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 136, 53, 52), //personality
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 157, 5, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 155, 3, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 140, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 139, 47, 46), //statfs|fstatfs
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 153, 46, 45), //getpriority|setpriority|sched_setparam|sched_getparam|sched_setscheduler|sched_getscheduler|sched_get_priority_max|sched_get_priority_min|sched_rr_get_interval|mlock|munlock|mlockall|munlockall
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 156, 45, 44), //pivot_root
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 139, 49, 48), //statfs|fstatfs
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 153, 48, 47), //getpriority|setpriority|sched_setparam|sched_getparam|sched_setscheduler|sched_getscheduler|sched_get_priority_max|sched_get_priority_min|sched_rr_get_interval|mlock|munlock|mlockall|munlockall
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 156, 47, 46), //pivot_root
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 169, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 168, 43, 42), //prctl|arch_prctl|adjtimex|setrlimit|chroot|sync|acct|settimeofday|mount|umount2|swapon
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 172, 42, 41), //reboot|sethostname|setdomainname
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 262, 21, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 233, 11, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 168, 45, 44), //prctl|arch_prctl|adjtimex|setrlimit|chroot|sync|acct|settimeofday|mount|umount2|swapon
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 172, 44, 43), //reboot|sethostname|setdomainname
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 257, 21, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 221, 11, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 202, 5, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 186, 3, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 179, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 177, 36, 35), //init_module|delete_module
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 180, 35, 34), //quotactl
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 201, 34, 33), //gettid|readahead|setxattr|lsetxattr|fsetxattr|getxattr|lgetxattr|fgetxattr|listxattr|llistxattr|flistxattr|removexattr|lremovexattr|fremovexattr|tkill
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 221, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 217, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 205, 31, 30), //futex|sched_setaffinity|sched_getaffinity
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 220, 30, 29), //getdents64|set_tid_address|restart_syscall
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 232, 29, 28), //fadvise64|timer_create|timer_settime|timer_gettime|timer_getoverrun|timer_delete|clock_settime|clock_gettime|clock_getres|clock_nanosleep|exit_group
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 254, 5, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 250, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 247, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 235, 25, 24), //epoll_ctl|tgkill
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 249, 24, 23), //waitid|add_key
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 177, 38, 37), //init_module|delete_module
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 180, 37, 36), //quotactl
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 201, 36, 35), //gettid|readahead|setxattr|lsetxattr|fsetxattr|getxattr|lgetxattr|fgetxattr|listxattr|llistxattr|flistxattr|removexattr|lremovexattr|fremovexattr|tkill
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 217, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 206, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 205, 33, 32), //futex|sched_setaffinity|sched_getaffinity
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 211, 32, 31), //io_setup|io_destroy|io_getevents|io_submit|io_cancel
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 220, 31, 30), //getdents64|set_tid_address|restart_syscall
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 250, 5, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 247, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 233, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 232, 27, 26), //fadvise64|timer_create|timer_settime|timer_gettime|timer_getoverrun|timer_delete|clock_settime|clock_gettime|clock_getres|clock_nanosleep|exit_group
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 235, 26, 25), //epoll_ctl|tgkill
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 249, 25, 24), //waitid|add_key
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 254, 1, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 253, 23, 22), //keyctl|ioprio_set|ioprio_get
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 257, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 256, 21, 20), //inotify_add_watch|inotify_rm_watch
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 261, 20, 19), //openat|mkdirat|mknodat|fchownat
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 302, 9, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 283, 5, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 280, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 275, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 273, 15, 14), //newfstatat|unlinkat|renameat|linkat|symlinkat|readlinkat|fchmodat|faccessat|pselect6|ppoll|unshare
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 279, 14, 13), //splice|tee|sync_file_range|vmsplice
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 282, 13, 12), //utimensat|epoll_pwait
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 285, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 256, 22, 21), //inotify_add_watch|inotify_rm_watch
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 302, 11, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 280, 5, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 275, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 262, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 261, 17, 16), //openat|mkdirat|mknodat|fchownat
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 273, 16, 15), //newfstatat|unlinkat|renameat|linkat|symlinkat|readlinkat|fchmodat|faccessat|pselect6|ppoll|unshare
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 279, 15, 14), //splice|tee|sync_file_range|vmsplice
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 285, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 283, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 282, 12, 11), //utimensat|epoll_pwait
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 284, 11, 10), //timerfd_create
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 300, 10, 9), //fallocate|timerfd_settime|timerfd_gettime|accept4|signalfd4|eventfd2|epoll_create1|dup3|pipe2|inotify_init1|preadv|pwritev|rt_tgsigqueueinfo|perf_event_open|recvmmsg
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 322, 5, 0),
diff --git a/libc/seccomp/x86_global_policy.cpp b/libc/seccomp/x86_global_policy.cpp
index 36f4884..9305729 100644
--- a/libc/seccomp/x86_global_policy.cpp
+++ b/libc/seccomp/x86_global_policy.cpp
@@ -5,109 +5,111 @@
#include "seccomp_bpfs.h"
const sock_filter x86_global_filter[] = {
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 0, 0, 118),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 0, 0, 120),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 136, 59, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 66, 29, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 41, 15, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 24, 7, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 10, 3, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 8, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 7, 111, 110), //restart_syscall|exit|fork|read|write|open|close
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 9, 110, 109), //creat
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 7, 113, 112), //restart_syscall|exit|fork|read|write|open|close
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 9, 112, 111), //creat
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 19, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 13, 108, 107), //unlink|execve|chdir
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 22, 107, 106), //lseek|getpid|mount
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 13, 110, 109), //unlink|execve|chdir
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 22, 109, 108), //lseek|getpid|mount
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 33, 3, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 26, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 25, 104, 103), //getuid
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 27, 103, 102), //ptrace
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 25, 106, 105), //getuid
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 27, 105, 104), //ptrace
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 36, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 34, 101, 100), //access
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 40, 100, 99), //sync|kill|rename|mkdir
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 34, 103, 102), //access
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 40, 102, 101), //sync|kill|rename|mkdir
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 57, 7, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 51, 3, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 45, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 44, 96, 95), //dup|pipe|times
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 46, 95, 94), //brk
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 44, 98, 97), //dup|pipe|times
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 46, 97, 96), //brk
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 54, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 53, 93, 92), //acct|umount2
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 56, 92, 91), //ioctl|fcntl
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 53, 95, 94), //acct|umount2
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 56, 94, 93), //ioctl|fcntl
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 63, 3, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 60, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 58, 89, 88), //setpgid
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 62, 88, 87), //umask|chroot
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 65, 87, 86), //dup2|getppid
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 58, 91, 90), //setpgid
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 62, 90, 89), //umask|chroot
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 65, 89, 88), //dup2|getppid
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 102, 15, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 87, 7, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 77, 3, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 74, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 68, 82, 81), //setsid|sigaction
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 76, 81, 80), //sethostname|setrlimit
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 68, 84, 83), //setsid|sigaction
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 76, 83, 82), //sethostname|setrlimit
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 85, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 80, 79, 78), //getrusage|gettimeofday|settimeofday
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 86, 78, 77), //readlink
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 80, 81, 80), //getrusage|gettimeofday|settimeofday
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 86, 80, 79), //readlink
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 94, 3, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 90, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 89, 75, 74), //swapon|reboot
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 93, 74, 73), //mmap|munmap|truncate
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 89, 77, 76), //swapon|reboot
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 93, 76, 75), //mmap|munmap|truncate
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 96, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 95, 72, 71), //fchmod
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 98, 71, 70), //getpriority|setpriority
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 95, 74, 73), //fchmod
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 98, 73, 72), //getpriority|setpriority
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 124, 7, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 116, 3, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 114, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 106, 67, 66), //socketcall|syslog|setitimer|getitimer
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 115, 66, 65), //wait4
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 106, 69, 68), //socketcall|syslog|setitimer|getitimer
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 115, 68, 67), //wait4
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 118, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 117, 64, 63), //sysinfo
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 123, 63, 62), //fsync|sigreturn|clone|setdomainname|uname
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 117, 66, 65), //sysinfo
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 123, 65, 64), //fsync|sigreturn|clone|setdomainname|uname
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 131, 3, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 128, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 126, 60, 59), //adjtimex|mprotect
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 130, 59, 58), //init_module|delete_module
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 134, 58, 57), //quotactl|getpgid|fchdir
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 286, 29, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 126, 62, 61), //adjtimex|mprotect
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 130, 61, 60), //init_module|delete_module
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 134, 60, 59), //quotactl|getpgid|fchdir
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 284, 29, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 213, 15, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 172, 7, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 150, 3, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 138, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 137, 52, 51), //personality
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 149, 51, 50), //setfsuid|setfsgid|_llseek|getdents|_newselect|flock|msync|readv|writev|getsid|fdatasync
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 137, 54, 53), //personality
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 149, 53, 52), //setfsuid|setfsgid|_llseek|getdents|_newselect|flock|msync|readv|writev|getsid|fdatasync
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 168, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 164, 49, 48), //mlock|munlock|mlockall|munlockall|sched_setparam|sched_getparam|sched_setscheduler|sched_getscheduler|sched_yield|sched_get_priority_max|sched_get_priority_min|sched_rr_get_interval|nanosleep|mremap
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 169, 48, 47), //poll
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 164, 51, 50), //mlock|munlock|mlockall|munlockall|sched_setparam|sched_getparam|sched_setscheduler|sched_getscheduler|sched_yield|sched_get_priority_max|sched_get_priority_min|sched_rr_get_interval|nanosleep|mremap
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 169, 50, 49), //poll
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 190, 3, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 183, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 182, 45, 44), //prctl|rt_sigreturn|rt_sigaction|rt_sigprocmask|rt_sigpending|rt_sigtimedwait|rt_sigqueueinfo|rt_sigsuspend|pread64|pwrite64
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 188, 44, 43), //getcwd|capget|capset|sigaltstack|sendfile
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 182, 47, 46), //prctl|rt_sigreturn|rt_sigaction|rt_sigprocmask|rt_sigpending|rt_sigtimedwait|rt_sigqueueinfo|rt_sigsuspend|pread64|pwrite64
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 188, 46, 45), //getcwd|capget|capset|sigaltstack|sendfile
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 199, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 198, 42, 41), //vfork|ugetrlimit|mmap2|truncate64|ftruncate64|stat64|lstat64|fstat64
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 212, 41, 40), //getuid32|getgid32|geteuid32|getegid32|setreuid32|setregid32|getgroups32|setgroups32|fchown32|setresuid32|getresuid32|setresgid32|getresgid32
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 254, 7, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 198, 44, 43), //vfork|ugetrlimit|mmap2|truncate64|ftruncate64|stat64|lstat64|fstat64
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 212, 43, 42), //getuid32|getgid32|geteuid32|getegid32|setreuid32|setregid32|getgroups32|setgroups32|fchown32|setresuid32|getresuid32|setresgid32|getresgid32
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 252, 7, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 224, 3, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 218, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 215, 37, 36), //setuid32|setgid32
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 222, 36, 35), //mincore|madvise|getdents64|fcntl64
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 252, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 244, 34, 33), //gettid|readahead|setxattr|lsetxattr|fsetxattr|getxattr|lgetxattr|fgetxattr|listxattr|llistxattr|flistxattr|removexattr|lremovexattr|fremovexattr|tkill|sendfile64|futex|sched_setaffinity|sched_getaffinity|set_thread_area
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 253, 33, 32), //exit_group
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 284, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 272, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 271, 30, 29), //epoll_create|epoll_ctl|epoll_wait|remap_file_pages|set_tid_address|timer_create|timer_settime|timer_gettime|timer_getoverrun|timer_delete|clock_settime|clock_gettime|clock_getres|clock_nanosleep|statfs64|fstatfs64|tgkill
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 273, 29, 28), //fadvise64_64
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 285, 28, 27), //waitid
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 322, 13, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 300, 7, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 291, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 288, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 287, 23, 22), //add_key
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 215, 39, 38), //setuid32|setgid32
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 222, 38, 37), //mincore|madvise|getdents64|fcntl64
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 245, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 244, 36, 35), //gettid|readahead|setxattr|lsetxattr|fsetxattr|getxattr|lgetxattr|fgetxattr|listxattr|llistxattr|flistxattr|removexattr|lremovexattr|fremovexattr|tkill|sendfile64|futex|sched_setaffinity|sched_getaffinity|set_thread_area
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 250, 35, 34), //io_setup|io_destroy|io_getevents|io_submit|io_cancel
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 272, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 254, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 253, 32, 31), //exit_group
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 271, 31, 30), //epoll_create|epoll_ctl|epoll_wait|remap_file_pages|set_tid_address|timer_create|timer_settime|timer_gettime|timer_getoverrun|timer_delete|clock_settime|clock_gettime|clock_getres|clock_nanosleep|statfs64|fstatfs64|tgkill
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 273, 30, 29), //fadvise64_64
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 322, 15, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 295, 7, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 288, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 286, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 285, 25, 24), //waitid
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 287, 24, 23), //add_key
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 291, 1, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 289, 22, 21), //keyctl
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 295, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 294, 20, 19), //inotify_init|inotify_add_watch|inotify_rm_watch
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 299, 19, 18), //openat|mkdirat|mknodat|fchownat
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 318, 3, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 313, 1, 0),
-BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 311, 16, 15), //fstatat64|unlinkat|renameat|linkat|symlinkat|readlinkat|fchmodat|faccessat|pselect6|ppoll|unshare
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 294, 21, 20), //inotify_init|inotify_add_watch|inotify_rm_watch
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 313, 3, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 300, 1, 0),
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 299, 18, 17), //openat|mkdirat|mknodat|fchownat
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 311, 17, 16), //fstatat64|unlinkat|renameat|linkat|symlinkat|readlinkat|fchmodat|faccessat|pselect6|ppoll|unshare
+BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 318, 1, 0),
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 317, 15, 14), //splice|sync_file_range|tee|vmsplice
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 321, 14, 13), //getcpu|epoll_pwait|utimensat
BPF_JUMP(BPF_JMP|BPF_JGE|BPF_K, 350, 7, 0),
diff --git a/libc/upstream-freebsd/android/include/collate.h b/libc/upstream-freebsd/android/include/collate.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/libc/upstream-freebsd/android/include/collate.h
diff --git a/libc/upstream-freebsd/android/include/freebsd-compat.h b/libc/upstream-freebsd/android/include/freebsd-compat.h
index 7acdf7c..8f0a307 100644
--- a/libc/upstream-freebsd/android/include/freebsd-compat.h
+++ b/libc/upstream-freebsd/android/include/freebsd-compat.h
@@ -18,6 +18,10 @@
#define _BIONIC_FREEBSD_COMPAT_H_included
#define _BSD_SOURCE
+
+#include <sys/cdefs.h>
+#include <stddef.h> // For size_t.
+
#define REPLACE_GETOPT
/*
@@ -40,4 +44,12 @@
/* Redirect internal C library calls to the public function. */
#define _nanosleep nanosleep
+/* FreeBSD has this as API, but we just use it internally. */
+void* reallocarray(void*, size_t, size_t);
+
+/* FreeBSD has this, but we can't really implement it correctly on Linux. */
+#define issetugid() 0
+
+#define ARG_MAX sysconf(_SC_ARG_MAX)
+
#endif
diff --git a/libc/upstream-freebsd/lib/libc/gen/glob.c b/libc/upstream-freebsd/lib/libc/gen/glob.c
new file mode 100644
index 0000000..026f68e
--- /dev/null
+++ b/libc/upstream-freebsd/lib/libc/gen/glob.c
@@ -0,0 +1,1125 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Guido van Rossum.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)glob.c 8.3 (Berkeley) 10/13/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: head/lib/libc/gen/glob.c 317913 2017-05-07 19:52:56Z jilles $");
+
+/*
+ * glob(3) -- a superset of the one defined in POSIX 1003.2.
+ *
+ * The [!...] convention to negate a range is supported (SysV, Posix, ksh).
+ *
+ * Optional extra services, controlled by flags not defined by POSIX:
+ *
+ * GLOB_QUOTE:
+ * Escaping convention: \ inhibits any special meaning the following
+ * character might have (except \ at end of string is retained).
+ * GLOB_MAGCHAR:
+ * Set in gl_flags if pattern contained a globbing character.
+ * GLOB_NOMAGIC:
+ * Same as GLOB_NOCHECK, but it will only append pattern if it did
+ * not contain any magic characters. [Used in csh style globbing]
+ * GLOB_ALTDIRFUNC:
+ * Use alternately specified directory access functions.
+ * GLOB_TILDE:
+ * expand ~user/foo to the /home/dir/of/user/foo
+ * GLOB_BRACE:
+ * expand {1,2}{a,b} to 1a 1b 2a 2b
+ * gl_matchc:
+ * Number of matches in the current invocation of glob.
+ */
+
+/*
+ * Some notes on multibyte character support:
+ * 1. Patterns with illegal byte sequences match nothing - even if
+ * GLOB_NOCHECK is specified.
+ * 2. Illegal byte sequences in filenames are handled by treating them as
+ * single-byte characters with a values of such bytes of the sequence
+ * cast to wchar_t.
+ * 3. State-dependent encodings are not currently supported.
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <dirent.h>
+#include <errno.h>
+#include <glob.h>
+#include <limits.h>
+#include <pwd.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <wchar.h>
+
+#include "collate.h"
+
+/*
+ * glob(3) expansion limits. Stop the expansion if any of these limits
+ * is reached. This caps the runtime in the face of DoS attacks. See
+ * also CVE-2010-2632
+ */
+#define GLOB_LIMIT_BRACE 128 /* number of brace calls */
+#define GLOB_LIMIT_PATH 65536 /* number of path elements */
+#define GLOB_LIMIT_READDIR 16384 /* number of readdirs */
+#define GLOB_LIMIT_STAT 1024 /* number of stat system calls */
+#define GLOB_LIMIT_STRING ARG_MAX /* maximum total size for paths */
+
+struct glob_limit {
+ size_t l_brace_cnt;
+ size_t l_path_lim;
+ size_t l_readdir_cnt;
+ size_t l_stat_cnt;
+ size_t l_string_cnt;
+};
+
+#define DOT L'.'
+#define EOS L'\0'
+#define LBRACKET L'['
+#define NOT L'!'
+#define QUESTION L'?'
+#define QUOTE L'\\'
+#define RANGE L'-'
+#define RBRACKET L']'
+#define SEP L'/'
+#define STAR L'*'
+#define TILDE L'~'
+#define LBRACE L'{'
+#define RBRACE L'}'
+#define COMMA L','
+
+#define M_QUOTE 0x8000000000ULL
+#define M_PROTECT 0x4000000000ULL
+#define M_MASK 0xffffffffffULL
+#define M_CHAR 0x00ffffffffULL
+
+typedef uint_fast64_t Char;
+
+#define CHAR(c) ((Char)((c)&M_CHAR))
+#define META(c) ((Char)((c)|M_QUOTE))
+#define UNPROT(c) ((c) & ~M_PROTECT)
+#define M_ALL META(L'*')
+#define M_END META(L']')
+#define M_NOT META(L'!')
+#define M_ONE META(L'?')
+#define M_RNG META(L'-')
+#define M_SET META(L'[')
+#define ismeta(c) (((c)&M_QUOTE) != 0)
+#ifdef DEBUG
+#define isprot(c) (((c)&M_PROTECT) != 0)
+#endif
+
+static int compare(const void *, const void *);
+static int g_Ctoc(const Char *, char *, size_t);
+static int g_lstat(Char *, struct stat *, glob_t *);
+static DIR *g_opendir(Char *, glob_t *);
+static const Char *g_strchr(const Char *, wchar_t);
+#ifdef notdef
+static Char *g_strcat(Char *, const Char *);
+#endif
+static int g_stat(Char *, struct stat *, glob_t *);
+static int glob0(const Char *, glob_t *, struct glob_limit *,
+ const char *);
+static int glob1(Char *, glob_t *, struct glob_limit *);
+static int glob2(Char *, Char *, Char *, Char *, glob_t *,
+ struct glob_limit *);
+static int glob3(Char *, Char *, Char *, Char *, Char *, glob_t *,
+ struct glob_limit *);
+static int globextend(const Char *, glob_t *, struct glob_limit *,
+ const char *);
+static const Char *
+ globtilde(const Char *, Char *, size_t, glob_t *);
+static int globexp0(const Char *, glob_t *, struct glob_limit *,
+ const char *);
+static int globexp1(const Char *, glob_t *, struct glob_limit *);
+static int globexp2(const Char *, const Char *, glob_t *,
+ struct glob_limit *);
+static int globfinal(glob_t *, struct glob_limit *, size_t,
+ const char *);
+static int match(Char *, Char *, Char *);
+static int err_nomatch(glob_t *, struct glob_limit *, const char *);
+static int err_aborted(glob_t *, int, char *);
+#ifdef DEBUG
+static void qprintf(const char *, Char *);
+#endif
+
+int
+glob(const char * __restrict pattern, int flags,
+ int (*errfunc)(const char *, int), glob_t * __restrict pglob)
+{
+ struct glob_limit limit = { 0, 0, 0, 0, 0 };
+ const char *patnext;
+ Char *bufnext, *bufend, patbuf[MAXPATHLEN], prot;
+ mbstate_t mbs;
+ wchar_t wc;
+ size_t clen;
+ int too_long;
+
+ patnext = pattern;
+ if (!(flags & GLOB_APPEND)) {
+ pglob->gl_pathc = 0;
+ pglob->gl_pathv = NULL;
+ if (!(flags & GLOB_DOOFFS))
+ pglob->gl_offs = 0;
+ }
+ if (flags & GLOB_LIMIT) {
+ limit.l_path_lim = pglob->gl_matchc;
+ if (limit.l_path_lim == 0)
+ limit.l_path_lim = GLOB_LIMIT_PATH;
+ }
+ pglob->gl_flags = flags & ~GLOB_MAGCHAR;
+ pglob->gl_errfunc = errfunc;
+ pglob->gl_matchc = 0;
+
+ bufnext = patbuf;
+ bufend = bufnext + MAXPATHLEN - 1;
+ too_long = 1;
+ if (flags & GLOB_NOESCAPE) {
+ memset(&mbs, 0, sizeof(mbs));
+ while (bufnext <= bufend) {
+ clen = mbrtowc(&wc, patnext, MB_LEN_MAX, &mbs);
+ if (clen == (size_t)-1 || clen == (size_t)-2)
+ return (err_nomatch(pglob, &limit, pattern));
+ else if (clen == 0) {
+ too_long = 0;
+ break;
+ }
+ *bufnext++ = wc;
+ patnext += clen;
+ }
+ } else {
+ /* Protect the quoted characters. */
+ memset(&mbs, 0, sizeof(mbs));
+ while (bufnext <= bufend) {
+ if (*patnext == '\\') {
+ if (*++patnext == '\0') {
+ *bufnext++ = QUOTE;
+ continue;
+ }
+ prot = M_PROTECT;
+ } else
+ prot = 0;
+ clen = mbrtowc(&wc, patnext, MB_LEN_MAX, &mbs);
+ if (clen == (size_t)-1 || clen == (size_t)-2)
+ return (err_nomatch(pglob, &limit, pattern));
+ else if (clen == 0) {
+ too_long = 0;
+ break;
+ }
+ *bufnext++ = wc | prot;
+ patnext += clen;
+ }
+ }
+ if (too_long)
+ return (err_nomatch(pglob, &limit, pattern));
+ *bufnext = EOS;
+
+ if (flags & GLOB_BRACE)
+ return (globexp0(patbuf, pglob, &limit, pattern));
+ else
+ return (glob0(patbuf, pglob, &limit, pattern));
+}
+
+static int
+globexp0(const Char *pattern, glob_t *pglob, struct glob_limit *limit,
+ const char *origpat) {
+ int rv;
+ size_t oldpathc;
+
+ /* Protect a single {}, for find(1), like csh */
+ if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS) {
+ if ((pglob->gl_flags & GLOB_LIMIT) &&
+ limit->l_brace_cnt++ >= GLOB_LIMIT_BRACE) {
+ errno = E2BIG;
+ return (GLOB_NOSPACE);
+ }
+ return (glob0(pattern, pglob, limit, origpat));
+ }
+
+ oldpathc = pglob->gl_pathc;
+
+ if ((rv = globexp1(pattern, pglob, limit)) != 0)
+ return rv;
+
+ return (globfinal(pglob, limit, oldpathc, origpat));
+}
+
+/*
+ * Expand recursively a glob {} pattern. When there is no more expansion
+ * invoke the standard globbing routine to glob the rest of the magic
+ * characters
+ */
+static int
+globexp1(const Char *pattern, glob_t *pglob, struct glob_limit *limit)
+{
+ const Char* ptr;
+
+ if ((ptr = g_strchr(pattern, LBRACE)) != NULL) {
+ if ((pglob->gl_flags & GLOB_LIMIT) &&
+ limit->l_brace_cnt++ >= GLOB_LIMIT_BRACE) {
+ errno = E2BIG;
+ return (GLOB_NOSPACE);
+ }
+ return (globexp2(ptr, pattern, pglob, limit));
+ }
+
+ return (glob0(pattern, pglob, limit, NULL));
+}
+
+
+/*
+ * Recursive brace globbing helper. Tries to expand a single brace.
+ * If it succeeds then it invokes globexp1 with the new pattern.
+ * If it fails then it tries to glob the rest of the pattern and returns.
+ */
+static int
+globexp2(const Char *ptr, const Char *pattern, glob_t *pglob,
+ struct glob_limit *limit)
+{
+ int i, rv;
+ Char *lm, *ls;
+ const Char *pe, *pm, *pm1, *pl;
+ Char patbuf[MAXPATHLEN];
+
+ /* copy part up to the brace */
+ for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++)
+ continue;
+ *lm = EOS;
+ ls = lm;
+
+ /* Find the balanced brace */
+ for (i = 0, pe = ++ptr; *pe != EOS; pe++)
+ if (*pe == LBRACKET) {
+ /* Ignore everything between [] */
+ for (pm = pe++; *pe != RBRACKET && *pe != EOS; pe++)
+ continue;
+ if (*pe == EOS) {
+ /*
+ * We could not find a matching RBRACKET.
+ * Ignore and just look for RBRACE
+ */
+ pe = pm;
+ }
+ }
+ else if (*pe == LBRACE)
+ i++;
+ else if (*pe == RBRACE) {
+ if (i == 0)
+ break;
+ i--;
+ }
+
+ /* Non matching braces; just glob the pattern */
+ if (i != 0 || *pe == EOS)
+ return (glob0(pattern, pglob, limit, NULL));
+
+ for (i = 0, pl = pm = ptr; pm <= pe; pm++)
+ switch (*pm) {
+ case LBRACKET:
+ /* Ignore everything between [] */
+ for (pm1 = pm++; *pm != RBRACKET && *pm != EOS; pm++)
+ continue;
+ if (*pm == EOS) {
+ /*
+ * We could not find a matching RBRACKET.
+ * Ignore and just look for RBRACE
+ */
+ pm = pm1;
+ }
+ break;
+
+ case LBRACE:
+ i++;
+ break;
+
+ case RBRACE:
+ if (i) {
+ i--;
+ break;
+ }
+ /* FALLTHROUGH */
+ case COMMA:
+ if (i && *pm == COMMA)
+ break;
+ else {
+ /* Append the current string */
+ for (lm = ls; (pl < pm); *lm++ = *pl++)
+ continue;
+ /*
+ * Append the rest of the pattern after the
+ * closing brace
+ */
+ for (pl = pe + 1; (*lm++ = *pl++) != EOS;)
+ continue;
+
+ /* Expand the current pattern */
+#ifdef DEBUG
+ qprintf("globexp2:", patbuf);
+#endif
+ rv = globexp1(patbuf, pglob, limit);
+ if (rv)
+ return (rv);
+
+ /* move after the comma, to the next string */
+ pl = pm + 1;
+ }
+ break;
+
+ default:
+ break;
+ }
+ return (0);
+}
+
+
+
+/*
+ * expand tilde from the passwd file.
+ */
+static const Char *
+globtilde(const Char *pattern, Char *patbuf, size_t patbuf_len, glob_t *pglob)
+{
+ struct passwd *pwd;
+ char *h, *sc;
+ const Char *p;
+ Char *b, *eb;
+ wchar_t wc;
+ wchar_t wbuf[MAXPATHLEN];
+ wchar_t *wbufend, *dc;
+ size_t clen;
+ mbstate_t mbs;
+ int too_long;
+
+ if (*pattern != TILDE || !(pglob->gl_flags & GLOB_TILDE))
+ return (pattern);
+
+ /*
+ * Copy up to the end of the string or /
+ */
+ eb = &patbuf[patbuf_len - 1];
+ for (p = pattern + 1, b = patbuf;
+ b < eb && *p != EOS && UNPROT(*p) != SEP; *b++ = *p++)
+ continue;
+
+ if (*p != EOS && UNPROT(*p) != SEP)
+ return (NULL);
+
+ *b = EOS;
+ h = NULL;
+
+ if (patbuf[0] == EOS) {
+ /*
+ * handle a plain ~ or ~/ by expanding $HOME first (iff
+ * we're not running setuid or setgid) and then trying
+ * the password file
+ */
+ if (issetugid() != 0 ||
+ (h = getenv("HOME")) == NULL) {
+ if (((h = getlogin()) != NULL &&
+ (pwd = getpwnam(h)) != NULL) ||
+ (pwd = getpwuid(getuid())) != NULL)
+ h = pwd->pw_dir;
+ else
+ return (pattern);
+ }
+ }
+ else {
+ /*
+ * Expand a ~user
+ */
+ if (g_Ctoc(patbuf, (char *)wbuf, sizeof(wbuf)))
+ return (NULL);
+ if ((pwd = getpwnam((char *)wbuf)) == NULL)
+ return (pattern);
+ else
+ h = pwd->pw_dir;
+ }
+
+ /* Copy the home directory */
+ dc = wbuf;
+ sc = h;
+ wbufend = wbuf + MAXPATHLEN - 1;
+ too_long = 1;
+ memset(&mbs, 0, sizeof(mbs));
+ while (dc <= wbufend) {
+ clen = mbrtowc(&wc, sc, MB_LEN_MAX, &mbs);
+ if (clen == (size_t)-1 || clen == (size_t)-2) {
+ /* XXX See initial comment #2. */
+ wc = (unsigned char)*sc;
+ clen = 1;
+ memset(&mbs, 0, sizeof(mbs));
+ }
+ if ((*dc++ = wc) == EOS) {
+ too_long = 0;
+ break;
+ }
+ sc += clen;
+ }
+ if (too_long)
+ return (NULL);
+
+ dc = wbuf;
+ for (b = patbuf; b < eb && *dc != EOS; *b++ = *dc++ | M_PROTECT)
+ continue;
+ if (*dc != EOS)
+ return (NULL);
+
+ /* Append the rest of the pattern */
+ if (*p != EOS) {
+ too_long = 1;
+ while (b <= eb) {
+ if ((*b++ = *p++) == EOS) {
+ too_long = 0;
+ break;
+ }
+ }
+ if (too_long)
+ return (NULL);
+ } else
+ *b = EOS;
+
+ return (patbuf);
+}
+
+
+/*
+ * The main glob() routine: compiles the pattern (optionally processing
+ * quotes), calls glob1() to do the real pattern matching, and finally
+ * sorts the list (unless unsorted operation is requested). Returns 0
+ * if things went well, nonzero if errors occurred.
+ */
+static int
+glob0(const Char *pattern, glob_t *pglob, struct glob_limit *limit,
+ const char *origpat) {
+ const Char *qpatnext;
+ int err;
+ size_t oldpathc;
+ Char *bufnext, c, patbuf[MAXPATHLEN];
+
+ qpatnext = globtilde(pattern, patbuf, MAXPATHLEN, pglob);
+ if (qpatnext == NULL) {
+ errno = E2BIG;
+ return (GLOB_NOSPACE);
+ }
+ oldpathc = pglob->gl_pathc;
+ bufnext = patbuf;
+
+ /* We don't need to check for buffer overflow any more. */
+ while ((c = *qpatnext++) != EOS) {
+ switch (c) {
+ case LBRACKET:
+ c = *qpatnext;
+ if (c == NOT)
+ ++qpatnext;
+ if (*qpatnext == EOS ||
+ g_strchr(qpatnext+1, RBRACKET) == NULL) {
+ *bufnext++ = LBRACKET;
+ if (c == NOT)
+ --qpatnext;
+ break;
+ }
+ *bufnext++ = M_SET;
+ if (c == NOT)
+ *bufnext++ = M_NOT;
+ c = *qpatnext++;
+ do {
+ *bufnext++ = CHAR(c);
+ if (*qpatnext == RANGE &&
+ (c = qpatnext[1]) != RBRACKET) {
+ *bufnext++ = M_RNG;
+ *bufnext++ = CHAR(c);
+ qpatnext += 2;
+ }
+ } while ((c = *qpatnext++) != RBRACKET);
+ pglob->gl_flags |= GLOB_MAGCHAR;
+ *bufnext++ = M_END;
+ break;
+ case QUESTION:
+ pglob->gl_flags |= GLOB_MAGCHAR;
+ *bufnext++ = M_ONE;
+ break;
+ case STAR:
+ pglob->gl_flags |= GLOB_MAGCHAR;
+ /* collapse adjacent stars to one,
+ * to ensure "**" at the end continues to match the
+ * empty string
+ */
+ if (bufnext == patbuf || bufnext[-1] != M_ALL)
+ *bufnext++ = M_ALL;
+ break;
+ default:
+ *bufnext++ = CHAR(c);
+ break;
+ }
+ }
+ *bufnext = EOS;
+#ifdef DEBUG
+ qprintf("glob0:", patbuf);
+#endif
+
+ if ((err = glob1(patbuf, pglob, limit)) != 0)
+ return(err);
+
+ if (origpat != NULL)
+ return (globfinal(pglob, limit, oldpathc, origpat));
+
+ return (0);
+}
+
+static int
+globfinal(glob_t *pglob, struct glob_limit *limit, size_t oldpathc,
+ const char *origpat) {
+ if (pglob->gl_pathc == oldpathc)
+ return (err_nomatch(pglob, limit, origpat));
+
+ if (!(pglob->gl_flags & GLOB_NOSORT))
+ qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc,
+ pglob->gl_pathc - oldpathc, sizeof(char *), compare);
+
+ return (0);
+}
+
+static int
+compare(const void *p, const void *q)
+{
+ return (strcoll(*(char **)p, *(char **)q));
+}
+
+static int
+glob1(Char *pattern, glob_t *pglob, struct glob_limit *limit)
+{
+ Char pathbuf[MAXPATHLEN];
+
+ /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */
+ if (*pattern == EOS)
+ return (0);
+ return (glob2(pathbuf, pathbuf, pathbuf + MAXPATHLEN - 1,
+ pattern, pglob, limit));
+}
+
+/*
+ * The functions glob2 and glob3 are mutually recursive; there is one level
+ * of recursion for each segment in the pattern that contains one or more
+ * meta characters.
+ */
+static int
+glob2(Char *pathbuf, Char *pathend, Char *pathend_last, Char *pattern,
+ glob_t *pglob, struct glob_limit *limit)
+{
+ struct stat sb;
+ Char *p, *q;
+ int anymeta;
+
+ /*
+ * Loop over pattern segments until end of pattern or until
+ * segment with meta character found.
+ */
+ for (anymeta = 0;;) {
+ if (*pattern == EOS) { /* End of pattern? */
+ *pathend = EOS;
+ if (g_lstat(pathbuf, &sb, pglob))
+ return (0);
+
+ if ((pglob->gl_flags & GLOB_LIMIT) &&
+ limit->l_stat_cnt++ >= GLOB_LIMIT_STAT) {
+ errno = E2BIG;
+ return (GLOB_NOSPACE);
+ }
+ if ((pglob->gl_flags & GLOB_MARK) &&
+ UNPROT(pathend[-1]) != SEP &&
+ (S_ISDIR(sb.st_mode) ||
+ (S_ISLNK(sb.st_mode) &&
+ g_stat(pathbuf, &sb, pglob) == 0 &&
+ S_ISDIR(sb.st_mode)))) {
+ if (pathend + 1 > pathend_last) {
+ errno = E2BIG;
+ return (GLOB_NOSPACE);
+ }
+ *pathend++ = SEP;
+ *pathend = EOS;
+ }
+ ++pglob->gl_matchc;
+ return (globextend(pathbuf, pglob, limit, NULL));
+ }
+
+ /* Find end of next segment, copy tentatively to pathend. */
+ q = pathend;
+ p = pattern;
+ while (*p != EOS && UNPROT(*p) != SEP) {
+ if (ismeta(*p))
+ anymeta = 1;
+ if (q + 1 > pathend_last) {
+ errno = E2BIG;
+ return (GLOB_NOSPACE);
+ }
+ *q++ = *p++;
+ }
+
+ if (!anymeta) { /* No expansion, do next segment. */
+ pathend = q;
+ pattern = p;
+ while (UNPROT(*pattern) == SEP) {
+ if (pathend + 1 > pathend_last) {
+ errno = E2BIG;
+ return (GLOB_NOSPACE);
+ }
+ *pathend++ = *pattern++;
+ }
+ } else /* Need expansion, recurse. */
+ return (glob3(pathbuf, pathend, pathend_last, pattern,
+ p, pglob, limit));
+ }
+ /* NOTREACHED */
+}
+
+static int
+glob3(Char *pathbuf, Char *pathend, Char *pathend_last,
+ Char *pattern, Char *restpattern,
+ glob_t *pglob, struct glob_limit *limit)
+{
+ struct dirent *dp;
+ DIR *dirp;
+ int err, too_long, saverrno, saverrno2;
+ char buf[MAXPATHLEN + MB_LEN_MAX - 1];
+
+ struct dirent *(*readdirfunc)(DIR *);
+
+ if (pathend > pathend_last) {
+ errno = E2BIG;
+ return (GLOB_NOSPACE);
+ }
+ *pathend = EOS;
+ if (pglob->gl_errfunc != NULL &&
+ g_Ctoc(pathbuf, buf, sizeof(buf))) {
+ errno = E2BIG;
+ return (GLOB_NOSPACE);
+ }
+
+ saverrno = errno;
+ errno = 0;
+ if ((dirp = g_opendir(pathbuf, pglob)) == NULL) {
+ if (errno == ENOENT || errno == ENOTDIR)
+ return (0);
+ err = err_aborted(pglob, errno, buf);
+ if (errno == 0)
+ errno = saverrno;
+ return (err);
+ }
+
+ err = 0;
+
+ /* pglob->gl_readdir takes a void *, fix this manually */
+ if (pglob->gl_flags & GLOB_ALTDIRFUNC)
+ readdirfunc = (struct dirent *(*)(DIR *))pglob->gl_readdir;
+ else
+ readdirfunc = readdir;
+
+ errno = 0;
+ /* Search directory for matching names. */
+ while ((dp = (*readdirfunc)(dirp)) != NULL) {
+ char *sc;
+ Char *dc;
+ wchar_t wc;
+ size_t clen;
+ mbstate_t mbs;
+
+ if ((pglob->gl_flags & GLOB_LIMIT) &&
+ limit->l_readdir_cnt++ >= GLOB_LIMIT_READDIR) {
+ errno = E2BIG;
+ err = GLOB_NOSPACE;
+ break;
+ }
+
+ /* Initial DOT must be matched literally. */
+ if (dp->d_name[0] == '.' && UNPROT(*pattern) != DOT) {
+ errno = 0;
+ continue;
+ }
+ memset(&mbs, 0, sizeof(mbs));
+ dc = pathend;
+ sc = dp->d_name;
+ too_long = 1;
+ while (dc <= pathend_last) {
+ clen = mbrtowc(&wc, sc, MB_LEN_MAX, &mbs);
+ if (clen == (size_t)-1 || clen == (size_t)-2) {
+ /* XXX See initial comment #2. */
+ wc = (unsigned char)*sc;
+ clen = 1;
+ memset(&mbs, 0, sizeof(mbs));
+ }
+ if ((*dc++ = wc) == EOS) {
+ too_long = 0;
+ break;
+ }
+ sc += clen;
+ }
+ if (too_long && (err = err_aborted(pglob, ENAMETOOLONG,
+ buf))) {
+ errno = ENAMETOOLONG;
+ break;
+ }
+ if (too_long || !match(pathend, pattern, restpattern)) {
+ *pathend = EOS;
+ errno = 0;
+ continue;
+ }
+ if (errno == 0)
+ errno = saverrno;
+ err = glob2(pathbuf, --dc, pathend_last, restpattern,
+ pglob, limit);
+ if (err)
+ break;
+ errno = 0;
+ }
+
+ saverrno2 = errno;
+ if (pglob->gl_flags & GLOB_ALTDIRFUNC)
+ (*pglob->gl_closedir)(dirp);
+ else
+ closedir(dirp);
+ errno = saverrno2;
+
+ if (err)
+ return (err);
+
+ if (dp == NULL && errno != 0 &&
+ (err = err_aborted(pglob, errno, buf)))
+ return (err);
+
+ if (errno == 0)
+ errno = saverrno;
+ return (0);
+}
+
+
+/*
+ * Extend the gl_pathv member of a glob_t structure to accommodate a new item,
+ * add the new item, and update gl_pathc.
+ *
+ * This assumes the BSD realloc, which only copies the block when its size
+ * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic
+ * behavior.
+ *
+ * Return 0 if new item added, error code if memory couldn't be allocated.
+ *
+ * Invariant of the glob_t structure:
+ * Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and
+ * gl_pathv points to (gl_offs + gl_pathc + 1) items.
+ */
+static int
+globextend(const Char *path, glob_t *pglob, struct glob_limit *limit,
+ const char *origpat)
+{
+ char **pathv;
+ size_t i, newn, len;
+ char *copy;
+ const Char *p;
+
+ if ((pglob->gl_flags & GLOB_LIMIT) &&
+ pglob->gl_matchc > limit->l_path_lim) {
+ errno = E2BIG;
+ return (GLOB_NOSPACE);
+ }
+
+ newn = 2 + pglob->gl_pathc + pglob->gl_offs;
+ /* reallocarray(NULL, newn, size) is equivalent to malloc(newn*size). */
+ pathv = reallocarray(pglob->gl_pathv, newn, sizeof(*pathv));
+ if (pathv == NULL)
+ return (GLOB_NOSPACE);
+
+ if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) {
+ /* first time around -- clear initial gl_offs items */
+ pathv += pglob->gl_offs;
+ for (i = pglob->gl_offs + 1; --i > 0; )
+ *--pathv = NULL;
+ }
+ pglob->gl_pathv = pathv;
+
+ if (origpat != NULL)
+ copy = strdup(origpat);
+ else {
+ for (p = path; *p++ != EOS;)
+ continue;
+ len = MB_CUR_MAX * (size_t)(p - path); /* XXX overallocation */
+ if ((copy = malloc(len)) != NULL) {
+ if (g_Ctoc(path, copy, len)) {
+ free(copy);
+ errno = E2BIG;
+ return (GLOB_NOSPACE);
+ }
+ }
+ }
+ if (copy != NULL) {
+ limit->l_string_cnt += strlen(copy) + 1;
+ if ((pglob->gl_flags & GLOB_LIMIT) &&
+ limit->l_string_cnt >= GLOB_LIMIT_STRING) {
+ free(copy);
+ errno = E2BIG;
+ return (GLOB_NOSPACE);
+ }
+ pathv[pglob->gl_offs + pglob->gl_pathc++] = copy;
+ }
+ pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
+ return (copy == NULL ? GLOB_NOSPACE : 0);
+}
+
+/*
+ * pattern matching function for filenames.
+ */
+static int
+match(Char *name, Char *pat, Char *patend)
+{
+ int ok, negate_range;
+ Char c, k, *nextp, *nextn;
+#if !defined(__BIONIC__)
+ struct xlocale_collate *table =
+ (struct xlocale_collate*)__get_locale()->components[XLC_COLLATE];
+#endif
+
+ nextn = NULL;
+ nextp = NULL;
+
+ while (1) {
+ while (pat < patend) {
+ c = *pat++;
+ switch (c & M_MASK) {
+ case M_ALL:
+ if (pat == patend)
+ return (1);
+ if (*name == EOS)
+ return (0);
+ nextn = name + 1;
+ nextp = pat - 1;
+ break;
+ case M_ONE:
+ if (*name++ == EOS)
+ goto fail;
+ break;
+ case M_SET:
+ ok = 0;
+ if ((k = *name++) == EOS)
+ goto fail;
+ negate_range = ((*pat & M_MASK) == M_NOT);
+ if (negate_range != 0)
+ ++pat;
+ while (((c = *pat++) & M_MASK) != M_END)
+ if ((*pat & M_MASK) == M_RNG) {
+#if defined(__BIONIC__)
+ if (c <= k && k <= pat[1])
+#else
+ if (table->__collate_load_error ?
+ CHAR(c) <= CHAR(k) &&
+ CHAR(k) <= CHAR(pat[1]) :
+ __wcollate_range_cmp(CHAR(c),
+ CHAR(k)) <= 0 &&
+ __wcollate_range_cmp(CHAR(k),
+ CHAR(pat[1])) <= 0)
+#endif
+ ok = 1;
+ pat += 2;
+ } else if (c == k)
+ ok = 1;
+ if (ok == negate_range)
+ goto fail;
+ break;
+ default:
+ if (*name++ != c)
+ goto fail;
+ break;
+ }
+ }
+ if (*name == EOS)
+ return (1);
+
+ fail:
+ if (nextn == NULL)
+ break;
+ pat = nextp;
+ name = nextn;
+ }
+ return (0);
+}
+
+/* Free allocated data belonging to a glob_t structure. */
+void
+globfree(glob_t *pglob)
+{
+ size_t i;
+ char **pp;
+
+ if (pglob->gl_pathv != NULL) {
+ pp = pglob->gl_pathv + pglob->gl_offs;
+ for (i = pglob->gl_pathc; i--; ++pp)
+ if (*pp)
+ free(*pp);
+ free(pglob->gl_pathv);
+ pglob->gl_pathv = NULL;
+ }
+}
+
+static DIR *
+g_opendir(Char *str, glob_t *pglob)
+{
+ char buf[MAXPATHLEN + MB_LEN_MAX - 1];
+
+ if (*str == EOS)
+ strcpy(buf, ".");
+ else {
+ if (g_Ctoc(str, buf, sizeof(buf))) {
+ errno = ENAMETOOLONG;
+ return (NULL);
+ }
+ }
+
+ if (pglob->gl_flags & GLOB_ALTDIRFUNC)
+ return ((*pglob->gl_opendir)(buf));
+
+ return (opendir(buf));
+}
+
+static int
+g_lstat(Char *fn, struct stat *sb, glob_t *pglob)
+{
+ char buf[MAXPATHLEN + MB_LEN_MAX - 1];
+
+ if (g_Ctoc(fn, buf, sizeof(buf))) {
+ errno = ENAMETOOLONG;
+ return (-1);
+ }
+ if (pglob->gl_flags & GLOB_ALTDIRFUNC)
+ return((*pglob->gl_lstat)(buf, sb));
+ return (lstat(buf, sb));
+}
+
+static int
+g_stat(Char *fn, struct stat *sb, glob_t *pglob)
+{
+ char buf[MAXPATHLEN + MB_LEN_MAX - 1];
+
+ if (g_Ctoc(fn, buf, sizeof(buf))) {
+ errno = ENAMETOOLONG;
+ return (-1);
+ }
+ if (pglob->gl_flags & GLOB_ALTDIRFUNC)
+ return ((*pglob->gl_stat)(buf, sb));
+ return (stat(buf, sb));
+}
+
+static const Char *
+g_strchr(const Char *str, wchar_t ch)
+{
+
+ do {
+ if (*str == ch)
+ return (str);
+ } while (*str++);
+ return (NULL);
+}
+
+static int
+g_Ctoc(const Char *str, char *buf, size_t len)
+{
+ mbstate_t mbs;
+ size_t clen;
+
+ memset(&mbs, 0, sizeof(mbs));
+ while (len >= MB_CUR_MAX) {
+ clen = wcrtomb(buf, CHAR(*str), &mbs);
+ if (clen == (size_t)-1) {
+ /* XXX See initial comment #2. */
+ *buf = (char)CHAR(*str);
+ clen = 1;
+ memset(&mbs, 0, sizeof(mbs));
+ }
+ if (CHAR(*str) == EOS)
+ return (0);
+ str++;
+ buf += clen;
+ len -= clen;
+ }
+ return (1);
+}
+
+static int
+err_nomatch(glob_t *pglob, struct glob_limit *limit, const char *origpat) {
+ /*
+ * If there was no match we are going to append the origpat
+ * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified
+ * and the origpat did not contain any magic characters
+ * GLOB_NOMAGIC is there just for compatibility with csh.
+ */
+ if ((pglob->gl_flags & GLOB_NOCHECK) ||
+ ((pglob->gl_flags & GLOB_NOMAGIC) &&
+ !(pglob->gl_flags & GLOB_MAGCHAR)))
+ return (globextend(NULL, pglob, limit, origpat));
+ return (GLOB_NOMATCH);
+}
+
+static int
+err_aborted(glob_t *pglob, int err, char *buf) {
+ if ((pglob->gl_errfunc != NULL && pglob->gl_errfunc(buf, err)) ||
+ (pglob->gl_flags & GLOB_ERR))
+ return (GLOB_ABORTED);
+ return (0);
+}
+
+#ifdef DEBUG
+static void
+qprintf(const char *str, Char *s)
+{
+ Char *p;
+
+ (void)printf("%s\n", str);
+ if (s != NULL) {
+ for (p = s; *p != EOS; p++)
+ (void)printf("%c", (char)CHAR(*p));
+ (void)printf("\n");
+ for (p = s; *p != EOS; p++)
+ (void)printf("%c", (isprot(*p) ? '\\' : ' '));
+ (void)printf("\n");
+ for (p = s; *p != EOS; p++)
+ (void)printf("%c", (ismeta(*p) ? '_' : ' '));
+ (void)printf("\n");
+ }
+}
+#endif
diff --git a/libc/upstream-openbsd/android/include/openbsd-compat.h b/libc/upstream-openbsd/android/include/openbsd-compat.h
index d831435..f178149 100644
--- a/libc/upstream-openbsd/android/include/openbsd-compat.h
+++ b/libc/upstream-openbsd/android/include/openbsd-compat.h
@@ -18,10 +18,15 @@
#define _BIONIC_OPENBSD_COMPAT_H_included
#define _BSD_SOURCE
-
#include <sys/cdefs.h>
+
#include <stddef.h> // For size_t.
+// TODO: libandroid_support uses this file, so we need to wait for
+// <sys/random.h> to be in the NDK headers before we can lose this declaration.
+//#include <sys/random.h> // For getentropy.
+int getentropy(void*, size_t);
+
#define __BEGIN_HIDDEN_DECLS _Pragma("GCC visibility push(hidden)")
#define __END_HIDDEN_DECLS _Pragma("GCC visibility pop")
@@ -75,9 +80,6 @@
__LIBC_HIDDEN__ extern const char* __bionic_get_shell_path();
#define _PATH_BSHELL __bionic_get_shell_path()
-/* We have OpenBSD's getentropy_linux.c, but we don't mention getentropy in any header. */
-__LIBC_HIDDEN__ extern int getentropy(void*, size_t);
-
/* OpenBSD has this as API, but we just use it internally. */
__LIBC_HIDDEN__ void* reallocarray(void*, size_t, size_t);
diff --git a/libdl/Android.bp b/libdl/Android.bp
index 9f67ee8..b0bbe99 100644
--- a/libdl/Android.bp
+++ b/libdl/Android.bp
@@ -1,6 +1,28 @@
//
// libdl
//
+cc_library_static {
+ name: "libdl_static",
+
+ srcs: ["libdl.c", "libdl_cfi.cpp"],
+
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Wunused",
+ "-Werror",
+ ],
+
+ // For private/CFIShadow.h.
+ include_dirs: ["bionic/libc"],
+
+ stl: "none",
+
+ sanitize: {
+ never: true,
+ },
+}
+
cc_library {
name: "libdl",
@@ -45,7 +67,7 @@
},
},
shared: {
- srcs: ["libdl.c", "libdl_cfi.cpp"],
+ whole_static_libs: ["libdl_static"],
},
static: {
srcs: [ "libdl_static.c" ],
@@ -66,9 +88,6 @@
allow_undefined_symbols: true,
system_shared_libs: [],
- // For private/CFIShadow.h.
- include_dirs: ["bionic/libc"],
-
// This is placeholder library the actual implementation is (currently)
// provided by the linker.
shared_libs: [ "ld-android" ],
diff --git a/libdl/libdl.arm.map b/libdl/libdl.arm.map
index 9fc9d23..1fcfc58 100644
--- a/libdl/libdl.arm.map
+++ b/libdl/libdl.arm.map
@@ -34,11 +34,11 @@
dlvsym; # introduced=24
} LIBC;
-LIBC_OMR1 { # future
+LIBC_OMR1 { # introduced=27
global:
- __cfi_shadow_size; # future
- __cfi_slowpath; # future
- __cfi_slowpath_diag; # future
+ __cfi_shadow_size;
+ __cfi_slowpath;
+ __cfi_slowpath_diag;
} LIBC_N;
LIBC_PLATFORM {
diff --git a/libdl/libdl.arm64.map b/libdl/libdl.arm64.map
index bde6cab..8d4019c 100644
--- a/libdl/libdl.arm64.map
+++ b/libdl/libdl.arm64.map
@@ -33,11 +33,11 @@
dlvsym; # introduced=24
} LIBC;
-LIBC_OMR1 { # future
+LIBC_OMR1 { # introduced=27
global:
- __cfi_shadow_size; # future
- __cfi_slowpath; # future
- __cfi_slowpath_diag; # future
+ __cfi_shadow_size;
+ __cfi_slowpath;
+ __cfi_slowpath_diag;
} LIBC_N;
LIBC_PLATFORM {
diff --git a/libdl/libdl.c b/libdl/libdl.c
index 1a65b67..b747c22 100644
--- a/libdl/libdl.c
+++ b/libdl/libdl.c
@@ -98,34 +98,41 @@
struct android_namespace_t* __loader_android_get_exported_namespace(const char* name);
// Proxy calls to bionic loader
+__attribute__((__weak__))
void* dlopen(const char* filename, int flag) {
const void* caller_addr = __builtin_return_address(0);
return __loader_dlopen(filename, flag, caller_addr);
}
+__attribute__((__weak__))
char* dlerror() {
return __loader_dlerror();
}
+__attribute__((__weak__))
void* dlsym(void* handle, const char* symbol) {
const void* caller_addr = __builtin_return_address(0);
return __loader_dlsym(handle, symbol, caller_addr);
}
+__attribute__((__weak__))
void* dlvsym(void* handle, const char* symbol, const char* version) {
const void* caller_addr = __builtin_return_address(0);
return __loader_dlvsym(handle, symbol, version, caller_addr);
}
+__attribute__((__weak__))
int dladdr(const void* addr, Dl_info* info) {
return __loader_dladdr(addr, info);
}
+__attribute__((__weak__))
int dlclose(void* handle) {
return __loader_dlclose(handle);
}
#if defined(__arm__)
+__attribute__((__weak__))
_Unwind_Ptr dl_unwind_find_exidx(_Unwind_Ptr pc, int* pcount) {
return __loader_dl_unwind_find_exidx(pc, pcount);
}
@@ -140,31 +147,39 @@
return __loader_dl_iterate_phdr(cb, data);
}
+__attribute__((__weak__))
void android_get_LD_LIBRARY_PATH(char* buffer, size_t buffer_size) {
__loader_android_get_LD_LIBRARY_PATH(buffer, buffer_size);
}
+__attribute__((__weak__))
void android_update_LD_LIBRARY_PATH(const char* ld_library_path) {
__loader_android_update_LD_LIBRARY_PATH(ld_library_path);
}
+__attribute__((__weak__))
void* android_dlopen_ext(const char* filename, int flag, const android_dlextinfo* extinfo) {
const void* caller_addr = __builtin_return_address(0);
return __loader_android_dlopen_ext(filename, flag, extinfo, caller_addr);
}
+__attribute__((__weak__))
void android_set_application_target_sdk_version(uint32_t target) {
__loader_android_set_application_target_sdk_version(target);
}
+
+__attribute__((__weak__))
uint32_t android_get_application_target_sdk_version() {
return __loader_android_get_application_target_sdk_version();
}
+__attribute__((__weak__))
bool android_init_anonymous_namespace(const char* shared_libs_sonames,
const char* library_search_path) {
return __loader_android_init_anonymous_namespace(shared_libs_sonames, library_search_path);
}
+__attribute__((__weak__))
struct android_namespace_t* android_create_namespace(const char* name,
const char* ld_library_path,
const char* default_library_path,
@@ -181,16 +196,19 @@
caller_addr);
}
+__attribute__((__weak__))
bool android_link_namespaces(struct android_namespace_t* namespace_from,
struct android_namespace_t* namespace_to,
const char* shared_libs_sonames) {
return __loader_android_link_namespaces(namespace_from, namespace_to, shared_libs_sonames);
}
+__attribute__((__weak__))
void android_dlwarning(void* obj, void (*f)(void*, const char*)) {
__loader_android_dlwarning(obj, f);
}
+__attribute__((__weak__))
struct android_namespace_t* android_get_exported_namespace(const char* name) {
return __loader_android_get_exported_namespace(name);
}
diff --git a/libdl/libdl.map.txt b/libdl/libdl.map.txt
index d1f4ab8..002e9f8 100644
--- a/libdl/libdl.map.txt
+++ b/libdl/libdl.map.txt
@@ -33,11 +33,11 @@
dlvsym; # introduced=24
} LIBC;
-LIBC_OMR1 { # future
+LIBC_OMR1 { # introduced=27
global:
- __cfi_shadow_size; # future
- __cfi_slowpath; # future
- __cfi_slowpath_diag; # future
+ __cfi_shadow_size;
+ __cfi_slowpath;
+ __cfi_slowpath_diag;
} LIBC_N;
LIBC_PLATFORM {
diff --git a/libdl/libdl.mips.map b/libdl/libdl.mips.map
index bde6cab..8d4019c 100644
--- a/libdl/libdl.mips.map
+++ b/libdl/libdl.mips.map
@@ -33,11 +33,11 @@
dlvsym; # introduced=24
} LIBC;
-LIBC_OMR1 { # future
+LIBC_OMR1 { # introduced=27
global:
- __cfi_shadow_size; # future
- __cfi_slowpath; # future
- __cfi_slowpath_diag; # future
+ __cfi_shadow_size;
+ __cfi_slowpath;
+ __cfi_slowpath_diag;
} LIBC_N;
LIBC_PLATFORM {
diff --git a/libdl/libdl.mips64.map b/libdl/libdl.mips64.map
index bde6cab..8d4019c 100644
--- a/libdl/libdl.mips64.map
+++ b/libdl/libdl.mips64.map
@@ -33,11 +33,11 @@
dlvsym; # introduced=24
} LIBC;
-LIBC_OMR1 { # future
+LIBC_OMR1 { # introduced=27
global:
- __cfi_shadow_size; # future
- __cfi_slowpath; # future
- __cfi_slowpath_diag; # future
+ __cfi_shadow_size;
+ __cfi_slowpath;
+ __cfi_slowpath_diag;
} LIBC_N;
LIBC_PLATFORM {
diff --git a/libdl/libdl.x86.map b/libdl/libdl.x86.map
index bde6cab..8d4019c 100644
--- a/libdl/libdl.x86.map
+++ b/libdl/libdl.x86.map
@@ -33,11 +33,11 @@
dlvsym; # introduced=24
} LIBC;
-LIBC_OMR1 { # future
+LIBC_OMR1 { # introduced=27
global:
- __cfi_shadow_size; # future
- __cfi_slowpath; # future
- __cfi_slowpath_diag; # future
+ __cfi_shadow_size;
+ __cfi_slowpath;
+ __cfi_slowpath_diag;
} LIBC_N;
LIBC_PLATFORM {
diff --git a/libdl/libdl.x86_64.map b/libdl/libdl.x86_64.map
index bde6cab..8d4019c 100644
--- a/libdl/libdl.x86_64.map
+++ b/libdl/libdl.x86_64.map
@@ -33,11 +33,11 @@
dlvsym; # introduced=24
} LIBC;
-LIBC_OMR1 { # future
+LIBC_OMR1 { # introduced=27
global:
- __cfi_shadow_size; # future
- __cfi_slowpath; # future
- __cfi_slowpath_diag; # future
+ __cfi_shadow_size;
+ __cfi_slowpath;
+ __cfi_slowpath_diag;
} LIBC_N;
LIBC_PLATFORM {
diff --git a/libm/libm.arm.map b/libm/libm.arm.map
index 7e3175d..bee08d4 100644
--- a/libm/libm.arm.map
+++ b/libm/libm.arm.map
@@ -272,7 +272,7 @@
*;
};
-LIBC_O {
+LIBC_O { # introduced=O
global:
cacoshl;
cacosl;
diff --git a/libm/libm.arm64.map b/libm/libm.arm64.map
index 3e259dd..550c39b 100644
--- a/libm/libm.arm64.map
+++ b/libm/libm.arm64.map
@@ -272,7 +272,7 @@
*;
};
-LIBC_O {
+LIBC_O { # introduced=O
global:
cacoshl;
cacosl;
diff --git a/libm/libm.mips.map b/libm/libm.mips.map
index b368d41..0b6dc02 100644
--- a/libm/libm.mips.map
+++ b/libm/libm.mips.map
@@ -272,7 +272,7 @@
*;
};
-LIBC_O {
+LIBC_O { # introduced=O
global:
cacoshl;
cacosl;
diff --git a/libm/libm.mips64.map b/libm/libm.mips64.map
index 3e259dd..550c39b 100644
--- a/libm/libm.mips64.map
+++ b/libm/libm.mips64.map
@@ -272,7 +272,7 @@
*;
};
-LIBC_O {
+LIBC_O { # introduced=O
global:
cacoshl;
cacosl;
diff --git a/libm/libm.x86.map b/libm/libm.x86.map
index 3e259dd..550c39b 100644
--- a/libm/libm.x86.map
+++ b/libm/libm.x86.map
@@ -272,7 +272,7 @@
*;
};
-LIBC_O {
+LIBC_O { # introduced=O
global:
cacoshl;
cacosl;
diff --git a/libm/libm.x86_64.map b/libm/libm.x86_64.map
index 3e259dd..550c39b 100644
--- a/libm/libm.x86_64.map
+++ b/libm/libm.x86_64.map
@@ -272,7 +272,7 @@
*;
};
-LIBC_O {
+LIBC_O { # introduced=O
global:
cacoshl;
cacosl;
diff --git a/linker/Android.bp b/linker/Android.bp
index 9125fd6..f802f45 100644
--- a/linker/Android.bp
+++ b/linker/Android.bp
@@ -6,6 +6,7 @@
"linker_allocator.cpp",
"linker_memory.cpp",
],
+ cflags: ["-Wall", "-Werror"],
// We need to access Bionic private headers in the linker.
include_dirs: ["bionic/libc"],
@@ -26,7 +27,7 @@
device_supported: false,
target: {
linux_bionic: { enabled: true },
- linux: { enabled: false },
+ linux_glibc: { enabled: false },
darwin: { enabled: false },
},
diff --git a/linker/linker_config.cpp b/linker/linker_config.cpp
index f6d5072..e036c05 100644
--- a/linker/linker_config.cpp
+++ b/linker/linker_config.cpp
@@ -375,15 +375,6 @@
bool is_asan,
const Config** config,
std::string* error_msg) {
- // TODO(b/38114603) Currently, multiple namespaces does not support ASAN mode
- // where some symbols should be intercepted via LD_PRELOAD; LD_PRELOADed libs
- // are not being preloaded into the linked namespaces other than the default
- // namespace. Until we fix the problem, we temporarily disable ld.config.txt
- // in ASAN mode.
- if (is_asan) {
- return false;
- }
-
g_config.clear();
std::unordered_map<std::string, PropertyValue> property_map;
diff --git a/linker/linker_main.cpp b/linker/linker_main.cpp
index 3862d8c..4799739 100644
--- a/linker/linker_main.cpp
+++ b/linker/linker_main.cpp
@@ -154,6 +154,10 @@
si->prelink_image();
si->link_image(g_empty_list, soinfo_list_t::make_list(si), nullptr);
+ // prevents accidental unloads...
+ si->set_dt_flags_1(si->get_dt_flags_1() | DF_1_NODELETE);
+ si->set_linked();
+ si->call_constructors();
}
/* gdb expects the linker to be in the debug shared object list.
@@ -204,7 +208,17 @@
#endif
static void __linker_cannot_link(const char* argv0) {
- async_safe_fatal("CANNOT LINK EXECUTABLE \"%s\": %s", argv0, linker_get_error_buffer());
+ async_safe_format_fd(STDERR_FILENO,
+ "CANNOT LINK EXECUTABLE \"%s\": %s\n",
+ argv0,
+ linker_get_error_buffer());
+
+ async_safe_format_log(ANDROID_LOG_FATAL,
+ "linker",
+ "CANNOT LINK EXECUTABLE \"%s\": %s",
+ argv0,
+ linker_get_error_buffer());
+ _exit(EXIT_FAILURE);
}
/*
@@ -352,6 +366,8 @@
}
}
+ add_vdso(args);
+
// Load ld_preloads and dependencies.
std::vector<const char*> needed_library_name_list;
size_t ld_preloads_count = 0;
@@ -393,8 +409,6 @@
si->increment_ref_count();
}
- add_vdso(args);
-
if (!get_cfi_shadow()->InitialLinkDone(solist)) __linker_cannot_link(g_argv[0]);
si->call_pre_init_constructors();
diff --git a/linker/tests/linker_config_test.cpp b/linker/tests/linker_config_test.cpp
index 87609d0..c6fade9 100644
--- a/linker/tests/linker_config_test.cpp
+++ b/linker/tests/linker_config_test.cpp
@@ -168,7 +168,6 @@
run_linker_config_smoke_test(false);
}
-// TODO(b/38114603) revive this test when ld.config.txt is enabled for ASAN mode
-//TEST(linker_config, asan_smoke) {
-// run_linker_config_smoke_test(true);
-//}
+TEST(linker_config, asan_smoke) {
+ run_linker_config_smoke_test(true);
+}
diff --git a/tests/Android.bp b/tests/Android.bp
index 3731156..fb8b886 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -71,6 +71,7 @@
"ftw_test.cpp",
"getauxval_test.cpp",
"getcwd_test.cpp",
+ "glob_test.cpp",
"grp_pwd_test.cpp",
"iconv_test.cpp",
"ifaddrs_test.cpp",
@@ -131,6 +132,7 @@
"sys_procfs_test.cpp",
"sys_ptrace_test.cpp",
"sys_quota_test.cpp",
+ "sys_random_test.cpp",
"sys_resource_test.cpp",
"sys_select_test.cpp",
"sys_sem_test.cpp",
@@ -167,7 +169,7 @@
],
target: {
- android: {
+ bionic: {
whole_static_libs: ["libasync_safe"],
},
},
@@ -177,7 +179,6 @@
"liblog",
"libbase",
],
- host_ldlibs: ["-lrt"],
shared: {
enabled: false,
},
@@ -327,12 +328,6 @@
],
}
},
-
- product_variables: {
- debuggable: {
- cppflags: ["-DUSE_LD_CONFIG_FILE"],
- },
- },
}
// -----------------------------------------------------------------------------
@@ -610,8 +605,6 @@
host_ldlibs: [
"-lresolv",
- "-lrt",
- "-ldl",
"-lutil",
],
@@ -626,9 +619,9 @@
never: false,
},
- product_variables: {
- debuggable: {
- cppflags: ["-DUSE_LD_CONFIG_FILE"],
+ target: {
+ linux_bionic: {
+ enabled: false,
},
},
}
diff --git a/tests/dl_test.cpp b/tests/dl_test.cpp
index aaf2c37..2133a2c 100644
--- a/tests/dl_test.cpp
+++ b/tests/dl_test.cpp
@@ -162,7 +162,7 @@
chmod(helper.c_str(), 0755);
ExecTestHelper eth;
eth.SetArgs({ helper.c_str(), nullptr });
- eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, -6, error_message.c_str());
+ eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, EXIT_FAILURE, error_message.c_str());
#endif
}
@@ -180,12 +180,24 @@
}
#endif
-#ifdef USE_LD_CONFIG_FILE
+#if defined(__BIONIC__)
+static bool is_user_build() {
+ std::string build_type = android::base::GetProperty("ro.build.type", "user");
+ if (build_type == "userdebug" || build_type == "eng") {
+ return false;
+ }
+ return true;
+}
+#endif
// _lib1.so and _lib2.so are now searchable by having another namespace 'ns2'
// whose search paths include the 'ns2/' subdir.
TEST(dl, exec_with_ld_config_file) {
#if defined(__BIONIC__)
+ if (is_user_build()) {
+ // LD_CONFIG_FILE is not supported on user build
+ return;
+ }
std::string helper = get_testlib_root() +
"/ld_config_test_helper/ld_config_test_helper";
std::string config_file = get_testlib_root() + "/ld.config.txt";
@@ -204,6 +216,10 @@
// additional namespaces other than the default namespace.
TEST(dl, exec_with_ld_config_file_with_ld_preload) {
#if defined(__BIONIC__)
+ if (is_user_build()) {
+ // LD_CONFIG_FILE is not supported on user build
+ return;
+ }
std::string helper = get_testlib_root() +
"/ld_config_test_helper/ld_config_test_helper";
std::string config_file = get_testlib_root() + "/ld.config.txt";
@@ -218,8 +234,6 @@
#endif
}
-#endif // USE_LD_CONFIG_FILE
-
// ensures that LD_CONFIG_FILE env var does not work for production builds.
// The test input is the same as exec_with_ld_config_file, but it must fail in
// this case.
@@ -230,8 +244,7 @@
// This test is only for CTS.
return;
}
- std::string build_type = android::base::GetProperty("ro.build.type", "user");
- if (build_type == "userdebug" || build_type == "eng") {
+ if (!is_user_build()) {
// Skip the test for non production devices
return;
}
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index 1e2b6c9..66ea0f9 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -245,6 +245,12 @@
dlclose(handle);
}
+TEST(dlfcn, dlopen_vdso) {
+ void* handle = dlopen("linux-vdso.so.1", RTLD_NOW);
+ ASSERT_TRUE(handle != nullptr) << dlerror();
+ dlclose(handle);
+}
+
// mips doesn't support ifuncs
#if !defined(__mips__)
TEST(dlfcn, ifunc_variable) {
diff --git a/tests/glob_test.cpp b/tests/glob_test.cpp
new file mode 100644
index 0000000..623a2a3
--- /dev/null
+++ b/tests/glob_test.cpp
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <glob.h>
+
+#include <dirent.h>
+#include <gtest/gtest.h>
+
+#include <string>
+#include <vector>
+
+#include "TemporaryFile.h"
+
+#if defined(__BIONIC__)
+#define ASSERT_MATCH_COUNT(n_,g_) ASSERT_EQ(n_, g_.gl_matchc)
+#else
+#define ASSERT_MATCH_COUNT(n_,g_)
+#endif
+
+//
+// Helper for use with GLOB_ALTDIRFUNC to iterate over the elements of `fake_dir`.
+//
+
+static std::vector<std::string> fake_dir;
+static size_t fake_dir_offset;
+static void fake_closedir(void*) {
+}
+static dirent* fake_readdir(void*) {
+ static dirent d;
+ if (fake_dir_offset >= fake_dir.size()) return nullptr;
+ strcpy(d.d_name, fake_dir[fake_dir_offset++].c_str());
+ return &d;
+}
+static void* fake_opendir(const char* path) {
+ fake_dir_offset = 0;
+ if (strcmp(path, "/opendir-fail/") == 0) {
+ errno = EINVAL;
+ return nullptr;
+ }
+ return &fake_dir;
+}
+static int fake_lstat(const char*, struct stat*) {
+ return 0;
+}
+static int fake_stat(const char*, struct stat*) {
+ return 0;
+}
+static void InstallFake(glob_t* g) {
+ g->gl_closedir = fake_closedir;
+ g->gl_readdir = fake_readdir;
+ g->gl_opendir = fake_opendir;
+ g->gl_lstat = fake_lstat;
+ g->gl_stat = fake_stat;
+}
+
+TEST(glob, glob_result_GLOB_NOMATCH) {
+ glob_t g = {};
+ ASSERT_EQ(GLOB_NOMATCH, glob("/will/match/nothing", 0, nullptr, &g));
+ ASSERT_EQ(0U, g.gl_pathc);
+ ASSERT_MATCH_COUNT(0U, g);
+}
+
+TEST(glob, glob_GLOB_APPEND) {
+ glob_t g = {};
+ ASSERT_EQ(0, glob("/proc/version", 0, nullptr, &g));
+ ASSERT_EQ(1U, g.gl_pathc);
+ ASSERT_MATCH_COUNT(1U, g);
+ ASSERT_STREQ("/proc/version", g.gl_pathv[0]);
+ ASSERT_EQ(nullptr, g.gl_pathv[1]);
+ ASSERT_EQ(0, glob("/proc/version", GLOB_APPEND, nullptr, &g));
+ ASSERT_EQ(2U, g.gl_pathc);
+ ASSERT_MATCH_COUNT(1U, g);
+ ASSERT_STREQ("/proc/version", g.gl_pathv[0]);
+ ASSERT_STREQ("/proc/version", g.gl_pathv[1]);
+ ASSERT_EQ(nullptr, g.gl_pathv[2]);
+ globfree(&g);
+}
+
+TEST(glob, glob_GLOB_DOOFFS) {
+ glob_t g = {};
+ g.gl_offs = 2;
+ ASSERT_EQ(0, glob("/proc/version", GLOB_DOOFFS, nullptr, &g));
+ ASSERT_EQ(1U, g.gl_pathc);
+ ASSERT_MATCH_COUNT(1U, g);
+ ASSERT_EQ(nullptr, g.gl_pathv[0]);
+ ASSERT_EQ(nullptr, g.gl_pathv[1]);
+ ASSERT_STREQ("/proc/version", g.gl_pathv[2]);
+ ASSERT_EQ(nullptr, g.gl_pathv[3]);
+ globfree(&g);
+}
+
+static std::string g_failure_path;
+static int g_failure_errno;
+static int test_error_callback_result;
+static int test_error_callback(const char* failure_path, int failure_errno) {
+ g_failure_path = failure_path;
+ g_failure_errno = failure_errno;
+ return test_error_callback_result;
+}
+
+TEST(glob, glob_gl_errfunc) {
+ glob_t g = {};
+ InstallFake(&g);
+
+ test_error_callback_result = 0;
+ g_failure_errno = 0;
+ ASSERT_EQ(GLOB_NOMATCH, glob("/opendir-fail/x*", GLOB_ALTDIRFUNC, test_error_callback, &g));
+ ASSERT_EQ("/opendir-fail/", g_failure_path);
+ ASSERT_EQ(EINVAL, g_failure_errno);
+
+ test_error_callback_result = 1;
+ g_failure_errno = 0;
+ ASSERT_EQ(GLOB_ABORTED, glob("/opendir-fail/x*", GLOB_ALTDIRFUNC, test_error_callback, &g));
+ ASSERT_EQ("/opendir-fail/", g_failure_path);
+ ASSERT_EQ(EINVAL, g_failure_errno);
+}
+
+TEST(glob, glob_GLOB_ERR) {
+ glob_t g = {};
+ InstallFake(&g);
+
+ ASSERT_EQ(GLOB_NOMATCH, glob("/opendir-fail/x*", GLOB_ALTDIRFUNC, nullptr, &g));
+
+ ASSERT_EQ(GLOB_ABORTED, glob("/opendir-fail/x*", GLOB_ALTDIRFUNC | GLOB_ERR, nullptr, &g));
+}
+
+TEST(glob, glob_GLOB_MARK) {
+ TemporaryDir td;
+ // The pattern we're about to pass doesn't have a trailing '/'...
+ ASSERT_NE('/', std::string(td.dirname).back());
+
+ glob_t g = {};
+ // Using GLOB_MARK gets you a trailing '/' on a directory...
+ ASSERT_EQ(0, glob(td.dirname, GLOB_MARK, nullptr, &g));
+ ASSERT_EQ(1U, g.gl_pathc);
+ ASSERT_MATCH_COUNT(1U, g);
+ ASSERT_EQ(std::string(td.dirname) + "/", g.gl_pathv[0]);
+ ASSERT_EQ(nullptr, g.gl_pathv[1]);
+
+ TemporaryFile tf;
+ // But not on a file...
+ ASSERT_EQ(0, glob(tf.filename, GLOB_MARK, nullptr, &g));
+ ASSERT_EQ(1U, g.gl_pathc);
+ ASSERT_MATCH_COUNT(1U, g);
+ ASSERT_STREQ(tf.filename, g.gl_pathv[0]);
+ ASSERT_EQ(nullptr, g.gl_pathv[1]);
+
+ globfree(&g);
+}
+
+TEST(glob, glob_GLOB_NOCHECK) {
+ glob_t g = {};
+ ASSERT_EQ(0, glob("/will/match/nothing", GLOB_NOCHECK, nullptr, &g));
+ ASSERT_EQ(1U, g.gl_pathc);
+ ASSERT_MATCH_COUNT(0U, g);
+ ASSERT_STREQ("/will/match/nothing", g.gl_pathv[0]);
+ ASSERT_EQ(nullptr, g.gl_pathv[1]);
+ globfree(&g);
+}
+
+TEST(glob, glob_GLOB_NOSORT) {
+ fake_dir = { "c", "a", "d", "b" };
+
+ glob_t g = {};
+ InstallFake(&g);
+
+ ASSERT_EQ(0, glob("*", GLOB_ALTDIRFUNC, nullptr, &g));
+ ASSERT_EQ(4U, g.gl_pathc);
+ ASSERT_MATCH_COUNT(4U, g);
+ ASSERT_STREQ("a", g.gl_pathv[0]);
+ ASSERT_STREQ("b", g.gl_pathv[1]);
+ ASSERT_STREQ("c", g.gl_pathv[2]);
+ ASSERT_STREQ("d", g.gl_pathv[3]);
+ ASSERT_EQ(nullptr, g.gl_pathv[4]);
+
+ ASSERT_EQ(0, glob("*", GLOB_ALTDIRFUNC | GLOB_NOSORT, nullptr, &g));
+ ASSERT_EQ(4U, g.gl_pathc);
+ ASSERT_MATCH_COUNT(4U, g);
+ ASSERT_STREQ("c", g.gl_pathv[0]);
+ ASSERT_STREQ("a", g.gl_pathv[1]);
+ ASSERT_STREQ("d", g.gl_pathv[2]);
+ ASSERT_STREQ("b", g.gl_pathv[3]);
+ ASSERT_EQ(nullptr, g.gl_pathv[4]);
+}
+
+TEST(glob, glob_GLOB_MAGCHAR) {
+ glob_t g = {};
+ ASSERT_EQ(GLOB_NOMATCH, glob("/does-not-exist", 0, nullptr, &g));
+ ASSERT_TRUE((g.gl_flags & GLOB_MAGCHAR) == 0);
+ ASSERT_EQ(GLOB_NOMATCH, glob("/does-not-exist*", 0, nullptr, &g));
+ ASSERT_TRUE((g.gl_flags & GLOB_MAGCHAR) != 0);
+
+ // We can lie, but glob(3) will turn that into truth...
+ ASSERT_EQ(GLOB_NOMATCH, glob("/does-not-exist", GLOB_MAGCHAR, nullptr, &g));
+ ASSERT_TRUE((g.gl_flags & GLOB_MAGCHAR) == 0);
+}
+
+static void CheckGlob(const char* pattern, const std::vector<std::string>& expected_matches) {
+ glob_t g = {};
+ InstallFake(&g);
+
+ int expected_result = expected_matches.empty() ? GLOB_NOMATCH : 0;
+ ASSERT_EQ(expected_result, glob(pattern, GLOB_ALTDIRFUNC, nullptr, &g)) << pattern;
+ ASSERT_EQ(expected_matches.size(), g.gl_pathc);
+ ASSERT_MATCH_COUNT(expected_matches.size(), g);
+ for (size_t i = 0; i < expected_matches.size(); ++i) {
+ ASSERT_EQ(expected_matches[i], g.gl_pathv[i]);
+ }
+ if (!expected_matches.empty()) {
+ ASSERT_EQ(nullptr, g.gl_pathv[expected_matches.size()]);
+ }
+ globfree(&g);
+}
+
+TEST(glob, glob_globbing) {
+ fake_dir = { "f1", "f2", "f30", "f40" };
+
+ CheckGlob("f?", { "f1", "f2" });
+ CheckGlob("f??", { "f30", "f40" });
+ CheckGlob("f*", { "f1", "f2", "f30", "f40" });
+}
+
+TEST(glob, glob_globbing_rsc) {
+ // https://research.swtch.com/glob
+ fake_dir = { "axbxcxdxe" };
+ CheckGlob("a*b*c*d*e*", { "axbxcxdxe" });
+ fake_dir = { "axbxcxdxexxx" };
+ CheckGlob("a*b*c*d*e*", { "axbxcxdxexxx" });
+ fake_dir = { "abxbbxdbxebxczzx" };
+ CheckGlob("a*b?c*x", { "abxbbxdbxebxczzx" });
+ fake_dir = { "abxbbxdbxebxczzy" };
+ CheckGlob("a*b?c*x", {});
+
+ fake_dir = { std::string(100, 'a') };
+ CheckGlob("a*a*a*a*b", {});
+}
diff --git a/tests/leak_test.cpp b/tests/leak_test.cpp
index a356640..de08869 100644
--- a/tests/leak_test.cpp
+++ b/tests/leak_test.cpp
@@ -35,20 +35,6 @@
using namespace std::chrono_literals;
-static size_t GetMappingSize() {
- std::vector<map_record> maps;
- if (!Maps::parse_maps(&maps)) {
- err(1, "failed to parse maps");
- }
-
- size_t result = 0;
- for (const map_record& map : maps) {
- result += map.addr_end - map.addr_start;
- }
-
- return result;
-}
-
static void WaitUntilAllExited(pid_t* pids, size_t pid_count) {
// Wait until all children have exited.
bool alive = true;
@@ -70,6 +56,9 @@
class LeakChecker {
public:
LeakChecker() {
+ // Avoid resizing and using memory later.
+ // 64Ki is the default limit on VMAs per process.
+ maps_.reserve(64*1024);
Reset();
}
@@ -87,6 +76,7 @@
private:
size_t previous_size_;
+ std::vector<map_record> maps_;
void Check() {
auto current_size = GetMappingSize();
@@ -94,6 +84,19 @@
FAIL() << "increase in process map size: " << previous_size_ << " -> " << current_size;
}
}
+
+ size_t GetMappingSize() {
+ if (!Maps::parse_maps(&maps_)) {
+ err(1, "failed to parse maps");
+ }
+
+ size_t result = 0;
+ for (const map_record& map : maps_) {
+ result += map.addr_end - map.addr_start;
+ }
+
+ return result;
+ }
};
std::ostream& operator<<(std::ostream& os, const LeakChecker& lc) {
@@ -116,27 +119,24 @@
LeakChecker lc;
for (size_t pass = 0; pass < 2; ++pass) {
+ constexpr int kThreadCount = 100;
+ struct thread_data { pthread_barrier_t* barrier; pid_t* tid; } threads[kThreadCount] = {};
+
pthread_barrier_t barrier;
- constexpr int thread_count = 100;
- ASSERT_EQ(pthread_barrier_init(&barrier, nullptr, thread_count + 1), 0);
+ ASSERT_EQ(pthread_barrier_init(&barrier, nullptr, kThreadCount + 1), 0);
// Start child threads.
- struct thread_data { pthread_barrier_t* barrier; pid_t* tid; };
- pid_t tids[thread_count];
- for (int i = 0; i < thread_count; ++i) {
- thread_data* td = new thread_data{&barrier, &tids[i]};
+ pid_t tids[kThreadCount];
+ for (int i = 0; i < kThreadCount; ++i) {
+ threads[i] = {&barrier, &tids[i]};
const auto thread_function = +[](void* ptr) -> void* {
thread_data* data = static_cast<thread_data*>(ptr);
*data->tid = gettid();
pthread_barrier_wait(data->barrier);
- // Doing this delete allocates new VMAs for jemalloc bookkeeping,
- // but the two-pass nature of this test means we can check that
- // it's a pool rather than an unbounded leak.
- delete data;
return nullptr;
};
pthread_t thread;
- ASSERT_EQ(0, pthread_create(&thread, nullptr, thread_function, td));
+ ASSERT_EQ(0, pthread_create(&thread, nullptr, thread_function, &threads[i]));
ASSERT_EQ(0, pthread_detach(thread));
}
diff --git a/tests/libs/Android.bp b/tests/libs/Android.bp
index c1600cc..858f2b1 100644
--- a/tests/libs/Android.bp
+++ b/tests/libs/Android.bp
@@ -17,6 +17,10 @@
cc_defaults {
name: "bionic_testlib_defaults",
host_supported: true,
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
ldflags: [
"-Wl,--rpath,${ORIGIN}",
"-Wl,--enable-new-dtags",
@@ -282,15 +286,6 @@
enabled: false,
},
},
-
- target: {
- android: {
- shared_libs: ["libdl"],
- },
- host: {
- host_ldlibs: ["-ldl"],
- },
- },
}
cc_test_library {
@@ -307,15 +302,6 @@
enabled: false,
},
},
-
- target: {
- android: {
- shared_libs: ["libdl"],
- },
- host: {
- host_ldlibs: ["-ldl"],
- },
- },
}
cc_test_library {
@@ -331,15 +317,6 @@
enabled: false,
},
},
-
- target: {
- android: {
- shared_libs: ["libdl"],
- },
- host: {
- host_ldlibs: ["-ldl"],
- },
- },
}
// -----------------------------------------------------------------------------
@@ -416,15 +393,6 @@
defaults: ["bionic_testlib_defaults"],
srcs: ["dlsym_from_this_symbol.cpp"],
shared_libs: ["libtest_dlsym_from_this_child"],
-
- target: {
- android: {
- shared_libs: ["libdl"],
- },
- host: {
- host_ldlibs: ["-ldl"],
- },
- },
}
// -----------------------------------------------------------------------------
@@ -433,14 +401,6 @@
defaults: ["bionic_testlib_defaults"],
srcs: ["dlsym_from_this_functions.cpp"],
shared_libs: ["libtest_dlsym_from_this_grandchild"],
- target: {
- android: {
- shared_libs: ["libdl"],
- },
- host: {
- host_ldlibs: ["-ldl"],
- },
- },
}
// -----------------------------------------------------------------------------
@@ -475,15 +435,6 @@
name: "libtest_check_rtld_next_from_library",
defaults: ["bionic_testlib_defaults"],
srcs: ["check_rtld_next_from_library.cpp"],
-
- target: {
- android: {
- shared_libs: ["libdl"],
- },
- host: {
- host_ldlibs: ["-ldl"],
- },
- },
}
// -----------------------------------------------------------------------------
@@ -493,14 +444,6 @@
name: "libtest_dlopen_from_ctor",
defaults: ["bionic_testlib_defaults"],
srcs: ["dlopen_testlib_dlopen_from_ctor.cpp"],
- target: {
- android: {
- shared_libs: ["libdl"],
- },
- host: {
- host_ldlibs: ["-ldl"],
- },
- },
}
// -----------------------------------------------------------------------------
diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp
index 46140bb..f342577 100755
--- a/tests/pthread_test.cpp
+++ b/tests/pthread_test.cpp
@@ -2117,8 +2117,9 @@
const auto kPageSize = sysconf(_SC_PAGE_SIZE);
- // Use up all the VMAs. By default this is 64Ki.
+ // Use up all the VMAs. By default this is 64Ki (though some will already be in use).
std::vector<void*> pages;
+ pages.reserve(64 * 1024);
int prot = PROT_NONE;
while (true) {
void* page = mmap(nullptr, kPageSize, prot, MAP_ANON|MAP_PRIVATE, -1, 0);
diff --git a/tests/sys_random_test.cpp b/tests/sys_random_test.cpp
new file mode 100644
index 0000000..78cbf4a
--- /dev/null
+++ b/tests/sys_random_test.cpp
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// <sys/random.h> was only added as of glibc version 2.25.
+// Don't try to compile this code on older glibc versions.
+
+#include <sys/cdefs.h>
+#if defined(__BIONIC__)
+ #define HAVE_SYS_RANDOM 1
+#elif defined(__GLIBC_PREREQ)
+ #if __GLIBC_PREREQ(2, 25)
+ #define HAVE_SYS_RANDOM 1
+ #endif
+#endif
+
+
+#if defined(HAVE_SYS_RANDOM)
+#include <sys/random.h>
+#endif
+
+#include <errno.h>
+#include <gtest/gtest.h>
+
+TEST(sys_random, getentropy) {
+#if defined(HAVE_SYS_RANDOM)
+ char buf1[64];
+ char buf2[64];
+
+ ASSERT_EQ(0, getentropy(buf1, sizeof(buf1)));
+ ASSERT_EQ(0, getentropy(buf2, sizeof(buf2)));
+ ASSERT_TRUE(memcmp(buf1, buf2, sizeof(buf1)) != 0);
+#else
+ GTEST_LOG_(INFO) << "This test requires a C library with <sys/random.h>.\n";
+#endif
+}
+
+TEST(sys_random, getentropy_EFAULT) {
+#if defined(HAVE_SYS_RANDOM)
+ errno = 0;
+ ASSERT_EQ(-1, getentropy(nullptr, 1));
+ ASSERT_EQ(EFAULT, errno);
+#else
+ GTEST_LOG_(INFO) << "This test requires a C library with <sys/random.h>.\n";
+#endif
+}
+
+TEST(sys_random, getentropy_EIO) {
+#if defined(HAVE_SYS_RANDOM)
+ char buf[BUFSIZ];
+ static_assert(BUFSIZ > 256, "BUFSIZ <= 256!");
+
+ errno = 0;
+ ASSERT_EQ(-1, getentropy(buf, sizeof(buf)));
+ ASSERT_EQ(EIO, errno);
+#else
+ GTEST_LOG_(INFO) << "This test requires a C library with <sys/random.h>.\n";
+#endif
+}
+
+TEST(sys_random, getrandom) {
+#if defined(HAVE_SYS_RANDOM)
+ char buf1[64];
+ char buf2[64];
+
+ ASSERT_EQ(64, getrandom(buf1, sizeof(buf1), 0));
+ ASSERT_EQ(64, getrandom(buf2, sizeof(buf2), 0));
+ ASSERT_TRUE(memcmp(buf1, buf2, sizeof(buf1)) != 0);
+#else
+ GTEST_LOG_(INFO) << "This test requires a C library with <sys/random.h>.\n";
+#endif
+}
+
+TEST(sys_random, getrandom_EFAULT) {
+#if defined(HAVE_SYS_RANDOM)
+ errno = 0;
+ ASSERT_EQ(-1, getrandom(nullptr, 256, 0));
+ ASSERT_EQ(EFAULT, errno);
+#else
+ GTEST_LOG_(INFO) << "This test requires a C library with <sys/random.h>.\n";
+#endif
+}
+
+TEST(sys_random, getrandom_EINVAL) {
+#if defined(HAVE_SYS_RANDOM)
+ errno = 0;
+ char buf[64];
+ ASSERT_EQ(-1, getrandom(buf, sizeof(buf), ~0));
+ ASSERT_EQ(EINVAL, errno);
+#else
+ GTEST_LOG_(INFO) << "This test requires a C library with <sys/random.h>.\n";
+#endif
+}
diff --git a/tests/time_test.cpp b/tests/time_test.cpp
index 4e3fa83..d553ff5 100644
--- a/tests/time_test.cpp
+++ b/tests/time_test.cpp
@@ -574,6 +574,31 @@
ASSERT_LT(ts2.tv_nsec, 1000000);
}
+TEST(time, clock_gettime_CLOCK_REALTIME) {
+ timespec ts;
+ ASSERT_EQ(0, clock_gettime(CLOCK_REALTIME, &ts));
+}
+
+TEST(time, clock_gettime_CLOCK_MONOTONIC) {
+ timespec ts;
+ ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, &ts));
+}
+
+TEST(time, clock_gettime_CLOCK_PROCESS_CPUTIME_ID) {
+ timespec ts;
+ ASSERT_EQ(0, clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts));
+}
+
+TEST(time, clock_gettime_CLOCK_THREAD_CPUTIME_ID) {
+ timespec ts;
+ ASSERT_EQ(0, clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts));
+}
+
+TEST(time, clock_gettime_CLOCK_BOOTTIME) {
+ timespec ts;
+ ASSERT_EQ(0, clock_gettime(CLOCK_BOOTTIME, &ts));
+}
+
TEST(time, clock) {
// clock(3) is hard to test, but a 1s sleep should cost less than 1ms.
clock_t t0 = clock();
diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp
index 8af2263..9203215 100644
--- a/tests/unistd_test.cpp
+++ b/tests/unistd_test.cpp
@@ -701,7 +701,7 @@
EXPECT_GT(_POSIX_CHILD_MAX, 0);
EXPECT_NE(_POSIX_CHOWN_RESTRICTED, -1);
EXPECT_EQ(_POSIX_VERSION, _POSIX_CLOCK_SELECTION);
- EXPECT_EQ(0, _POSIX_CPUTIME); // Use sysconf to detect support at runtime.
+ EXPECT_EQ(_POSIX_VERSION, _POSIX_CPUTIME);
EXPECT_GT(_POSIX_DELAYTIMER_MAX, 0);
EXPECT_EQ(_POSIX_VERSION, _POSIX_FSYNC);
EXPECT_GT(_POSIX_HOST_NAME_MAX, 0);
@@ -715,7 +715,7 @@
EXPECT_EQ(_POSIX_VERSION, _POSIX_MEMLOCK);
EXPECT_EQ(_POSIX_VERSION, _POSIX_MEMLOCK_RANGE);
EXPECT_EQ(_POSIX_VERSION, _POSIX_MEMORY_PROTECTION);
- EXPECT_EQ(0, _POSIX_MONOTONIC_CLOCK);
+ EXPECT_EQ(_POSIX_VERSION, _POSIX_MONOTONIC_CLOCK);
EXPECT_GT(_POSIX_MQ_OPEN_MAX, 0);
EXPECT_GT(_POSIX_MQ_PRIO_MAX, 0);
EXPECT_GT(_POSIX_NAME_MAX, 0);
@@ -736,7 +736,7 @@
EXPECT_GT(_POSIX_SEM_VALUE_MAX, 0);
EXPECT_GT(_POSIX_SHELL, 0);
EXPECT_GT(_POSIX_SIGQUEUE_MAX, 0);
- EXPECT_EQ(-1, _POSIX_SPORADIC_SERVER);
+ EXPECT_EQ(_POSIX_VERSION, _POSIX_SPORADIC_SERVER);
EXPECT_GT(_POSIX_SSIZE_MAX, 0);
EXPECT_GT(_POSIX_STREAM_MAX, 0);
EXPECT_GT(_POSIX_SYMLINK_MAX, 0);
@@ -745,7 +745,7 @@
EXPECT_EQ(_POSIX_VERSION, _POSIX_THREADS);
EXPECT_EQ(_POSIX_VERSION, _POSIX_THREAD_ATTR_STACKADDR);
EXPECT_EQ(_POSIX_VERSION, _POSIX_THREAD_ATTR_STACKSIZE);
- EXPECT_EQ(0, _POSIX_THREAD_CPUTIME); // Use sysconf to detect support at runtime.
+ EXPECT_EQ(_POSIX_VERSION, _POSIX_THREAD_CPUTIME);
EXPECT_GT(_POSIX_THREAD_DESTRUCTOR_ITERATIONS, 0);
EXPECT_EQ(_POSIX_THREAD_KEYS_MAX, 128);
EXPECT_EQ(_POSIX_VERSION, _POSIX_THREAD_PRIORITY_SCHEDULING);
@@ -754,7 +754,7 @@
EXPECT_EQ(_POSIX_VERSION, _POSIX_THREAD_PROCESS_SHARED);
EXPECT_EQ(-1, _POSIX_THREAD_ROBUST_PRIO_PROTECT);
EXPECT_EQ(_POSIX_VERSION, _POSIX_THREAD_SAFE_FUNCTIONS);
- EXPECT_EQ(-1, _POSIX_THREAD_SPORADIC_SERVER);
+ EXPECT_EQ(_POSIX_VERSION, _POSIX_THREAD_SPORADIC_SERVER);
EXPECT_GT(_POSIX_THREAD_THREADS_MAX, 0);
EXPECT_EQ(_POSIX_VERSION, _POSIX_TIMEOUTS);
EXPECT_EQ(_POSIX_VERSION, _POSIX_TIMERS);
@@ -784,12 +784,6 @@
EXPECT_GT(_XOPEN_IOV_MAX, 0);
EXPECT_GT(_XOPEN_UNIX, 0);
- // In O, the headers still have -1 (even though all the functionality has
- // been there for a long time). This was fixed in O-DR, but there isn't a
- // separate CTS for O-DR, so we'll accept both.
- EXPECT_TRUE(_POSIX_THREAD_PROCESS_SHARED == -1 ||
- _POSIX_THREAD_PROCESS_SHARED == _POSIX_VERSION);
-
#if defined(__BIONIC__)
// These tests only pass on bionic, as bionic and glibc has different support on these macros.
// Macros like _POSIX_ASYNCHRONOUS_IO are not supported on bionic yet.
@@ -921,11 +915,11 @@
VERIFY_SYSCONF_POSIX_VERSION(_SC_READER_WRITER_LOCKS);
VERIFY_SYSCONF_POSITIVE(_SC_REGEXP);
VERIFY_SYSCONF_POSITIVE(_SC_SHELL);
- VERIFY_SYSCONF_UNSUPPORTED(_SC_SPORADIC_SERVER);
+ VERIFY_SYSCONF_POSIX_VERSION(_SC_SPORADIC_SERVER);
VERIFY_SYSCONF_POSITIVE(_SC_SYMLOOP_MAX);
VERIFY_SYSCONF_POSIX_VERSION(_SC_THREAD_CPUTIME);
VERIFY_SYSCONF_POSIX_VERSION(_SC_THREAD_PROCESS_SHARED);
- VERIFY_SYSCONF_UNSUPPORTED(_SC_THREAD_SPORADIC_SERVER);
+ VERIFY_SYSCONF_POSIX_VERSION(_SC_THREAD_SPORADIC_SERVER);
VERIFY_SYSCONF_POSIX_VERSION(_SC_TIMEOUTS);
VERIFY_SYSCONF_UNSUPPORTED(_SC_TRACE);
VERIFY_SYSCONF_UNSUPPORTED(_SC_TRACE_EVENT_FILTER);
diff --git a/tests/utils.h b/tests/utils.h
index 8638850..daf382e 100644
--- a/tests/utils.h
+++ b/tests/utils.h
@@ -71,15 +71,13 @@
class Maps {
public:
static bool parse_maps(std::vector<map_record>* maps) {
- FILE* fp = fopen("/proc/self/maps", "re");
- if (fp == nullptr) {
- return false;
- }
+ maps->clear();
- auto fp_guard = android::base::make_scope_guard([&]() { fclose(fp); });
+ std::unique_ptr<FILE, decltype(&fclose)> fp(fopen("/proc/self/maps", "re"), fclose);
+ if (!fp) return false;
char line[BUFSIZ];
- while (fgets(line, sizeof(line), fp) != nullptr) {
+ while (fgets(line, sizeof(line), fp.get()) != nullptr) {
map_record record;
uint32_t dev_major, dev_minor;
int path_offset;
diff --git a/tools/relocation_packer/Android.bp b/tools/relocation_packer/Android.bp
index 2907b31..cd6053a 100644
--- a/tools/relocation_packer/Android.bp
+++ b/tools/relocation_packer/Android.bp
@@ -16,11 +16,13 @@
cc_defaults {
name: "relocation_packer_flags",
- cppflags: [
+ cflags: [
"-Wall",
+ "-Werror",
+ ],
+ cppflags: [
"-Wextra",
"-Wunused",
- "-Werror",
"-Wold-style-cast",
],
diff --git a/tools/relocation_packer/src/main.cc b/tools/relocation_packer/src/main.cc
index d0a0dd4..1589043 100644
--- a/tools/relocation_packer/src/main.cc
+++ b/tools/relocation_packer/src/main.cc
@@ -106,7 +106,7 @@
// We need to detect elf class in order to create
// correct implementation
uint8_t e_ident[EI_NIDENT];
- if (TEMP_FAILURE_RETRY(read(fd.get(), e_ident, EI_NIDENT) != EI_NIDENT)) {
+ if (TEMP_FAILURE_RETRY(read(fd.get(), e_ident, EI_NIDENT)) != EI_NIDENT) {
LOG(ERROR) << file << ": failed to read elf header:" << strerror(errno);
return 1;
}
diff --git a/tools/update_seccomp.sh b/tools/update_seccomp.sh
new file mode 100755
index 0000000..d108e35
--- /dev/null
+++ b/tools/update_seccomp.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+cd $DIR/..
+./libc/tools/genseccomp.py
+
+git diff --exit-code HEAD libc/seccomp/
+exit $?
diff --git a/tools/update_syscalls.sh b/tools/update_syscalls.sh
new file mode 100755
index 0000000..3ad95ed
--- /dev/null
+++ b/tools/update_syscalls.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+cd $DIR/..
+./libc/tools/gensyscalls.py
+
+git diff --exit-code HEAD libc/arch-*/syscalls/
+exit $?
diff --git a/tools/update_version_scripts.sh b/tools/update_version_scripts.sh
new file mode 100755
index 0000000..ccba475
--- /dev/null
+++ b/tools/update_version_scripts.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+cd $DIR/..
+./libc/tools/genversion-scripts.py
+
+git diff --exit-code HEAD libc/*.map libdl/*.map libm/*.map linker/*.map
+exit $?