Merge "Disable HWASAN on ifunc resolvers."
diff --git a/android-changes-for-ndk-developers.md b/android-changes-for-ndk-developers.md
index a0f3c3c..da07c79 100644
--- a/android-changes-for-ndk-developers.md
+++ b/android-changes-for-ndk-developers.md
@@ -175,11 +175,9 @@
 temporarily support these libraries; so if you see a warning that means
 your code will not work in a future release -- please fix it now!
 
-In O and later, the system property `debug.ld.greylist_disabled` can be
-used to deny access to the greylist even to an app that would normally
-be allowed it. This allows you to test compatibility without bumping the
-app's `targetSdkVersion`. Use `setprop debug.ld.greylist_disabled true`
-to turn this on (any other value leaves the greylist enabled).
+Between O and R, this compatibility mode could be disabled by setting a
+system property (`debug.ld.greylist_disabled`). This property is ignored
+in S and later.
 
 ```
 $ readelf --dynamic libBroken.so | grep NEEDED
@@ -218,7 +216,7 @@
 
 Each ELF file has additional information contained in the section
 headers. These headers must be present now, because the dynamic linker
-uses them for sanity checking. Some developers strip them in an
+uses them for validity checking. Some developers strip them in an
 attempt to obfuscate the binary and prevent reverse engineering. (This
 doesn't really help because it is possible to reconstruct the stripped
 information using widely-available tools.)
diff --git a/apex/Android.bp b/apex/Android.bp
index ce9d82b..100430d 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -65,10 +65,14 @@
 
 module_exports {
     name: "runtime-module-host-exports",
-    defaults: ["linux_bionic_supported"],
+    host_supported: true,
     device_supported: false,
+    compile_multilib: "64",
 
-    native_binaries: [
-        "linker",
-    ],
+    native_binaries: ["linkerconfig"],
+    target: {
+        linux_bionic: {
+            native_binaries: ["linker"],
+        },
+    },
 }
diff --git a/benchmarks/linker_relocation/regen/gen_bench.py b/benchmarks/linker_relocation/regen/gen_bench.py
index 7482319..09efa75 100755
--- a/benchmarks/linker_relocation/regen/gen_bench.py
+++ b/benchmarks/linker_relocation/regen/gen_bench.py
@@ -137,7 +137,7 @@
     return defs
 
 
-def sanity_check_rels(root: LoadedLibrary, defs: Definitions) -> None:
+def check_rels(root: LoadedLibrary, defs: Definitions) -> None:
     # Find every symbol for every relocation in the load group.
     has_missing = False
     for lib in bfs_walk(root):
@@ -389,7 +389,7 @@
     with open(Path(args.input)) as f:
         root = json_to_elf_tree(json.load(f))
     defs = build_symbol_index(root)
-    sanity_check_rels(root, defs)
+    check_rels(root, defs)
 
     if out.exists(): shutil.rmtree(out)
     os.makedirs(str(out))
diff --git a/benchmarks/pthread_benchmark.cpp b/benchmarks/pthread_benchmark.cpp
index 9a68a12..856f150 100644
--- a/benchmarks/pthread_benchmark.cpp
+++ b/benchmarks/pthread_benchmark.cpp
@@ -53,15 +53,14 @@
 }
 BIONIC_BENCHMARK(BM_pthread_setspecific);
 
-static void DummyPthreadOnceInitFunction() {
-}
+static void NoOpPthreadOnceInitFunction() {}
 
 static void BM_pthread_once(benchmark::State& state) {
   static pthread_once_t once = PTHREAD_ONCE_INIT;
-  pthread_once(&once, DummyPthreadOnceInitFunction);
+  pthread_once(&once, NoOpPthreadOnceInitFunction);
 
   while (state.KeepRunning()) {
-    pthread_once(&once, DummyPthreadOnceInitFunction);
+    pthread_once(&once, NoOpPthreadOnceInitFunction);
   }
 }
 BIONIC_BENCHMARK(BM_pthread_once);
diff --git a/benchmarks/semaphore_benchmark.cpp b/benchmarks/semaphore_benchmark.cpp
index cf51489..ffccc82 100644
--- a/benchmarks/semaphore_benchmark.cpp
+++ b/benchmarks/semaphore_benchmark.cpp
@@ -28,8 +28,8 @@
   sem_init(&semaphore, 1, 1);
 
   while (state.KeepRunning()) {
-    int dummy;
-    sem_getvalue(&semaphore, &dummy);
+    int unused;
+    sem_getvalue(&semaphore, &unused);
   }
 }
 BIONIC_BENCHMARK(BM_semaphore_sem_getvalue);
@@ -44,112 +44,3 @@
   }
 }
 BIONIC_BENCHMARK(BM_semaphore_sem_wait_sem_post);
-
-// This test reports the overhead of the underlying futex wake syscall on
-// the producer. It does not report the overhead from issuing the wake to the
-// point where the posted consumer thread wakes up. It suffers from
-// clock_gettime syscall overhead. Lock the CPU speed for consistent results
-// as we may not reach >50% cpu utilization.
-//
-// We will run a background thread that catches the sem_post wakeup and
-// loops immediately returning back to sleep in sem_wait for the next one. This
-// thread is run with policy SCHED_OTHER (normal policy), a middle policy.
-//
-// The primary thread will run at SCHED_IDLE (lowest priority policy) when
-// monitoring the background thread to detect when it hits sem_wait sleep. It
-// will do so with no clock running. Once we are ready, we will switch to
-// SCHED_FIFO (highest priority policy) to time the act of running sem_post
-// with the benchmark clock running. This ensures nothing else in the system
-// can preempt our timed activity, including the background thread. We are
-// also protected with the scheduling policy of letting a process hit a
-// resource limit rather than get hit with a context switch.
-//
-// The background thread will start executing either on another CPU, or
-// after we back down from SCHED_FIFO, but certainly not in the context of
-// the timing of the sem_post.
-
-static atomic_int BM_semaphore_sem_post_running;
-
-static void* BM_semaphore_sem_post_start_thread(void* arg) {
-  sem_t* semaphore = reinterpret_cast<sem_t*>(arg);
-  while ((BM_semaphore_sem_post_running > 0) && !sem_wait(semaphore)) {
-  }
-  BM_semaphore_sem_post_running = -1;
-  return nullptr;
-}
-
-class SemaphoreFixture : public benchmark::Fixture {
- public:
-  void SetUp(const benchmark::State&) override {
-    sem_init(&semaphore, 0, 0);
-
-    pthread_attr_t attr;
-    pthread_attr_init(&attr);
-
-    memset(&param, 0, sizeof(param));
-    pthread_attr_setschedparam(&attr, &param);
-    pthread_attr_setschedpolicy(&attr, SCHED_OTHER);
-    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-    pthread_t pthread;
-    pthread_create(&pthread, &attr, BM_semaphore_sem_post_start_thread, &semaphore);
-    pthread_attr_destroy(&attr);
-
-    sched_setscheduler(0, SCHED_IDLE, &param);
-
-    BM_semaphore_sem_post_running = 1;
-    setup = true;
-  }
-
-  ~SemaphoreFixture() override {
-    if (setup) {
-      // Only do this if the test was actually run.
-      sched_setscheduler(0, SCHED_OTHER, &param);
-
-      if (BM_semaphore_sem_post_running > 0) {
-        BM_semaphore_sem_post_running = 0;
-      }
-      do {
-        sem_post(&semaphore);
-        sched_yield();
-      } while (BM_semaphore_sem_post_running != -1);
-    }
-  }
-
-  sem_t semaphore;
-  sched_param param;
-  bool setup = false;
-};
-
-// This is commented out because dynamic benchmark registering doesn't currently support fixtures.
-// Uncomment it and recompile to run this benchmark on every run.
-/* BENCHMARK_F(SemaphoreFixture, semaphore_sem_post)(benchmark::State& state) {
-  while (state.KeepRunning()) {
-    state.PauseTiming();
-
-    int trys = 3, dummy = 0;
-    do {
-      if (BM_semaphore_sem_post_running < 0) {
-        sched_setscheduler(0, SCHED_OTHER, &param);
-        fprintf(stderr, "BM_semaphore_sem_post: start_thread died unexpectedly\n");
-        abort();
-      }
-      sched_yield();
-      sem_getvalue(&semaphore, &dummy);
-      if (dummy < 0) {  // POSIX.1-2001 possibility 1
-        break;
-      }
-      if (dummy == 0) { // POSIX.1-2001 possibility 2
-        --trys;
-      }
-    } while (trys);
-
-    param.sched_priority = 1;
-    sched_setscheduler(0, SCHED_FIFO, &param);
-
-    state.ResumeTiming();
-    sem_post(&semaphore);
-
-    param.sched_priority = 0;
-    sched_setscheduler(0, SCHED_IDLE, &param);
-  }
-}*/
diff --git a/build/coverage.sh b/build/coverage.sh
new file mode 100755
index 0000000..13fabc5
--- /dev/null
+++ b/build/coverage.sh
@@ -0,0 +1,65 @@
+#!/bin/bash
+
+# This script generates coverage for bionic.
+#
+# Prereqs: Coverage-enabled build.
+#
+#   $ lunch <target>
+#   $ m NATIVE_COVERAGE_PATHS="bionic" CLANG_COVERAGE=true
+#   $ m NATIVE_COVERAGE_PATHS="bionic" CLANG_COVERAGE=true bionic-unit-tests
+#
+# Do *NOT* then rebuild at the top level, or you'll clobber the
+# coverage-enabled libc!
+#
+# Flash image and set $ANDROID_SERIAL.
+#
+# Usage: $ bionic/build/coverage.sh
+# Output: HTML report is generated to /tmp/bionic-coverage/html/index.html
+#
+
+eval "$(cd ${ANDROID_BUILD_TOP}; build/soong/soong_ui.bash --dumpvars-mode --vars="TARGET_ARCH TARGET_ARCH_VARIANT")"
+
+LLVM_PROFDATA=${ANDROID_BUILD_TOP}/prebuilts/clang/host/linux-x86/llvm-binutils-stable/llvm-profdata
+LLVM_COV=${ANDROID_BUILD_TOP}/prebuilts/clang/host/linux-x86/llvm-binutils-stable/llvm-cov
+
+DEVICE_TEST_DIR32=/data/local/tmp/bionic-coverage32
+DEVICE_TEST_DIR64=/data/local/tmp/bionic-coverage64
+DEVICE_PROF_DIR=/data/local/tmp/bionic-profraw
+HOST_PROFDATA_DIR=/tmp/bionic-coverage
+
+# Run bionic-unit-tests
+adb shell rm -rf ${DEVICE_TEST_DIR32} ${DEVICE_TEST_DIR64} ${DEVICE_PROF_DIR}
+adb shell mkdir ${DEVICE_TEST_DIR32} ${DEVICE_TEST_DIR64} ${DEVICE_PROF_DIR}
+adb push $OUT/data/nativetest/bionic-loader-test-libs ${DEVICE_TEST_DIR32}
+adb push $OUT/data/nativetest/bionic-unit-tests ${DEVICE_TEST_DIR32}
+adb push $OUT/data/nativetest64/bionic-loader-test-libs ${DEVICE_TEST_DIR64}
+adb push $OUT/data/nativetest64/bionic-unit-tests ${DEVICE_TEST_DIR64}
+adb shell LLVM_PROFILE_FILE=${DEVICE_PROF_DIR}/bionic-%p-%m.profraw \
+  LD_LIBRARY_PATH=${DEVICE_TEST_DIR32}/bionic-loader-test-libs \
+  ${DEVICE_TEST_DIR32}/bionic-unit-tests/bionic-unit-tests
+adb shell LLVM_PROFILE_FILE=${DEVICE_PROF_DIR}/bionic-%p-%m.profraw \
+  LD_LIBRARY_PATH=${DEVICE_TEST_DIR64}/bionic-loader-test-libs \
+  ${DEVICE_TEST_DIR64}/bionic-unit-tests/bionic-unit-tests
+
+# Pull coverage files and post-process
+rm -rf ${HOST_PROFDATA_DIR}
+mkdir ${HOST_PROFDATA_DIR}
+adb pull ${DEVICE_PROF_DIR} ${HOST_PROFDATA_DIR}/profraws
+
+${LLVM_PROFDATA} merge \
+  --output=${HOST_PROFDATA_DIR}/bionic.profdata \
+  ${HOST_PROFDATA_DIR}/profraws/*.profraw
+
+${LLVM_COV} show \
+  --instr-profile=${HOST_PROFDATA_DIR}/bionic.profdata \
+  --format=html \
+  $OUT/symbols/apex/com.android.runtime/lib64/bionic/libc.so \
+  --object=$OUT/symbols/apex/com.android.runtime/lib64/bionic/libm.so \
+  --object=$OUT/symbols/data/nativetest64/bionic-unit-tests/bionic-unit-tests \
+  --object=$OUT/symbols/apex/com.android.runtime/lib/bionic/libc.so \
+  --object=$OUT/symbols/apex/com.android.runtime/lib/bionic/libm.so \
+  --object=$OUT/symbols/data/nativetest/bionic-unit-tests/bionic-unit-tests \
+  /proc/self/cwd/bionic/libc \
+  /proc/self/cwd/bionic/libm \
+  --output-dir=${HOST_PROFDATA_DIR}/html \
+  --show-region-summary=false
diff --git a/docs/libc_assembler.md b/docs/libc_assembler.md
index 44c0036..43bcfc7 100644
--- a/docs/libc_assembler.md
+++ b/docs/libc_assembler.md
@@ -10,7 +10,8 @@
 * Rerun the benchmarks using the updated image that uses the code for
 the new routine. See the [Performance](#Performance) section for details about
 benchmarking.
-* Verify that unwind information for new routine looks sane. See the [Unwind Info](#unwind-info) section for details about how to verify this.
+* Verify that unwind information for new routine looks correct. See
+the [Unwind Info](#unwind-info) section for details about how to verify this.
 
 When benchmarking, it's best to verify on the latest Pixel device supported.
 Make sure that you benchmark both the big and little cores to verify that
diff --git a/libc/Android.bp b/libc/Android.bp
index 48c9dd0..6b36f96 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -8,7 +8,6 @@
     "bionic/fts.c",
     "bionic/initgroups.c",
     "bionic/isatty.c",
-    "bionic/pututline.c",
     "bionic/sched_cpualloc.c",
     "bionic/sched_cpucount.c",
     "stdio/fmemopen.cpp",
@@ -81,7 +80,6 @@
         // TODO(b/132640749): Fix broken fuzzer support.
         fuzzer: false,
     },
-    native_coverage: false,
     ramdisk_available: true,
     recovery_available: true,
     native_bridge_supported: true,
@@ -100,6 +98,9 @@
         malloc_pattern_fill_contents: {
             cflags: ["-DSCUDO_PATTERN_FILL_CONTENTS"],
         },
+        malloc_not_svelte: {
+            cflags: ["-DUSE_SCUDO"],
+        },
     },
 }
 
@@ -389,7 +390,6 @@
         "upstream-netbsd/lib/libc/gen/nice.c",
         "upstream-netbsd/lib/libc/gen/psignal.c",
         "upstream-netbsd/lib/libc/gen/utime.c",
-        "upstream-netbsd/lib/libc/gen/utmp.c",
         "upstream-netbsd/lib/libc/inet/nsap_addr.c",
         "upstream-netbsd/lib/libc/regex/regcomp.c",
         "upstream-netbsd/lib/libc/regex/regerror.c",
@@ -525,6 +525,7 @@
         "upstream-openbsd/lib/libc/stdlib/llabs.c",
         "upstream-openbsd/lib/libc/stdlib/lldiv.c",
         "upstream-openbsd/lib/libc/stdlib/lsearch.c",
+        "upstream-openbsd/lib/libc/stdlib/recallocarray.c",
         "upstream-openbsd/lib/libc/stdlib/remque.c",
         "upstream-openbsd/lib/libc/stdlib/setenv.c",
         "upstream-openbsd/lib/libc/stdlib/tfind.c",
@@ -566,6 +567,7 @@
     srcs: [
         "stdio/vfprintf.cpp",
         "stdio/vfwprintf.cpp",
+        "upstream-openbsd/lib/libc/string/memmem.c",
         "upstream-openbsd/lib/libc/string/strstr.c",
     ],
     cflags: [
@@ -1009,7 +1011,6 @@
         "bionic/bionic_arc4random.cpp",
         "bionic/bionic_futex.cpp",
         "bionic/bionic_netlink.cpp",
-        "bionic/bionic_systrace.cpp",
         "bionic/bionic_time_conversions.cpp",
         "bionic/brk.cpp",
         "bionic/c16rtomb.cpp",
@@ -1074,7 +1075,6 @@
         "bionic/mblen.cpp",
         "bionic/mbrtoc16.cpp",
         "bionic/mbrtoc32.cpp",
-        "bionic/memmem.cpp",
         "bionic/mempcpy.cpp",
         "bionic/mkdir.cpp",
         "bionic/mkfifo.cpp",
@@ -1152,6 +1152,7 @@
         "bionic/umount.cpp",
         "bionic/unlink.cpp",
         "bionic/usleep.cpp",
+        "bionic/utmp.cpp",
         "bionic/wait.cpp",
         "bionic/wchar.cpp",
         "bionic/wchar_l.cpp",
@@ -1176,7 +1177,10 @@
             cflags: ["-DTREBLE_LINKER_NAMESPACES"],
         },
     },
-    whole_static_libs: ["libsystemproperties"],
+    whole_static_libs: [
+        "libc_bionic_systrace",
+        "libsystemproperties",
+    ],
     cppflags: ["-Wold-style-cast"],
     local_include_dirs: ["stdio"],
     include_dirs: ["bionic/libstdc++/include"],
@@ -1185,6 +1189,21 @@
 }
 
 // ========================================================
+// libc_bionic_systrace.a
+// ========================================================
+
+cc_library_static {
+    name: "libc_bionic_systrace",
+    defaults: ["libc_defaults"],
+    srcs: [
+        "bionic/bionic_systrace.cpp",
+    ],
+    apex_available: [
+        "com.android.runtime",
+    ],
+}
+
+// ========================================================
 // libc_pthread.a - pthreads parts that previously lived in
 // libc_bionic.a. Relocated to their own library because
 // they can't be included in libc_ndk.a (as the layout of
@@ -1219,6 +1238,7 @@
         "bionic/pthread_setname_np.cpp",
         "bionic/pthread_setschedparam.cpp",
         "bionic/pthread_spinlock.cpp",
+        "bionic/sys_thread_properties.cpp",
 
         // The following implementations depend on pthread data or implementation,
         // so we can't include them in libc_ndk.a.
@@ -1982,8 +2002,10 @@
         "//apex_available:platform",
         "//apex_available:anyapex",
     ],
-    // crt* objects are used by most cc_binary/cc_library in "anyapex"
-    min_sdk_version: "apex_inherit",
+    // Generate NDK variants of the CRT objects for every supported API level.
+    min_sdk_version: "16",
+    stl: "none",
+    crt: true,
     cflags: [
         "-Wno-gcc-compat",
         "-Wall",
diff --git a/libc/NOTICE b/libc/NOTICE
index 2fd674b..e8dc4e7 100644
--- a/libc/NOTICE
+++ b/libc/NOTICE
@@ -3004,7 +3004,7 @@
 
 -------------------------------------------------------------------
 
-Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
+Copyright (c) 1997 Todd C. Miller <millert@openbsd.org>
 
 Permission to use, copy, modify, and distribute this software for any
 purpose with or without fee is hereby granted, provided that the above
@@ -3456,35 +3456,6 @@
 
 -------------------------------------------------------------------
 
-Copyright (c) 2002 The NetBSD Foundation, Inc.
-All rights reserved.
-
-This code is derived from software contributed to The NetBSD Foundation
-by Christos Zoulas.
-
-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.
-
-THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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) 2002 Tim J. Robbins
 All rights reserved.
 
@@ -4244,7 +4215,30 @@
 
 -------------------------------------------------------------------
 
-Copyright (c) 2005-2014 Rich Felker
+Copyright (c) 2005-2018 Rich Felker
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2005-2020 Rich Felker, et al.
 
 Permission is hereby granted, free of charge, to any person obtaining
 a copy of this software and associated documentation files (the
@@ -4602,7 +4596,23 @@
 
 -------------------------------------------------------------------
 
-Copyright (c) 2008 Todd C. Miller <millert@openbsd.org>
+Copyright (c) 2008, 2016 Todd C. Miller <millert@openbsd.org>
+
+Permission to use, copy, modify, and distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2008, 2017 Otto Moerbeek <otto@drijf.net>
 
 Permission to use, copy, modify, and distribute this software for any
 purpose with or without fee is hereby granted, provided that the above
diff --git a/libc/arch-arm/bionic/__restore.S b/libc/arch-arm/bionic/__restore.S
index 8c1e41d..5291743 100644
--- a/libc/arch-arm/bionic/__restore.S
+++ b/libc/arch-arm/bionic/__restore.S
@@ -28,13 +28,14 @@
 
 #include <private/bionic_asm.h>
 
-// gdb is smart enough to unwind through signal frames with just the regular
+// gdb is able to unwind through signal frames with just the regular
 // CFI information but libgcc and libunwind both need extra help. We do this
 // by using .fnstart/.fnend and inserting a nop before both __restore and
 // __restore_rt (but covered by the .fnstart/.fnend) so that although they're
 // not inside the functions from objdump's point of view, an unwinder that
-// blindly looks at the previous instruction (but is then smart enough to check
-// the unwind information to find out where it landed) gets the right answer.
+// just assumes it should look at the previous instruction (but is then smart
+// enough to check the unwind information to find out where it landed) gets
+// the right answer.
 // Make sure not to have both DWARF and ARM unwind information, so only
 // use the ARM unwind information.
 
diff --git a/libc/arch-x86/bionic/__libc_init_sysinfo.cpp b/libc/arch-x86/bionic/__libc_init_sysinfo.cpp
index 5c44b4e..db931d1 100644
--- a/libc/arch-x86/bionic/__libc_init_sysinfo.cpp
+++ b/libc/arch-x86/bionic/__libc_init_sysinfo.cpp
@@ -37,8 +37,8 @@
 }
 
 __LIBC_HIDDEN__ void __libc_init_sysinfo() {
-  bool dummy;
-  __libc_sysinfo = reinterpret_cast<void*>(__bionic_getauxval(AT_SYSINFO, dummy));
+  bool unused;
+  __libc_sysinfo = reinterpret_cast<void*>(__bionic_getauxval(AT_SYSINFO, &unused));
 }
 
 // TODO: lose this function and just access __libc_sysinfo directly.
diff --git a/libc/bionic/android_unsafe_frame_pointer_chase.cpp b/libc/bionic/android_unsafe_frame_pointer_chase.cpp
index e25867b..b3b1942 100644
--- a/libc/bionic/android_unsafe_frame_pointer_chase.cpp
+++ b/libc/bionic/android_unsafe_frame_pointer_chase.cpp
@@ -28,8 +28,14 @@
 
 #include "platform/bionic/android_unsafe_frame_pointer_chase.h"
 
-#include "pthread_internal.h"
 #include "platform/bionic/mte.h"
+#include "private/bionic_defs.h"
+#include "pthread_internal.h"
+
+__BIONIC_WEAK_FOR_NATIVE_BRIDGE
+extern "C" __LIBC_HIDDEN__ uintptr_t __get_thread_stack_top() {
+  return __get_thread()->stack_top;
+}
 
 /*
  * Implement fast stack unwinding for stack frames with frame pointers. Stores at most num_entries
@@ -56,7 +62,7 @@
   };
 
   auto begin = reinterpret_cast<uintptr_t>(__builtin_frame_address(0));
-  uintptr_t end = __get_thread()->stack_top;
+  auto end = __get_thread_stack_top();
 
   stack_t ss;
   if (sigaltstack(nullptr, &ss) == 0 && (ss.ss_flags & SS_ONSTACK)) {
diff --git a/libc/bionic/bionic_allocator.cpp b/libc/bionic/bionic_allocator.cpp
index b6d6ba7..98183d4 100644
--- a/libc/bionic/bionic_allocator.cpp
+++ b/libc/bionic/bionic_allocator.cpp
@@ -394,6 +394,26 @@
   }
 }
 
+size_t BionicAllocator::get_chunk_size(void* ptr) {
+  if (ptr == nullptr) return 0;
+
+  page_info* info = get_page_info_unchecked(ptr);
+  if (memcmp(info->signature, kSignature, sizeof(kSignature)) != 0) {
+    // Invalid pointer (mismatched signature)
+    return 0;
+  }
+  if (info->type == kLargeObject) {
+    return info->allocated_size - (static_cast<char*>(ptr) - reinterpret_cast<char*>(info));
+  }
+
+  BionicSmallObjectAllocator* allocator = get_small_object_allocator(info->type);
+  if (allocator != info->allocator_addr) {
+    // Invalid pointer.
+    return 0;
+  }
+  return allocator->get_block_size();
+}
+
 BionicSmallObjectAllocator* BionicAllocator::get_small_object_allocator(uint32_t type) {
   if (type < kSmallObjectMinSizeLog2 || type > kSmallObjectMaxSizeLog2) {
     async_safe_fatal("invalid type: %u", type);
diff --git a/libc/bionic/bionic_elf_tls.cpp b/libc/bionic/bionic_elf_tls.cpp
index 61d826c..d5fb05a 100644
--- a/libc/bionic/bionic_elf_tls.cpp
+++ b/libc/bionic/bionic_elf_tls.cpp
@@ -28,6 +28,7 @@
 
 #include "private/bionic_elf_tls.h"
 
+#include <async_safe/CHECK.h>
 #include <async_safe/log.h>
 #include <string.h>
 #include <sys/param.h>
@@ -269,6 +270,12 @@
         continue;
       }
     }
+    if (modules.on_destruction_cb != nullptr) {
+      void* dtls_begin = dtv->modules[i];
+      void* dtls_end =
+          static_cast<void*>(static_cast<char*>(dtls_begin) + allocator.get_chunk_size(dtls_begin));
+      modules.on_destruction_cb(dtls_begin, dtls_end);
+    }
     allocator.free(dtv->modules[i]);
     dtv->modules[i] = nullptr;
   }
@@ -297,6 +304,12 @@
       memcpy(mod_ptr, segment.init_ptr, segment.init_size);
     }
     dtv->modules[module_idx] = mod_ptr;
+
+    // Reports the allocation to the listener, if any.
+    if (modules.on_creation_cb != nullptr) {
+      modules.on_creation_cb(mod_ptr,
+                             static_cast<void*>(static_cast<char*>(mod_ptr) + segment.size));
+    }
   }
 
   return static_cast<char*>(mod_ptr) + ti->offset;
@@ -351,6 +364,14 @@
       // This module's TLS memory is allocated statically, so don't free it here.
       continue;
     }
+
+    if (modules.on_destruction_cb != nullptr) {
+      void* dtls_begin = dtv->modules[i];
+      void* dtls_end =
+          static_cast<void*>(static_cast<char*>(dtls_begin) + allocator.get_chunk_size(dtls_begin));
+      modules.on_destruction_cb(dtls_begin, dtls_end);
+    }
+
     allocator.free(dtv->modules[i]);
   }
 
@@ -364,3 +385,22 @@
   // Clear the DTV slot. The DTV must not be used again with this thread.
   tcb->tls_slot(TLS_SLOT_DTV) = nullptr;
 }
+
+// Invokes all the registered thread_exit callbacks, if any.
+void __notify_thread_exit_callbacks() {
+  TlsModules& modules = __libc_shared_globals()->tls_modules;
+  if (modules.first_thread_exit_callback == nullptr) {
+    // If there is no first_thread_exit_callback, there shouldn't be a tail.
+    CHECK(modules.thread_exit_callback_tail_node == nullptr);
+    return;
+  }
+
+  // Callbacks are supposed to be invoked in the reverse order
+  // in which they were registered.
+  CallbackHolder* node = modules.thread_exit_callback_tail_node;
+  while (node != nullptr) {
+    node->cb();
+    node = node->prev;
+  }
+  modules.first_thread_exit_callback();
+}
diff --git a/libc/bionic/fdsan.cpp b/libc/bionic/fdsan.cpp
index 4b89918..043510c 100644
--- a/libc/bionic/fdsan.cpp
+++ b/libc/bionic/fdsan.cpp
@@ -137,7 +137,7 @@
     return;
   }
 
-  // Lots of code will (sensibly) fork, blindly call close on all of their fds,
+  // Lots of code will (sensibly) fork, call close on all of their fds,
   // and then exec. Compare our cached pid value against the real one to detect
   // this scenario and permit it.
   pid_t cached_pid = __get_cached_pid();
diff --git a/libc/bionic/fork.cpp b/libc/bionic/fork.cpp
index 3814ed0..5bc7d3f 100644
--- a/libc/bionic/fork.cpp
+++ b/libc/bionic/fork.cpp
@@ -34,7 +34,7 @@
 #include "pthread_internal.h"
 
 __BIONIC_WEAK_FOR_NATIVE_BRIDGE
-int __clone_for_fork() {
+extern "C" __LIBC_HIDDEN__ int __clone_for_fork() {
   pthread_internal_t* self = __get_thread();
 
   int result = clone(nullptr, nullptr, (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD),
@@ -56,7 +56,7 @@
 
   if (result == 0) {
     // Disable fdsan post-fork, so we don't falsely trigger on processes that
-    // fork, close all of their fds blindly, and then exec.
+    // fork, close all of their fds, and then exec.
     android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_DISABLED);
 
     // Reset the stack_and_tls VMA name so it doesn't end with a tid from the
diff --git a/libc/bionic/fortify.cpp b/libc/bionic/fortify.cpp
index 3b804b0..88ae477 100644
--- a/libc/bionic/fortify.cpp
+++ b/libc/bionic/fortify.cpp
@@ -94,9 +94,6 @@
 }
 
 char* __fgets_chk(char* dst, int supplied_size, FILE* stream, size_t dst_len_from_compiler) {
-  if (supplied_size < 0) {
-    __fortify_fatal("fgets: buffer size %d < 0", supplied_size);
-  }
   __check_buffer_access("fgets", "write into", supplied_size, dst_len_from_compiler);
   return fgets(dst, supplied_size, stream);
 }
diff --git a/libc/bionic/getauxval.cpp b/libc/bionic/getauxval.cpp
index d6f75f8..a3c6b19 100644
--- a/libc/bionic/getauxval.cpp
+++ b/libc/bionic/getauxval.cpp
@@ -37,20 +37,20 @@
 
 // This function needs to be safe to call before TLS is set up, so it can't
 // access errno or the stack protector.
-__LIBC_HIDDEN__ unsigned long __bionic_getauxval(unsigned long type, bool& exists) {
+__LIBC_HIDDEN__ unsigned long __bionic_getauxval(unsigned long type, bool* exists) {
   for (ElfW(auxv_t)* v = __libc_shared_globals()->auxv; v->a_type != AT_NULL; ++v) {
     if (v->a_type == type) {
-      exists = true;
+      *exists = true;
       return v->a_un.a_val;
     }
   }
-  exists = false;
+  *exists = false;
   return 0;
 }
 
 extern "C" unsigned long getauxval(unsigned long type) {
   bool exists;
-  unsigned long result = __bionic_getauxval(type, exists);
+  unsigned long result = __bionic_getauxval(type, &exists);
   if (!exists) errno = ENOENT;
   return result;
 }
diff --git a/libc/bionic/gethostname.cpp b/libc/bionic/gethostname.cpp
index 962fea1..b780a2f 100644
--- a/libc/bionic/gethostname.cpp
+++ b/libc/bionic/gethostname.cpp
@@ -32,10 +32,8 @@
 #include <unistd.h>
 
 int gethostname(char* buf, size_t n) {
-  struct utsname name;
-  if (uname(&name) == -1) {
-    return -1;
-  }
+  utsname name = {};
+  uname(&name);
 
   size_t name_length = static_cast<size_t>(strlen(name.nodename) + 1);
   if (name_length > n) {
diff --git a/libc/bionic/ifaddrs.cpp b/libc/bionic/ifaddrs.cpp
index e89b0bf..1536333 100644
--- a/libc/bionic/ifaddrs.cpp
+++ b/libc/bionic/ifaddrs.cpp
@@ -28,6 +28,7 @@
 
 #include <ifaddrs.h>
 
+#include <async_safe/log.h>
 #include <cutils/misc.h>           // FIRST_APPLICATION_UID
 #include <errno.h>
 #include <linux/if_packet.h>
@@ -205,12 +206,12 @@
     new_addr->interface_index = static_cast<int>(msg->ifa_index);
 
     // If this is a known interface, copy what we already know.
+    // If we don't know about this interface yet, we try to resolve the name and flags using ioctl
+    // calls during postprocessing.
     if (known_addr != nullptr) {
       strcpy(new_addr->name, known_addr->name);
       new_addr->ifa.ifa_name = new_addr->name;
       new_addr->ifa.ifa_flags = known_addr->ifa.ifa_flags;
-    } else {
-      new_addr->ifa.ifa_flags = msg->ifa_flags;
     }
 
     // Go through the various bits of information and find the name, address
@@ -271,10 +272,34 @@
     } else {
       prev_addr = addr;
     }
+
     addr = reinterpret_cast<ifaddrs_storage*>(next_addr);
   }
 }
 
+static void get_interface_flags_via_ioctl(ifaddrs** list) {
+  ScopedFd s(socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0));
+  if (s.get() == -1) {
+    async_safe_format_log(ANDROID_LOG_ERROR, "libc",
+                          "socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC) failed in ifaddrs: %s",
+                          strerror(errno));
+    return;
+  }
+
+  for (ifaddrs_storage* addr = reinterpret_cast<ifaddrs_storage*>(*list); addr != nullptr;
+       addr = reinterpret_cast<ifaddrs_storage*>(addr->ifa.ifa_next)) {
+    ifreq ifr = {};
+    strlcpy(ifr.ifr_name, addr->ifa.ifa_name, sizeof(ifr.ifr_name));
+    if (ioctl(s.get(), SIOCGIFFLAGS, &ifr) != -1) {
+      addr->ifa.ifa_flags = ifr.ifr_flags;
+    } else {
+      async_safe_format_log(ANDROID_LOG_ERROR, "libc",
+                            "ioctl(SIOCGIFFLAGS) for \"%s\" failed in ifaddrs: %s",
+                            addr->ifa.ifa_name, strerror(errno));
+    }
+  }
+}
+
 int getifaddrs(ifaddrs** out) {
   // We construct the result directly into `out`, so terminate the list.
   *out = nullptr;
@@ -303,6 +328,9 @@
     // If we weren't able to depend on GETLINK messages, it's possible some
     // interfaces never got their name set. Resolve them using if_indextoname or remove them.
     resolve_or_remove_nameless_interfaces(out);
+    // Similarly, without GETLINK messages, interfaces will not have their flags set.
+    // Resolve them using the SIOCGIFFLAGS ioctl call.
+    get_interface_flags_via_ioctl(out);
   }
 
   return 0;
diff --git a/libc/bionic/libc_init_common.cpp b/libc/bionic/libc_init_common.cpp
index 1ede969..01b6a42 100644
--- a/libc/bionic/libc_init_common.cpp
+++ b/libc/bionic/libc_init_common.cpp
@@ -86,11 +86,14 @@
 }
 
 static void __libc_init_malloc_fill_contents() {
+// TODO(b/158870657) make this unconditional when all devices support SCUDO.
+#if defined(USE_SCUDO)
 #if defined(SCUDO_PATTERN_FILL_CONTENTS)
   scudo_malloc_set_pattern_fill_contents(1);
 #elif defined(SCUDO_ZERO_CONTENTS)
   scudo_malloc_set_zero_contents(1);
 #endif
+#endif
 }
 
 __BIONIC_WEAK_FOR_NATIVE_BRIDGE
@@ -359,10 +362,8 @@
   Dtor* fini_array = reinterpret_cast<Dtor*>(array);
   const Dtor minus1 = reinterpret_cast<Dtor>(static_cast<uintptr_t>(-1));
 
-  // Sanity check - first entry must be -1.
-  if (array == nullptr || fini_array[0] != minus1) {
-    return;
-  }
+  // Validity check: the first entry must be -1.
+  if (array == nullptr || fini_array[0] != minus1) return;
 
   // Skip over it.
   fini_array += 1;
@@ -373,15 +374,9 @@
     ++count;
   }
 
-  // Now call each destructor in reverse order.
+  // Now call each destructor in reverse order, ignoring any -1s.
   while (count > 0) {
     Dtor dtor = fini_array[--count];
-
-    // Sanity check, any -1 in the list is ignored.
-    if (dtor == minus1) {
-      continue;
-    }
-
-    dtor();
+    if (dtor != minus1) dtor();
   }
 }
diff --git a/libc/bionic/libc_init_static.cpp b/libc/bionic/libc_init_static.cpp
index cf5423e..e3a447d 100644
--- a/libc/bionic/libc_init_static.cpp
+++ b/libc/bionic/libc_init_static.cpp
@@ -147,6 +147,7 @@
     mod.first_generation = kTlsGenerationFirst;
 
     modules.module_count = 1;
+    modules.static_module_count = 1;
     modules.module_table = &mod;
   } else {
     layout.reserve_exe_segment_and_tcb(nullptr, progname);
diff --git a/libc/bionic/memmem.cpp b/libc/bionic/memmem.cpp
deleted file mode 100644
index 019e772..0000000
--- a/libc/bionic/memmem.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2008 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.
- */
-
-#include <string.h>
-
-void* memmem(const void* void_haystack, size_t n, const void* void_needle, size_t m) {
-  const unsigned char* haystack = reinterpret_cast<const unsigned char*>(void_haystack);
-  const unsigned char* needle = reinterpret_cast<const unsigned char*>(void_needle);
-
-  if (n < m) return nullptr;
-
-  if (m == 0) return const_cast<void*>(void_haystack);
-  if (m == 1) return const_cast<void*>(memchr(haystack, needle[0], n));
-
-  // This uses the "Not So Naive" algorithm, a very simple but usually effective algorithm.
-  // http://www-igm.univ-mlv.fr/~lecroq/string/
-  const unsigned char* y = haystack;
-  const unsigned char* x = needle;
-  size_t j = 0;
-  size_t k = 1, l = 2;
-
-  if (x[0] == x[1]) {
-    k = 2;
-    l = 1;
-  }
-  while (j <= n-m) {
-    if (x[1] != y[j+1]) {
-      j += k;
-    } else {
-      if (!memcmp(x+2, y+j+2, m-2) && x[0] == y[j]) return const_cast<unsigned char*>(&y[j]);
-      j += l;
-    }
-  }
-  return nullptr;
-}
diff --git a/libc/bionic/ndk_cruft.cpp b/libc/bionic/ndk_cruft.cpp
index e9a5b5b..b15a317 100644
--- a/libc/bionic/ndk_cruft.cpp
+++ b/libc/bionic/ndk_cruft.cpp
@@ -55,8 +55,9 @@
 // By the time any NDK-built code is running, there are plenty of threads.
 int __isthreaded = 1;
 
-// These were accidentally declared in <unistd.h> because we stupidly used to inline
-// getpagesize() and __getpageshift(). Needed for backwards compatibility with old NDK apps.
+// These were accidentally declared in <unistd.h> because we used to inline
+// getpagesize() and __getpageshift(). Needed for backwards compatibility
+// with old NDK apps.
 unsigned int __page_size = PAGE_SIZE;
 unsigned int __page_shift = 12;
 
diff --git a/libc/bionic/pthread_attr.cpp b/libc/bionic/pthread_attr.cpp
index 1551c1f..89aa289 100644
--- a/libc/bionic/pthread_attr.cpp
+++ b/libc/bionic/pthread_attr.cpp
@@ -192,7 +192,8 @@
     return errno;
   }
 
-  // If the current RLIMIT_STACK is RLIM_INFINITY, only admit to an 8MiB stack for sanity's sake.
+  // If the current RLIMIT_STACK is RLIM_INFINITY, only admit to an 8MiB stack
+  // in case callers such as ART take infinity too literally.
   if (stack_limit.rlim_cur == RLIM_INFINITY) {
     stack_limit.rlim_cur = 8 * 1024 * 1024;
   }
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index d4a8bef..c528105 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -350,7 +350,7 @@
   return 0;
 }
 
-// A dummy start routine for pthread_create failures where we've created a thread but aren't
+// A no-op start routine for pthread_create failures where we've created a thread but aren't
 // going to run user code on it. We swap out the user's start routine for this and take advantage
 // of the regular thread teardown to free up resources.
 static void* __do_nothing(void*) {
diff --git a/libc/bionic/pthread_exit.cpp b/libc/bionic/pthread_exit.cpp
index 3b873b3..81dab57 100644
--- a/libc/bionic/pthread_exit.cpp
+++ b/libc/bionic/pthread_exit.cpp
@@ -112,7 +112,6 @@
   munmap(thread->shadow_call_stack_guard_region, SCS_GUARD_REGION_SIZE);
 #endif
 
-  // Free the ELF TLS DTV and all dynamically-allocated ELF TLS memory.
   __free_dynamic_tls(__get_bionic_tcb());
 
   if (old_state == THREAD_DETACHED) {
@@ -128,6 +127,7 @@
     if (thread->mmap_size != 0) {
       // We need to free mapped space for detached threads when they exit.
       // That's not something we can do in C.
+      __notify_thread_exit_callbacks();
       __hwasan_thread_exit();
       _exit_with_stack_teardown(thread->mmap_base, thread->mmap_size);
     }
@@ -135,6 +135,8 @@
 
   // No need to free mapped space. Either there was no space mapped, or it is left for
   // the pthread_join caller to clean up.
+  __notify_thread_exit_callbacks();
   __hwasan_thread_exit();
+
   __exit(0);
 }
diff --git a/libc/bionic/pty.cpp b/libc/bionic/pty.cpp
index 71e14d9..c0e2721 100644
--- a/libc/bionic/pty.cpp
+++ b/libc/bionic/pty.cpp
@@ -112,14 +112,14 @@
   return ioctl(fd, TIOCSPTLCK, &unlock);
 }
 
-int openpty(int* master, int* slave, char* name, const termios* t, const winsize* ws) {
-  *master = getpt();
-  if (*master == -1) {
+int openpty(int* pty, int* tty, char* name, const termios* t, const winsize* ws) {
+  *pty = getpt();
+  if (*pty == -1) {
     return -1;
   }
 
-  if (grantpt(*master) == -1 || unlockpt(*master) == -1) {
-    close(*master);
+  if (grantpt(*pty) == -1 || unlockpt(*pty) == -1) {
+    close(*pty);
     return -1;
   }
 
@@ -127,54 +127,54 @@
   if (name == nullptr) {
     name = buf;
   }
-  if (ptsname_r(*master, name, sizeof(buf)) != 0) {
-    close(*master);
+  if (ptsname_r(*pty, name, sizeof(buf)) != 0) {
+    close(*pty);
     return -1;
   }
 
-  *slave = open(name, O_RDWR|O_NOCTTY);
-  if (*slave == -1) {
-    close(*master);
+  *tty = open(name, O_RDWR | O_NOCTTY);
+  if (*tty == -1) {
+    close(*pty);
     return -1;
   }
 
   if (t != nullptr) {
-    tcsetattr(*slave, TCSAFLUSH, t);
+    tcsetattr(*tty, TCSAFLUSH, t);
   }
   if (ws != nullptr) {
-    ioctl(*slave, TIOCSWINSZ, ws);
+    ioctl(*tty, TIOCSWINSZ, ws);
   }
 
   return 0;
 }
 
-int forkpty(int* amaster, char* name, const termios* t, const winsize* ws) {
-  int master;
-  int slave;
-  if (openpty(&master, &slave, name, t, ws) == -1) {
+int forkpty(int* parent_pty, char* child_tty_name, const termios* t, const winsize* ws) {
+  int pty;
+  int tty;
+  if (openpty(&pty, &tty, child_tty_name, t, ws) == -1) {
     return -1;
   }
 
   pid_t pid = fork();
   if (pid == -1) {
-    close(master);
-    close(slave);
+    close(pty);
+    close(tty);
     return -1;
   }
 
   if (pid == 0) {
     // Child.
-    *amaster = -1;
-    close(master);
-    if (login_tty(slave) == -1) {
+    *parent_pty = -1;
+    close(pty);
+    if (login_tty(tty) == -1) {
       _exit(1);
     }
     return 0;
   }
 
   // Parent.
-  *amaster = master;
-  close(slave);
+  *parent_pty = pty;
+  close(tty);
   return pid;
 }
 
diff --git a/libc/bionic/strtol.cpp b/libc/bionic/strtol.cpp
index 63ac102..77f1d92 100644
--- a/libc/bionic/strtol.cpp
+++ b/libc/bionic/strtol.cpp
@@ -184,9 +184,7 @@
 }
 
 // Public API since L, but not in any header.
-extern "C" long long strtoq(const char* s, char** end, int base) {
-  return strtoll(s, end, base);
-}
+__strong_alias(strtoq, strtoll);
 
 unsigned long strtoul(const char* s, char** end, int base) {
   return StrToU<unsigned long, ULONG_MAX>(s, end, base);
@@ -201,6 +199,4 @@
 }
 
 // Public API since L, but not in any header.
-extern "C" unsigned long long strtouq(const char* s, char** end, int base) {
-  return strtoull(s, end, base);
-}
+__strong_alias(strtouq, strtoull);
diff --git a/libc/bionic/swab.cpp b/libc/bionic/swab.cpp
index bc53ba4..59e1c0f 100644
--- a/libc/bionic/swab.cpp
+++ b/libc/bionic/swab.cpp
@@ -28,14 +28,5 @@
 
 #include <unistd.h>
 
-void swab(const void* void_src, void* void_dst, ssize_t byte_count) {
-  const uint8_t* src = static_cast<const uint8_t*>(void_src);
-  uint8_t* dst = static_cast<uint8_t*>(void_dst);
-  while (byte_count > 1) {
-    uint8_t x = *src++;
-    uint8_t y = *src++;
-    *dst++ = y;
-    *dst++ = x;
-    byte_count -= 2;
-  }
-}
+#define __BIONIC_SWAB_INLINE /* Out of line. */
+#include <bits/swab.h>
diff --git a/libc/bionic/sys_thread_properties.cpp b/libc/bionic/sys_thread_properties.cpp
new file mode 100644
index 0000000..24d7551
--- /dev/null
+++ b/libc/bionic/sys_thread_properties.cpp
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#include <sys/thread_properties.h>
+
+#include <async_safe/CHECK.h>
+#include <async_safe/log.h>
+
+#include <elf.h>
+#include <pthread.h>
+#include <unistd.h>
+
+#include <sys/ptrace.h>
+#include <sys/uio.h>
+#include <sys/user.h>
+
+#include "private/bionic_elf_tls.h"
+#include "private/bionic_globals.h"
+#include "private/bionic_tls.h"
+#include "pthread_internal.h"
+
+void __libc_get_static_tls_bounds(void** stls_begin, void** stls_end) {
+  const StaticTlsLayout& layout = __libc_shared_globals()->static_tls_layout;
+  *stls_begin = reinterpret_cast<char*>(__get_bionic_tcb()) - layout.offset_bionic_tcb();
+  *stls_end = reinterpret_cast<char*>(*stls_begin) + layout.size();
+}
+
+void __libc_register_thread_exit_callback(thread_exit_cb_t cb) {
+  TlsModules& modules = __libc_shared_globals()->tls_modules;
+
+  if (modules.first_thread_exit_callback == nullptr) {
+    modules.first_thread_exit_callback = cb;
+    return;
+  };
+
+  BionicAllocator& allocator = __libc_shared_globals()->tls_allocator;
+  CallbackHolder* new_node =
+      reinterpret_cast<CallbackHolder*>(allocator.alloc(sizeof(CallbackHolder)));
+  new_node->cb = cb;
+  new_node->prev = modules.thread_exit_callback_tail_node;
+  modules.thread_exit_callback_tail_node = new_node;
+}
+
+static inline __always_inline bionic_tcb* __get_bionic_tcb_for_thread(pid_t tid) {
+  // If tid is same as self, then we don't need ptrace.
+  if (gettid() == tid) return __get_bionic_tcb();
+
+  // Find the thread-pointer register for the given thread.
+  void** tp_reg = nullptr;
+
+#if defined(__x86_64__) || defined(__i386__)
+  struct user_regs_struct regs;
+  struct iovec pt_iov = {
+      .iov_base = &regs,
+      .iov_len = sizeof(regs),
+  };
+  if (ptrace(PTRACE_GETREGSET, tid, NT_PRSTATUS, &pt_iov) == 0) {
+#if defined(__x86_64__)
+    tp_reg = reinterpret_cast<void**>(regs.fs);
+#elif defined(__i386__)
+    tp_reg = reinterpret_cast<void**>(regs.xgs);
+#endif
+  }
+#elif defined(__aarch64__) || defined(__arm__)
+  uint64_t reg;
+  struct iovec pt_iov {
+    .iov_base = &reg, .iov_len = sizeof(reg),
+  };
+
+  if (ptrace(PTRACE_GETREGSET, tid, NT_ARM_TLS, &pt_iov) == 0) {
+    tp_reg = reinterpret_cast<void**>(reg);
+  }
+#endif
+
+  if (tp_reg == nullptr) {
+    async_safe_write_log(ANDROID_LOG_FATAL, "libc",
+                         "__get_bionic_tcb_for_thread failed to read thread register.");
+  }
+
+  return reinterpret_cast<bionic_tcb*>(&tp_reg[MIN_TLS_SLOT]);
+}
+
+void __libc_iterate_dynamic_tls(pid_t tid,
+                                void (*cb)(void* __dynamic_tls_begin, void* __dynamic_tls_end,
+                                           size_t __dso_id, void* __arg),
+                                void* arg) {
+  TlsModules& modules = __libc_shared_globals()->tls_modules;
+  bionic_tcb* const tcb = __get_bionic_tcb_for_thread(tid);
+  TlsDtv* const dtv = __get_tcb_dtv(tcb);
+  BionicAllocator& allocator = __libc_shared_globals()->tls_allocator;
+
+  for (size_t i = modules.static_module_count; i < dtv->count; ++i) {
+    void* dtls_begin = dtv->modules[i];
+    if (dtls_begin == nullptr) continue;
+    void* dtls_end =
+        static_cast<void*>(static_cast<char*>(dtls_begin) + allocator.get_chunk_size(dtls_begin));
+    size_t dso_id = __tls_module_idx_to_id(i);
+
+    cb(dtls_begin, dtls_end, dso_id, arg);
+  }
+}
+
+void __libc_register_dynamic_tls_listeners(dtls_listener_t on_creation,
+                                           dtls_listener_t on_destruction) {
+  TlsModules& tls_modules = __libc_shared_globals()->tls_modules;
+  tls_modules.on_creation_cb = on_creation;
+  tls_modules.on_destruction_cb = on_destruction;
+}
diff --git a/libc/bionic/sysinfo.cpp b/libc/bionic/sysinfo.cpp
index 1d1070e..7ab8e9e 100644
--- a/libc/bionic/sysinfo.cpp
+++ b/libc/bionic/sysinfo.cpp
@@ -38,9 +38,10 @@
 
 static bool __matches_cpuN(const char* s) {
   // The %c trick is to ensure that we have the anchored match "^cpu[0-9]+$".
+  // We can't use %*c because the return value is how many were *assigned*.
   unsigned cpu;
-  char dummy;
-  return (sscanf(s, "cpu%u%c", &cpu, &dummy) == 1);
+  char unused;
+  return (sscanf(s, "cpu%u%c", &cpu, &unused) == 1);
 }
 
 int get_nprocs_conf() {
diff --git a/libc/bionic/pututline.c b/libc/bionic/utmp.cpp
similarity index 64%
rename from libc/bionic/pututline.c
rename to libc/bionic/utmp.cpp
index 8cbf470..aa00cd5 100644
--- a/libc/bionic/pututline.c
+++ b/libc/bionic/utmp.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2020 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -25,40 +25,24 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
-#include <string.h>
-#include <stdio.h>
+
 #include <utmp.h>
 
+#include <errno.h>
 
-void pututline(struct utmp* utmp)
-{
-    FILE* f;
-    struct utmp u;
-    long i;
+void endutent() {}
 
-    if (!(f = fopen(_PATH_UTMP, "w+e")))
-        return;
+void setutent() {}
 
-    while (fread(&u, sizeof(struct utmp), 1, f) == 1)
-    {
-        if (!strncmp(utmp->ut_line, u.ut_line, sizeof(u.ut_line) -1))
-        {
-            if ((i = ftell(f)) < 0)
-                goto ret;
-            if (fseek(f, i - sizeof(struct utmp), SEEK_SET) < 0)
-                goto ret;
-            fwrite(utmp, sizeof(struct utmp), 1, f);
-            goto ret;
-        }
-    }
+utmp* getutent() {
+  return nullptr;
+}
 
+utmp* pututline(const utmp*) {
+  return nullptr;
+}
 
-    fclose(f);
-
-    if (!(f = fopen(_PATH_UTMP, "w+e")))
-        return;
-    fwrite(utmp, sizeof(struct utmp), 1, f);
-
-ret:
-    fclose(f);
+int utmpname(const char*) {
+  errno = ENOTSUP;
+  return -1;
 }
diff --git a/libc/include/android/api-level.h b/libc/include/android/api-level.h
index 50cb61a..bcddddd 100644
--- a/libc/include/android/api-level.h
+++ b/libc/include/android/api-level.h
@@ -29,6 +29,13 @@
 #pragma once
 
 /**
+ * @defgroup apilevels API Levels
+ *
+ * Defines functions and constants for working with Android API levels.
+ * @{
+ */
+
+/**
  * @file android/api-level.h
  * @brief Functions and constants for dealing with multiple API levels.
  *
@@ -50,9 +57,40 @@
 /* This #ifndef should never be true except when doxygen is generating docs. */
 #ifndef __ANDROID_API__
 /**
- * `__ANDROID_API__` is the API level being targeted. For the OS,
- * this is `__ANDROID_API_FUTURE__`. For the NDK, this is set by the
- * compiler system based on the API level you claimed to target. See
+ * `__ANDROID_API__` is the [API
+ * level](https://developer.android.com/guide/topics/manifest/uses-sdk-element#ApiLevels)
+ * this code is being built for. The resulting binaries are only guaranteed to
+ * be compatible with devices which have an API level greater than or equal to
+ * `__ANDROID_API__`.
+ *
+ * For NDK and APEX builds, this macro will always be defined. It is set
+ * automatically by Clang using the version suffix that is a part of the target
+ * name. For example, `__ANDROID_API__` will be 24 when Clang is given the
+ * argument `-target aarch64-linux-android24`.
+ *
+ * For non-APEX OS code, this defaults to  __ANDROID_API_FUTURE__.
+ *
+ * The value of `__ANDROID_API__` can be compared to the named constants in
+ * `<android/api-level.h>`.
+ *
+ * The interpretation of `__ANDROID_API__` is similar to the AndroidManifest.xml
+ * `minSdkVersion`. In most cases `__ANDROID_API__` will be identical to
+ * `minSdkVersion`, but as it is a build time constant it is possible for
+ * library code to use a different value than the app it will be included in.
+ * When libraries and applications build for different API levels, the
+ * `minSdkVersion` of the application must be at least as high as the highest
+ * API level used by any of its libraries which are loaded unconditionally.
+ *
+ * Note that in some cases the resulting binaries may load successfully on
+ * devices with an older API level. That behavior should not be relied upon,
+ * even if you are careful to avoid using new APIs, as the toolchain may make
+ * use of new features by default. For example, additional FORTIFY features may
+ * implicitly make use of new APIs, SysV hashes may be omitted in favor of GNU
+ * hashes to improve library load times, or relocation packing may be enabled to
+ * reduce binary size.
+ *
+ * See android_get_device_api_level(),
+ * android_get_application_target_sdk_version() and
  * https://android.googlesource.com/platform/bionic/+/master/docs/defines.md.
  */
 #define __ANDROID_API__ __ANDROID_API_FUTURE__
@@ -114,9 +152,9 @@
 #define __ANDROID_API_S__ 31
 
 /**
- * Returns the `targetSdkVersion` of the caller, or `__ANDROID_API_FUTURE__`
- * if there is no known target SDK version (for code not running in the
- * context of an app).
+ * Returns the `targetSdkVersion` of the caller, or `__ANDROID_API_FUTURE__` if
+ * there is no known target SDK version (for code not running in the context of
+ * an app).
  *
  * The returned values correspond to the named constants in `<android/api-level.h>`,
  * and is equivalent to the AndroidManifest.xml `targetSdkVersion`.
@@ -148,3 +186,5 @@
 #endif
 
 __END_DECLS
+
+/** @} */
diff --git a/libc/include/android/fdsan.h b/libc/include/android/fdsan.h
index 83b9318..e23de85 100644
--- a/libc/include/android/fdsan.h
+++ b/libc/include/android/fdsan.h
@@ -186,7 +186,8 @@
  * Set the error level and return the previous state.
  *
  * Error checking is automatically disabled in the child of a fork, to maintain
- * compatibility with code that forks, blindly closes FDs, and then execs.
+ * compatibility with code that forks, closes all file descriptors, and then
+ * execs.
  *
  * In cases such as the zygote, where the child has no intention of calling
  * exec, call this function to reenable fdsan checks.
diff --git a/libc/bionic/pututline.c b/libc/include/android/legacy_unistd_inlines.h
similarity index 62%
copy from libc/bionic/pututline.c
copy to libc/include/android/legacy_unistd_inlines.h
index 8cbf470..4a5206b 100644
--- a/libc/bionic/pututline.c
+++ b/libc/include/android/legacy_unistd_inlines.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2019 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -25,40 +25,14 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
-#include <string.h>
-#include <stdio.h>
-#include <utmp.h>
 
+#pragma once
 
-void pututline(struct utmp* utmp)
-{
-    FILE* f;
-    struct utmp u;
-    long i;
+#include <sys/cdefs.h>
 
-    if (!(f = fopen(_PATH_UTMP, "w+e")))
-        return;
+#if __ANDROID_API__ < 28
 
-    while (fread(&u, sizeof(struct utmp), 1, f) == 1)
-    {
-        if (!strncmp(utmp->ut_line, u.ut_line, sizeof(u.ut_line) -1))
-        {
-            if ((i = ftell(f)) < 0)
-                goto ret;
-            if (fseek(f, i - sizeof(struct utmp), SEEK_SET) < 0)
-                goto ret;
-            fwrite(utmp, sizeof(struct utmp), 1, f);
-            goto ret;
-        }
-    }
+#define __BIONIC_SWAB_INLINE static __inline
+#include <bits/swab.h>
 
-
-    fclose(f);
-
-    if (!(f = fopen(_PATH_UTMP, "w+e")))
-        return;
-    fwrite(utmp, sizeof(struct utmp), 1, f);
-
-ret:
-    fclose(f);
-}
+#endif
diff --git a/libc/include/bits/glibc-syscalls.h b/libc/include/bits/glibc-syscalls.h
index 0e3014d..71e67a3 100644
--- a/libc/include/bits/glibc-syscalls.h
+++ b/libc/include/bits/glibc-syscalls.h
@@ -186,6 +186,9 @@
 #if defined(__NR_faccessat)
   #define SYS_faccessat __NR_faccessat
 #endif
+#if defined(__NR_faccessat2)
+  #define SYS_faccessat2 __NR_faccessat2
+#endif
 #if defined(__NR_fadvise64)
   #define SYS_fadvise64 __NR_fadvise64
 #endif
diff --git a/libc/bionic/pututline.c b/libc/include/bits/swab.h
similarity index 63%
copy from libc/bionic/pututline.c
copy to libc/include/bits/swab.h
index 8cbf470..63281b6 100644
--- a/libc/bionic/pututline.c
+++ b/libc/include/bits/swab.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2019 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -25,40 +25,29 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
-#include <string.h>
-#include <stdio.h>
-#include <utmp.h>
 
+#pragma once
 
-void pututline(struct utmp* utmp)
-{
-    FILE* f;
-    struct utmp u;
-    long i;
+#include <stdint.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
 
-    if (!(f = fopen(_PATH_UTMP, "w+e")))
-        return;
+#if !defined(__BIONIC_SWAB_INLINE)
+#define __BIONIC_SWAB_INLINE static __inline
+#endif
 
-    while (fread(&u, sizeof(struct utmp), 1, f) == 1)
-    {
-        if (!strncmp(utmp->ut_line, u.ut_line, sizeof(u.ut_line) -1))
-        {
-            if ((i = ftell(f)) < 0)
-                goto ret;
-            if (fseek(f, i - sizeof(struct utmp), SEEK_SET) < 0)
-                goto ret;
-            fwrite(utmp, sizeof(struct utmp), 1, f);
-            goto ret;
-        }
-    }
+__BEGIN_DECLS
 
-
-    fclose(f);
-
-    if (!(f = fopen(_PATH_UTMP, "w+e")))
-        return;
-    fwrite(utmp, sizeof(struct utmp), 1, f);
-
-ret:
-    fclose(f);
+__BIONIC_SWAB_INLINE void swab(const void* __void_src, void* __void_dst, ssize_t __byte_count) {
+  const uint8_t* __src = __BIONIC_CAST(static_cast, const uint8_t*, __void_src);
+  uint8_t* __dst = __BIONIC_CAST(static_cast, uint8_t*, __void_dst);
+  while (__byte_count > 1) {
+    uint8_t x = *__src++;
+    uint8_t y = *__src++;
+    *__dst++ = y;
+    *__dst++ = x;
+    __byte_count -= 2;
+  }
 }
+
+__END_DECLS
diff --git a/libc/include/malloc.h b/libc/include/malloc.h
index ba0af3c..833fa59 100644
--- a/libc/include/malloc.h
+++ b/libc/include/malloc.h
@@ -170,6 +170,28 @@
  * Available since API level 28.
  */
 #define M_PURGE (-101)
+/**
+ * mallopt() option to set the maximum number of items in the secondary
+ * cache of the scudo allocator.
+ *
+ * Available since API level 31.
+ */
+#define M_CACHE_COUNT_MAX (-200)
+/**
+ * mallopt() option to set the maximum size in bytes of a cacheable item in
+ * the secondary cache of the scudo allocator.
+ *
+ * Available since API level 31.
+ */
+#define M_CACHE_SIZE_MAX (-201)
+/**
+ * mallopt() option to increase the maximum number of shared thread-specific
+ * data structures that can be created. This number cannot be decreased,
+ * only increased and only applies to the scudo allocator.
+ *
+ * Available since API level 31.
+ */
+#define M_TSDS_COUNT_MAX (-202)
 
 /**
  * [mallopt(3)](http://man7.org/linux/man-pages/man3/mallopt.3.html) modifies
diff --git a/libc/include/nl_types.h b/libc/include/nl_types.h
index 622880a..1c80e4e 100644
--- a/libc/include/nl_types.h
+++ b/libc/include/nl_types.h
@@ -32,7 +32,7 @@
  * @file nl_types.h
  * @brief Message catalogs.
  *
- * Android offers a dummy implementation of these functions to ease porting of historical software.
+ * Android offers a no-op implementation of these functions to ease porting of historical software.
  */
 
 #include <sys/cdefs.h>
diff --git a/libc/include/pty.h b/libc/include/pty.h
index 90d6686..be447d6 100644
--- a/libc/include/pty.h
+++ b/libc/include/pty.h
@@ -49,16 +49,17 @@
  *
  * Available since API level 23.
  */
-int openpty(int* _Nonnull __master_fd, int* _Nonnull __slave_fd, char* _Nullable __slave_name, const struct termios* _Nullable __termios_ptr, const struct winsize* _Nullable __winsize_ptr) __INTRODUCED_IN(23);
+int openpty(int* _Nonnull __pty_fd, int* _Nonnull __tty_fd, char* _Nullable __tty_name, const struct termios* _Nullable __termios_ptr, const struct winsize* _Nullable __winsize_ptr) __INTRODUCED_IN(23);
 
 /**
  * [forkpty(3)](http://man7.org/linux/man-pages/man3/forkpty.3.html) creates
  * a new process connected to a pseudoterminal from openpty().
  *
- * Returns 0 on success and returns -1 and sets `errno` on failure.
+ * Returns 0 in the child/the pid of the child in the parent on success,
+ * and returns -1 and sets `errno` on failure.
  *
  * Available since API level 23.
  */
-int forkpty(int* _Nonnull __master_fd, char* _Nullable __slave_name, const struct termios* _Nullable __termios_ptr, const struct winsize* _Nullable __winsize_ptr) __INTRODUCED_IN(23);
+int forkpty(int* _Nonnull __parent_pty_fd, char* _Nullable __child_tty_name, const struct termios* _Nullable __termios_ptr, const struct winsize* _Nullable __winsize_ptr) __INTRODUCED_IN(23);
 
 __END_DECLS
diff --git a/libc/include/sys/thread_properties.h b/libc/include/sys/thread_properties.h
new file mode 100644
index 0000000..b5d30c7
--- /dev/null
+++ b/libc/include/sys/thread_properties.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2020 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
+
+/**
+ * @file thread_properties.h
+ * @brief Thread properties API.
+ *
+ * https://sourceware.org/glibc/wiki/ThreadPropertiesAPI
+ * API for querying various properties of the current thread, used mostly by
+ * the sanitizers.
+ *
+ * Available since API level 31.
+ *
+ */
+
+#include <sys/cdefs.h>
+#include <unistd.h>
+
+__BEGIN_DECLS
+
+/**
+ * Gets the bounds of static TLS for the current thread.
+ *
+ * Available since API level 31.
+ */
+void __libc_get_static_tls_bounds(void** __static_tls_begin,
+                                  void** __static_tls_end) __INTRODUCED_IN(31);
+
+
+/**
+ * Registers callback to be called right before the thread is dead.
+ * The callbacks are chained, they are called in the order opposite to the order
+ * they were registered.
+ *
+ * The callbacks must be registered only before any threads were created.
+ * No signals may arrive during the calls to these callbacks.
+ * The callbacks may not access the thread's dynamic TLS because they will have
+ * been freed by the time these callbacks are invoked.
+ *
+ * Available since API level 31.
+ */
+void __libc_register_thread_exit_callback(void (*__cb)(void)) __INTRODUCED_IN(31);
+
+/**
+ * Iterates over all dynamic TLS chunks for the given thread.
+ * The thread should have been suspended. It is undefined-behaviour if there is concurrent
+ * modification of the target thread's dynamic TLS.
+ *
+ * Available since API level 31.
+ */
+void __libc_iterate_dynamic_tls(pid_t __tid,
+                                void (*__cb)(void* __dynamic_tls_begin,
+                                             void* __dynamic_tls_end,
+                                             size_t __dso_id,
+                                             void* __arg),
+                                void* __arg) __INTRODUCED_IN(31);
+
+/**
+ * Register on_creation and on_destruction callbacks, which will be called after a dynamic
+ * TLS creation and before a dynamic TLS destruction, respectively.
+ *
+ * Available since API level 31.
+ */
+void __libc_register_dynamic_tls_listeners(
+    void (*__on_creation)(void* __dynamic_tls_begin,
+                          void* __dynamic_tls_end),
+    void (*__on_destruction)(void* __dynamic_tls_begin,
+                             void* __dynamic_tls_end)) __INTRODUCED_IN(31);
+
+__END_DECLS
diff --git a/libc/include/unistd.h b/libc/include/unistd.h
index aaa8f22..e360421 100644
--- a/libc/include/unistd.h
+++ b/libc/include/unistd.h
@@ -313,7 +313,9 @@
 int getdomainname(char* __buf, size_t __buf_size) __INTRODUCED_IN(26);
 int setdomainname(const char* __name, size_t __n) __INTRODUCED_IN(26);
 
+#if __ANDROID_API__ >= 28
 void swab(const void* __src, void* __dst, ssize_t __byte_count) __INTRODUCED_IN(28);
+#endif
 
 #if defined(__BIONIC_INCLUDE_FORTIFY_HEADERS)
 #define _UNISTD_H_
@@ -322,3 +324,5 @@
 #endif
 
 __END_DECLS
+
+#include <android/legacy_unistd_inlines.h>
diff --git a/libc/include/utmp.h b/libc/include/utmp.h
index 6a52511..cb72ce2 100644
--- a/libc/include/utmp.h
+++ b/libc/include/utmp.h
@@ -25,8 +25,13 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
-#ifndef _UTMP_H_
-#define _UTMP_H_
+
+#pragma once
+
+/**
+ * @file utmp.h
+ * @brief POSIX login records.
+ */
 
 #include <sys/cdefs.h>
 #include <sys/types.h>
@@ -57,52 +62,71 @@
 #define DEAD_PROCESS  8
 #define ACCOUNTING    9
 
-struct lastlog
-{
-    time_t ll_time;
-    char ll_line[UT_LINESIZE];
-    char ll_host[UT_HOSTSIZE];
+struct lastlog {
+  time_t ll_time;
+  char ll_line[UT_LINESIZE];
+  char ll_host[UT_HOSTSIZE];
 };
 
-struct exit_status
-{
-    short int e_termination;
-    short int e_exit;
+struct exit_status {
+  short int e_termination;
+  short int e_exit;
 };
 
+struct utmp {
+  short int ut_type;
+  pid_t ut_pid;
+  char ut_line[UT_LINESIZE];
+  char ut_id[4];
+  char ut_user[UT_NAMESIZE];
+  char ut_host[UT_HOSTSIZE];
 
-struct utmp
-{
-    short int ut_type;
-    pid_t ut_pid;
-    char ut_line[UT_LINESIZE];
-    char ut_id[4];
-    char ut_user[UT_NAMESIZE];
-    char ut_host[UT_HOSTSIZE];
+  struct exit_status ut_exit;
 
-    struct exit_status ut_exit;
+  long int ut_session;
+  struct timeval ut_tv;
 
-    long int ut_session;
-    struct timeval ut_tv;
-
-    int32_t ut_addr_v6[4];
-    char unsed[20];
+  int32_t ut_addr_v6[4];
+  char unused[20];
 };
 
-
 #define ut_name ut_user
 #define ut_time ut_tv.tv_sec
 #define ut_addr ut_addr_v6[0]
 
 __BEGIN_DECLS
 
+/**
+ * Does nothing.
+ */
 int utmpname(const char* __path);
+/**
+ * Does nothing.
+ */
 void setutent(void);
+/**
+ * Does nothing.
+ */
 struct utmp* getutent(void);
+/**
+ * Does nothing.
+ */
+struct utmp* pututline(const struct utmp* __entry);
+/**
+ * Does nothing.
+ */
 void endutent(void);
 
+/**
+ * [login_tty(3)](https://www.man7.org/linux/man-pages/man3/login_tty.3.html)
+ * prepares for login on the given file descriptor.
+ *
+ * See also forkpty() which combines openpty(), fork(), and login_tty().
+ *
+ * Returns 0 on success and returns -1 and sets `errno` on failure.
+ *
+ * Available since API level 23.
+ */
 int login_tty(int __fd) __INTRODUCED_IN(23);
 
 __END_DECLS
-
-#endif /* _UTMP_H_ */
diff --git a/libc/kernel/tools/cpp.py b/libc/kernel/tools/cpp.py
index b6a1538..8538eb0 100755
--- a/libc/kernel/tools/cpp.py
+++ b/libc/kernel/tools/cpp.py
@@ -267,7 +267,7 @@
 
     def parseString(self, lines):
         """Parse a list of text lines into a BlockList object."""
-        file_ = 'dummy.c'
+        file_ = 'no-filename-available.c'
         self._tu = self._indexer.parse(file_, self.clang_flags,
                                        unsaved_files=[(file_, lines)],
                                        options=self.options)
diff --git a/libc/kernel/uapi/asm-arm/asm/unistd-common.h b/libc/kernel/uapi/asm-arm/asm/unistd-common.h
index 261328e..5784399 100644
--- a/libc/kernel/uapi/asm-arm/asm/unistd-common.h
+++ b/libc/kernel/uapi/asm-arm/asm/unistd-common.h
@@ -409,4 +409,5 @@
 #define __NR_clone3 (__NR_SYSCALL_BASE + 435)
 #define __NR_openat2 (__NR_SYSCALL_BASE + 437)
 #define __NR_pidfd_getfd (__NR_SYSCALL_BASE + 438)
+#define __NR_faccessat2 (__NR_SYSCALL_BASE + 439)
 #endif
diff --git a/libc/kernel/uapi/asm-arm64/asm/hwcap.h b/libc/kernel/uapi/asm-arm64/asm/hwcap.h
index ebe2fa4..dcca79b 100644
--- a/libc/kernel/uapi/asm-arm64/asm/hwcap.h
+++ b/libc/kernel/uapi/asm-arm64/asm/hwcap.h
@@ -67,4 +67,5 @@
 #define HWCAP2_BF16 (1 << 14)
 #define HWCAP2_DGH (1 << 15)
 #define HWCAP2_RNG (1 << 16)
+#define HWCAP2_BTI (1 << 17)
 #endif
diff --git a/libc/kernel/uapi/asm-arm64/asm/mman.h b/libc/kernel/uapi/asm-arm64/asm/mman.h
index 6c23fb6..ed77d09 100644
--- a/libc/kernel/uapi/asm-arm64/asm/mman.h
+++ b/libc/kernel/uapi/asm-arm64/asm/mman.h
@@ -16,4 +16,8 @@
  ***
  ****************************************************************************
  ****************************************************************************/
+#ifndef _UAPI__ASM_MMAN_H
+#define _UAPI__ASM_MMAN_H
 #include <asm-generic/mman.h>
+#define PROT_BTI 0x10
+#endif
diff --git a/libc/kernel/uapi/asm-arm64/asm/ptrace.h b/libc/kernel/uapi/asm-arm64/asm/ptrace.h
index 23ab407..31ba117 100644
--- a/libc/kernel/uapi/asm-arm64/asm/ptrace.h
+++ b/libc/kernel/uapi/asm-arm64/asm/ptrace.h
@@ -34,6 +34,7 @@
 #define PSR_I_BIT 0x00000080
 #define PSR_A_BIT 0x00000100
 #define PSR_D_BIT 0x00000200
+#define PSR_BTYPE_MASK 0x00000c00
 #define PSR_SSBS_BIT 0x00001000
 #define PSR_PAN_BIT 0x00400000
 #define PSR_UAO_BIT 0x00800000
@@ -42,10 +43,15 @@
 #define PSR_C_BIT 0x20000000
 #define PSR_Z_BIT 0x40000000
 #define PSR_N_BIT 0x80000000
+#define PSR_BTYPE_SHIFT 10
 #define PSR_f 0xff000000
 #define PSR_s 0x00ff0000
 #define PSR_x 0x0000ff00
 #define PSR_c 0x000000ff
+#define PSR_BTYPE_NONE (0b00 << PSR_BTYPE_SHIFT)
+#define PSR_BTYPE_JC (0b01 << PSR_BTYPE_SHIFT)
+#define PSR_BTYPE_C (0b10 << PSR_BTYPE_SHIFT)
+#define PSR_BTYPE_J (0b11 << PSR_BTYPE_SHIFT)
 #define PTRACE_SYSEMU 31
 #define PTRACE_SYSEMU_SINGLESTEP 32
 #ifndef __ASSEMBLY__
diff --git a/libc/kernel/uapi/asm-generic/unistd.h b/libc/kernel/uapi/asm-generic/unistd.h
index 1b85b30..efb5218 100644
--- a/libc/kernel/uapi/asm-generic/unistd.h
+++ b/libc/kernel/uapi/asm-generic/unistd.h
@@ -398,8 +398,9 @@
 #endif
 #define __NR_openat2 437
 #define __NR_pidfd_getfd 438
+#define __NR_faccessat2 439
 #undef __NR_syscalls
-#define __NR_syscalls 439
+#define __NR_syscalls 440
 #if __BITS_PER_LONG == 64 && !defined(__SYSCALL_COMPAT)
 #define __NR_fcntl __NR3264_fcntl
 #define __NR_statfs __NR3264_statfs
diff --git a/libc/kernel/uapi/asm-x86/asm/kvm.h b/libc/kernel/uapi/asm-x86/asm/kvm.h
index 1e88a69..58a20ce 100644
--- a/libc/kernel/uapi/asm-x86/asm/kvm.h
+++ b/libc/kernel/uapi/asm-x86/asm/kvm.h
@@ -325,9 +325,12 @@
 #define KVM_STATE_NESTED_RUN_PENDING 0x00000002
 #define KVM_STATE_NESTED_EVMCS 0x00000004
 #define KVM_STATE_NESTED_MTF_PENDING 0x00000008
+#define KVM_STATE_NESTED_GIF_SET 0x00000100
 #define KVM_STATE_NESTED_SMM_GUEST_MODE 0x00000001
 #define KVM_STATE_NESTED_SMM_VMXON 0x00000002
 #define KVM_STATE_NESTED_VMX_VMCS_SIZE 0x1000
+#define KVM_STATE_NESTED_SVM_VMCB_SIZE 0x1000
+#define KVM_STATE_VMX_PREEMPTION_TIMER_DEADLINE 0x00000001
 struct kvm_vmx_nested_state_data {
   __u8 vmcs12[KVM_STATE_NESTED_VMX_VMCS_SIZE];
   __u8 shadow_vmcs12[KVM_STATE_NESTED_VMX_VMCS_SIZE];
@@ -338,6 +341,14 @@
   struct {
     __u16 flags;
   } smm;
+  __u32 flags;
+  __u64 preemption_timer_deadline;
+};
+struct kvm_svm_nested_state_data {
+  __u8 vmcb12[KVM_STATE_NESTED_SVM_VMCB_SIZE];
+};
+struct kvm_svm_nested_state_hdr {
+  __u64 vmcb_pa;
 };
 struct kvm_nested_state {
   __u16 flags;
@@ -345,10 +356,12 @@
   __u32 size;
   union {
     struct kvm_vmx_nested_state_hdr vmx;
+    struct kvm_svm_nested_state_hdr svm;
     __u8 pad[120];
   } hdr;
   union {
     struct kvm_vmx_nested_state_data vmx[0];
+    struct kvm_svm_nested_state_data svm[0];
   } data;
 };
 struct kvm_pmu_event_filter {
diff --git a/libc/kernel/uapi/asm-x86/asm/kvm_para.h b/libc/kernel/uapi/asm-x86/asm/kvm_para.h
index ad8fe0b..8352761 100644
--- a/libc/kernel/uapi/asm-x86/asm/kvm_para.h
+++ b/libc/kernel/uapi/asm-x86/asm/kvm_para.h
@@ -34,6 +34,7 @@
 #define KVM_FEATURE_PV_SEND_IPI 11
 #define KVM_FEATURE_POLL_CONTROL 12
 #define KVM_FEATURE_PV_SCHED_YIELD 13
+#define KVM_FEATURE_ASYNC_PF_INT 14
 #define KVM_HINTS_REALTIME 0
 #define KVM_FEATURE_CLOCKSOURCE_STABLE_BIT 24
 #define MSR_KVM_WALL_CLOCK 0x11
@@ -45,6 +46,8 @@
 #define MSR_KVM_STEAL_TIME 0x4b564d03
 #define MSR_KVM_PV_EOI_EN 0x4b564d04
 #define MSR_KVM_POLL_CONTROL 0x4b564d05
+#define MSR_KVM_ASYNC_PF_INT 0x4b564d06
+#define MSR_KVM_ASYNC_PF_ACK 0x4b564d07
 struct kvm_steal_time {
   __u64 steal;
   __u32 version;
@@ -70,6 +73,8 @@
 #define KVM_ASYNC_PF_ENABLED (1 << 0)
 #define KVM_ASYNC_PF_SEND_ALWAYS (1 << 1)
 #define KVM_ASYNC_PF_DELIVERY_AS_PF_VMEXIT (1 << 2)
+#define KVM_ASYNC_PF_DELIVERY_AS_INT (1 << 3)
+#define KVM_ASYNC_PF_VEC_MASK GENMASK(7, 0)
 #define KVM_MMU_OP_WRITE_PTE 1
 #define KVM_MMU_OP_FLUSH_TLB 2
 #define KVM_MMU_OP_RELEASE_PT 3
@@ -92,8 +97,9 @@
 #define KVM_PV_REASON_PAGE_NOT_PRESENT 1
 #define KVM_PV_REASON_PAGE_READY 2
 struct kvm_vcpu_pv_apf_data {
-  __u32 reason;
-  __u8 pad[60];
+  __u32 flags;
+  __u32 token;
+  __u8 pad[56];
   __u32 enabled;
 };
 #define KVM_PV_EOI_BIT 0
diff --git a/libc/kernel/uapi/asm-x86/asm/mce.h b/libc/kernel/uapi/asm-x86/asm/mce.h
index 4a3230c..359af57 100644
--- a/libc/kernel/uapi/asm-x86/asm/mce.h
+++ b/libc/kernel/uapi/asm-x86/asm/mce.h
@@ -45,6 +45,7 @@
   __u64 ipid;
   __u64 ppin;
   __u32 microcode;
+  __u64 kflags;
 };
 #define MCE_GET_RECORD_LEN _IOR('M', 1, int)
 #define MCE_GET_LOG_LEN _IOR('M', 2, int)
diff --git a/libc/kernel/uapi/asm-x86/asm/unistd_32.h b/libc/kernel/uapi/asm-x86/asm/unistd_32.h
index bbb0a6c..a3256c0 100644
--- a/libc/kernel/uapi/asm-x86/asm/unistd_32.h
+++ b/libc/kernel/uapi/asm-x86/asm/unistd_32.h
@@ -445,4 +445,5 @@
 #define __NR_clone3 435
 #define __NR_openat2 437
 #define __NR_pidfd_getfd 438
+#define __NR_faccessat2 439
 #endif
diff --git a/libc/kernel/uapi/asm-x86/asm/unistd_64.h b/libc/kernel/uapi/asm-x86/asm/unistd_64.h
index 6a59d78..9c12a3d 100644
--- a/libc/kernel/uapi/asm-x86/asm/unistd_64.h
+++ b/libc/kernel/uapi/asm-x86/asm/unistd_64.h
@@ -367,4 +367,5 @@
 #define __NR_clone3 435
 #define __NR_openat2 437
 #define __NR_pidfd_getfd 438
+#define __NR_faccessat2 439
 #endif
diff --git a/libc/kernel/uapi/asm-x86/asm/unistd_x32.h b/libc/kernel/uapi/asm-x86/asm/unistd_x32.h
index e674447..5f92cfd 100644
--- a/libc/kernel/uapi/asm-x86/asm/unistd_x32.h
+++ b/libc/kernel/uapi/asm-x86/asm/unistd_x32.h
@@ -320,6 +320,7 @@
 #define __NR_clone3 (__X32_SYSCALL_BIT + 435)
 #define __NR_openat2 (__X32_SYSCALL_BIT + 437)
 #define __NR_pidfd_getfd (__X32_SYSCALL_BIT + 438)
+#define __NR_faccessat2 (__X32_SYSCALL_BIT + 439)
 #define __NR_rt_sigaction (__X32_SYSCALL_BIT + 512)
 #define __NR_rt_sigreturn (__X32_SYSCALL_BIT + 513)
 #define __NR_ioctl (__X32_SYSCALL_BIT + 514)
diff --git a/libc/kernel/uapi/asm-x86/asm/vmx.h b/libc/kernel/uapi/asm-x86/asm/vmx.h
index a0c748d..47d5fb2 100644
--- a/libc/kernel/uapi/asm-x86/asm/vmx.h
+++ b/libc/kernel/uapi/asm-x86/asm/vmx.h
@@ -79,6 +79,7 @@
 #define EXIT_REASON_UMWAIT 67
 #define EXIT_REASON_TPAUSE 68
 #define VMX_EXIT_REASONS { EXIT_REASON_EXCEPTION_NMI, "EXCEPTION_NMI" }, { EXIT_REASON_EXTERNAL_INTERRUPT, "EXTERNAL_INTERRUPT" }, { EXIT_REASON_TRIPLE_FAULT, "TRIPLE_FAULT" }, { EXIT_REASON_INIT_SIGNAL, "INIT_SIGNAL" }, { EXIT_REASON_INTERRUPT_WINDOW, "INTERRUPT_WINDOW" }, { EXIT_REASON_NMI_WINDOW, "NMI_WINDOW" }, { EXIT_REASON_TASK_SWITCH, "TASK_SWITCH" }, { EXIT_REASON_CPUID, "CPUID" }, { EXIT_REASON_HLT, "HLT" }, { EXIT_REASON_INVD, "INVD" }, { EXIT_REASON_INVLPG, "INVLPG" }, { EXIT_REASON_RDPMC, "RDPMC" }, { EXIT_REASON_RDTSC, "RDTSC" }, { EXIT_REASON_VMCALL, "VMCALL" }, { EXIT_REASON_VMCLEAR, "VMCLEAR" }, { EXIT_REASON_VMLAUNCH, "VMLAUNCH" }, { EXIT_REASON_VMPTRLD, "VMPTRLD" }, { EXIT_REASON_VMPTRST, "VMPTRST" }, { EXIT_REASON_VMREAD, "VMREAD" }, { EXIT_REASON_VMRESUME, "VMRESUME" }, { EXIT_REASON_VMWRITE, "VMWRITE" }, { EXIT_REASON_VMOFF, "VMOFF" }, { EXIT_REASON_VMON, "VMON" }, { EXIT_REASON_CR_ACCESS, "CR_ACCESS" }, { EXIT_REASON_DR_ACCESS, "DR_ACCESS" }, { EXIT_REASON_IO_INSTRUCTION, "IO_INSTRUCTION" }, { EXIT_REASON_MSR_READ, "MSR_READ" }, { EXIT_REASON_MSR_WRITE, "MSR_WRITE" }, { EXIT_REASON_INVALID_STATE, "INVALID_STATE" }, { EXIT_REASON_MSR_LOAD_FAIL, "MSR_LOAD_FAIL" }, { EXIT_REASON_MWAIT_INSTRUCTION, "MWAIT_INSTRUCTION" }, { EXIT_REASON_MONITOR_TRAP_FLAG, "MONITOR_TRAP_FLAG" }, { EXIT_REASON_MONITOR_INSTRUCTION, "MONITOR_INSTRUCTION" }, { EXIT_REASON_PAUSE_INSTRUCTION, "PAUSE_INSTRUCTION" }, { EXIT_REASON_MCE_DURING_VMENTRY, "MCE_DURING_VMENTRY" }, { EXIT_REASON_TPR_BELOW_THRESHOLD, "TPR_BELOW_THRESHOLD" }, { EXIT_REASON_APIC_ACCESS, "APIC_ACCESS" }, { EXIT_REASON_EOI_INDUCED, "EOI_INDUCED" }, { EXIT_REASON_GDTR_IDTR, "GDTR_IDTR" }, { EXIT_REASON_LDTR_TR, "LDTR_TR" }, { EXIT_REASON_EPT_VIOLATION, "EPT_VIOLATION" }, { EXIT_REASON_EPT_MISCONFIG, "EPT_MISCONFIG" }, { EXIT_REASON_INVEPT, "INVEPT" }, { EXIT_REASON_RDTSCP, "RDTSCP" }, { EXIT_REASON_PREEMPTION_TIMER, "PREEMPTION_TIMER" }, { EXIT_REASON_INVVPID, "INVVPID" }, { EXIT_REASON_WBINVD, "WBINVD" }, { EXIT_REASON_XSETBV, "XSETBV" }, { EXIT_REASON_APIC_WRITE, "APIC_WRITE" }, { EXIT_REASON_RDRAND, "RDRAND" }, { EXIT_REASON_INVPCID, "INVPCID" }, { EXIT_REASON_VMFUNC, "VMFUNC" }, { EXIT_REASON_ENCLS, "ENCLS" }, { EXIT_REASON_RDSEED, "RDSEED" }, { EXIT_REASON_PML_FULL, "PML_FULL" }, { EXIT_REASON_XSAVES, "XSAVES" }, { EXIT_REASON_XRSTORS, "XRSTORS" }, { EXIT_REASON_UMWAIT, "UMWAIT" }, { EXIT_REASON_TPAUSE, "TPAUSE" }
+#define VMX_EXIT_REASON_FLAGS { VMX_EXIT_REASONS_FAILED_VMENTRY, "FAILED_VMENTRY" }
 #define VMX_ABORT_SAVE_GUEST_MSR_FAIL 1
 #define VMX_ABORT_LOAD_HOST_PDPTE_FAIL 2
 #define VMX_ABORT_LOAD_HOST_MSR_FAIL 4
diff --git a/libc/kernel/uapi/drm/amdgpu_drm.h b/libc/kernel/uapi/drm/amdgpu_drm.h
index 429d978..91d0a7e 100644
--- a/libc/kernel/uapi/drm/amdgpu_drm.h
+++ b/libc/kernel/uapi/drm/amdgpu_drm.h
@@ -71,6 +71,7 @@
 #define AMDGPU_GEM_CREATE_EXPLICIT_SYNC (1 << 7)
 #define AMDGPU_GEM_CREATE_CP_MQD_GFX9 (1 << 8)
 #define AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE (1 << 9)
+#define AMDGPU_GEM_CREATE_ENCRYPTED (1 << 10)
 struct drm_amdgpu_gem_create_in {
   __u64 bo_size;
   __u64 alignment;
@@ -344,7 +345,7 @@
   __u32 ctx_id;
   __u32 bo_list_handle;
   __u32 num_chunks;
-  __u32 _pad;
+  __u32 flags;
   __u64 chunks;
 };
 struct drm_amdgpu_cs_out {
@@ -359,6 +360,8 @@
 #define AMDGPU_IB_FLAG_PREEMPT (1 << 2)
 #define AMDGPU_IB_FLAG_TC_WB_NOT_INVALIDATE (1 << 3)
 #define AMDGPU_IB_FLAG_RESET_GDS_MAX_WAVE_ID (1 << 4)
+#define AMDGPU_IB_FLAGS_SECURE (1 << 5)
+#define AMDGPU_IB_FLAG_EMIT_MEM_SYNC (1 << 6)
 struct drm_amdgpu_cs_chunk_ib {
   __u32 _pad;
   __u32 flags;
diff --git a/libc/kernel/uapi/drm/drm_fourcc.h b/libc/kernel/uapi/drm/drm_fourcc.h
index 898d9ad..0ea5c83 100644
--- a/libc/kernel/uapi/drm/drm_fourcc.h
+++ b/libc/kernel/uapi/drm/drm_fourcc.h
@@ -158,13 +158,14 @@
 #define DRM_FORMAT_MOD_VIVANTE_SPLIT_TILED fourcc_mod_code(VIVANTE, 3)
 #define DRM_FORMAT_MOD_VIVANTE_SPLIT_SUPER_TILED fourcc_mod_code(VIVANTE, 4)
 #define DRM_FORMAT_MOD_NVIDIA_TEGRA_TILED fourcc_mod_code(NVIDIA, 1)
-#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(v) fourcc_mod_code(NVIDIA, 0x10 | ((v) & 0xf))
-#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_ONE_GOB fourcc_mod_code(NVIDIA, 0x10)
-#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_TWO_GOB fourcc_mod_code(NVIDIA, 0x11)
-#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_FOUR_GOB fourcc_mod_code(NVIDIA, 0x12)
-#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_EIGHT_GOB fourcc_mod_code(NVIDIA, 0x13)
-#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_SIXTEEN_GOB fourcc_mod_code(NVIDIA, 0x14)
-#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_THIRTYTWO_GOB fourcc_mod_code(NVIDIA, 0x15)
+#define DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(c,s,g,k,h) fourcc_mod_code(NVIDIA, (0x10 | ((h) & 0xf) | (((k) & 0xff) << 12) | (((g) & 0x3) << 20) | (((s) & 0x1) << 22) | (((c) & 0x7) << 23)))
+#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(v) DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 0, 0, 0, (v))
+#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_ONE_GOB DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(0)
+#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_TWO_GOB DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(1)
+#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_FOUR_GOB DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(2)
+#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_EIGHT_GOB DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(3)
+#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_SIXTEEN_GOB DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(4)
+#define DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK_THIRTYTWO_GOB DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(5)
 #define __fourcc_mod_broadcom_param_shift 8
 #define __fourcc_mod_broadcom_param_bits 48
 #define fourcc_mod_broadcom_code(val,params) fourcc_mod_code(BROADCOM, ((((__u64) params) << __fourcc_mod_broadcom_param_shift) | val))
diff --git a/libc/kernel/uapi/drm/i915_drm.h b/libc/kernel/uapi/drm/i915_drm.h
index 41b4dda..001ebd5 100644
--- a/libc/kernel/uapi/drm/i915_drm.h
+++ b/libc/kernel/uapi/drm/i915_drm.h
@@ -836,6 +836,8 @@
   DRM_I915_PERF_PROP_OA_FORMAT,
   DRM_I915_PERF_PROP_OA_EXPONENT,
   DRM_I915_PERF_PROP_HOLD_PREEMPTION,
+  DRM_I915_PERF_PROP_GLOBAL_SSEU,
+  DRM_I915_PERF_PROP_POLL_OA_PERIOD,
   DRM_I915_PERF_PROP_MAX
 };
 struct drm_i915_perf_open_param {
diff --git a/libc/kernel/uapi/drm/msm_drm.h b/libc/kernel/uapi/drm/msm_drm.h
index 3c1b734..fcfcc20 100644
--- a/libc/kernel/uapi/drm/msm_drm.h
+++ b/libc/kernel/uapi/drm/msm_drm.h
@@ -114,7 +114,16 @@
 #define MSM_SUBMIT_FENCE_FD_IN 0x40000000
 #define MSM_SUBMIT_FENCE_FD_OUT 0x20000000
 #define MSM_SUBMIT_SUDO 0x10000000
-#define MSM_SUBMIT_FLAGS (MSM_SUBMIT_NO_IMPLICIT | MSM_SUBMIT_FENCE_FD_IN | MSM_SUBMIT_FENCE_FD_OUT | MSM_SUBMIT_SUDO | 0)
+#define MSM_SUBMIT_SYNCOBJ_IN 0x08000000
+#define MSM_SUBMIT_SYNCOBJ_OUT 0x04000000
+#define MSM_SUBMIT_FLAGS (MSM_SUBMIT_NO_IMPLICIT | MSM_SUBMIT_FENCE_FD_IN | MSM_SUBMIT_FENCE_FD_OUT | MSM_SUBMIT_SUDO | MSM_SUBMIT_SYNCOBJ_IN | MSM_SUBMIT_SYNCOBJ_OUT | 0)
+#define MSM_SUBMIT_SYNCOBJ_RESET 0x00000001
+#define MSM_SUBMIT_SYNCOBJ_FLAGS (MSM_SUBMIT_SYNCOBJ_RESET | 0)
+struct drm_msm_gem_submit_syncobj {
+  __u32 handle;
+  __u32 flags;
+  __u64 point;
+};
 struct drm_msm_gem_submit {
   __u32 flags;
   __u32 fence;
@@ -124,6 +133,12 @@
   __u64 cmds;
   __s32 fence_fd;
   __u32 queueid;
+  __u64 in_syncobjs;
+  __u64 out_syncobjs;
+  __u32 nr_in_syncobjs;
+  __u32 nr_out_syncobjs;
+  __u32 syncobj_stride;
+  __u32 pad;
 };
 struct drm_msm_wait_fence {
   __u32 fence;
diff --git a/libc/kernel/uapi/linux/audit.h b/libc/kernel/uapi/linux/audit.h
index a4bb3b5..d7f1e04 100644
--- a/libc/kernel/uapi/linux/audit.h
+++ b/libc/kernel/uapi/linux/audit.h
@@ -82,6 +82,7 @@
 #define AUDIT_TIME_INJOFFSET 1332
 #define AUDIT_TIME_ADJNTPVAL 1333
 #define AUDIT_BPF 1334
+#define AUDIT_EVENT_LISTENER 1335
 #define AUDIT_AVC 1400
 #define AUDIT_SELINUX_ERR 1401
 #define AUDIT_AVC_PATH 1402
diff --git a/libc/kernel/uapi/linux/bpf.h b/libc/kernel/uapi/linux/bpf.h
index 815fd6a..54b7849 100644
--- a/libc/kernel/uapi/linux/bpf.h
+++ b/libc/kernel/uapi/linux/bpf.h
@@ -101,6 +101,10 @@
   BPF_MAP_DELETE_BATCH,
   BPF_LINK_CREATE,
   BPF_LINK_UPDATE,
+  BPF_LINK_GET_FD_BY_ID,
+  BPF_LINK_GET_NEXT_ID,
+  BPF_ENABLE_STATS,
+  BPF_ITER_CREATE,
 };
 enum bpf_map_type {
   BPF_MAP_TYPE_UNSPEC,
@@ -130,6 +134,7 @@
   BPF_MAP_TYPE_SK_STORAGE,
   BPF_MAP_TYPE_DEVMAP_HASH,
   BPF_MAP_TYPE_STRUCT_OPS,
+  BPF_MAP_TYPE_RINGBUF,
 };
 enum bpf_prog_type {
   BPF_PROG_TYPE_UNSPEC,
@@ -192,9 +197,24 @@
   BPF_TRACE_FEXIT,
   BPF_MODIFY_RETURN,
   BPF_LSM_MAC,
+  BPF_TRACE_ITER,
+  BPF_CGROUP_INET4_GETPEERNAME,
+  BPF_CGROUP_INET6_GETPEERNAME,
+  BPF_CGROUP_INET4_GETSOCKNAME,
+  BPF_CGROUP_INET6_GETSOCKNAME,
+  BPF_XDP_DEVMAP,
   __MAX_BPF_ATTACH_TYPE
 };
 #define MAX_BPF_ATTACH_TYPE __MAX_BPF_ATTACH_TYPE
+enum bpf_link_type {
+  BPF_LINK_TYPE_UNSPEC = 0,
+  BPF_LINK_TYPE_RAW_TRACEPOINT = 1,
+  BPF_LINK_TYPE_TRACING = 2,
+  BPF_LINK_TYPE_CGROUP = 3,
+  BPF_LINK_TYPE_ITER = 4,
+  BPF_LINK_TYPE_NETNS = 5,
+  MAX_BPF_LINK_TYPE,
+};
 #define BPF_F_ALLOW_OVERRIDE (1U << 0)
 #define BPF_F_ALLOW_MULTI (1U << 1)
 #define BPF_F_REPLACE (1U << 2)
@@ -225,6 +245,9 @@
   BPF_F_MMAPABLE = (1U << 10),
 };
 #define BPF_F_QUERY_EFFECTIVE (1U << 0)
+enum bpf_stats_type {
+  BPF_STATS_RUN_TIME = 0,
+};
 enum bpf_stack_build_id_status {
   BPF_STACK_BUILD_ID_EMPTY = 0,
   BPF_STACK_BUILD_ID_VALID = 1,
@@ -330,6 +353,7 @@
       __u32 prog_id;
       __u32 map_id;
       __u32 btf_id;
+      __u32 link_id;
     };
     __u32 next_id;
     __u32 open_flags;
@@ -381,8 +405,15 @@
     __u32 flags;
     __u32 old_prog_fd;
   } link_update;
+  struct {
+    __u32 type;
+  } enable_stats;
+  struct {
+    __u32 link_fd;
+    __u32 flags;
+  } iter_create;
 } __attribute__((aligned(8)));
-#define __BPF_FUNC_MAPPER(FN) FN(unspec), FN(map_lookup_elem), FN(map_update_elem), FN(map_delete_elem), FN(probe_read), FN(ktime_get_ns), FN(trace_printk), FN(get_prandom_u32), FN(get_smp_processor_id), FN(skb_store_bytes), FN(l3_csum_replace), FN(l4_csum_replace), FN(tail_call), FN(clone_redirect), FN(get_current_pid_tgid), FN(get_current_uid_gid), FN(get_current_comm), FN(get_cgroup_classid), FN(skb_vlan_push), FN(skb_vlan_pop), FN(skb_get_tunnel_key), FN(skb_set_tunnel_key), FN(perf_event_read), FN(redirect), FN(get_route_realm), FN(perf_event_output), FN(skb_load_bytes), FN(get_stackid), FN(csum_diff), FN(skb_get_tunnel_opt), FN(skb_set_tunnel_opt), FN(skb_change_proto), FN(skb_change_type), FN(skb_under_cgroup), FN(get_hash_recalc), FN(get_current_task), FN(probe_write_user), FN(current_task_under_cgroup), FN(skb_change_tail), FN(skb_pull_data), FN(csum_update), FN(set_hash_invalid), FN(get_numa_node_id), FN(skb_change_head), FN(xdp_adjust_head), FN(probe_read_str), FN(get_socket_cookie), FN(get_socket_uid), FN(set_hash), FN(setsockopt), FN(skb_adjust_room), FN(redirect_map), FN(sk_redirect_map), FN(sock_map_update), FN(xdp_adjust_meta), FN(perf_event_read_value), FN(perf_prog_read_value), FN(getsockopt), FN(override_return), FN(sock_ops_cb_flags_set), FN(msg_redirect_map), FN(msg_apply_bytes), FN(msg_cork_bytes), FN(msg_pull_data), FN(bind), FN(xdp_adjust_tail), FN(skb_get_xfrm_state), FN(get_stack), FN(skb_load_bytes_relative), FN(fib_lookup), FN(sock_hash_update), FN(msg_redirect_hash), FN(sk_redirect_hash), FN(lwt_push_encap), FN(lwt_seg6_store_bytes), FN(lwt_seg6_adjust_srh), FN(lwt_seg6_action), FN(rc_repeat), FN(rc_keydown), FN(skb_cgroup_id), FN(get_current_cgroup_id), FN(get_local_storage), FN(sk_select_reuseport), FN(skb_ancestor_cgroup_id), FN(sk_lookup_tcp), FN(sk_lookup_udp), FN(sk_release), FN(map_push_elem), FN(map_pop_elem), FN(map_peek_elem), FN(msg_push_data), FN(msg_pop_data), FN(rc_pointer_rel), FN(spin_lock), FN(spin_unlock), FN(sk_fullsock), FN(tcp_sock), FN(skb_ecn_set_ce), FN(get_listener_sock), FN(skc_lookup_tcp), FN(tcp_check_syncookie), FN(sysctl_get_name), FN(sysctl_get_current_value), FN(sysctl_get_new_value), FN(sysctl_set_new_value), FN(strtol), FN(strtoul), FN(sk_storage_get), FN(sk_storage_delete), FN(send_signal), FN(tcp_gen_syncookie), FN(skb_output), FN(probe_read_user), FN(probe_read_kernel), FN(probe_read_user_str), FN(probe_read_kernel_str), FN(tcp_send_ack), FN(send_signal_thread), FN(jiffies64), FN(read_branch_records), FN(get_ns_current_pid_tgid), FN(xdp_output), FN(get_netns_cookie), FN(get_current_ancestor_cgroup_id), FN(sk_assign),
+#define __BPF_FUNC_MAPPER(FN) FN(unspec), FN(map_lookup_elem), FN(map_update_elem), FN(map_delete_elem), FN(probe_read), FN(ktime_get_ns), FN(trace_printk), FN(get_prandom_u32), FN(get_smp_processor_id), FN(skb_store_bytes), FN(l3_csum_replace), FN(l4_csum_replace), FN(tail_call), FN(clone_redirect), FN(get_current_pid_tgid), FN(get_current_uid_gid), FN(get_current_comm), FN(get_cgroup_classid), FN(skb_vlan_push), FN(skb_vlan_pop), FN(skb_get_tunnel_key), FN(skb_set_tunnel_key), FN(perf_event_read), FN(redirect), FN(get_route_realm), FN(perf_event_output), FN(skb_load_bytes), FN(get_stackid), FN(csum_diff), FN(skb_get_tunnel_opt), FN(skb_set_tunnel_opt), FN(skb_change_proto), FN(skb_change_type), FN(skb_under_cgroup), FN(get_hash_recalc), FN(get_current_task), FN(probe_write_user), FN(current_task_under_cgroup), FN(skb_change_tail), FN(skb_pull_data), FN(csum_update), FN(set_hash_invalid), FN(get_numa_node_id), FN(skb_change_head), FN(xdp_adjust_head), FN(probe_read_str), FN(get_socket_cookie), FN(get_socket_uid), FN(set_hash), FN(setsockopt), FN(skb_adjust_room), FN(redirect_map), FN(sk_redirect_map), FN(sock_map_update), FN(xdp_adjust_meta), FN(perf_event_read_value), FN(perf_prog_read_value), FN(getsockopt), FN(override_return), FN(sock_ops_cb_flags_set), FN(msg_redirect_map), FN(msg_apply_bytes), FN(msg_cork_bytes), FN(msg_pull_data), FN(bind), FN(xdp_adjust_tail), FN(skb_get_xfrm_state), FN(get_stack), FN(skb_load_bytes_relative), FN(fib_lookup), FN(sock_hash_update), FN(msg_redirect_hash), FN(sk_redirect_hash), FN(lwt_push_encap), FN(lwt_seg6_store_bytes), FN(lwt_seg6_adjust_srh), FN(lwt_seg6_action), FN(rc_repeat), FN(rc_keydown), FN(skb_cgroup_id), FN(get_current_cgroup_id), FN(get_local_storage), FN(sk_select_reuseport), FN(skb_ancestor_cgroup_id), FN(sk_lookup_tcp), FN(sk_lookup_udp), FN(sk_release), FN(map_push_elem), FN(map_pop_elem), FN(map_peek_elem), FN(msg_push_data), FN(msg_pop_data), FN(rc_pointer_rel), FN(spin_lock), FN(spin_unlock), FN(sk_fullsock), FN(tcp_sock), FN(skb_ecn_set_ce), FN(get_listener_sock), FN(skc_lookup_tcp), FN(tcp_check_syncookie), FN(sysctl_get_name), FN(sysctl_get_current_value), FN(sysctl_get_new_value), FN(sysctl_set_new_value), FN(strtol), FN(strtoul), FN(sk_storage_get), FN(sk_storage_delete), FN(send_signal), FN(tcp_gen_syncookie), FN(skb_output), FN(probe_read_user), FN(probe_read_kernel), FN(probe_read_user_str), FN(probe_read_kernel_str), FN(tcp_send_ack), FN(send_signal_thread), FN(jiffies64), FN(read_branch_records), FN(get_ns_current_pid_tgid), FN(xdp_output), FN(get_netns_cookie), FN(get_current_ancestor_cgroup_id), FN(sk_assign), FN(ktime_get_boot_ns), FN(seq_printf), FN(seq_write), FN(sk_cgroup_id), FN(sk_ancestor_cgroup_id), FN(ringbuf_output), FN(ringbuf_reserve), FN(ringbuf_submit), FN(ringbuf_discard), FN(ringbuf_query), FN(csum_level),
 #define __BPF_ENUM_FN(x) BPF_FUNC_ ##x
 enum bpf_func_id {
   __BPF_FUNC_MAPPER(__BPF_ENUM_FN) __BPF_FUNC_MAX_ID,
@@ -427,11 +458,18 @@
   BPF_F_CURRENT_NETNS = (- 1L),
 };
 enum {
+  BPF_CSUM_LEVEL_QUERY,
+  BPF_CSUM_LEVEL_INC,
+  BPF_CSUM_LEVEL_DEC,
+  BPF_CSUM_LEVEL_RESET,
+};
+enum {
   BPF_F_ADJ_ROOM_FIXED_GSO = (1ULL << 0),
   BPF_F_ADJ_ROOM_ENCAP_L3_IPV4 = (1ULL << 1),
   BPF_F_ADJ_ROOM_ENCAP_L3_IPV6 = (1ULL << 2),
   BPF_F_ADJ_ROOM_ENCAP_L4_GRE = (1ULL << 3),
   BPF_F_ADJ_ROOM_ENCAP_L4_UDP = (1ULL << 4),
+  BPF_F_ADJ_ROOM_NO_CSUM_RESET = (1ULL << 5),
 };
 enum {
   BPF_ADJ_ROOM_ENCAP_L2_MASK = 0xff,
@@ -447,6 +485,21 @@
 enum {
   BPF_F_GET_BRANCH_RECORDS_SIZE = (1ULL << 0),
 };
+enum {
+  BPF_RB_NO_WAKEUP = (1ULL << 0),
+  BPF_RB_FORCE_WAKEUP = (1ULL << 1),
+};
+enum {
+  BPF_RB_AVAIL_DATA = 0,
+  BPF_RB_RING_SIZE = 1,
+  BPF_RB_CONS_POS = 2,
+  BPF_RB_PROD_POS = 3,
+};
+enum {
+  BPF_RINGBUF_BUSY_BIT = (1U << 31),
+  BPF_RINGBUF_DISCARD_BIT = (1U << 30),
+  BPF_RINGBUF_HDR_SZ = 8,
+};
 enum bpf_adj_room_mode {
   BPF_ADJ_ROOM_NET,
   BPF_ADJ_ROOM_MAC,
@@ -537,6 +590,7 @@
   __u32 dst_ip4;
   __u32 dst_ip6[4];
   __u32 state;
+  __s32 rx_queue_mapping;
 };
 struct bpf_tcp_sock {
   __u32 snd_cwnd;
@@ -599,6 +653,14 @@
   __u32 data_meta;
   __u32 ingress_ifindex;
   __u32 rx_queue_index;
+  __u32 egress_ifindex;
+};
+struct bpf_devmap_val {
+  __u32 ifindex;
+  union {
+    int fd;
+    __u32 id;
+  } bpf_prog;
 };
 enum sk_action {
   SK_DROP = 0,
@@ -615,6 +677,7 @@
   __u32 remote_port;
   __u32 local_port;
   __u32 size;
+  __bpf_md_ptr(struct bpf_sock *, sk);
 };
 struct sk_reuseport_md {
   __bpf_md_ptr(void *, data);
@@ -684,6 +747,28 @@
   __u32 btf_size;
   __u32 id;
 } __attribute__((aligned(8)));
+struct bpf_link_info {
+  __u32 type;
+  __u32 id;
+  __u32 prog_id;
+  union {
+    struct {
+      __aligned_u64 tp_name;
+      __u32 tp_name_len;
+    } raw_tracepoint;
+    struct {
+      __u32 attach_type;
+    } tracing;
+    struct {
+      __u64 cgroup_id;
+      __u32 attach_type;
+    } cgroup;
+    struct {
+      __u32 netns_ino;
+      __u32 attach_type;
+    } netns;
+  };
+} __attribute__((aligned(8)));
 struct bpf_sock_addr {
   __u32 user_family;
   __u32 user_ip4;
diff --git a/libc/kernel/uapi/linux/btrfs_tree.h b/libc/kernel/uapi/linux/btrfs_tree.h
index 50ada36..6049127 100644
--- a/libc/kernel/uapi/linux/btrfs_tree.h
+++ b/libc/kernel/uapi/linux/btrfs_tree.h
@@ -201,12 +201,6 @@
   __u8 type;
   __le64 offset;
 } __attribute__((__packed__));
-struct btrfs_extent_ref_v0 {
-  __le64 root;
-  __le64 generation;
-  __le64 objectid;
-  __le32 count;
-} __attribute__((__packed__));
 struct btrfs_dev_extent {
   __le64 chunk_tree;
   __le64 chunk_objectid;
diff --git a/libc/kernel/uapi/linux/capability.h b/libc/kernel/uapi/linux/capability.h
index 8ba448e..b830fd6 100644
--- a/libc/kernel/uapi/linux/capability.h
+++ b/libc/kernel/uapi/linux/capability.h
@@ -105,7 +105,9 @@
 #define CAP_WAKE_ALARM 35
 #define CAP_BLOCK_SUSPEND 36
 #define CAP_AUDIT_READ 37
-#define CAP_LAST_CAP CAP_AUDIT_READ
+#define CAP_PERFMON 38
+#define CAP_BPF 39
+#define CAP_LAST_CAP CAP_BPF
 #define cap_valid(x) ((x) >= 0 && (x) <= CAP_LAST_CAP)
 #define CAP_TO_INDEX(x) ((x) >> 5)
 #define CAP_TO_MASK(x) (1 << ((x) & 31))
diff --git a/libc/kernel/uapi/linux/devlink.h b/libc/kernel/uapi/linux/devlink.h
index 18f7da5..7730a45 100644
--- a/libc/kernel/uapi/linux/devlink.h
+++ b/libc/kernel/uapi/linux/devlink.h
@@ -166,10 +166,12 @@
 enum devlink_trap_action {
   DEVLINK_TRAP_ACTION_DROP,
   DEVLINK_TRAP_ACTION_TRAP,
+  DEVLINK_TRAP_ACTION_MIRROR,
 };
 enum devlink_trap_type {
   DEVLINK_TRAP_TYPE_DROP,
   DEVLINK_TRAP_TYPE_EXCEPTION,
+  DEVLINK_TRAP_TYPE_CONTROL,
 };
 enum {
   DEVLINK_ATTR_TRAP_METADATA_TYPE_IN_PORT,
diff --git a/libc/kernel/uapi/linux/elf.h b/libc/kernel/uapi/linux/elf.h
index 8f2e668..428da63 100644
--- a/libc/kernel/uapi/linux/elf.h
+++ b/libc/kernel/uapi/linux/elf.h
@@ -46,6 +46,7 @@
 #define PT_LOPROC 0x70000000
 #define PT_HIPROC 0x7fffffff
 #define PT_GNU_EH_FRAME 0x6474e550
+#define PT_GNU_PROPERTY 0x6474e553
 #define PT_GNU_STACK (PT_LOOS + 0x474e551)
 #define PN_XNUM 0xffff
 #define ET_NONE 0
@@ -363,6 +364,7 @@
 #define NT_MIPS_DSP 0x800
 #define NT_MIPS_FP_MODE 0x801
 #define NT_MIPS_MSA 0x802
+#define NT_GNU_PROPERTY_TYPE_0 5
 typedef struct elf32_note {
   Elf32_Word n_namesz;
   Elf32_Word n_descsz;
@@ -373,4 +375,6 @@
   Elf64_Word n_descsz;
   Elf64_Word n_type;
 } Elf64_Nhdr;
+#define GNU_PROPERTY_AARCH64_FEATURE_1_AND 0xc0000000
+#define GNU_PROPERTY_AARCH64_FEATURE_1_BTI (1U << 0)
 #endif
diff --git a/libc/kernel/uapi/linux/ethtool.h b/libc/kernel/uapi/linux/ethtool.h
index 8733bca..9f8678a 100644
--- a/libc/kernel/uapi/linux/ethtool.h
+++ b/libc/kernel/uapi/linux/ethtool.h
@@ -709,6 +709,17 @@
 #define DUPLEX_HALF 0x00
 #define DUPLEX_FULL 0x01
 #define DUPLEX_UNKNOWN 0xff
+#define MASTER_SLAVE_CFG_UNSUPPORTED 0
+#define MASTER_SLAVE_CFG_UNKNOWN 1
+#define MASTER_SLAVE_CFG_MASTER_PREFERRED 2
+#define MASTER_SLAVE_CFG_SLAVE_PREFERRED 3
+#define MASTER_SLAVE_CFG_MASTER_FORCE 4
+#define MASTER_SLAVE_CFG_SLAVE_FORCE 5
+#define MASTER_SLAVE_STATE_UNSUPPORTED 0
+#define MASTER_SLAVE_STATE_UNKNOWN 1
+#define MASTER_SLAVE_STATE_MASTER 2
+#define MASTER_SLAVE_STATE_SLAVE 3
+#define MASTER_SLAVE_STATE_ERR 4
 #define PORT_TP 0x00
 #define PORT_AUI 0x01
 #define PORT_MII 0x02
@@ -808,7 +819,9 @@
   __u8 eth_tp_mdix_ctrl;
   __s8 link_mode_masks_nwords;
   __u8 transceiver;
-  __u8 reserved1[3];
+  __u8 master_slave_cfg;
+  __u8 master_slave_state;
+  __u8 reserved1[1];
   __u32 reserved[7];
   __u32 link_mode_masks[0];
 };
diff --git a/libc/kernel/uapi/linux/ethtool_netlink.h b/libc/kernel/uapi/linux/ethtool_netlink.h
index 52d435e..868d3c6 100644
--- a/libc/kernel/uapi/linux/ethtool_netlink.h
+++ b/libc/kernel/uapi/linux/ethtool_netlink.h
@@ -46,6 +46,8 @@
   ETHTOOL_MSG_EEE_GET,
   ETHTOOL_MSG_EEE_SET,
   ETHTOOL_MSG_TSINFO_GET,
+  ETHTOOL_MSG_CABLE_TEST_ACT,
+  ETHTOOL_MSG_CABLE_TEST_TDR_ACT,
   __ETHTOOL_MSG_USER_CNT,
   ETHTOOL_MSG_USER_MAX = __ETHTOOL_MSG_USER_CNT - 1
 };
@@ -77,6 +79,8 @@
   ETHTOOL_MSG_EEE_GET_REPLY,
   ETHTOOL_MSG_EEE_NTF,
   ETHTOOL_MSG_TSINFO_GET_REPLY,
+  ETHTOOL_MSG_CABLE_TEST_NTF,
+  ETHTOOL_MSG_CABLE_TEST_TDR_NTF,
   __ETHTOOL_MSG_KERNEL_CNT,
   ETHTOOL_MSG_KERNEL_MAX = __ETHTOOL_MSG_KERNEL_CNT - 1
 };
@@ -169,6 +173,8 @@
   ETHTOOL_A_LINKMODES_PEER,
   ETHTOOL_A_LINKMODES_SPEED,
   ETHTOOL_A_LINKMODES_DUPLEX,
+  ETHTOOL_A_LINKMODES_MASTER_SLAVE_CFG,
+  ETHTOOL_A_LINKMODES_MASTER_SLAVE_STATE,
   __ETHTOOL_A_LINKMODES_CNT,
   ETHTOOL_A_LINKMODES_MAX = __ETHTOOL_A_LINKMODES_CNT - 1
 };
@@ -176,6 +182,8 @@
   ETHTOOL_A_LINKSTATE_UNSPEC,
   ETHTOOL_A_LINKSTATE_HEADER,
   ETHTOOL_A_LINKSTATE_LINK,
+  ETHTOOL_A_LINKSTATE_SQI,
+  ETHTOOL_A_LINKSTATE_SQI_MAX,
   __ETHTOOL_A_LINKSTATE_CNT,
   ETHTOOL_A_LINKSTATE_MAX = __ETHTOOL_A_LINKSTATE_CNT - 1
 };
@@ -298,6 +306,112 @@
   __ETHTOOL_A_TSINFO_CNT,
   ETHTOOL_A_TSINFO_MAX = (__ETHTOOL_A_TSINFO_CNT - 1)
 };
+enum {
+  ETHTOOL_A_CABLE_TEST_UNSPEC,
+  ETHTOOL_A_CABLE_TEST_HEADER,
+  __ETHTOOL_A_CABLE_TEST_CNT,
+  ETHTOOL_A_CABLE_TEST_MAX = __ETHTOOL_A_CABLE_TEST_CNT - 1
+};
+enum {
+  ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC,
+  ETHTOOL_A_CABLE_RESULT_CODE_OK,
+  ETHTOOL_A_CABLE_RESULT_CODE_OPEN,
+  ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT,
+  ETHTOOL_A_CABLE_RESULT_CODE_CROSS_SHORT,
+};
+enum {
+  ETHTOOL_A_CABLE_PAIR_A,
+  ETHTOOL_A_CABLE_PAIR_B,
+  ETHTOOL_A_CABLE_PAIR_C,
+  ETHTOOL_A_CABLE_PAIR_D,
+};
+enum {
+  ETHTOOL_A_CABLE_RESULT_UNSPEC,
+  ETHTOOL_A_CABLE_RESULT_PAIR,
+  ETHTOOL_A_CABLE_RESULT_CODE,
+  __ETHTOOL_A_CABLE_RESULT_CNT,
+  ETHTOOL_A_CABLE_RESULT_MAX = (__ETHTOOL_A_CABLE_RESULT_CNT - 1)
+};
+enum {
+  ETHTOOL_A_CABLE_FAULT_LENGTH_UNSPEC,
+  ETHTOOL_A_CABLE_FAULT_LENGTH_PAIR,
+  ETHTOOL_A_CABLE_FAULT_LENGTH_CM,
+  __ETHTOOL_A_CABLE_FAULT_LENGTH_CNT,
+  ETHTOOL_A_CABLE_FAULT_LENGTH_MAX = (__ETHTOOL_A_CABLE_FAULT_LENGTH_CNT - 1)
+};
+enum {
+  ETHTOOL_A_CABLE_TEST_NTF_STATUS_UNSPEC,
+  ETHTOOL_A_CABLE_TEST_NTF_STATUS_STARTED,
+  ETHTOOL_A_CABLE_TEST_NTF_STATUS_COMPLETED
+};
+enum {
+  ETHTOOL_A_CABLE_NEST_UNSPEC,
+  ETHTOOL_A_CABLE_NEST_RESULT,
+  ETHTOOL_A_CABLE_NEST_FAULT_LENGTH,
+  __ETHTOOL_A_CABLE_NEST_CNT,
+  ETHTOOL_A_CABLE_NEST_MAX = (__ETHTOOL_A_CABLE_NEST_CNT - 1)
+};
+enum {
+  ETHTOOL_A_CABLE_TEST_NTF_UNSPEC,
+  ETHTOOL_A_CABLE_TEST_NTF_HEADER,
+  ETHTOOL_A_CABLE_TEST_NTF_STATUS,
+  ETHTOOL_A_CABLE_TEST_NTF_NEST,
+  __ETHTOOL_A_CABLE_TEST_NTF_CNT,
+  ETHTOOL_A_CABLE_TEST_NTF_MAX = (__ETHTOOL_A_CABLE_TEST_NTF_CNT - 1)
+};
+enum {
+  ETHTOOL_A_CABLE_TEST_TDR_CFG_UNSPEC,
+  ETHTOOL_A_CABLE_TEST_TDR_CFG_FIRST,
+  ETHTOOL_A_CABLE_TEST_TDR_CFG_LAST,
+  ETHTOOL_A_CABLE_TEST_TDR_CFG_STEP,
+  ETHTOOL_A_CABLE_TEST_TDR_CFG_PAIR,
+  __ETHTOOL_A_CABLE_TEST_TDR_CFG_CNT,
+  ETHTOOL_A_CABLE_TEST_TDR_CFG_MAX = __ETHTOOL_A_CABLE_TEST_TDR_CFG_CNT - 1
+};
+enum {
+  ETHTOOL_A_CABLE_TEST_TDR_UNSPEC,
+  ETHTOOL_A_CABLE_TEST_TDR_HEADER,
+  ETHTOOL_A_CABLE_TEST_TDR_CFG,
+  __ETHTOOL_A_CABLE_TEST_TDR_CNT,
+  ETHTOOL_A_CABLE_TEST_TDR_MAX = __ETHTOOL_A_CABLE_TEST_TDR_CNT - 1
+};
+enum {
+  ETHTOOL_A_CABLE_AMPLITUDE_UNSPEC,
+  ETHTOOL_A_CABLE_AMPLITUDE_PAIR,
+  ETHTOOL_A_CABLE_AMPLITUDE_mV,
+  __ETHTOOL_A_CABLE_AMPLITUDE_CNT,
+  ETHTOOL_A_CABLE_AMPLITUDE_MAX = (__ETHTOOL_A_CABLE_AMPLITUDE_CNT - 1)
+};
+enum {
+  ETHTOOL_A_CABLE_PULSE_UNSPEC,
+  ETHTOOL_A_CABLE_PULSE_mV,
+  __ETHTOOL_A_CABLE_PULSE_CNT,
+  ETHTOOL_A_CABLE_PULSE_MAX = (__ETHTOOL_A_CABLE_PULSE_CNT - 1)
+};
+enum {
+  ETHTOOL_A_CABLE_STEP_UNSPEC,
+  ETHTOOL_A_CABLE_STEP_FIRST_DISTANCE,
+  ETHTOOL_A_CABLE_STEP_LAST_DISTANCE,
+  ETHTOOL_A_CABLE_STEP_STEP_DISTANCE,
+  __ETHTOOL_A_CABLE_STEP_CNT,
+  ETHTOOL_A_CABLE_STEP_MAX = (__ETHTOOL_A_CABLE_STEP_CNT - 1)
+};
+enum {
+  ETHTOOL_A_CABLE_TDR_NEST_UNSPEC,
+  ETHTOOL_A_CABLE_TDR_NEST_STEP,
+  ETHTOOL_A_CABLE_TDR_NEST_AMPLITUDE,
+  ETHTOOL_A_CABLE_TDR_NEST_PULSE,
+  __ETHTOOL_A_CABLE_TDR_NEST_CNT,
+  ETHTOOL_A_CABLE_TDR_NEST_MAX = (__ETHTOOL_A_CABLE_TDR_NEST_CNT - 1)
+};
+enum {
+  ETHTOOL_A_CABLE_TEST_TDR_NTF_UNSPEC,
+  ETHTOOL_A_CABLE_TEST_TDR_NTF_HEADER,
+  ETHTOOL_A_CABLE_TEST_TDR_NTF_STATUS,
+  ETHTOOL_A_CABLE_TEST_TDR_NTF_NEST,
+  __ETHTOOL_A_CABLE_TEST_TDR_NTF_CNT,
+  ETHTOOL_A_CABLE_TEST_TDR_NTF_MAX = __ETHTOOL_A_CABLE_TEST_TDR_NTF_CNT - 1
+};
 #define ETHTOOL_GENL_NAME "ethtool"
 #define ETHTOOL_GENL_VERSION 1
 #define ETHTOOL_MCGRP_MONITOR_NAME "monitor"
diff --git a/libc/kernel/uapi/linux/fb.h b/libc/kernel/uapi/linux/fb.h
index 38da042..a0ef0c4 100644
--- a/libc/kernel/uapi/linux/fb.h
+++ b/libc/kernel/uapi/linux/fb.h
@@ -182,6 +182,7 @@
 #define FB_ACTIVATE_ALL 64
 #define FB_ACTIVATE_FORCE 128
 #define FB_ACTIVATE_INV_MODE 256
+#define FB_ACTIVATE_KD_TEXT 512
 #define FB_ACCELF_TEXT 1
 #define FB_SYNC_HOR_HIGH_ACT 1
 #define FB_SYNC_VERT_HIGH_ACT 2
diff --git a/libc/kernel/uapi/linux/fcntl.h b/libc/kernel/uapi/linux/fcntl.h
index 84f0095..a46726b 100644
--- a/libc/kernel/uapi/linux/fcntl.h
+++ b/libc/kernel/uapi/linux/fcntl.h
@@ -54,6 +54,7 @@
 #define DN_MULTISHOT 0x80000000
 #define AT_FDCWD - 100
 #define AT_SYMLINK_NOFOLLOW 0x100
+#define AT_EACCESS 0x200
 #define AT_REMOVEDIR 0x200
 #define AT_SYMLINK_FOLLOW 0x400
 #define AT_NO_AUTOMOUNT 0x800
diff --git a/libc/kernel/uapi/linux/fd.h b/libc/kernel/uapi/linux/fd.h
index f3c2d50..4d72d69 100644
--- a/libc/kernel/uapi/linux/fd.h
+++ b/libc/kernel/uapi/linux/fd.h
@@ -84,7 +84,8 @@
 #define FD_SILENT_DCL_CLEAR 0x4
 #define FD_INVERTED_DCL 0x80
   char read_track;
-  short autodetect[8];
+#define FD_AUTODETECT_SIZE 8
+  short autodetect[FD_AUTODETECT_SIZE];
   int checkfreq;
   int native_format;
 };
@@ -181,10 +182,18 @@
   long phys_length;
   int buffer_length;
   unsigned char rate;
+#define FD_RAW_CMD_SIZE 16
+#define FD_RAW_REPLY_SIZE 16
+#define FD_RAW_CMD_FULLSIZE (FD_RAW_CMD_SIZE + 1 + FD_RAW_REPLY_SIZE)
   unsigned char cmd_count;
-  unsigned char cmd[16];
-  unsigned char reply_count;
-  unsigned char reply[16];
+  union {
+    struct {
+      unsigned char cmd[FD_RAW_CMD_SIZE];
+      unsigned char reply_count;
+      unsigned char reply[FD_RAW_REPLY_SIZE];
+    };
+    unsigned char fullcmd[FD_RAW_CMD_FULLSIZE];
+  };
   int track;
   int resultcode;
   int reserved1;
diff --git a/libc/kernel/uapi/linux/fdreg.h b/libc/kernel/uapi/linux/fdreg.h
index 6d9f42d..2aeaf9a 100644
--- a/libc/kernel/uapi/linux/fdreg.h
+++ b/libc/kernel/uapi/linux/fdreg.h
@@ -18,9 +18,13 @@
  ****************************************************************************/
 #ifndef _LINUX_FDREG_H
 #define _LINUX_FDREG_H
+#define FD_SRA 0
+#define FD_SRB 1
+#define FD_DOR 2
+#define FD_TDR 3
+#define FD_DSR 4
 #define FD_STATUS 4
 #define FD_DATA 5
-#define FD_DOR 2
 #define FD_DIR 7
 #define FD_DCR 7
 #define STATUS_BUSYMASK 0x0F
diff --git a/libc/kernel/uapi/linux/fiemap.h b/libc/kernel/uapi/linux/fiemap.h
index 77c3cc5..4310786 100644
--- a/libc/kernel/uapi/linux/fiemap.h
+++ b/libc/kernel/uapi/linux/fiemap.h
@@ -16,8 +16,8 @@
  ***
  ****************************************************************************
  ****************************************************************************/
-#ifndef _LINUX_FIEMAP_H
-#define _LINUX_FIEMAP_H
+#ifndef _UAPI_LINUX_FIEMAP_H
+#define _UAPI_LINUX_FIEMAP_H
 #include <linux/types.h>
 struct fiemap_extent {
   __u64 fe_logical;
diff --git a/libc/kernel/uapi/linux/fs.h b/libc/kernel/uapi/linux/fs.h
index 1dd1602..0601768 100644
--- a/libc/kernel/uapi/linux/fs.h
+++ b/libc/kernel/uapi/linux/fs.h
@@ -177,6 +177,7 @@
 #define FS_EA_INODE_FL 0x00200000
 #define FS_EOFBLOCKS_FL 0x00400000
 #define FS_NOCOW_FL 0x00800000
+#define FS_DAX_FL 0x02000000
 #define FS_INLINE_DATA_FL 0x10000000
 #define FS_PROJINHERIT_FL 0x20000000
 #define FS_CASEFOLD_FL 0x40000000
diff --git a/libc/kernel/uapi/linux/genetlink.h b/libc/kernel/uapi/linux/genetlink.h
index a6e3760..2cef95e 100644
--- a/libc/kernel/uapi/linux/genetlink.h
+++ b/libc/kernel/uapi/linux/genetlink.h
@@ -49,6 +49,7 @@
   CTRL_CMD_NEWMCAST_GRP,
   CTRL_CMD_DELMCAST_GRP,
   CTRL_CMD_GETMCAST_GRP,
+  CTRL_CMD_GETPOLICY,
   __CTRL_CMD_MAX,
 };
 #define CTRL_CMD_MAX (__CTRL_CMD_MAX - 1)
@@ -61,6 +62,7 @@
   CTRL_ATTR_MAXATTR,
   CTRL_ATTR_OPS,
   CTRL_ATTR_MCAST_GROUPS,
+  CTRL_ATTR_POLICY,
   __CTRL_ATTR_MAX,
 };
 #define CTRL_ATTR_MAX (__CTRL_ATTR_MAX - 1)
diff --git a/libc/kernel/uapi/linux/gfs2_ondisk.h b/libc/kernel/uapi/linux/gfs2_ondisk.h
index 7d03ba5..a8fb59e 100644
--- a/libc/kernel/uapi/linux/gfs2_ondisk.h
+++ b/libc/kernel/uapi/linux/gfs2_ondisk.h
@@ -117,6 +117,11 @@
 #define GFS2_RGF_DATAONLY 0x00000004
 #define GFS2_RGF_NOALLOC 0x00000008
 #define GFS2_RGF_TRIMMED 0x00000010
+struct gfs2_inode_lvb {
+  __be32 ri_magic;
+  __be32 __pad;
+  __be64 ri_generation_deleted;
+};
 struct gfs2_rgrp_lvb {
   __be32 rl_magic;
   __be32 rl_flags;
diff --git a/libc/kernel/uapi/linux/idxd.h b/libc/kernel/uapi/linux/idxd.h
index 9565ff7..3c8492e 100644
--- a/libc/kernel/uapi/linux/idxd.h
+++ b/libc/kernel/uapi/linux/idxd.h
@@ -116,6 +116,8 @@
     struct {
       uint64_t delta_addr;
       uint32_t max_delta_size;
+      uint32_t delt_rsvd;
+      uint8_t expected_res_mask;
     };
     uint32_t delta_rec_size;
     uint64_t dest2;
diff --git a/libc/kernel/uapi/linux/if.h b/libc/kernel/uapi/linux/if.h
index 0821f2b..63c77eb 100644
--- a/libc/kernel/uapi/linux/if.h
+++ b/libc/kernel/uapi/linux/if.h
@@ -114,6 +114,7 @@
 enum {
   IF_LINK_MODE_DEFAULT,
   IF_LINK_MODE_DORMANT,
+  IF_LINK_MODE_TESTING,
 };
 #if __UAPI_DEF_IF_IFMAP
 struct ifmap {
diff --git a/libc/kernel/uapi/linux/if_bridge.h b/libc/kernel/uapi/linux/if_bridge.h
index b34116c..2c72ddf 100644
--- a/libc/kernel/uapi/linux/if_bridge.h
+++ b/libc/kernel/uapi/linux/if_bridge.h
@@ -106,6 +106,7 @@
   IFLA_BRIDGE_MODE,
   IFLA_BRIDGE_VLAN_INFO,
   IFLA_BRIDGE_VLAN_TUNNEL_INFO,
+  IFLA_BRIDGE_MRP,
   __IFLA_BRIDGE_MAX,
 };
 #define IFLA_BRIDGE_MAX (__IFLA_BRIDGE_MAX - 1)
@@ -137,6 +138,83 @@
   __u16 flags;
   __u32 pad2;
 };
+enum {
+  IFLA_BRIDGE_MRP_UNSPEC,
+  IFLA_BRIDGE_MRP_INSTANCE,
+  IFLA_BRIDGE_MRP_PORT_STATE,
+  IFLA_BRIDGE_MRP_PORT_ROLE,
+  IFLA_BRIDGE_MRP_RING_STATE,
+  IFLA_BRIDGE_MRP_RING_ROLE,
+  IFLA_BRIDGE_MRP_START_TEST,
+  __IFLA_BRIDGE_MRP_MAX,
+};
+#define IFLA_BRIDGE_MRP_MAX (__IFLA_BRIDGE_MRP_MAX - 1)
+enum {
+  IFLA_BRIDGE_MRP_INSTANCE_UNSPEC,
+  IFLA_BRIDGE_MRP_INSTANCE_RING_ID,
+  IFLA_BRIDGE_MRP_INSTANCE_P_IFINDEX,
+  IFLA_BRIDGE_MRP_INSTANCE_S_IFINDEX,
+  IFLA_BRIDGE_MRP_INSTANCE_PRIO,
+  __IFLA_BRIDGE_MRP_INSTANCE_MAX,
+};
+#define IFLA_BRIDGE_MRP_INSTANCE_MAX (__IFLA_BRIDGE_MRP_INSTANCE_MAX - 1)
+enum {
+  IFLA_BRIDGE_MRP_PORT_STATE_UNSPEC,
+  IFLA_BRIDGE_MRP_PORT_STATE_STATE,
+  __IFLA_BRIDGE_MRP_PORT_STATE_MAX,
+};
+#define IFLA_BRIDGE_MRP_PORT_STATE_MAX (__IFLA_BRIDGE_MRP_PORT_STATE_MAX - 1)
+enum {
+  IFLA_BRIDGE_MRP_PORT_ROLE_UNSPEC,
+  IFLA_BRIDGE_MRP_PORT_ROLE_ROLE,
+  __IFLA_BRIDGE_MRP_PORT_ROLE_MAX,
+};
+#define IFLA_BRIDGE_MRP_PORT_ROLE_MAX (__IFLA_BRIDGE_MRP_PORT_ROLE_MAX - 1)
+enum {
+  IFLA_BRIDGE_MRP_RING_STATE_UNSPEC,
+  IFLA_BRIDGE_MRP_RING_STATE_RING_ID,
+  IFLA_BRIDGE_MRP_RING_STATE_STATE,
+  __IFLA_BRIDGE_MRP_RING_STATE_MAX,
+};
+#define IFLA_BRIDGE_MRP_RING_STATE_MAX (__IFLA_BRIDGE_MRP_RING_STATE_MAX - 1)
+enum {
+  IFLA_BRIDGE_MRP_RING_ROLE_UNSPEC,
+  IFLA_BRIDGE_MRP_RING_ROLE_RING_ID,
+  IFLA_BRIDGE_MRP_RING_ROLE_ROLE,
+  __IFLA_BRIDGE_MRP_RING_ROLE_MAX,
+};
+#define IFLA_BRIDGE_MRP_RING_ROLE_MAX (__IFLA_BRIDGE_MRP_RING_ROLE_MAX - 1)
+enum {
+  IFLA_BRIDGE_MRP_START_TEST_UNSPEC,
+  IFLA_BRIDGE_MRP_START_TEST_RING_ID,
+  IFLA_BRIDGE_MRP_START_TEST_INTERVAL,
+  IFLA_BRIDGE_MRP_START_TEST_MAX_MISS,
+  IFLA_BRIDGE_MRP_START_TEST_PERIOD,
+  IFLA_BRIDGE_MRP_START_TEST_MONITOR,
+  __IFLA_BRIDGE_MRP_START_TEST_MAX,
+};
+#define IFLA_BRIDGE_MRP_START_TEST_MAX (__IFLA_BRIDGE_MRP_START_TEST_MAX - 1)
+struct br_mrp_instance {
+  __u32 ring_id;
+  __u32 p_ifindex;
+  __u32 s_ifindex;
+  __u16 prio;
+};
+struct br_mrp_ring_state {
+  __u32 ring_id;
+  __u32 ring_state;
+};
+struct br_mrp_ring_role {
+  __u32 ring_id;
+  __u32 ring_role;
+};
+struct br_mrp_start_test {
+  __u32 ring_id;
+  __u32 interval;
+  __u32 max_miss;
+  __u32 period;
+  __u32 monitor;
+};
 struct bridge_stp_xstats {
   __u64 transition_blk;
   __u64 transition_fwd;
diff --git a/libc/kernel/uapi/linux/if_ether.h b/libc/kernel/uapi/linux/if_ether.h
index dd2dedb..c3e0718 100644
--- a/libc/kernel/uapi/linux/if_ether.h
+++ b/libc/kernel/uapi/linux/if_ether.h
@@ -73,6 +73,7 @@
 #define ETH_P_PREAUTH 0x88C7
 #define ETH_P_TIPC 0x88CA
 #define ETH_P_LLDP 0x88CC
+#define ETH_P_MRP 0x88E3
 #define ETH_P_MACSEC 0x88E5
 #define ETH_P_8021AH 0x88E7
 #define ETH_P_MVRP 0x88F5
diff --git a/libc/kernel/uapi/linux/if_link.h b/libc/kernel/uapi/linux/if_link.h
index 790f1d2..b248a6b 100644
--- a/libc/kernel/uapi/linux/if_link.h
+++ b/libc/kernel/uapi/linux/if_link.h
@@ -272,6 +272,7 @@
   IFLA_BRPORT_NEIGH_SUPPRESS,
   IFLA_BRPORT_ISOLATED,
   IFLA_BRPORT_BACKUP_PORT,
+  IFLA_BRPORT_MRP_RING_OPEN,
   __IFLA_BRPORT_MAX
 };
 #define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1)
diff --git a/libc/kernel/uapi/linux/inet_diag.h b/libc/kernel/uapi/linux/inet_diag.h
index fedbd85..1c3c128 100644
--- a/libc/kernel/uapi/linux/inet_diag.h
+++ b/libc/kernel/uapi/linux/inet_diag.h
@@ -82,6 +82,7 @@
   INET_DIAG_BC_MARK_COND,
   INET_DIAG_BC_S_EQ,
   INET_DIAG_BC_D_EQ,
+  INET_DIAG_BC_CGROUP_COND,
 };
 struct inet_diag_hostcond {
   __u8 family;
@@ -127,6 +128,7 @@
   INET_DIAG_MD5SIG,
   INET_DIAG_ULP_INFO,
   INET_DIAG_SK_BPF_STORAGES,
+  INET_DIAG_CGROUP_ID,
   __INET_DIAG_MAX,
 };
 #define INET_DIAG_MAX (__INET_DIAG_MAX - 1)
diff --git a/libc/kernel/uapi/linux/input-event-codes.h b/libc/kernel/uapi/linux/input-event-codes.h
index 46cc7f0..1275b26 100644
--- a/libc/kernel/uapi/linux/input-event-codes.h
+++ b/libc/kernel/uapi/linux/input-event-codes.h
@@ -734,10 +734,8 @@
 #define SW_LINEIN_INSERT 0x0d
 #define SW_MUTE_DEVICE 0x0e
 #define SW_PEN_INSERTED 0x0f
-#define SW_HPHL_OVERCURRENT 0x10
-#define SW_HPHR_OVERCURRENT 0x11
-#define SW_UNSUPPORT_INSERT 0x12
-#define SW_MAX 0x20
+#define SW_MACHINE_COVER 0x10
+#define SW_MAX 0x10
 #define SW_CNT (SW_MAX + 1)
 #define MSC_SERIAL 0x00
 #define MSC_PULSELED 0x01
diff --git a/libc/kernel/uapi/linux/io_uring.h b/libc/kernel/uapi/linux/io_uring.h
index ef3ee51..9912405 100644
--- a/libc/kernel/uapi/linux/io_uring.h
+++ b/libc/kernel/uapi/linux/io_uring.h
@@ -115,6 +115,7 @@
   IORING_OP_SPLICE,
   IORING_OP_PROVIDE_BUFFERS,
   IORING_OP_REMOVE_BUFFERS,
+  IORING_OP_TEE,
   IORING_OP_LAST,
 };
 #define IORING_FSYNC_DATASYNC (1U << 0)
@@ -144,6 +145,7 @@
   __u64 resv2;
 };
 #define IORING_SQ_NEED_WAKEUP (1U << 0)
+#define IORING_SQ_CQ_OVERFLOW (1U << 1)
 struct io_cqring_offsets {
   __u32 head;
   __u32 tail;
@@ -151,8 +153,11 @@
   __u32 ring_entries;
   __u32 overflow;
   __u32 cqes;
-  __u64 resv[2];
+  __u32 flags;
+  __u32 resv1;
+  __u64 resv2;
 };
+#define IORING_CQ_EVENTFD_DISABLED (1U << 0)
 #define IORING_ENTER_GETEVENTS (1U << 0)
 #define IORING_ENTER_SQ_WAKEUP (1U << 1)
 struct io_uring_params {
diff --git a/libc/kernel/uapi/linux/iommu.h b/libc/kernel/uapi/linux/iommu.h
index 54452c3..172be9c 100644
--- a/libc/kernel/uapi/linux/iommu.h
+++ b/libc/kernel/uapi/linux/iommu.h
@@ -133,6 +133,7 @@
   __u32 pat;
   __u32 emt;
 };
+#define IOMMU_SVA_VTD_GPASID_MTS_MASK (IOMMU_SVA_VTD_GPASID_CD | IOMMU_SVA_VTD_GPASID_EMTE | IOMMU_SVA_VTD_GPASID_PCD | IOMMU_SVA_VTD_GPASID_PWT)
 struct iommu_gpasid_bind_data {
 #define IOMMU_GPASID_BIND_VERSION_1 1
   __u32 version;
diff --git a/libc/kernel/uapi/linux/keyctl.h b/libc/kernel/uapi/linux/keyctl.h
index e3fef38..01ea576 100644
--- a/libc/kernel/uapi/linux/keyctl.h
+++ b/libc/kernel/uapi/linux/keyctl.h
@@ -68,6 +68,7 @@
 #define KEYCTL_RESTRICT_KEYRING 29
 #define KEYCTL_MOVE 30
 #define KEYCTL_CAPABILITIES 31
+#define KEYCTL_WATCH_KEY 32
 struct keyctl_dh_params {
   union {
 #ifndef __cplusplus
@@ -117,4 +118,5 @@
 #define KEYCTL_CAPS0_MOVE 0x80
 #define KEYCTL_CAPS1_NS_KEYRING_NAME 0x01
 #define KEYCTL_CAPS1_NS_KEY_TAG 0x02
+#define KEYCTL_CAPS1_NOTIFICATIONS 0x04
 #endif
diff --git a/libc/kernel/uapi/linux/kfd_ioctl.h b/libc/kernel/uapi/linux/kfd_ioctl.h
index 8b09f00..d9f7bfc 100644
--- a/libc/kernel/uapi/linux/kfd_ioctl.h
+++ b/libc/kernel/uapi/linux/kfd_ioctl.h
@@ -267,6 +267,12 @@
   __u32 n_devices;
   __u32 n_success;
 };
+struct kfd_ioctl_alloc_queue_gws_args {
+  __u32 queue_id;
+  __u32 num_gws;
+  __u32 first_gws;
+  __u32 pad;
+};
 struct kfd_ioctl_get_dmabuf_info_args {
   __u64 size;
   __u64 metadata_ptr;
@@ -319,6 +325,7 @@
 #define AMDKFD_IOC_GET_QUEUE_WAVE_STATE AMDKFD_IOWR(0x1B, struct kfd_ioctl_get_queue_wave_state_args)
 #define AMDKFD_IOC_GET_DMABUF_INFO AMDKFD_IOWR(0x1C, struct kfd_ioctl_get_dmabuf_info_args)
 #define AMDKFD_IOC_IMPORT_DMABUF AMDKFD_IOWR(0x1D, struct kfd_ioctl_import_dmabuf_args)
+#define AMDKFD_IOC_ALLOC_QUEUE_GWS AMDKFD_IOWR(0x1E, struct kfd_ioctl_alloc_queue_gws_args)
 #define AMDKFD_COMMAND_START 0x01
-#define AMDKFD_COMMAND_END 0x1E
+#define AMDKFD_COMMAND_END 0x1F
 #endif
diff --git a/libc/kernel/uapi/linux/kvm.h b/libc/kernel/uapi/linux/kvm.h
index ea6bca5..7e13990 100644
--- a/libc/kernel/uapi/linux/kvm.h
+++ b/libc/kernel/uapi/linux/kvm.h
@@ -137,10 +137,13 @@
 struct kvm_hyperv_exit {
 #define KVM_EXIT_HYPERV_SYNIC 1
 #define KVM_EXIT_HYPERV_HCALL 2
+#define KVM_EXIT_HYPERV_SYNDBG 3
   __u32 type;
+  __u32 pad1;
   union {
     struct {
       __u32 msr;
+      __u32 pad2;
       __u64 control;
       __u64 evt_page;
       __u64 msg_page;
@@ -150,6 +153,15 @@
       __u64 result;
       __u64 params[2];
     } hcall;
+    struct {
+      __u32 msr;
+      __u32 pad2;
+      __u64 control;
+      __u64 status;
+      __u64 send_page;
+      __u64 recv_page;
+      __u64 pending_page;
+    } syndbg;
   } u;
 };
 #define KVM_S390_GET_SKEYS_NONE 1
@@ -796,6 +808,8 @@
 #define KVM_CAP_S390_VCPU_RESETS 179
 #define KVM_CAP_S390_PROTECTED 180
 #define KVM_CAP_PPC_SECURE_GUEST 181
+#define KVM_CAP_HALT_POLL 182
+#define KVM_CAP_ASYNC_PF_INT 183
 #ifdef KVM_CAP_IRQ_ROUTING
 struct kvm_irq_routing_irqchip {
   __u32 irqchip;
diff --git a/libc/kernel/uapi/linux/loop.h b/libc/kernel/uapi/linux/loop.h
index d5a23b5..56eba91 100644
--- a/libc/kernel/uapi/linux/loop.h
+++ b/libc/kernel/uapi/linux/loop.h
@@ -26,6 +26,9 @@
   LO_FLAGS_PARTSCAN = 8,
   LO_FLAGS_DIRECT_IO = 16,
 };
+#define LOOP_SET_STATUS_SETTABLE_FLAGS (LO_FLAGS_AUTOCLEAR | LO_FLAGS_PARTSCAN)
+#define LOOP_SET_STATUS_CLEARABLE_FLAGS (LO_FLAGS_AUTOCLEAR)
+#define LOOP_CONFIGURE_SETTABLE_FLAGS (LO_FLAGS_READ_ONLY | LO_FLAGS_AUTOCLEAR | LO_FLAGS_PARTSCAN | LO_FLAGS_DIRECT_IO)
 #include <asm/posix_types.h>
 #include <linux/types.h>
 struct loop_info {
@@ -57,6 +60,12 @@
   __u8 lo_encrypt_key[LO_KEY_SIZE];
   __u64 lo_init[2];
 };
+struct loop_config {
+  __u32 fd;
+  __u32 block_size;
+  struct loop_info64 info;
+  __u64 __reserved[8];
+};
 #define LO_CRYPT_NONE 0
 #define LO_CRYPT_XOR 1
 #define LO_CRYPT_DES 2
@@ -78,6 +87,7 @@
 #define LOOP_SET_CAPACITY 0x4C07
 #define LOOP_SET_DIRECT_IO 0x4C08
 #define LOOP_SET_BLOCK_SIZE 0x4C09
+#define LOOP_CONFIGURE 0x4C0A
 #define LOOP_CTL_ADD 0x4C80
 #define LOOP_CTL_REMOVE 0x4C81
 #define LOOP_CTL_GET_FREE 0x4C82
diff --git a/libc/kernel/uapi/linux/magic.h b/libc/kernel/uapi/linux/magic.h
index 82b9dce..479ae81 100644
--- a/libc/kernel/uapi/linux/magic.h
+++ b/libc/kernel/uapi/linux/magic.h
@@ -97,6 +97,7 @@
 #define BALLOON_KVM_MAGIC 0x13661366
 #define ZSMALLOC_MAGIC 0x58295829
 #define DMA_BUF_MAGIC 0x444d4142
+#define DEVMEM_MAGIC 0x454d444d
 #define Z3FOLD_MAGIC 0x33
 #define PPC_CMM_MAGIC 0xc7571590
 #endif
diff --git a/libc/kernel/uapi/linux/mii.h b/libc/kernel/uapi/linux/mii.h
index 75b29fd..a489015 100644
--- a/libc/kernel/uapi/linux/mii.h
+++ b/libc/kernel/uapi/linux/mii.h
@@ -137,9 +137,11 @@
 #define LPA_SGMII_LINK 0x8000
 #define ADVERTISE_1000FULL 0x0200
 #define ADVERTISE_1000HALF 0x0100
+#define CTL1000_PREFER_MASTER 0x0400
 #define CTL1000_AS_MASTER 0x0800
 #define CTL1000_ENABLE_MASTER 0x1000
 #define LPA_1000MSFAIL 0x8000
+#define LPA_1000MSRES 0x4000
 #define LPA_1000LOCALRXOK 0x2000
 #define LPA_1000REMRXOK 0x1000
 #define LPA_1000FULL 0x0800
diff --git a/libc/kernel/uapi/linux/mmc/ioctl.h b/libc/kernel/uapi/linux/mmc/ioctl.h
index 101eb8c..afea6a5 100644
--- a/libc/kernel/uapi/linux/mmc/ioctl.h
+++ b/libc/kernel/uapi/linux/mmc/ioctl.h
@@ -19,6 +19,7 @@
 #ifndef LINUX_MMC_IOCTL_H
 #define LINUX_MMC_IOCTL_H
 #include <linux/types.h>
+#include <linux/major.h>
 struct mmc_ioc_cmd {
   int write_flag;
   int is_acmd;
diff --git a/libc/kernel/uapi/linux/mrp_bridge.h b/libc/kernel/uapi/linux/mrp_bridge.h
new file mode 100644
index 0000000..cbfc322
--- /dev/null
+++ b/libc/kernel/uapi/linux/mrp_bridge.h
@@ -0,0 +1,117 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ***   To edit the content of this header, modify the corresponding
+ ***   source file (e.g. under external/kernel-headers/original/) then
+ ***   run bionic/libc/kernel/tools/update_all.py
+ ***
+ ***   Any manual change here will be lost the next time this script will
+ ***   be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _UAPI_LINUX_MRP_BRIDGE_H_
+#define _UAPI_LINUX_MRP_BRIDGE_H_
+#include <linux/types.h>
+#include <linux/if_ether.h>
+#define MRP_MAX_FRAME_LENGTH 200
+#define MRP_DEFAULT_PRIO 0x8000
+#define MRP_DOMAIN_UUID_LENGTH 16
+#define MRP_VERSION 1
+#define MRP_FRAME_PRIO 7
+#define MRP_OUI_LENGTH 3
+#define MRP_MANUFACTURE_DATA_LENGTH 2
+enum br_mrp_ring_role_type {
+  BR_MRP_RING_ROLE_DISABLED,
+  BR_MRP_RING_ROLE_MRC,
+  BR_MRP_RING_ROLE_MRM,
+  BR_MRP_RING_ROLE_MRA,
+};
+enum br_mrp_ring_state_type {
+  BR_MRP_RING_STATE_OPEN,
+  BR_MRP_RING_STATE_CLOSED,
+};
+enum br_mrp_port_state_type {
+  BR_MRP_PORT_STATE_DISABLED,
+  BR_MRP_PORT_STATE_BLOCKED,
+  BR_MRP_PORT_STATE_FORWARDING,
+  BR_MRP_PORT_STATE_NOT_CONNECTED,
+};
+enum br_mrp_port_role_type {
+  BR_MRP_PORT_ROLE_PRIMARY,
+  BR_MRP_PORT_ROLE_SECONDARY,
+};
+enum br_mrp_tlv_header_type {
+  BR_MRP_TLV_HEADER_END = 0x0,
+  BR_MRP_TLV_HEADER_COMMON = 0x1,
+  BR_MRP_TLV_HEADER_RING_TEST = 0x2,
+  BR_MRP_TLV_HEADER_RING_TOPO = 0x3,
+  BR_MRP_TLV_HEADER_RING_LINK_DOWN = 0x4,
+  BR_MRP_TLV_HEADER_RING_LINK_UP = 0x5,
+  BR_MRP_TLV_HEADER_OPTION = 0x7f,
+};
+enum br_mrp_sub_tlv_header_type {
+  BR_MRP_SUB_TLV_HEADER_TEST_MGR_NACK = 0x1,
+  BR_MRP_SUB_TLV_HEADER_TEST_PROPAGATE = 0x2,
+  BR_MRP_SUB_TLV_HEADER_TEST_AUTO_MGR = 0x3,
+};
+struct br_mrp_tlv_hdr {
+  __u8 type;
+  __u8 length;
+};
+struct br_mrp_sub_tlv_hdr {
+  __u8 type;
+  __u8 length;
+};
+struct br_mrp_end_hdr {
+  struct br_mrp_tlv_hdr hdr;
+};
+struct br_mrp_common_hdr {
+  __be16 seq_id;
+  __u8 domain[MRP_DOMAIN_UUID_LENGTH];
+};
+struct br_mrp_ring_test_hdr {
+  __be16 prio;
+  __u8 sa[ETH_ALEN];
+  __be16 port_role;
+  __be16 state;
+  __be16 transitions;
+  __be32 timestamp;
+};
+struct br_mrp_ring_topo_hdr {
+  __be16 prio;
+  __u8 sa[ETH_ALEN];
+  __be16 interval;
+};
+struct br_mrp_ring_link_hdr {
+  __u8 sa[ETH_ALEN];
+  __be16 port_role;
+  __be16 interval;
+  __be16 blocked;
+};
+struct br_mrp_sub_opt_hdr {
+  __u8 type;
+  __u8 manufacture_data[MRP_MANUFACTURE_DATA_LENGTH];
+};
+struct br_mrp_test_mgr_nack_hdr {
+  __be16 prio;
+  __u8 sa[ETH_ALEN];
+  __be16 other_prio;
+  __u8 other_sa[ETH_ALEN];
+};
+struct br_mrp_test_prop_hdr {
+  __be16 prio;
+  __u8 sa[ETH_ALEN];
+  __be16 other_prio;
+  __u8 other_sa[ETH_ALEN];
+};
+struct br_mrp_oui_hdr {
+  __u8 oui[MRP_OUI_LENGTH];
+};
+#endif
diff --git a/libc/kernel/uapi/linux/ndctl.h b/libc/kernel/uapi/linux/ndctl.h
index e47091f..61c8929 100644
--- a/libc/kernel/uapi/linux/ndctl.h
+++ b/libc/kernel/uapi/linux/ndctl.h
@@ -158,5 +158,6 @@
 #define NVDIMM_FAMILY_HPE2 2
 #define NVDIMM_FAMILY_MSFT 3
 #define NVDIMM_FAMILY_HYPERV 4
+#define NVDIMM_FAMILY_PAPR 5
 #define ND_IOCTL_CALL _IOWR(ND_IOCTL, ND_CMD_CALL, struct nd_cmd_pkg)
 #endif
diff --git a/libc/kernel/uapi/linux/neighbour.h b/libc/kernel/uapi/linux/neighbour.h
index 4ce4736..eb4babd 100644
--- a/libc/kernel/uapi/linux/neighbour.h
+++ b/libc/kernel/uapi/linux/neighbour.h
@@ -43,6 +43,7 @@
   NDA_LINK_NETNSID,
   NDA_SRC_VNI,
   NDA_PROTOCOL,
+  NDA_NH_ID,
   __NDA_MAX
 };
 #define NDA_MAX (__NDA_MAX - 1)
diff --git a/libc/kernel/uapi/linux/netfilter/nf_conntrack_common.h b/libc/kernel/uapi/linux/netfilter/nf_conntrack_common.h
index 152584a..3ff6030 100644
--- a/libc/kernel/uapi/linux/netfilter/nf_conntrack_common.h
+++ b/libc/kernel/uapi/linux/netfilter/nf_conntrack_common.h
@@ -64,8 +64,10 @@
   IPS_HELPER = (1 << IPS_HELPER_BIT),
   IPS_OFFLOAD_BIT = 14,
   IPS_OFFLOAD = (1 << IPS_OFFLOAD_BIT),
-  IPS_UNCHANGEABLE_MASK = (IPS_NAT_DONE_MASK | IPS_NAT_MASK | IPS_EXPECTED | IPS_CONFIRMED | IPS_DYING | IPS_SEQ_ADJUST | IPS_TEMPLATE | IPS_UNTRACKED | IPS_OFFLOAD),
-  __IPS_MAX_BIT = 15,
+  IPS_HW_OFFLOAD_BIT = 15,
+  IPS_HW_OFFLOAD = (1 << IPS_HW_OFFLOAD_BIT),
+  IPS_UNCHANGEABLE_MASK = (IPS_NAT_DONE_MASK | IPS_NAT_MASK | IPS_EXPECTED | IPS_CONFIRMED | IPS_DYING | IPS_SEQ_ADJUST | IPS_TEMPLATE | IPS_UNTRACKED | IPS_OFFLOAD | IPS_HW_OFFLOAD),
+  __IPS_MAX_BIT = 16,
 };
 enum ip_conntrack_events {
   IPCT_NEW,
diff --git a/libc/kernel/uapi/linux/netfilter/nf_nat.h b/libc/kernel/uapi/linux/netfilter/nf_nat.h
index f01669b..84373ed 100644
--- a/libc/kernel/uapi/linux/netfilter/nf_nat.h
+++ b/libc/kernel/uapi/linux/netfilter/nf_nat.h
@@ -26,8 +26,9 @@
 #define NF_NAT_RANGE_PERSISTENT (1 << 3)
 #define NF_NAT_RANGE_PROTO_RANDOM_FULLY (1 << 4)
 #define NF_NAT_RANGE_PROTO_OFFSET (1 << 5)
+#define NF_NAT_RANGE_NETMAP (1 << 6)
 #define NF_NAT_RANGE_PROTO_RANDOM_ALL (NF_NAT_RANGE_PROTO_RANDOM | NF_NAT_RANGE_PROTO_RANDOM_FULLY)
-#define NF_NAT_RANGE_MASK (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED | NF_NAT_RANGE_PROTO_RANDOM | NF_NAT_RANGE_PERSISTENT | NF_NAT_RANGE_PROTO_RANDOM_FULLY | NF_NAT_RANGE_PROTO_OFFSET)
+#define NF_NAT_RANGE_MASK (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED | NF_NAT_RANGE_PROTO_RANDOM | NF_NAT_RANGE_PERSISTENT | NF_NAT_RANGE_PROTO_RANDOM_FULLY | NF_NAT_RANGE_PROTO_OFFSET | NF_NAT_RANGE_NETMAP)
 struct nf_nat_ipv4_range {
   unsigned int flags;
   __be32 min_ip;
diff --git a/libc/kernel/uapi/linux/netfilter/nfnetlink_conntrack.h b/libc/kernel/uapi/linux/netfilter/nfnetlink_conntrack.h
index 4981fc1..8e48f80 100644
--- a/libc/kernel/uapi/linux/netfilter/nfnetlink_conntrack.h
+++ b/libc/kernel/uapi/linux/netfilter/nfnetlink_conntrack.h
@@ -66,6 +66,7 @@
   CTA_LABELS,
   CTA_LABELS_MASK,
   CTA_SYNPROXY,
+  CTA_FILTER,
   __CTA_MAX
 };
 #define CTA_MAX (__CTA_MAX - 1)
@@ -265,4 +266,11 @@
   __CTA_STATS_EXP_MAX,
 };
 #define CTA_STATS_EXP_MAX (__CTA_STATS_EXP_MAX - 1)
+enum ctattr_filter {
+  CTA_FILTER_UNSPEC,
+  CTA_FILTER_ORIG_FLAGS,
+  CTA_FILTER_REPLY_FLAGS,
+  __CTA_FILTER_MAX
+};
+#define CTA_FILTER_MAX (__CTA_FILTER_MAX - 1)
 #endif
diff --git a/libc/kernel/uapi/linux/netlink.h b/libc/kernel/uapi/linux/netlink.h
index 4c0fd1f..acbf884 100644
--- a/libc/kernel/uapi/linux/netlink.h
+++ b/libc/kernel/uapi/linux/netlink.h
@@ -159,4 +159,38 @@
   __u32 value;
   __u32 selector;
 };
+enum netlink_attribute_type {
+  NL_ATTR_TYPE_INVALID,
+  NL_ATTR_TYPE_FLAG,
+  NL_ATTR_TYPE_U8,
+  NL_ATTR_TYPE_U16,
+  NL_ATTR_TYPE_U32,
+  NL_ATTR_TYPE_U64,
+  NL_ATTR_TYPE_S8,
+  NL_ATTR_TYPE_S16,
+  NL_ATTR_TYPE_S32,
+  NL_ATTR_TYPE_S64,
+  NL_ATTR_TYPE_BINARY,
+  NL_ATTR_TYPE_STRING,
+  NL_ATTR_TYPE_NUL_STRING,
+  NL_ATTR_TYPE_NESTED,
+  NL_ATTR_TYPE_NESTED_ARRAY,
+  NL_ATTR_TYPE_BITFIELD32,
+};
+enum netlink_policy_type_attr {
+  NL_POLICY_TYPE_ATTR_UNSPEC,
+  NL_POLICY_TYPE_ATTR_TYPE,
+  NL_POLICY_TYPE_ATTR_MIN_VALUE_S,
+  NL_POLICY_TYPE_ATTR_MAX_VALUE_S,
+  NL_POLICY_TYPE_ATTR_MIN_VALUE_U,
+  NL_POLICY_TYPE_ATTR_MAX_VALUE_U,
+  NL_POLICY_TYPE_ATTR_MIN_LENGTH,
+  NL_POLICY_TYPE_ATTR_MAX_LENGTH,
+  NL_POLICY_TYPE_ATTR_POLICY_IDX,
+  NL_POLICY_TYPE_ATTR_POLICY_MAXTYPE,
+  NL_POLICY_TYPE_ATTR_BITFIELD32_MASK,
+  NL_POLICY_TYPE_ATTR_PAD,
+  __NL_POLICY_TYPE_ATTR_MAX,
+  NL_POLICY_TYPE_ATTR_MAX = __NL_POLICY_TYPE_ATTR_MAX - 1
+};
 #endif
diff --git a/libc/kernel/uapi/linux/nexthop.h b/libc/kernel/uapi/linux/nexthop.h
index a2a959f..f99a074 100644
--- a/libc/kernel/uapi/linux/nexthop.h
+++ b/libc/kernel/uapi/linux/nexthop.h
@@ -49,6 +49,7 @@
   NHA_ENCAP,
   NHA_GROUPS,
   NHA_MASTER,
+  NHA_FDB,
   __NHA_MAX,
 };
 #define NHA_MAX (__NHA_MAX - 1)
diff --git a/libc/kernel/uapi/linux/nl80211.h b/libc/kernel/uapi/linux/nl80211.h
index 7f8b45f..75d51c9 100644
--- a/libc/kernel/uapi/linux/nl80211.h
+++ b/libc/kernel/uapi/linux/nl80211.h
@@ -175,6 +175,8 @@
   NL80211_CMD_UPDATE_OWE_INFO,
   NL80211_CMD_PROBE_MESH_LINK,
   NL80211_CMD_SET_TID_CONFIG,
+  NL80211_CMD_UNPROT_BEACON,
+  NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS,
   __NL80211_CMD_AFTER_LAST,
   NL80211_CMD_MAX = __NL80211_CMD_AFTER_LAST - 1
 };
@@ -480,6 +482,11 @@
   NL80211_ATTR_CONTROL_PORT_NO_PREAUTH,
   NL80211_ATTR_PMK_LIFETIME,
   NL80211_ATTR_PMK_REAUTH_THRESHOLD,
+  NL80211_ATTR_RECEIVE_MULTICAST,
+  NL80211_ATTR_WIPHY_FREQ_OFFSET,
+  NL80211_ATTR_CENTER_FREQ1_OFFSET,
+  NL80211_ATTR_SCAN_FREQ_KHZ,
+  NL80211_ATTR_HE_6GHZ_CAPABILITY,
   __NL80211_ATTR_AFTER_LAST,
   NUM_NL80211_ATTR = __NL80211_ATTR_AFTER_LAST,
   NL80211_ATTR_MAX = __NL80211_ATTR_AFTER_LAST - 1
@@ -713,6 +720,7 @@
   NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY,
   NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET,
   NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE,
+  NL80211_BAND_IFTYPE_ATTR_HE_6GHZ_CAPA,
   __NL80211_BAND_IFTYPE_ATTR_AFTER_LAST,
   NL80211_BAND_IFTYPE_ATTR_MAX = __NL80211_BAND_IFTYPE_ATTR_AFTER_LAST - 1
 };
@@ -763,6 +771,7 @@
   NL80211_FREQUENCY_ATTR_NO_10MHZ,
   NL80211_FREQUENCY_ATTR_WMM,
   NL80211_FREQUENCY_ATTR_NO_HE,
+  NL80211_FREQUENCY_ATTR_OFFSET,
   __NL80211_FREQUENCY_ATTR_AFTER_LAST,
   NL80211_FREQUENCY_ATTR_MAX = __NL80211_FREQUENCY_ATTR_AFTER_LAST - 1
 };
@@ -1005,6 +1014,7 @@
   NL80211_BSS_PARENT_TSF,
   NL80211_BSS_PARENT_BSSID,
   NL80211_BSS_CHAIN_SIGNAL,
+  NL80211_BSS_FREQUENCY_OFFSET,
   __NL80211_BSS_AFTER_LAST,
   NL80211_BSS_MAX = __NL80211_BSS_AFTER_LAST - 1
 };
@@ -1121,6 +1131,11 @@
   NL80211_TID_CONFIG_ENABLE,
   NL80211_TID_CONFIG_DISABLE,
 };
+enum nl80211_tx_rate_setting {
+  NL80211_TX_RATE_AUTOMATIC,
+  NL80211_TX_RATE_LIMITED,
+  NL80211_TX_RATE_FIXED,
+};
 enum nl80211_tid_config_attr {
   __NL80211_TID_CONFIG_ATTR_INVALID,
   NL80211_TID_CONFIG_ATTR_PAD,
@@ -1133,6 +1148,9 @@
   NL80211_TID_CONFIG_ATTR_RETRY_LONG,
   NL80211_TID_CONFIG_ATTR_AMPDU_CTRL,
   NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL,
+  NL80211_TID_CONFIG_ATTR_AMSDU_CTRL,
+  NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE,
+  NL80211_TID_CONFIG_ATTR_TX_RATE,
   __NL80211_TID_CONFIG_ATTR_AFTER_LAST,
   NL80211_TID_CONFIG_ATTR_MAX = __NL80211_TID_CONFIG_ATTR_AFTER_LAST - 1
 };
@@ -1262,12 +1280,15 @@
 };
 #define NL80211_KCK_LEN 16
 #define NL80211_KEK_LEN 16
+#define NL80211_KCK_EXT_LEN 24
+#define NL80211_KEK_EXT_LEN 32
 #define NL80211_REPLAY_CTR_LEN 8
 enum nl80211_rekey_data {
   __NL80211_REKEY_DATA_INVALID,
   NL80211_REKEY_DATA_KEK,
   NL80211_REKEY_DATA_KCK,
   NL80211_REKEY_DATA_REPLAY_CTR,
+  NL80211_REKEY_DATA_AKM,
   NUM_NL80211_REKEY_DATA,
   MAX_NL80211_REKEY_DATA = NUM_NL80211_REKEY_DATA - 1
 };
@@ -1378,6 +1399,10 @@
   NL80211_EXT_FEATURE_CONTROL_PORT_NO_PREAUTH,
   NL80211_EXT_FEATURE_PROTECTED_TWT,
   NL80211_EXT_FEATURE_DEL_IBSS_STA,
+  NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS,
+  NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT,
+  NL80211_EXT_FEATURE_SCAN_FREQ_KHZ,
+  NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211_TX_STATUS,
   NUM_NL80211_EXT_FEATURES,
   MAX_NL80211_EXT_FEATURES = NUM_NL80211_EXT_FEATURES - 1
 };
@@ -1411,6 +1436,7 @@
   NL80211_SCAN_FLAG_HIGH_ACCURACY = 1 << 10,
   NL80211_SCAN_FLAG_RANDOM_SN = 1 << 11,
   NL80211_SCAN_FLAG_MIN_PREQ_CONTENT = 1 << 12,
+  NL80211_SCAN_FLAG_FREQ_KHZ = 1 << 13,
 };
 enum nl80211_acl_policy {
   NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED,
diff --git a/libc/kernel/uapi/linux/pkt_cls.h b/libc/kernel/uapi/linux/pkt_cls.h
index d77d46e..a5e8149 100644
--- a/libc/kernel/uapi/linux/pkt_cls.h
+++ b/libc/kernel/uapi/linux/pkt_cls.h
@@ -103,6 +103,7 @@
   TCA_ID_CTINFO,
   TCA_ID_MPLS,
   TCA_ID_CT,
+  TCA_ID_GATE,
   __TCA_ID_MAX = 255
 };
 #define TCA_ID_MAX __TCA_ID_MAX
@@ -450,6 +451,7 @@
   TCA_FLOWER_KEY_CT_MARK_MASK,
   TCA_FLOWER_KEY_CT_LABELS,
   TCA_FLOWER_KEY_CT_LABELS_MASK,
+  TCA_FLOWER_KEY_MPLS_OPTS,
   __TCA_FLOWER_MAX,
 };
 #define TCA_FLOWER_MAX (__TCA_FLOWER_MAX - 1)
@@ -491,6 +493,22 @@
 };
 #define TCA_FLOWER_KEY_ENC_OPT_ERSPAN_MAX (__TCA_FLOWER_KEY_ENC_OPT_ERSPAN_MAX - 1)
 enum {
+  TCA_FLOWER_KEY_MPLS_OPTS_UNSPEC,
+  TCA_FLOWER_KEY_MPLS_OPTS_LSE,
+  __TCA_FLOWER_KEY_MPLS_OPTS_MAX,
+};
+#define TCA_FLOWER_KEY_MPLS_OPTS_MAX (__TCA_FLOWER_KEY_MPLS_OPTS_MAX - 1)
+enum {
+  TCA_FLOWER_KEY_MPLS_OPT_LSE_UNSPEC,
+  TCA_FLOWER_KEY_MPLS_OPT_LSE_DEPTH,
+  TCA_FLOWER_KEY_MPLS_OPT_LSE_TTL,
+  TCA_FLOWER_KEY_MPLS_OPT_LSE_BOS,
+  TCA_FLOWER_KEY_MPLS_OPT_LSE_TC,
+  TCA_FLOWER_KEY_MPLS_OPT_LSE_LABEL,
+  __TCA_FLOWER_KEY_MPLS_OPT_LSE_MAX,
+};
+#define TCA_FLOWER_KEY_MPLS_OPT_LSE_MAX (__TCA_FLOWER_KEY_MPLS_OPT_LSE_MAX - 1)
+enum {
   TCA_FLOWER_KEY_FLAGS_IS_FRAGMENT = (1 << 0),
   TCA_FLOWER_KEY_FLAGS_FRAG_IS_FIRST = (1 << 1),
 };
diff --git a/libc/kernel/uapi/linux/pkt_sched.h b/libc/kernel/uapi/linux/pkt_sched.h
index db7f5cb..9579583 100644
--- a/libc/kernel/uapi/linux/pkt_sched.h
+++ b/libc/kernel/uapi/linux/pkt_sched.h
@@ -669,6 +669,8 @@
   TCA_FQ_LOW_RATE_THRESHOLD,
   TCA_FQ_CE_THRESHOLD,
   TCA_FQ_TIMER_SLACK,
+  TCA_FQ_HORIZON,
+  TCA_FQ_HORIZON_DROP,
   __TCA_FQ_MAX
 };
 #define TCA_FQ_MAX (__TCA_FQ_MAX - 1)
@@ -686,6 +688,8 @@
   __u32 throttled_flows;
   __u32 unthrottle_latency_ns;
   __u64 ce_mark;
+  __u64 horizon_drops;
+  __u64 horizon_caps;
 };
 enum {
   TCA_HHF_UNSPEC,
diff --git a/libc/kernel/uapi/linux/psample.h b/libc/kernel/uapi/linux/psample.h
index d90956b..1f8b325 100644
--- a/libc/kernel/uapi/linux/psample.h
+++ b/libc/kernel/uapi/linux/psample.h
@@ -26,6 +26,7 @@
   PSAMPLE_ATTR_GROUP_SEQ,
   PSAMPLE_ATTR_SAMPLE_RATE,
   PSAMPLE_ATTR_DATA,
+  PSAMPLE_ATTR_TUNNEL,
   PSAMPLE_ATTR_GROUP_REFCOUNT,
   __PSAMPLE_ATTR_MAX
 };
@@ -35,6 +36,26 @@
   PSAMPLE_CMD_NEW_GROUP,
   PSAMPLE_CMD_DEL_GROUP,
 };
+enum psample_tunnel_key_attr {
+  PSAMPLE_TUNNEL_KEY_ATTR_ID,
+  PSAMPLE_TUNNEL_KEY_ATTR_IPV4_SRC,
+  PSAMPLE_TUNNEL_KEY_ATTR_IPV4_DST,
+  PSAMPLE_TUNNEL_KEY_ATTR_TOS,
+  PSAMPLE_TUNNEL_KEY_ATTR_TTL,
+  PSAMPLE_TUNNEL_KEY_ATTR_DONT_FRAGMENT,
+  PSAMPLE_TUNNEL_KEY_ATTR_CSUM,
+  PSAMPLE_TUNNEL_KEY_ATTR_OAM,
+  PSAMPLE_TUNNEL_KEY_ATTR_GENEVE_OPTS,
+  PSAMPLE_TUNNEL_KEY_ATTR_TP_SRC,
+  PSAMPLE_TUNNEL_KEY_ATTR_TP_DST,
+  PSAMPLE_TUNNEL_KEY_ATTR_VXLAN_OPTS,
+  PSAMPLE_TUNNEL_KEY_ATTR_IPV6_SRC,
+  PSAMPLE_TUNNEL_KEY_ATTR_IPV6_DST,
+  PSAMPLE_TUNNEL_KEY_ATTR_PAD,
+  PSAMPLE_TUNNEL_KEY_ATTR_ERSPAN_OPTS,
+  PSAMPLE_TUNNEL_KEY_ATTR_IPV4_INFO_BRIDGE,
+  __PSAMPLE_TUNNEL_KEY_ATTR_MAX
+};
 #define PSAMPLE_ATTR_MAX (__PSAMPLE_ATTR_MAX - 1)
 #define PSAMPLE_NL_MCGRP_CONFIG_NAME "config"
 #define PSAMPLE_NL_MCGRP_SAMPLE_NAME "packets"
diff --git a/libc/kernel/uapi/linux/psp-sev.h b/libc/kernel/uapi/linux/psp-sev.h
index fcdb102..6c4f73d 100644
--- a/libc/kernel/uapi/linux/psp-sev.h
+++ b/libc/kernel/uapi/linux/psp-sev.h
@@ -67,6 +67,7 @@
   __u8 build;
   __u32 guest_count;
 } __packed;
+#define SEV_STATUS_FLAGS_CONFIG_ES 0x0100
 struct sev_user_data_pek_csr {
   __u64 address;
   __u32 length;
diff --git a/libc/kernel/uapi/linux/ptp_clock.h b/libc/kernel/uapi/linux/ptp_clock.h
index 8618101..3d0dc24 100644
--- a/libc/kernel/uapi/linux/ptp_clock.h
+++ b/libc/kernel/uapi/linux/ptp_clock.h
@@ -43,7 +43,8 @@
   int pps;
   int n_pins;
   int cross_timestamping;
-  int rsv[13];
+  int adjust_phase;
+  int rsv[12];
 };
 struct ptp_extts_request {
   unsigned int index;
diff --git a/libc/kernel/uapi/linux/rds.h b/libc/kernel/uapi/linux/rds.h
index 537aab5..bc29233 100644
--- a/libc/kernel/uapi/linux/rds.h
+++ b/libc/kernel/uapi/linux/rds.h
@@ -32,10 +32,11 @@
 #define SO_RDS_TRANSPORT 8
 #define SO_RDS_MSG_RXPATH_LATENCY 10
 #define RDS_TRANS_IB 0
-#define RDS_TRANS_IWARP 1
+#define RDS_TRANS_GAP 1
 #define RDS_TRANS_TCP 2
 #define RDS_TRANS_COUNT 3
 #define RDS_TRANS_NONE (~0)
+#define RDS_TRANS_IWARP RDS_TRANS_GAP
 #define SIOCRDSSETTOS (SIOCPROTOPRIVATE)
 #define SIOCRDSGETTOS (SIOCPROTOPRIVATE + 1)
 typedef __u8 rds_tos_t;
diff --git a/libc/kernel/uapi/linux/rtc.h b/libc/kernel/uapi/linux/rtc.h
index 3312f69..8e70eba 100644
--- a/libc/kernel/uapi/linux/rtc.h
+++ b/libc/kernel/uapi/linux/rtc.h
@@ -69,6 +69,7 @@
 #define RTC_VL_BACKUP_LOW _BITUL(1)
 #define RTC_VL_BACKUP_EMPTY _BITUL(2)
 #define RTC_VL_ACCURACY_LOW _BITUL(3)
+#define RTC_VL_BACKUP_SWITCH _BITUL(4)
 #define RTC_VL_READ _IOR('p', 0x13, unsigned int)
 #define RTC_VL_CLR _IO('p', 0x14)
 #define RTC_IRQF 0x80
diff --git a/libc/kernel/uapi/linux/rtnetlink.h b/libc/kernel/uapi/linux/rtnetlink.h
index 295fbed..f7be4a5 100644
--- a/libc/kernel/uapi/linux/rtnetlink.h
+++ b/libc/kernel/uapi/linux/rtnetlink.h
@@ -444,9 +444,11 @@
   TCA_HW_OFFLOAD,
   TCA_INGRESS_BLOCK,
   TCA_EGRESS_BLOCK,
+  TCA_DUMP_FLAGS,
   __TCA_MAX
 };
 #define TCA_MAX (__TCA_MAX - 1)
+#define TCA_DUMP_FLAGS_TERSE (1 << 0)
 #define TCA_RTA(r) ((struct rtattr *) (((char *) (r)) + NLMSG_ALIGN(sizeof(struct tcmsg))))
 #define TCA_PAYLOAD(n) NLMSG_PAYLOAD(n, sizeof(struct tcmsg))
 struct nduseroptmsg {
diff --git a/libc/kernel/uapi/linux/spi/spidev.h b/libc/kernel/uapi/linux/spi/spidev.h
index 343285b..dede0f0 100644
--- a/libc/kernel/uapi/linux/spi/spidev.h
+++ b/libc/kernel/uapi/linux/spi/spidev.h
@@ -36,6 +36,10 @@
 #define SPI_TX_QUAD 0x200
 #define SPI_RX_DUAL 0x400
 #define SPI_RX_QUAD 0x800
+#define SPI_CS_WORD 0x1000
+#define SPI_TX_OCTAL 0x2000
+#define SPI_RX_OCTAL 0x4000
+#define SPI_3WIRE_HIZ 0x8000
 #define SPI_IOC_MAGIC 'k'
 struct spi_ioc_transfer {
   __u64 tx_buf;
diff --git a/libc/kernel/uapi/linux/stat.h b/libc/kernel/uapi/linux/stat.h
index 98fdbea..919763e 100644
--- a/libc/kernel/uapi/linux/stat.h
+++ b/libc/kernel/uapi/linux/stat.h
@@ -77,7 +77,9 @@
   __u32 stx_rdev_minor;
   __u32 stx_dev_major;
   __u32 stx_dev_minor;
-  __u64 __spare2[14];
+  __u64 stx_mnt_id;
+  __u64 __spare2;
+  __u64 __spare3[12];
 };
 #define STATX_TYPE 0x00000001U
 #define STATX_MODE 0x00000002U
@@ -92,13 +94,16 @@
 #define STATX_BLOCKS 0x00000400U
 #define STATX_BASIC_STATS 0x000007ffU
 #define STATX_BTIME 0x00000800U
-#define STATX_ALL 0x00000fffU
+#define STATX_MNT_ID 0x00001000U
 #define STATX__RESERVED 0x80000000U
+#define STATX_ALL 0x00000fffU
 #define STATX_ATTR_COMPRESSED 0x00000004
 #define STATX_ATTR_IMMUTABLE 0x00000010
 #define STATX_ATTR_APPEND 0x00000020
 #define STATX_ATTR_NODUMP 0x00000040
 #define STATX_ATTR_ENCRYPTED 0x00000800
 #define STATX_ATTR_AUTOMOUNT 0x00001000
+#define STATX_ATTR_MOUNT_ROOT 0x00002000
 #define STATX_ATTR_VERITY 0x00100000
+#define STATX_ATTR_DAX 0x00002000
 #endif
diff --git a/libc/kernel/uapi/linux/tc_act/tc_gate.h b/libc/kernel/uapi/linux/tc_act/tc_gate.h
new file mode 100644
index 0000000..f0a6412
--- /dev/null
+++ b/libc/kernel/uapi/linux/tc_act/tc_gate.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ***   To edit the content of this header, modify the corresponding
+ ***   source file (e.g. under external/kernel-headers/original/) then
+ ***   run bionic/libc/kernel/tools/update_all.py
+ ***
+ ***   Any manual change here will be lost the next time this script will
+ ***   be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef __LINUX_TC_GATE_H
+#define __LINUX_TC_GATE_H
+#include <linux/pkt_cls.h>
+struct tc_gate {
+  tc_gen;
+};
+enum {
+  TCA_GATE_ENTRY_UNSPEC,
+  TCA_GATE_ENTRY_INDEX,
+  TCA_GATE_ENTRY_GATE,
+  TCA_GATE_ENTRY_INTERVAL,
+  TCA_GATE_ENTRY_IPV,
+  TCA_GATE_ENTRY_MAX_OCTETS,
+  __TCA_GATE_ENTRY_MAX,
+};
+#define TCA_GATE_ENTRY_MAX (__TCA_GATE_ENTRY_MAX - 1)
+enum {
+  TCA_GATE_ONE_ENTRY_UNSPEC,
+  TCA_GATE_ONE_ENTRY,
+  __TCA_GATE_ONE_ENTRY_MAX,
+};
+#define TCA_GATE_ONE_ENTRY_MAX (__TCA_GATE_ONE_ENTRY_MAX - 1)
+enum {
+  TCA_GATE_UNSPEC,
+  TCA_GATE_TM,
+  TCA_GATE_PARMS,
+  TCA_GATE_PAD,
+  TCA_GATE_PRIORITY,
+  TCA_GATE_ENTRY_LIST,
+  TCA_GATE_BASE_TIME,
+  TCA_GATE_CYCLE_TIME,
+  TCA_GATE_CYCLE_TIME_EXT,
+  TCA_GATE_FLAGS,
+  TCA_GATE_CLOCKID,
+  __TCA_GATE_MAX,
+};
+#define TCA_GATE_MAX (__TCA_GATE_MAX - 1)
+#endif
diff --git a/libc/kernel/uapi/linux/tee.h b/libc/kernel/uapi/linux/tee.h
index 9ddcf19..f23e000 100644
--- a/libc/kernel/uapi/linux/tee.h
+++ b/libc/kernel/uapi/linux/tee.h
@@ -63,6 +63,9 @@
 #define TEE_IOCTL_LOGIN_APPLICATION 4
 #define TEE_IOCTL_LOGIN_USER_APPLICATION 5
 #define TEE_IOCTL_LOGIN_GROUP_APPLICATION 6
+#define TEE_IOCTL_LOGIN_REE_KERNEL_MIN 0x80000000
+#define TEE_IOCTL_LOGIN_REE_KERNEL_MAX 0xBFFFFFFF
+#define TEE_IOCTL_LOGIN_REE_KERNEL 0x80000000
 struct tee_ioctl_param {
   __u64 attr;
   __u64 a;
diff --git a/libc/kernel/uapi/linux/v4l2-controls.h b/libc/kernel/uapi/linux/v4l2-controls.h
index e38620d..d060744 100644
--- a/libc/kernel/uapi/linux/v4l2-controls.h
+++ b/libc/kernel/uapi/linux/v4l2-controls.h
@@ -781,6 +781,11 @@
 };
 #define V4L2_CID_PAN_SPEED (V4L2_CID_CAMERA_CLASS_BASE + 32)
 #define V4L2_CID_TILT_SPEED (V4L2_CID_CAMERA_CLASS_BASE + 33)
+#define V4L2_CID_CAMERA_ORIENTATION (V4L2_CID_CAMERA_CLASS_BASE + 34)
+#define V4L2_CAMERA_ORIENTATION_FRONT 0
+#define V4L2_CAMERA_ORIENTATION_BACK 1
+#define V4L2_CAMERA_ORIENTATION_EXTERNAL 2
+#define V4L2_CID_CAMERA_SENSOR_ROTATION (V4L2_CID_CAMERA_CLASS_BASE + 35)
 #define V4L2_CID_FM_TX_CLASS_BASE (V4L2_CTRL_CLASS_FM_TX | 0x900)
 #define V4L2_CID_FM_TX_CLASS (V4L2_CTRL_CLASS_FM_TX | 1)
 #define V4L2_CID_RDS_TX_DEVIATION (V4L2_CID_FM_TX_CLASS_BASE + 1)
diff --git a/libc/kernel/uapi/linux/v4l2-subdev.h b/libc/kernel/uapi/linux/v4l2-subdev.h
index 303d167..da81738 100644
--- a/libc/kernel/uapi/linux/v4l2-subdev.h
+++ b/libc/kernel/uapi/linux/v4l2-subdev.h
@@ -79,7 +79,14 @@
   struct v4l2_rect r;
   __u32 reserved[8];
 };
+struct v4l2_subdev_capability {
+  __u32 version;
+  __u32 capabilities;
+  __u32 reserved[14];
+};
+#define V4L2_SUBDEV_CAP_RO_SUBDEV BIT(0)
 #define v4l2_subdev_edid v4l2_edid
+#define VIDIOC_SUBDEV_QUERYCAP _IOR('V', 0, struct v4l2_subdev_capability)
 #define VIDIOC_SUBDEV_G_FMT _IOWR('V', 4, struct v4l2_subdev_format)
 #define VIDIOC_SUBDEV_S_FMT _IOWR('V', 5, struct v4l2_subdev_format)
 #define VIDIOC_SUBDEV_G_FRAME_INTERVAL _IOWR('V', 21, struct v4l2_subdev_frame_interval)
diff --git a/libc/kernel/uapi/linux/vboxguest.h b/libc/kernel/uapi/linux/vboxguest.h
index 2eb80ef..d9dfa9a 100644
--- a/libc/kernel/uapi/linux/vboxguest.h
+++ b/libc/kernel/uapi/linux/vboxguest.h
@@ -53,7 +53,7 @@
 };
 #define VBG_IOCTL_DRIVER_VERSION_INFO _IOWR('V', 0, struct vbg_ioctl_driver_version_info)
 #define VBG_IOCTL_VMMDEV_REQUEST(s) _IOC(_IOC_READ | _IOC_WRITE, 'V', 2, s)
-#define VBG_IOCTL_VMMDEV_REQUEST_BIG _IOC(_IOC_READ | _IOC_WRITE, 'V', 3, 0)
+#define VBG_IOCTL_VMMDEV_REQUEST_BIG _IO('V', 3)
 struct vbg_ioctl_hgcm_connect {
   struct vbg_ioctl_hdr hdr;
   union {
@@ -99,7 +99,7 @@
     } in;
   } u;
 };
-#define VBG_IOCTL_LOG(s) _IOC(_IOC_READ | _IOC_WRITE, 'V', 9, s)
+#define VBG_IOCTL_LOG(s) _IO('V', 9)
 struct vbg_ioctl_wait_for_events {
   struct vbg_ioctl_hdr hdr;
   union {
diff --git a/libc/kernel/uapi/linux/version.h b/libc/kernel/uapi/linux/version.h
index 5da4041..05b1551 100644
--- a/libc/kernel/uapi/linux/version.h
+++ b/libc/kernel/uapi/linux/version.h
@@ -16,5 +16,5 @@
  ***
  ****************************************************************************
  ****************************************************************************/
-#define LINUX_VERSION_CODE 329472
+#define LINUX_VERSION_CODE 329728
 #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
diff --git a/libc/kernel/uapi/linux/vfio.h b/libc/kernel/uapi/linux/vfio.h
index 88f8168..e0bba31 100644
--- a/libc/kernel/uapi/linux/vfio.h
+++ b/libc/kernel/uapi/linux/vfio.h
@@ -101,6 +101,7 @@
 #define VFIO_REGION_TYPE_PCI_VENDOR_MASK (0xffff)
 #define VFIO_REGION_TYPE_GFX (1)
 #define VFIO_REGION_TYPE_CCW (2)
+#define VFIO_REGION_TYPE_MIGRATION (3)
 #define VFIO_REGION_SUBTYPE_INTEL_IGD_OPREGION (1)
 #define VFIO_REGION_SUBTYPE_INTEL_IGD_HOST_CFG (2)
 #define VFIO_REGION_SUBTYPE_INTEL_IGD_LPC_CFG (3)
@@ -118,6 +119,24 @@
 #define VFIO_DEVICE_GFX_LINK_STATE_DOWN 2
 };
 #define VFIO_REGION_SUBTYPE_CCW_ASYNC_CMD (1)
+#define VFIO_REGION_SUBTYPE_CCW_SCHIB (2)
+#define VFIO_REGION_SUBTYPE_CCW_CRW (3)
+#define VFIO_REGION_SUBTYPE_MIGRATION (1)
+struct vfio_device_migration_info {
+  __u32 device_state;
+#define VFIO_DEVICE_STATE_STOP (0)
+#define VFIO_DEVICE_STATE_RUNNING (1 << 0)
+#define VFIO_DEVICE_STATE_SAVING (1 << 1)
+#define VFIO_DEVICE_STATE_RESUMING (1 << 2)
+#define VFIO_DEVICE_STATE_MASK (VFIO_DEVICE_STATE_RUNNING | VFIO_DEVICE_STATE_SAVING | VFIO_DEVICE_STATE_RESUMING)
+#define VFIO_DEVICE_STATE_VALID(state) (state & VFIO_DEVICE_STATE_RESUMING ? (state & VFIO_DEVICE_STATE_MASK) == VFIO_DEVICE_STATE_RESUMING : 1)
+#define VFIO_DEVICE_STATE_IS_ERROR(state) ((state & VFIO_DEVICE_STATE_MASK) == (VFIO_DEVICE_STATE_SAVING | VFIO_DEVICE_STATE_RESUMING))
+#define VFIO_DEVICE_STATE_SET_ERROR(state) ((state & ~VFIO_DEVICE_STATE_MASK) | VFIO_DEVICE_SATE_SAVING | VFIO_DEVICE_STATE_RESUMING)
+  __u32 reserved;
+  __u64 pending_bytes;
+  __u64 data_offset;
+  __u64 data_size;
+};
 #define VFIO_REGION_INFO_CAP_MSIX_MAPPABLE 3
 #define VFIO_REGION_INFO_CAP_NVLINK2_SSATGT 4
 struct vfio_region_info_cap_nvlink2_ssatgt {
@@ -185,6 +204,7 @@
 };
 enum {
   VFIO_CCW_IO_IRQ_INDEX,
+  VFIO_CCW_CRW_IRQ_INDEX,
   VFIO_CCW_NUM_IRQS
 };
 struct vfio_pci_dependent_device {
@@ -274,6 +294,13 @@
   __u32 reserved;
   struct vfio_iova_range iova_ranges[];
 };
+#define VFIO_IOMMU_TYPE1_INFO_CAP_MIGRATION 2
+struct vfio_iommu_type1_info_cap_migration {
+  struct vfio_info_cap_header header;
+  __u32 flags;
+  __u64 pgsize_bitmap;
+  __u64 max_dirty_bitmap_size;
+};
 #define VFIO_IOMMU_GET_INFO _IO(VFIO_TYPE, VFIO_BASE + 12)
 struct vfio_iommu_type1_dma_map {
   __u32 argsz;
@@ -285,15 +312,36 @@
   __u64 size;
 };
 #define VFIO_IOMMU_MAP_DMA _IO(VFIO_TYPE, VFIO_BASE + 13)
+struct vfio_bitmap {
+  __u64 pgsize;
+  __u64 size;
+  __u64 __user * data;
+};
 struct vfio_iommu_type1_dma_unmap {
   __u32 argsz;
   __u32 flags;
+#define VFIO_DMA_UNMAP_FLAG_GET_DIRTY_BITMAP (1 << 0)
   __u64 iova;
   __u64 size;
+  __u8 data[];
 };
 #define VFIO_IOMMU_UNMAP_DMA _IO(VFIO_TYPE, VFIO_BASE + 14)
 #define VFIO_IOMMU_ENABLE _IO(VFIO_TYPE, VFIO_BASE + 15)
 #define VFIO_IOMMU_DISABLE _IO(VFIO_TYPE, VFIO_BASE + 16)
+struct vfio_iommu_type1_dirty_bitmap {
+  __u32 argsz;
+  __u32 flags;
+#define VFIO_IOMMU_DIRTY_PAGES_FLAG_START (1 << 0)
+#define VFIO_IOMMU_DIRTY_PAGES_FLAG_STOP (1 << 1)
+#define VFIO_IOMMU_DIRTY_PAGES_FLAG_GET_BITMAP (1 << 2)
+  __u8 data[];
+};
+struct vfio_iommu_type1_dirty_bitmap_get {
+  __u64 iova;
+  __u64 size;
+  struct vfio_bitmap bitmap;
+};
+#define VFIO_IOMMU_DIRTY_PAGES _IO(VFIO_TYPE, VFIO_BASE + 17)
 struct vfio_iommu_spapr_tce_ddw_info {
   __u64 pgsizes;
   __u32 max_dynamic_windows_supported;
diff --git a/libc/kernel/uapi/linux/vfio_ccw.h b/libc/kernel/uapi/linux/vfio_ccw.h
index 6ed6830..a6defc5 100644
--- a/libc/kernel/uapi/linux/vfio_ccw.h
+++ b/libc/kernel/uapi/linux/vfio_ccw.h
@@ -34,4 +34,12 @@
   __u32 command;
   __u32 ret_code;
 } __packed;
+struct ccw_schib_region {
+#define SCHIB_AREA_SIZE 52
+  __u8 schib_area[SCHIB_AREA_SIZE];
+} __packed;
+struct ccw_crw_region {
+  __u32 crw;
+  __u32 pad;
+} __packed;
 #endif
diff --git a/libc/kernel/uapi/linux/vhost.h b/libc/kernel/uapi/linux/vhost.h
index 4546023..0349fa7 100644
--- a/libc/kernel/uapi/linux/vhost.h
+++ b/libc/kernel/uapi/linux/vhost.h
@@ -21,6 +21,7 @@
 #include <linux/vhost_types.h>
 #include <linux/types.h>
 #include <linux/ioctl.h>
+#define VHOST_FILE_UNBIND - 1
 #define VHOST_VIRTIO 0xAF
 #define VHOST_GET_FEATURES _IOR(VHOST_VIRTIO, 0x00, __u64)
 #define VHOST_SET_FEATURES _IOW(VHOST_VIRTIO, 0x00, __u64)
@@ -60,4 +61,5 @@
 #define VHOST_VDPA_SET_CONFIG _IOW(VHOST_VIRTIO, 0x74, struct vhost_vdpa_config)
 #define VHOST_VDPA_SET_VRING_ENABLE _IOW(VHOST_VIRTIO, 0x75, struct vhost_vring_state)
 #define VHOST_VDPA_GET_VRING_NUM _IOR(VHOST_VIRTIO, 0x76, __u16)
+#define VHOST_VDPA_SET_CONFIG_CALL _IOW(VHOST_VIRTIO, 0x77, int)
 #endif
diff --git a/libc/kernel/uapi/linux/videodev2.h b/libc/kernel/uapi/linux/videodev2.h
index 1209fb7..d8c7549 100644
--- a/libc/kernel/uapi/linux/videodev2.h
+++ b/libc/kernel/uapi/linux/videodev2.h
@@ -188,6 +188,7 @@
 #define V4L2_CAP_STREAMING 0x04000000
 #define V4L2_CAP_META_OUTPUT 0x08000000
 #define V4L2_CAP_TOUCH 0x10000000
+#define V4L2_CAP_IO_MC 0x20000000
 #define V4L2_CAP_DEVICE_CAPS 0x80000000
 struct v4l2_pix_format {
   __u32 width;
@@ -420,7 +421,8 @@
   __u32 flags;
   __u8 description[32];
   __u32 pixelformat;
-  __u32 reserved[4];
+  __u32 mbus_code;
+  __u32 reserved[3];
 };
 #define V4L2_FMT_FLAG_COMPRESSED 0x0001
 #define V4L2_FMT_FLAG_EMULATED 0x0002
diff --git a/libc/kernel/uapi/linux/virtio_ids.h b/libc/kernel/uapi/linux/virtio_ids.h
index 9fd6b65..7b67d76 100644
--- a/libc/kernel/uapi/linux/virtio_ids.h
+++ b/libc/kernel/uapi/linux/virtio_ids.h
@@ -33,6 +33,7 @@
 #define VIRTIO_ID_VSOCK 19
 #define VIRTIO_ID_CRYPTO 20
 #define VIRTIO_ID_IOMMU 23
+#define VIRTIO_ID_MEM 24
 #define VIRTIO_ID_FS 26
 #define VIRTIO_ID_PMEM 27
 #define VIRTIO_ID_MAC80211_HWSIM 29
diff --git a/libc/kernel/uapi/linux/virtio_mem.h b/libc/kernel/uapi/linux/virtio_mem.h
new file mode 100644
index 0000000..854a2fe
--- /dev/null
+++ b/libc/kernel/uapi/linux/virtio_mem.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ***   To edit the content of this header, modify the corresponding
+ ***   source file (e.g. under external/kernel-headers/original/) then
+ ***   run bionic/libc/kernel/tools/update_all.py
+ ***
+ ***   Any manual change here will be lost the next time this script will
+ ***   be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _LINUX_VIRTIO_MEM_H
+#define _LINUX_VIRTIO_MEM_H
+#include <linux/types.h>
+#include <linux/virtio_types.h>
+#include <linux/virtio_ids.h>
+#include <linux/virtio_config.h>
+#define VIRTIO_MEM_F_ACPI_PXM 0
+#define VIRTIO_MEM_REQ_PLUG 0
+#define VIRTIO_MEM_REQ_UNPLUG 1
+#define VIRTIO_MEM_REQ_UNPLUG_ALL 2
+#define VIRTIO_MEM_REQ_STATE 3
+struct virtio_mem_req_plug {
+  __virtio64 addr;
+  __virtio16 nb_blocks;
+  __virtio16 padding[3];
+};
+struct virtio_mem_req_unplug {
+  __virtio64 addr;
+  __virtio16 nb_blocks;
+  __virtio16 padding[3];
+};
+struct virtio_mem_req_state {
+  __virtio64 addr;
+  __virtio16 nb_blocks;
+  __virtio16 padding[3];
+};
+struct virtio_mem_req {
+  __virtio16 type;
+  __virtio16 padding[3];
+  union {
+    struct virtio_mem_req_plug plug;
+    struct virtio_mem_req_unplug unplug;
+    struct virtio_mem_req_state state;
+  } u;
+};
+#define VIRTIO_MEM_RESP_ACK 0
+#define VIRTIO_MEM_RESP_NACK 1
+#define VIRTIO_MEM_RESP_BUSY 2
+#define VIRTIO_MEM_RESP_ERROR 3
+#define VIRTIO_MEM_STATE_PLUGGED 0
+#define VIRTIO_MEM_STATE_UNPLUGGED 1
+#define VIRTIO_MEM_STATE_MIXED 2
+struct virtio_mem_resp_state {
+  __virtio16 state;
+};
+struct virtio_mem_resp {
+  __virtio16 type;
+  __virtio16 padding[3];
+  union {
+    struct virtio_mem_resp_state state;
+  } u;
+};
+struct virtio_mem_config {
+  __u64 block_size;
+  __u16 node_id;
+  __u8 padding[6];
+  __u64 addr;
+  __u64 region_size;
+  __u64 usable_region_size;
+  __u64 plugged_size;
+  __u64 requested_size;
+};
+#endif
diff --git a/libc/kernel/uapi/linux/virtio_ring.h b/libc/kernel/uapi/linux/virtio_ring.h
index ba75940..24cf671 100644
--- a/libc/kernel/uapi/linux/virtio_ring.h
+++ b/libc/kernel/uapi/linux/virtio_ring.h
@@ -34,6 +34,9 @@
 #define VRING_PACKED_EVENT_F_WRAP_CTR 15
 #define VIRTIO_RING_F_INDIRECT_DESC 28
 #define VIRTIO_RING_F_EVENT_IDX 29
+#define VRING_AVAIL_ALIGN_SIZE 2
+#define VRING_USED_ALIGN_SIZE 4
+#define VRING_DESC_ALIGN_SIZE 16
 struct vring_desc {
   __virtio64 addr;
   __virtio32 len;
@@ -49,22 +52,25 @@
   __virtio32 id;
   __virtio32 len;
 };
+typedef struct vring_used_elem __attribute__((aligned(VRING_USED_ALIGN_SIZE))) vring_used_elem_t;
 struct vring_used {
   __virtio16 flags;
   __virtio16 idx;
-  struct vring_used_elem ring[];
+  vring_used_elem_t ring[];
 };
+typedef struct vring_desc __attribute__((aligned(VRING_DESC_ALIGN_SIZE))) vring_desc_t;
+typedef struct vring_avail __attribute__((aligned(VRING_AVAIL_ALIGN_SIZE))) vring_avail_t;
+typedef struct vring_used __attribute__((aligned(VRING_USED_ALIGN_SIZE))) vring_used_t;
 struct vring {
   unsigned int num;
-  struct vring_desc * desc;
-  struct vring_avail * avail;
-  struct vring_used * used;
+  vring_desc_t * desc;
+  vring_avail_t * avail;
+  vring_used_t * used;
 };
-#define VRING_AVAIL_ALIGN_SIZE 2
-#define VRING_USED_ALIGN_SIZE 4
-#define VRING_DESC_ALIGN_SIZE 16
+#ifndef VIRTIO_RING_NO_LEGACY
 #define vring_used_event(vr) ((vr)->avail->ring[(vr)->num])
 #define vring_avail_event(vr) (* (__virtio16 *) & (vr)->used->ring[(vr)->num])
+#endif
 struct vring_packed_desc_event {
   __le16 off_wrap;
   __le16 flags;
diff --git a/libc/kernel/uapi/linux/watch_queue.h b/libc/kernel/uapi/linux/watch_queue.h
new file mode 100644
index 0000000..4c4fd01
--- /dev/null
+++ b/libc/kernel/uapi/linux/watch_queue.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ***   To edit the content of this header, modify the corresponding
+ ***   source file (e.g. under external/kernel-headers/original/) then
+ ***   run bionic/libc/kernel/tools/update_all.py
+ ***
+ ***   Any manual change here will be lost the next time this script will
+ ***   be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _UAPI_LINUX_WATCH_QUEUE_H
+#define _UAPI_LINUX_WATCH_QUEUE_H
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/ioctl.h>
+#define O_NOTIFICATION_PIPE O_EXCL
+#define IOC_WATCH_QUEUE_SET_SIZE _IO('W', 0x60)
+#define IOC_WATCH_QUEUE_SET_FILTER _IO('W', 0x61)
+enum watch_notification_type {
+  WATCH_TYPE_META = 0,
+  WATCH_TYPE_KEY_NOTIFY = 1,
+  WATCH_TYPE__NR = 2
+};
+enum watch_meta_notification_subtype {
+  WATCH_META_REMOVAL_NOTIFICATION = 0,
+  WATCH_META_LOSS_NOTIFICATION = 1,
+};
+struct watch_notification {
+  __u32 type : 24;
+  __u32 subtype : 8;
+  __u32 info;
+#define WATCH_INFO_LENGTH 0x0000007f
+#define WATCH_INFO_LENGTH__SHIFT 0
+#define WATCH_INFO_ID 0x0000ff00
+#define WATCH_INFO_ID__SHIFT 8
+#define WATCH_INFO_TYPE_INFO 0xffff0000
+#define WATCH_INFO_TYPE_INFO__SHIFT 16
+#define WATCH_INFO_FLAG_0 0x00010000
+#define WATCH_INFO_FLAG_1 0x00020000
+#define WATCH_INFO_FLAG_2 0x00040000
+#define WATCH_INFO_FLAG_3 0x00080000
+#define WATCH_INFO_FLAG_4 0x00100000
+#define WATCH_INFO_FLAG_5 0x00200000
+#define WATCH_INFO_FLAG_6 0x00400000
+#define WATCH_INFO_FLAG_7 0x00800000
+};
+struct watch_notification_type_filter {
+  __u32 type;
+  __u32 info_filter;
+  __u32 info_mask;
+  __u32 subtype_filter[8];
+};
+struct watch_notification_filter {
+  __u32 nr_filters;
+  __u32 __reserved;
+  struct watch_notification_type_filter filters[];
+};
+struct watch_notification_removal {
+  struct watch_notification watch;
+  __u64 id;
+};
+enum key_notification_subtype {
+  NOTIFY_KEY_INSTANTIATED = 0,
+  NOTIFY_KEY_UPDATED = 1,
+  NOTIFY_KEY_LINKED = 2,
+  NOTIFY_KEY_UNLINKED = 3,
+  NOTIFY_KEY_CLEARED = 4,
+  NOTIFY_KEY_REVOKED = 5,
+  NOTIFY_KEY_INVALIDATED = 6,
+  NOTIFY_KEY_SETATTR = 7,
+};
+struct key_notification {
+  struct watch_notification watch;
+  __u32 key_id;
+  __u32 aux;
+};
+#endif
diff --git a/libc/kernel/uapi/linux/xattr.h b/libc/kernel/uapi/linux/xattr.h
index 7c098f4..fd02159 100644
--- a/libc/kernel/uapi/linux/xattr.h
+++ b/libc/kernel/uapi/linux/xattr.h
@@ -30,6 +30,8 @@
 #define XATTR_MAC_OSX_PREFIX_LEN (sizeof(XATTR_MAC_OSX_PREFIX) - 1)
 #define XATTR_BTRFS_PREFIX "btrfs."
 #define XATTR_BTRFS_PREFIX_LEN (sizeof(XATTR_BTRFS_PREFIX) - 1)
+#define XATTR_HURD_PREFIX "gnu."
+#define XATTR_HURD_PREFIX_LEN (sizeof(XATTR_HURD_PREFIX) - 1)
 #define XATTR_SECURITY_PREFIX "security."
 #define XATTR_SECURITY_PREFIX_LEN (sizeof(XATTR_SECURITY_PREFIX) - 1)
 #define XATTR_SYSTEM_PREFIX "system."
diff --git a/libc/kernel/uapi/misc/habanalabs.h b/libc/kernel/uapi/misc/habanalabs.h
index 91849ec..3ae1722 100644
--- a/libc/kernel/uapi/misc/habanalabs.h
+++ b/libc/kernel/uapi/misc/habanalabs.h
@@ -21,6 +21,9 @@
 #include <linux/types.h>
 #include <linux/ioctl.h>
 #define GOYA_KMD_SRAM_RESERVED_SIZE_FROM_START 0x8000
+#define GAUDI_DRIVER_SRAM_RESERVED_SIZE_FROM_START 0x80
+#define GAUDI_FIRST_AVAILABLE_W_S_SYNC_OBJECT 48
+#define GAUDI_FIRST_AVAILABLE_W_S_MONITOR 24
 enum goya_queue_id {
   GOYA_QUEUE_ID_DMA_0 = 0,
   GOYA_QUEUE_ID_DMA_1 = 1,
@@ -39,6 +42,122 @@
   GOYA_QUEUE_ID_TPC7 = 14,
   GOYA_QUEUE_ID_SIZE
 };
+enum gaudi_queue_id {
+  GAUDI_QUEUE_ID_DMA_0_0 = 0,
+  GAUDI_QUEUE_ID_DMA_0_1 = 1,
+  GAUDI_QUEUE_ID_DMA_0_2 = 2,
+  GAUDI_QUEUE_ID_DMA_0_3 = 3,
+  GAUDI_QUEUE_ID_DMA_1_0 = 4,
+  GAUDI_QUEUE_ID_DMA_1_1 = 5,
+  GAUDI_QUEUE_ID_DMA_1_2 = 6,
+  GAUDI_QUEUE_ID_DMA_1_3 = 7,
+  GAUDI_QUEUE_ID_CPU_PQ = 8,
+  GAUDI_QUEUE_ID_DMA_2_0 = 9,
+  GAUDI_QUEUE_ID_DMA_2_1 = 10,
+  GAUDI_QUEUE_ID_DMA_2_2 = 11,
+  GAUDI_QUEUE_ID_DMA_2_3 = 12,
+  GAUDI_QUEUE_ID_DMA_3_0 = 13,
+  GAUDI_QUEUE_ID_DMA_3_1 = 14,
+  GAUDI_QUEUE_ID_DMA_3_2 = 15,
+  GAUDI_QUEUE_ID_DMA_3_3 = 16,
+  GAUDI_QUEUE_ID_DMA_4_0 = 17,
+  GAUDI_QUEUE_ID_DMA_4_1 = 18,
+  GAUDI_QUEUE_ID_DMA_4_2 = 19,
+  GAUDI_QUEUE_ID_DMA_4_3 = 20,
+  GAUDI_QUEUE_ID_DMA_5_0 = 21,
+  GAUDI_QUEUE_ID_DMA_5_1 = 22,
+  GAUDI_QUEUE_ID_DMA_5_2 = 23,
+  GAUDI_QUEUE_ID_DMA_5_3 = 24,
+  GAUDI_QUEUE_ID_DMA_6_0 = 25,
+  GAUDI_QUEUE_ID_DMA_6_1 = 26,
+  GAUDI_QUEUE_ID_DMA_6_2 = 27,
+  GAUDI_QUEUE_ID_DMA_6_3 = 28,
+  GAUDI_QUEUE_ID_DMA_7_0 = 29,
+  GAUDI_QUEUE_ID_DMA_7_1 = 30,
+  GAUDI_QUEUE_ID_DMA_7_2 = 31,
+  GAUDI_QUEUE_ID_DMA_7_3 = 32,
+  GAUDI_QUEUE_ID_MME_0_0 = 33,
+  GAUDI_QUEUE_ID_MME_0_1 = 34,
+  GAUDI_QUEUE_ID_MME_0_2 = 35,
+  GAUDI_QUEUE_ID_MME_0_3 = 36,
+  GAUDI_QUEUE_ID_MME_1_0 = 37,
+  GAUDI_QUEUE_ID_MME_1_1 = 38,
+  GAUDI_QUEUE_ID_MME_1_2 = 39,
+  GAUDI_QUEUE_ID_MME_1_3 = 40,
+  GAUDI_QUEUE_ID_TPC_0_0 = 41,
+  GAUDI_QUEUE_ID_TPC_0_1 = 42,
+  GAUDI_QUEUE_ID_TPC_0_2 = 43,
+  GAUDI_QUEUE_ID_TPC_0_3 = 44,
+  GAUDI_QUEUE_ID_TPC_1_0 = 45,
+  GAUDI_QUEUE_ID_TPC_1_1 = 46,
+  GAUDI_QUEUE_ID_TPC_1_2 = 47,
+  GAUDI_QUEUE_ID_TPC_1_3 = 48,
+  GAUDI_QUEUE_ID_TPC_2_0 = 49,
+  GAUDI_QUEUE_ID_TPC_2_1 = 50,
+  GAUDI_QUEUE_ID_TPC_2_2 = 51,
+  GAUDI_QUEUE_ID_TPC_2_3 = 52,
+  GAUDI_QUEUE_ID_TPC_3_0 = 53,
+  GAUDI_QUEUE_ID_TPC_3_1 = 54,
+  GAUDI_QUEUE_ID_TPC_3_2 = 55,
+  GAUDI_QUEUE_ID_TPC_3_3 = 56,
+  GAUDI_QUEUE_ID_TPC_4_0 = 57,
+  GAUDI_QUEUE_ID_TPC_4_1 = 58,
+  GAUDI_QUEUE_ID_TPC_4_2 = 59,
+  GAUDI_QUEUE_ID_TPC_4_3 = 60,
+  GAUDI_QUEUE_ID_TPC_5_0 = 61,
+  GAUDI_QUEUE_ID_TPC_5_1 = 62,
+  GAUDI_QUEUE_ID_TPC_5_2 = 63,
+  GAUDI_QUEUE_ID_TPC_5_3 = 64,
+  GAUDI_QUEUE_ID_TPC_6_0 = 65,
+  GAUDI_QUEUE_ID_TPC_6_1 = 66,
+  GAUDI_QUEUE_ID_TPC_6_2 = 67,
+  GAUDI_QUEUE_ID_TPC_6_3 = 68,
+  GAUDI_QUEUE_ID_TPC_7_0 = 69,
+  GAUDI_QUEUE_ID_TPC_7_1 = 70,
+  GAUDI_QUEUE_ID_TPC_7_2 = 71,
+  GAUDI_QUEUE_ID_TPC_7_3 = 72,
+  GAUDI_QUEUE_ID_NIC_0_0 = 73,
+  GAUDI_QUEUE_ID_NIC_0_1 = 74,
+  GAUDI_QUEUE_ID_NIC_0_2 = 75,
+  GAUDI_QUEUE_ID_NIC_0_3 = 76,
+  GAUDI_QUEUE_ID_NIC_1_0 = 77,
+  GAUDI_QUEUE_ID_NIC_1_1 = 78,
+  GAUDI_QUEUE_ID_NIC_1_2 = 79,
+  GAUDI_QUEUE_ID_NIC_1_3 = 80,
+  GAUDI_QUEUE_ID_NIC_2_0 = 81,
+  GAUDI_QUEUE_ID_NIC_2_1 = 82,
+  GAUDI_QUEUE_ID_NIC_2_2 = 83,
+  GAUDI_QUEUE_ID_NIC_2_3 = 84,
+  GAUDI_QUEUE_ID_NIC_3_0 = 85,
+  GAUDI_QUEUE_ID_NIC_3_1 = 86,
+  GAUDI_QUEUE_ID_NIC_3_2 = 87,
+  GAUDI_QUEUE_ID_NIC_3_3 = 88,
+  GAUDI_QUEUE_ID_NIC_4_0 = 89,
+  GAUDI_QUEUE_ID_NIC_4_1 = 90,
+  GAUDI_QUEUE_ID_NIC_4_2 = 91,
+  GAUDI_QUEUE_ID_NIC_4_3 = 92,
+  GAUDI_QUEUE_ID_NIC_5_0 = 93,
+  GAUDI_QUEUE_ID_NIC_5_1 = 94,
+  GAUDI_QUEUE_ID_NIC_5_2 = 95,
+  GAUDI_QUEUE_ID_NIC_5_3 = 96,
+  GAUDI_QUEUE_ID_NIC_6_0 = 97,
+  GAUDI_QUEUE_ID_NIC_6_1 = 98,
+  GAUDI_QUEUE_ID_NIC_6_2 = 99,
+  GAUDI_QUEUE_ID_NIC_6_3 = 100,
+  GAUDI_QUEUE_ID_NIC_7_0 = 101,
+  GAUDI_QUEUE_ID_NIC_7_1 = 102,
+  GAUDI_QUEUE_ID_NIC_7_2 = 103,
+  GAUDI_QUEUE_ID_NIC_7_3 = 104,
+  GAUDI_QUEUE_ID_NIC_8_0 = 105,
+  GAUDI_QUEUE_ID_NIC_8_1 = 106,
+  GAUDI_QUEUE_ID_NIC_8_2 = 107,
+  GAUDI_QUEUE_ID_NIC_8_3 = 108,
+  GAUDI_QUEUE_ID_NIC_9_0 = 109,
+  GAUDI_QUEUE_ID_NIC_9_1 = 110,
+  GAUDI_QUEUE_ID_NIC_9_2 = 111,
+  GAUDI_QUEUE_ID_NIC_9_3 = 112,
+  GAUDI_QUEUE_ID_SIZE
+};
 enum goya_engine_id {
   GOYA_ENGINE_ID_DMA_0 = 0,
   GOYA_ENGINE_ID_DMA_1,
@@ -56,6 +175,39 @@
   GOYA_ENGINE_ID_TPC_7,
   GOYA_ENGINE_ID_SIZE
 };
+enum gaudi_engine_id {
+  GAUDI_ENGINE_ID_DMA_0 = 0,
+  GAUDI_ENGINE_ID_DMA_1,
+  GAUDI_ENGINE_ID_DMA_2,
+  GAUDI_ENGINE_ID_DMA_3,
+  GAUDI_ENGINE_ID_DMA_4,
+  GAUDI_ENGINE_ID_DMA_5,
+  GAUDI_ENGINE_ID_DMA_6,
+  GAUDI_ENGINE_ID_DMA_7,
+  GAUDI_ENGINE_ID_MME_0,
+  GAUDI_ENGINE_ID_MME_1,
+  GAUDI_ENGINE_ID_MME_2,
+  GAUDI_ENGINE_ID_MME_3,
+  GAUDI_ENGINE_ID_TPC_0,
+  GAUDI_ENGINE_ID_TPC_1,
+  GAUDI_ENGINE_ID_TPC_2,
+  GAUDI_ENGINE_ID_TPC_3,
+  GAUDI_ENGINE_ID_TPC_4,
+  GAUDI_ENGINE_ID_TPC_5,
+  GAUDI_ENGINE_ID_TPC_6,
+  GAUDI_ENGINE_ID_TPC_7,
+  GAUDI_ENGINE_ID_NIC_0,
+  GAUDI_ENGINE_ID_NIC_1,
+  GAUDI_ENGINE_ID_NIC_2,
+  GAUDI_ENGINE_ID_NIC_3,
+  GAUDI_ENGINE_ID_NIC_4,
+  GAUDI_ENGINE_ID_NIC_5,
+  GAUDI_ENGINE_ID_NIC_6,
+  GAUDI_ENGINE_ID_NIC_7,
+  GAUDI_ENGINE_ID_NIC_8,
+  GAUDI_ENGINE_ID_NIC_9,
+  GAUDI_ENGINE_ID_SIZE
+};
 enum hl_device_status {
   HL_DEVICE_STATUS_OPERATIONAL,
   HL_DEVICE_STATUS_IN_RESET,
@@ -70,6 +222,7 @@
 #define HL_INFO_HW_EVENTS_AGGREGATE 7
 #define HL_INFO_CLK_RATE 8
 #define HL_INFO_RESET_COUNT 9
+#define HL_INFO_TIME_SYNC 10
 #define HL_INFO_VERSION_MAX_LEN 128
 #define HL_INFO_CARD_NAME_MAX_LEN 16
 struct hl_info_hw_ip_info {
@@ -79,7 +232,8 @@
   __u32 sram_size;
   __u32 num_of_events;
   __u32 device_id;
-  __u32 reserved[3];
+  __u32 module_id;
+  __u32 reserved[2];
   __u32 armcp_cpld_version;
   __u32 psoc_pci_pll_nr;
   __u32 psoc_pci_pll_nf;
@@ -115,6 +269,10 @@
   __u32 hard_reset_cnt;
   __u32 soft_reset_cnt;
 };
+struct hl_info_time_sync {
+  __u64 device_time;
+  __u64 host_time;
+};
 struct hl_info_args {
   __u64 return_pointer;
   __u32 return_size;
@@ -127,7 +285,7 @@
 };
 #define HL_CB_OP_CREATE 0
 #define HL_CB_OP_DESTROY 1
-#define HL_MAX_CB_SIZE 0x200000
+#define HL_MAX_CB_SIZE (0x200000 - 32)
 struct hl_cb_in {
   __u64 cb_handle;
   __u32 op;
@@ -143,13 +301,21 @@
   struct hl_cb_out out;
 };
 struct hl_cs_chunk {
-  __u64 cb_handle;
+  union {
+    __u64 cb_handle;
+    __u64 signal_seq_arr;
+  };
   __u32 queue_index;
-  __u32 cb_size;
+  union {
+    __u32 cb_size;
+    __u32 num_signal_seq_arr;
+  };
   __u32 cs_chunk_flags;
   __u32 pad[11];
 };
 #define HL_CS_FLAGS_FORCE_RESTORE 0x1
+#define HL_CS_FLAGS_SIGNAL 0x2
+#define HL_CS_FLAGS_WAIT 0x4
 #define HL_CS_STATUS_SUCCESS 0
 #define HL_MAX_JOBS_PER_CS 512
 struct hl_cs_in {
diff --git a/libc/kernel/uapi/mtd/mtd-abi.h b/libc/kernel/uapi/mtd/mtd-abi.h
index e1e0d59..680ac1e 100644
--- a/libc/kernel/uapi/mtd/mtd-abi.h
+++ b/libc/kernel/uapi/mtd/mtd-abi.h
@@ -64,6 +64,7 @@
 #define MTD_BIT_WRITEABLE 0x800
 #define MTD_NO_ERASE 0x1000
 #define MTD_POWERUP_LOCK 0x2000
+#define MTD_SLC_ON_MLC_EMULATION 0x4000
 #define MTD_CAP_ROM 0
 #define MTD_CAP_RAM (MTD_WRITEABLE | MTD_BIT_WRITEABLE | MTD_NO_ERASE)
 #define MTD_CAP_NORFLASH (MTD_WRITEABLE | MTD_BIT_WRITEABLE)
diff --git a/libc/kernel/uapi/rdma/hfi/hfi1_user.h b/libc/kernel/uapi/rdma/hfi/hfi1_user.h
index e74d837..3352907 100644
--- a/libc/kernel/uapi/rdma/hfi/hfi1_user.h
+++ b/libc/kernel/uapi/rdma/hfi/hfi1_user.h
@@ -42,6 +42,7 @@
 #define HFI1_CAP_OPFN (1UL << 16)
 #define HFI1_CAP_SDMA_HEAD_CHECK (1UL << 17)
 #define HFI1_CAP_EARLY_CREDIT_RETURN (1UL << 18)
+#define HFI1_CAP_AIP (1UL << 19)
 #define HFI1_RCVHDR_ENTSIZE_2 (1UL << 0)
 #define HFI1_RCVHDR_ENTSIZE_16 (1UL << 1)
 #define HFI1_RCVDHR_ENTSIZE_32 (1UL << 2)
diff --git a/libc/kernel/uapi/rdma/ib_user_ioctl_cmds.h b/libc/kernel/uapi/rdma/ib_user_ioctl_cmds.h
index 3933841..e38bd93 100644
--- a/libc/kernel/uapi/rdma/ib_user_ioctl_cmds.h
+++ b/libc/kernel/uapi/rdma/ib_user_ioctl_cmds.h
@@ -72,6 +72,7 @@
   UVERBS_ATTR_CREATE_CQ_COMP_VECTOR,
   UVERBS_ATTR_CREATE_CQ_FLAGS,
   UVERBS_ATTR_CREATE_CQ_RESP_CQE,
+  UVERBS_ATTR_CREATE_CQ_EVENT_FD,
 };
 enum uverbs_attrs_destroy_cq_cmd_attr_ids {
   UVERBS_ATTR_DESTROY_CQ_HANDLE,
@@ -91,10 +92,81 @@
 enum uverbs_attrs_destroy_flow_action_esp {
   UVERBS_ATTR_DESTROY_FLOW_ACTION_HANDLE,
 };
+enum uverbs_attrs_create_qp_cmd_attr_ids {
+  UVERBS_ATTR_CREATE_QP_HANDLE,
+  UVERBS_ATTR_CREATE_QP_XRCD_HANDLE,
+  UVERBS_ATTR_CREATE_QP_PD_HANDLE,
+  UVERBS_ATTR_CREATE_QP_SRQ_HANDLE,
+  UVERBS_ATTR_CREATE_QP_SEND_CQ_HANDLE,
+  UVERBS_ATTR_CREATE_QP_RECV_CQ_HANDLE,
+  UVERBS_ATTR_CREATE_QP_IND_TABLE_HANDLE,
+  UVERBS_ATTR_CREATE_QP_USER_HANDLE,
+  UVERBS_ATTR_CREATE_QP_CAP,
+  UVERBS_ATTR_CREATE_QP_TYPE,
+  UVERBS_ATTR_CREATE_QP_FLAGS,
+  UVERBS_ATTR_CREATE_QP_SOURCE_QPN,
+  UVERBS_ATTR_CREATE_QP_EVENT_FD,
+  UVERBS_ATTR_CREATE_QP_RESP_CAP,
+  UVERBS_ATTR_CREATE_QP_RESP_QP_NUM,
+};
+enum uverbs_attrs_destroy_qp_cmd_attr_ids {
+  UVERBS_ATTR_DESTROY_QP_HANDLE,
+  UVERBS_ATTR_DESTROY_QP_RESP,
+};
+enum uverbs_methods_qp {
+  UVERBS_METHOD_QP_CREATE,
+  UVERBS_METHOD_QP_DESTROY,
+};
+enum uverbs_attrs_create_srq_cmd_attr_ids {
+  UVERBS_ATTR_CREATE_SRQ_HANDLE,
+  UVERBS_ATTR_CREATE_SRQ_PD_HANDLE,
+  UVERBS_ATTR_CREATE_SRQ_XRCD_HANDLE,
+  UVERBS_ATTR_CREATE_SRQ_CQ_HANDLE,
+  UVERBS_ATTR_CREATE_SRQ_USER_HANDLE,
+  UVERBS_ATTR_CREATE_SRQ_MAX_WR,
+  UVERBS_ATTR_CREATE_SRQ_MAX_SGE,
+  UVERBS_ATTR_CREATE_SRQ_LIMIT,
+  UVERBS_ATTR_CREATE_SRQ_MAX_NUM_TAGS,
+  UVERBS_ATTR_CREATE_SRQ_TYPE,
+  UVERBS_ATTR_CREATE_SRQ_EVENT_FD,
+  UVERBS_ATTR_CREATE_SRQ_RESP_MAX_WR,
+  UVERBS_ATTR_CREATE_SRQ_RESP_MAX_SGE,
+  UVERBS_ATTR_CREATE_SRQ_RESP_SRQ_NUM,
+};
+enum uverbs_attrs_destroy_srq_cmd_attr_ids {
+  UVERBS_ATTR_DESTROY_SRQ_HANDLE,
+  UVERBS_ATTR_DESTROY_SRQ_RESP,
+};
+enum uverbs_methods_srq {
+  UVERBS_METHOD_SRQ_CREATE,
+  UVERBS_METHOD_SRQ_DESTROY,
+};
 enum uverbs_methods_cq {
   UVERBS_METHOD_CQ_CREATE,
   UVERBS_METHOD_CQ_DESTROY,
 };
+enum uverbs_attrs_create_wq_cmd_attr_ids {
+  UVERBS_ATTR_CREATE_WQ_HANDLE,
+  UVERBS_ATTR_CREATE_WQ_PD_HANDLE,
+  UVERBS_ATTR_CREATE_WQ_CQ_HANDLE,
+  UVERBS_ATTR_CREATE_WQ_USER_HANDLE,
+  UVERBS_ATTR_CREATE_WQ_TYPE,
+  UVERBS_ATTR_CREATE_WQ_EVENT_FD,
+  UVERBS_ATTR_CREATE_WQ_MAX_WR,
+  UVERBS_ATTR_CREATE_WQ_MAX_SGE,
+  UVERBS_ATTR_CREATE_WQ_FLAGS,
+  UVERBS_ATTR_CREATE_WQ_RESP_MAX_WR,
+  UVERBS_ATTR_CREATE_WQ_RESP_MAX_SGE,
+  UVERBS_ATTR_CREATE_WQ_RESP_WQ_NUM,
+};
+enum uverbs_attrs_destroy_wq_cmd_attr_ids {
+  UVERBS_ATTR_DESTROY_WQ_HANDLE,
+  UVERBS_ATTR_DESTROY_WQ_RESP,
+};
+enum uverbs_methods_wq {
+  UVERBS_METHOD_WQ_CREATE,
+  UVERBS_METHOD_WQ_DESTROY,
+};
 enum uverbs_methods_actions_flow_action_ops {
   UVERBS_METHOD_FLOW_ACTION_ESP_CREATE,
   UVERBS_METHOD_FLOW_ACTION_DESTROY,
diff --git a/libc/kernel/uapi/rdma/ib_user_ioctl_verbs.h b/libc/kernel/uapi/rdma/ib_user_ioctl_verbs.h
index ddf2abd..7880312 100644
--- a/libc/kernel/uapi/rdma/ib_user_ioctl_verbs.h
+++ b/libc/kernel/uapi/rdma/ib_user_ioctl_verbs.h
@@ -40,6 +40,36 @@
   IB_UVERBS_ACCESS_RELAXED_ORDERING = IB_UVERBS_ACCESS_OPTIONAL_FIRST,
   IB_UVERBS_ACCESS_OPTIONAL_RANGE = ((IB_UVERBS_ACCESS_OPTIONAL_LAST << 1) - 1) & ~(IB_UVERBS_ACCESS_OPTIONAL_FIRST - 1)
 };
+enum ib_uverbs_srq_type {
+  IB_UVERBS_SRQT_BASIC,
+  IB_UVERBS_SRQT_XRC,
+  IB_UVERBS_SRQT_TM,
+};
+enum ib_uverbs_wq_type {
+  IB_UVERBS_WQT_RQ,
+};
+enum ib_uverbs_wq_flags {
+  IB_UVERBS_WQ_FLAGS_CVLAN_STRIPPING = 1 << 0,
+  IB_UVERBS_WQ_FLAGS_SCATTER_FCS = 1 << 1,
+  IB_UVERBS_WQ_FLAGS_DELAY_DROP = 1 << 2,
+  IB_UVERBS_WQ_FLAGS_PCI_WRITE_END_PADDING = 1 << 3,
+};
+enum ib_uverbs_qp_type {
+  IB_UVERBS_QPT_RC = 2,
+  IB_UVERBS_QPT_UC,
+  IB_UVERBS_QPT_UD,
+  IB_UVERBS_QPT_RAW_PACKET = 8,
+  IB_UVERBS_QPT_XRC_INI,
+  IB_UVERBS_QPT_XRC_TGT,
+  IB_UVERBS_QPT_DRIVER = 0xFF,
+};
+enum ib_uverbs_qp_create_flags {
+  IB_UVERBS_QP_CREATE_BLOCK_MULTICAST_LOOPBACK = 1 << 1,
+  IB_UVERBS_QP_CREATE_SCATTER_FCS = 1 << 8,
+  IB_UVERBS_QP_CREATE_CVLAN_STRIPPING = 1 << 9,
+  IB_UVERBS_QP_CREATE_PCI_WRITE_END_PADDING = 1 << 11,
+  IB_UVERBS_QP_CREATE_SQ_SIG_ALL = 1 << 12,
+};
 enum ib_uverbs_query_port_cap_flags {
   IB_UVERBS_PCF_SM = 1 << 1,
   IB_UVERBS_PCF_NOTICE_SUP = 1 << 2,
@@ -132,6 +162,13 @@
   __u16 port_cap_flags2;
   __u8 reserved[6];
 };
+struct ib_uverbs_qp_cap {
+  __u32 max_send_wr;
+  __u32 max_recv_wr;
+  __u32 max_send_sge;
+  __u32 max_recv_sge;
+  __u32 max_inline_data;
+};
 enum rdma_driver_id {
   RDMA_DRIVER_UNKNOWN,
   RDMA_DRIVER_MLX5,
diff --git a/libc/kernel/uapi/rdma/mlx5-abi.h b/libc/kernel/uapi/rdma/mlx5-abi.h
index c7fedb6..59a9f53 100644
--- a/libc/kernel/uapi/rdma/mlx5-abi.h
+++ b/libc/kernel/uapi/rdma/mlx5-abi.h
@@ -66,6 +66,7 @@
 enum mlx5_ib_alloc_ucontext_resp_mask {
   MLX5_IB_ALLOC_UCONTEXT_RESP_MASK_CORE_CLOCK_OFFSET = 1UL << 0,
   MLX5_IB_ALLOC_UCONTEXT_RESP_MASK_DUMP_FILL_MKEY = 1UL << 1,
+  MLX5_IB_ALLOC_UCONTEXT_RESP_MASK_ECE = 1UL << 2,
 };
 enum mlx5_user_cmds_supp_uhw {
   MLX5_USER_CMDS_SUPP_UHW_QUERY_DEVICE = 1 << 0,
@@ -239,6 +240,8 @@
     __aligned_u64 sq_buf_addr;
     __aligned_u64 access_key;
   };
+  __u32 ece_options;
+  __u32 reserved;
 };
 enum mlx5_rx_hash_function_flags {
   MLX5_RX_HASH_FUNC_TOEPLITZ = 1 << 0,
@@ -273,7 +276,7 @@
 };
 struct mlx5_ib_create_qp_resp {
   __u32 bfreg_index;
-  __u32 reserved;
+  __u32 ece_options;
   __u32 comp_mask;
   __u32 tirn;
   __u32 tisn;
@@ -316,11 +319,13 @@
 struct mlx5_ib_modify_qp {
   __u32 comp_mask;
   struct mlx5_ib_burst_info burst_info;
-  __u32 reserved;
+  __u32 ece_options;
 };
 struct mlx5_ib_modify_qp_resp {
   __u32 response_length;
   __u32 dctn;
+  __u32 ece_options;
+  __u32 reserved;
 };
 struct mlx5_ib_create_wq_resp {
   __u32 response_length;
diff --git a/libc/kernel/uapi/rdma/mlx5_user_ioctl_cmds.h b/libc/kernel/uapi/rdma/mlx5_user_ioctl_cmds.h
index 37ad392..0b7cead 100644
--- a/libc/kernel/uapi/rdma/mlx5_user_ioctl_cmds.h
+++ b/libc/kernel/uapi/rdma/mlx5_user_ioctl_cmds.h
@@ -188,6 +188,10 @@
   MLX5_IB_FLOW_TYPE_ALL_DEFAULT,
   MLX5_IB_FLOW_TYPE_MC_DEFAULT,
 };
+enum mlx5_ib_create_flow_flags {
+  MLX5_IB_ATTR_CREATE_FLOW_FLAGS_DEFAULT_MISS = 1 << 0,
+  MLX5_IB_ATTR_CREATE_FLOW_FLAGS_DROP = 1 << 1,
+};
 enum mlx5_ib_create_flow_attrs {
   MLX5_IB_ATTR_CREATE_FLOW_HANDLE = (1U << UVERBS_ID_NS_SHIFT),
   MLX5_IB_ATTR_CREATE_FLOW_MATCH_VALUE,
@@ -198,6 +202,7 @@
   MLX5_IB_ATTR_CREATE_FLOW_TAG,
   MLX5_IB_ATTR_CREATE_FLOW_ARR_COUNTERS_DEVX,
   MLX5_IB_ATTR_CREATE_FLOW_ARR_COUNTERS_DEVX_OFFSET,
+  MLX5_IB_ATTR_CREATE_FLOW_FLAGS,
 };
 enum mlx5_ib_destoy_flow_attrs {
   MLX5_IB_ATTR_DESTROY_FLOW_HANDLE = (1U << UVERBS_ID_NS_SHIFT),
diff --git a/libc/kernel/uapi/rdma/rdma_user_cm.h b/libc/kernel/uapi/rdma/rdma_user_cm.h
index 9042b6f..9618734 100644
--- a/libc/kernel/uapi/rdma/rdma_user_cm.h
+++ b/libc/kernel/uapi/rdma/rdma_user_cm.h
@@ -127,6 +127,8 @@
   __u32 num_paths;
   __u8 port_num;
   __u8 reserved[3];
+  __u32 ibdev_index;
+  __u32 reserved1;
 };
 struct rdma_ucm_query_addr_resp {
   __aligned_u64 node_guid;
@@ -137,6 +139,8 @@
   __u16 dst_size;
   struct sockaddr_storage src_addr;
   struct sockaddr_storage dst_addr;
+  __u32 ibdev_index;
+  __u32 reserved1;
 };
 struct rdma_ucm_query_path_resp {
   __u32 num_paths;
@@ -164,10 +168,15 @@
   __u8 private_data_len;
   __u8 reserved[7];
 };
+struct rdma_ucm_ece {
+  __u32 vendor_id;
+  __u32 attr_mod;
+};
 struct rdma_ucm_connect {
   struct rdma_ucm_conn_param conn_param;
   __u32 id;
   __u32 reserved;
+  struct rdma_ucm_ece ece;
 };
 struct rdma_ucm_listen {
   __u32 id;
@@ -178,11 +187,13 @@
   struct rdma_ucm_conn_param conn_param;
   __u32 id;
   __u32 reserved;
+  struct rdma_ucm_ece ece;
 };
 struct rdma_ucm_reject {
   __u32 id;
   __u8 private_data_len;
-  __u8 reserved[3];
+  __u8 reason;
+  __u8 reserved[2];
   __u8 private_data[RDMA_MAX_PRIVATE_DATA];
 };
 struct rdma_ucm_disconnect {
@@ -229,6 +240,7 @@
     struct rdma_ucm_ud_param ud;
   } param;
   __u32 reserved;
+  struct rdma_ucm_ece ece;
 };
 enum {
   RDMA_OPTION_ID = 0,
diff --git a/libc/kernel/uapi/sound/skl-tplg-interface.h b/libc/kernel/uapi/sound/skl-tplg-interface.h
index 58e0afa..b516a08 100644
--- a/libc/kernel/uapi/sound/skl-tplg-interface.h
+++ b/libc/kernel/uapi/sound/skl-tplg-interface.h
@@ -21,6 +21,8 @@
 #include <linux/types.h>
 #define SKL_CONTROL_TYPE_BYTE_TLV 0x100
 #define SKL_CONTROL_TYPE_MIC_SELECT 0x102
+#define SKL_CONTROL_TYPE_MULTI_IO_SELECT 0x103
+#define SKL_CONTROL_TYPE_MULTI_IO_SELECT_DMIC 0x104
 #define HDA_SST_CFG_MAX 900
 #define MAX_IN_QUEUE 8
 #define MAX_OUT_QUEUE 8
diff --git a/libc/kernel/uapi/sound/sof/abi.h b/libc/kernel/uapi/sound/sof/abi.h
index b0adb11..54e9a50 100644
--- a/libc/kernel/uapi/sound/sof/abi.h
+++ b/libc/kernel/uapi/sound/sof/abi.h
@@ -19,7 +19,7 @@
 #ifndef __INCLUDE_UAPI_SOUND_SOF_ABI_H__
 #define __INCLUDE_UAPI_SOUND_SOF_ABI_H__
 #define SOF_ABI_MAJOR 3
-#define SOF_ABI_MINOR 13
+#define SOF_ABI_MINOR 16
 #define SOF_ABI_PATCH 0
 #define SOF_ABI_MAJOR_SHIFT 24
 #define SOF_ABI_MAJOR_MASK 0xff
diff --git a/libc/kernel/uapi/sound/sof/tokens.h b/libc/kernel/uapi/sound/sof/tokens.h
index 7ce5ddc..7d5ed89 100644
--- a/libc/kernel/uapi/sound/sof/tokens.h
+++ b/libc/kernel/uapi/sound/sof/tokens.h
@@ -77,4 +77,8 @@
 #define SOF_TKN_STREAM_CAPTURE_COMPATIBLE_D0I3 1201
 #define SOF_TKN_MUTE_LED_USE 1300
 #define SOF_TKN_MUTE_LED_DIRECTION 1301
+#define SOF_TKN_INTEL_ALH_RATE 1400
+#define SOF_TKN_INTEL_ALH_CH 1401
+#define SOF_TKN_INTEL_HDA_RATE 1500
+#define SOF_TKN_INTEL_HDA_CH 1501
 #endif
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
index 10732a1..e35d1fb 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -1554,6 +1554,10 @@
   global:
     ffsl;
     ffsll;
+    __libc_get_static_tls_bounds;
+    __libc_register_thread_exit_callback;
+    __libc_iterate_dynamic_tls;
+    __libc_register_dynamic_tls_listeners;
 } LIBC_R;
 
 LIBC_PRIVATE {
diff --git a/libc/private/bionic_allocator.h b/libc/private/bionic_allocator.h
index c705ce4..342fd51 100644
--- a/libc/private/bionic_allocator.h
+++ b/libc/private/bionic_allocator.h
@@ -110,6 +110,11 @@
   // Note that this implementation of realloc never shrinks allocation
   void* realloc(void* ptr, size_t size);
   void free(void* ptr);
+
+  // Returns the size of the given allocated heap chunk, if it is valid.
+  // Otherwise, this may return 0 or cause a segfault if the pointer is invalid.
+  size_t get_chunk_size(void* ptr);
+
  private:
   void* alloc_mmap(size_t align, size_t size);
   inline void* alloc_impl(size_t align, size_t size);
diff --git a/libc/private/bionic_auxv.h b/libc/private/bionic_auxv.h
index 8e33c1c..9d2cfdd 100644
--- a/libc/private/bionic_auxv.h
+++ b/libc/private/bionic_auxv.h
@@ -30,4 +30,4 @@
 
 #include <sys/cdefs.h>
 
-__LIBC_HIDDEN__ unsigned long __bionic_getauxval(unsigned long type, bool& exists);
+__LIBC_HIDDEN__ unsigned long __bionic_getauxval(unsigned long type, bool* exists);
diff --git a/libc/private/bionic_elf_tls.h b/libc/private/bionic_elf_tls.h
index fa1af76..e0ec7b5 100644
--- a/libc/private/bionic_elf_tls.h
+++ b/libc/private/bionic_elf_tls.h
@@ -111,6 +111,18 @@
   void* soinfo_ptr = nullptr;
 };
 
+// Signature of the callbacks that will be called after DTLS creation and
+// before DTLS destruction.
+typedef void (*dtls_listener_t)(void* dynamic_tls_begin, void* dynamic_tls_end);
+
+// Signature of the thread-exit callbacks.
+typedef void (*thread_exit_cb_t)(void);
+
+struct CallbackHolder {
+  thread_exit_cb_t cb;
+  CallbackHolder* prev;
+};
+
 // Table of the ELF TLS modules. Either the dynamic linker or the static
 // initialization code prepares this table, and it's then used during thread
 // creation and for dynamic TLS lookups.
@@ -128,7 +140,20 @@
   // Pointer to a block of TlsModule objects. The first module has ID 1 and
   // is stored at index 0 in this table.
   size_t module_count = 0;
+  size_t static_module_count = 0;
   TlsModule* module_table = nullptr;
+
+  // Callback to be invoked after a dynamic TLS allocation.
+  dtls_listener_t on_creation_cb = nullptr;
+
+  // Callback to be invoked before a dynamic TLS deallocation.
+  dtls_listener_t on_destruction_cb = nullptr;
+
+  // The first thread-exit callback; inlined to avoid allocation.
+  thread_exit_cb_t first_thread_exit_callback = nullptr;
+
+  // The additional callbacks, if any.
+  CallbackHolder* thread_exit_callback_tail_node = nullptr;
 };
 
 void __init_static_tls(void* static_tls);
@@ -175,3 +200,4 @@
 
 struct bionic_tcb;
 void __free_dynamic_tls(bionic_tcb* tcb);
+void __notify_thread_exit_callbacks();
diff --git a/libc/stdio/local.h b/libc/stdio/local.h
index 1ecf122..6ffda49 100644
--- a/libc/stdio/local.h
+++ b/libc/stdio/local.h
@@ -259,8 +259,8 @@
 size_t parsefloat(FILE*, char*, char*);
 size_t wparsefloat(FILE*, wchar_t*, wchar_t*);
 
-// Sanity check a FILE* for nullptr, so we can emit a message while crashing
-// instead of doing a blind null-dereference.
+// Check a FILE* isn't nullptr, so we can emit a clear diagnostic message
+// instead of just crashing with SIGSEGV.
 #define CHECK_FP(fp) \
   if (fp == nullptr) __fortify_fatal("%s: null FILE*", __FUNCTION__)
 
diff --git a/libc/stdio/stdio.cpp b/libc/stdio/stdio.cpp
index a0b4219..b8aced8 100644
--- a/libc/stdio/stdio.cpp
+++ b/libc/stdio/stdio.cpp
@@ -773,10 +773,7 @@
 // Returns first argument, or nullptr if no characters were read.
 // Does not return nullptr if n == 1.
 char* fgets_unlocked(char* buf, int n, FILE* fp) {
-  if (n <= 0) {
-    errno = EINVAL;
-    return nullptr;
-  }
+  if (n <= 0) __fortify_fatal("fgets: buffer size %d <= 0", n);
 
   _SET_ORIENTATION(fp, -1);
 
@@ -1026,9 +1023,9 @@
   __check_count("vsnprintf", "size", n);
 
   // Stdio internals do not deal correctly with zero length buffer.
-  char dummy;
+  char one_byte_buffer[1];
   if (n == 0) {
-    s = &dummy;
+    s = one_byte_buffer;
     n = 1;
   }
 
diff --git a/libc/system_properties/contexts_split.cpp b/libc/system_properties/contexts_split.cpp
index 96b01a4..ccb5bcd 100644
--- a/libc/system_properties/contexts_split.cpp
+++ b/libc/system_properties/contexts_split.cpp
@@ -269,7 +269,7 @@
     if (!InitializePropertiesFromFile("/system/etc/selinux/plat_property_contexts")) {
       return false;
     }
-    // Don't check for failure here, so we always have a sane list of properties.
+    // Don't check for failure here, since we don't always have all of these partitions.
     // E.g. In case of recovery, the vendor partition will not have mounted and we
     // still need the system / platform properties to function.
     if (access("/vendor/etc/selinux/vendor_property_contexts", R_OK) != -1) {
diff --git a/libc/tools/check-symbols-glibc.py b/libc/tools/check-symbols-glibc.py
index 4de0181..d8d1982 100755
--- a/libc/tools/check-symbols-glibc.py
+++ b/libc/tools/check-symbols-glibc.py
@@ -182,9 +182,9 @@
   '_ctype_',
   '__libc_init',
 ])
-# POSIX has some stuff that's too stupid for words (a64l) or not actually
-# implemented in glibc unless you count always failing with ENOSYS as
-# being implemented (fattach). Other stuff (fmtmsg) isn't used in any
+# POSIX has some stuff that's unusable in the modern world (a64l) or not
+# actually implemented in glibc unless you count always failing with ENOSYS
+# as being implemented (fattach). Other stuff (fmtmsg) isn't used in any
 # codebase I have access to, internal or external.
 in_posix_and_glibc_but_dead_or_useless = set([
   'a64l', # obsolete
diff --git a/libc/tools/pylintrc b/libc/tools/pylintrc
deleted file mode 100644
index dd7dbf6..0000000
--- a/libc/tools/pylintrc
+++ /dev/null
@@ -1,280 +0,0 @@
-[MASTER]
-
-# Specify a configuration file.
-#rcfile=
-
-# Python code to execute, usually for sys.path manipulation such as
-# pygtk.require().
-#init-hook=
-
-# Profiled execution.
-profile=no
-
-# Add files or directories to the ignore list. They should be base names, not
-# paths.
-ignore=CVS
-
-# Pickle collected data for later comparisons.
-persistent=yes
-
-# List of plugins (as comma separated values of python modules names) to load,
-# usually to register additional checkers.
-load-plugins=
-
-
-[MESSAGES CONTROL]
-
-# Enable the message, report, category or checker with the given id(s). You can
-# either give multiple identifier separated by comma (,) or put this option
-# multiple time. See also the "--disable" option for examples.
-#enable=
-
-# Disable the message, report, category or checker with the given id(s). You
-# can either give multiple identifiers separated by comma (,) or put this
-# option multiple times (only on the command line, not in the configuration
-# file where it should appear only once).You can also use "--disable=all" to
-# disable everything first and then reenable specific checks. For example, if
-# you want to run only the similarities checker, you can use "--disable=all
-# --enable=similarities". If you want to run only the classes checker, but have
-# no Warning level messages displayed, use"--disable=all --enable=classes
-# --disable=W"
-disable=missing-docstring,invalid-name,no-self-use,fixme,design
-
-
-[REPORTS]
-
-# Set the output format. Available formats are text, parseable, colorized, msvs
-# (visual studio) and html. You can also give a reporter class, eg
-# mypackage.mymodule.MyReporterClass.
-output-format=text
-
-# Put messages in a separate file for each module / package specified on the
-# command line instead of printing them on stdout. Reports (if any) will be
-# written in a file name "pylint_global.[txt|html]".
-files-output=no
-
-# Tells whether to display a full report or only the messages
-reports=yes
-
-# Python expression which should return a note less than 10 (10 is the highest
-# note). You have access to the variables errors warning, statement which
-# respectively contain the number of errors / warnings messages and the total
-# number of statements analyzed. This is used by the global evaluation report
-# (RP0004).
-evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
-
-# Add a comment according to your evaluation note. This is used by the global
-# evaluation report (RP0004).
-comment=no
-
-# Template used to display messages. This is a python new-style format string
-# used to format the message information. See doc for all details
-#msg-template=
-
-
-[BASIC]
-
-# Required attributes for module, separated by a comma
-required-attributes=
-
-# List of builtins function names that should not be used, separated by a comma
-bad-functions=map,filter,apply,input
-
-# Regular expression which should only match correct module names
-module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
-
-# Regular expression which should only match correct module level names
-const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
-
-# Regular expression which should only match correct class names
-class-rgx=[A-Z_][a-zA-Z0-9]+$
-
-# Regular expression which should only match correct function names
-function-rgx=[a-z_][a-z0-9_]{2,30}$
-
-# Regular expression which should only match correct method names
-method-rgx=[a-z_][a-z0-9_]{2,30}$
-
-# Regular expression which should only match correct instance attribute names
-attr-rgx=[a-z_][a-z0-9_]{2,30}$
-
-# Regular expression which should only match correct argument names
-argument-rgx=[a-z_][a-z0-9_]{2,30}$
-
-# Regular expression which should only match correct variable names
-variable-rgx=[a-z_][a-z0-9_]{2,30}$
-
-# Regular expression which should only match correct attribute names in class
-# bodies
-class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
-
-# Regular expression which should only match correct list comprehension /
-# generator expression variable names
-inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
-
-# Good variable names which should always be accepted, separated by a comma
-good-names=i,j,k,ex,Run,_
-
-# Bad variable names which should always be refused, separated by a comma
-bad-names=foo,bar,baz,toto,tutu,tata
-
-# Regular expression which should only match function or class names that do
-# not require a docstring.
-no-docstring-rgx=__.*__
-
-# Minimum line length for functions/classes that require docstrings, shorter
-# ones are exempt.
-docstring-min-length=-1
-
-
-[TYPECHECK]
-
-# Tells whether missing members accessed in mixin class should be ignored. A
-# mixin class is detected if its name ends with "mixin" (case insensitive).
-ignore-mixin-members=yes
-
-# List of classes names for which member attributes should not be checked
-# (useful for classes with attributes dynamically set).
-ignored-classes=SQLObject
-
-# When zope mode is activated, add a predefined set of Zope acquired attributes
-# to generated-members.
-zope=no
-
-# List of members which are set dynamically and missed by pylint inference
-# system, and so shouldn't trigger E0201 when accessed. Python regular
-# expressions are accepted.
-generated-members=REQUEST,acl_users,aq_parent
-
-
-[MISCELLANEOUS]
-
-# List of note tags to take in consideration, separated by a comma.
-notes=FIXME,XXX,TODO
-
-
-[SIMILARITIES]
-
-# Minimum lines number of a similarity.
-min-similarity-lines=4
-
-# Ignore comments when computing similarities.
-ignore-comments=yes
-
-# Ignore docstrings when computing similarities.
-ignore-docstrings=yes
-
-# Ignore imports when computing similarities.
-ignore-imports=no
-
-
-[VARIABLES]
-
-# Tells whether we should check for unused import in __init__ files.
-init-import=no
-
-# A regular expression matching the beginning of the name of dummy variables
-# (i.e. not used).
-dummy-variables-rgx=_$|dummy
-
-# List of additional names supposed to be defined in builtins. Remember that
-# you should avoid to define new builtins when possible.
-additional-builtins=
-
-
-[FORMAT]
-
-# Maximum number of characters on a single line.
-max-line-length=100
-
-# Regexp for a line that is allowed to be longer than the limit.
-ignore-long-lines=^\s*(# )?<?https?://\S+>?$
-
-# Allow the body of an if to be on the same line as the test if there is no
-# else.
-single-line-if-stmt=no
-
-# List of optional constructs for which whitespace checking is disabled
-no-space-check=trailing-comma,dict-separator
-
-# Maximum number of lines in a module
-max-module-lines=1000
-
-# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
-# tab).
-indent-string='  '
-
-
-[IMPORTS]
-
-# Deprecated modules which should not be used, separated by a comma
-deprecated-modules=regsub,TERMIOS,Bastion,rexec
-
-# Create a graph of every (i.e. internal and external) dependencies in the
-# given file (report RP0402 must not be disabled)
-import-graph=
-
-# Create a graph of external dependencies in the given file (report RP0402 must
-# not be disabled)
-ext-import-graph=
-
-# Create a graph of internal dependencies in the given file (report RP0402 must
-# not be disabled)
-int-import-graph=
-
-
-[DESIGN]
-
-# Maximum number of arguments for function / method
-max-args=5
-
-# Argument names that match this expression will be ignored. Default to name
-# with leading underscore
-ignored-argument-names=_.*
-
-# Maximum number of locals for function / method body
-max-locals=15
-
-# Maximum number of return / yield for function / method body
-max-returns=6
-
-# Maximum number of branch for function / method body
-max-branches=12
-
-# Maximum number of statements in function / method body
-max-statements=50
-
-# Maximum number of parents for a class (see R0901).
-max-parents=7
-
-# Maximum number of attributes for a class (see R0902).
-max-attributes=7
-
-# Minimum number of public methods for a class (see R0903).
-min-public-methods=2
-
-# Maximum number of public methods for a class (see R0904).
-max-public-methods=20
-
-
-[CLASSES]
-
-# List of interface methods to ignore, separated by a comma. This is used for
-# instance to not check methods defines in Zope's Interface base class.
-ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by
-
-# List of method names used to declare (i.e. assign) instance attributes.
-defining-attr-methods=__init__,__new__,setUp
-
-# List of valid names for the first argument in a class method.
-valid-classmethod-first-arg=cls
-
-# List of valid names for the first argument in a metaclass class method.
-valid-metaclass-classmethod-first-arg=mcs
-
-
-[EXCEPTIONS]
-
-# Exceptions that will emit a warning when being caught. Defaults to
-# "Exception"
-overgeneral-exceptions=Exception
diff --git a/libc/tzcode/bionic.cpp b/libc/tzcode/bionic.cpp
index 182fa89..e134aaa 100644
--- a/libc/tzcode/bionic.cpp
+++ b/libc/tzcode/bionic.cpp
@@ -90,12 +90,12 @@
 // byte[12] tzdata_version  -- "tzdata2012f\0"
 // int index_offset
 // int data_offset
-// int zonetab_offset
+// int final_offset
 struct bionic_tzdata_header_t {
   char tzdata_version[12];
   int32_t index_offset;
   int32_t data_offset;
-  int32_t zonetab_offset;
+  int32_t final_offset;
 };
 static constexpr size_t NAME_LENGTH = 40;
 struct index_entry_t {
diff --git a/libc/upstream-netbsd/lib/libc/gen/utmp.c b/libc/upstream-netbsd/lib/libc/gen/utmp.c
deleted file mode 100644
index 9fb0799..0000000
--- a/libc/upstream-netbsd/lib/libc/gen/utmp.c
+++ /dev/null
@@ -1,106 +0,0 @@
-/*	$NetBSD: utmp.c,v 1.10 2011/10/15 23:00:02 christos Exp $	 */
-
-/*-
- * Copyright (c) 2002 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Christos Zoulas.
- *
- * 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
- */
-#include <sys/cdefs.h>
-
-#if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: utmp.c,v 1.10 2011/10/15 23:00:02 christos Exp $");
-#endif /* LIBC_SCCS and not lint */
-
-#include "namespace.h"
-#include <sys/types.h>
-#include <sys/param.h>
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include <utmp.h>
-#include <sys/stat.h>
-
-static struct utmp utmp;
-static FILE *ut;
-static char utfile[MAXPATHLEN] = _PATH_UTMP;
-
-void
-setutent(void)
-{
-	if (ut == NULL)
-		return;
-	(void)fseeko(ut, (off_t)0, SEEK_SET);
-}
-
-struct utmp *
-getutent(void)
-{
-	if (ut == NULL) {
-		struct stat st;
-		off_t numentries;
-		if ((ut = fopen(utfile, "re")) == NULL)
-			return NULL;
-		if (fstat(fileno(ut), &st) == -1)
-			goto out;
-		/*
-		 * If we have a an old version utmp file bail.
-		 */
-		numentries = st.st_size / sizeof(utmp);
-		if ((off_t)(numentries * sizeof(utmp)) != st.st_size)
-			goto out;
-	}
-	if (fread(&utmp, sizeof(utmp), 1, ut) == 1)
-		return &utmp;
-out:
-	(void)fclose(ut);
-	return NULL;
-}
-
-void
-endutent(void)
-{
-	if (ut != NULL) {
-		(void)fclose(ut);
-		ut = NULL;
-	}
-}
-
-int
-utmpname(const char *fname)
-{
-	size_t len = strlen(fname);
-
-	if (len >= sizeof(utfile))
-		return 0;
-
-	/* must not end in x! */
-	if (fname[len - 1] == 'x')
-		return 0;
-
-	(void)strlcpy(utfile, fname, sizeof(utfile));
-	endutent();
-	return 1;
-}
diff --git a/libc/upstream-netbsd/lib/libc/stdlib/_rand48.c b/libc/upstream-netbsd/lib/libc/stdlib/_rand48.c
index 0468026..6e3e223 100644
--- a/libc/upstream-netbsd/lib/libc/stdlib/_rand48.c
+++ b/libc/upstream-netbsd/lib/libc/stdlib/_rand48.c
@@ -1,4 +1,4 @@
-/*	$NetBSD: _rand48.c,v 1.7 2005/06/12 05:21:27 lukem Exp $	*/
+/*	$NetBSD: _rand48.c,v 1.10 2020/02/23 09:53:42 kamil Exp $	*/
 
 /*
  * Copyright (c) 1993 Martin Birgmeier
@@ -15,7 +15,7 @@
 
 #include <sys/cdefs.h>
 #if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: _rand48.c,v 1.7 2005/06/12 05:21:27 lukem Exp $");
+__RCSID("$NetBSD: _rand48.c,v 1.10 2020/02/23 09:53:42 kamil Exp $");
 #endif /* LIBC_SCCS and not lint */
 
 #include <assert.h>
@@ -42,15 +42,17 @@
 
 	_DIAGASSERT(xseed != NULL);
 
-	accu = (unsigned long) __rand48_mult[0] * (unsigned long) xseed[0] +
-	 (unsigned long) __rand48_add;
+	accu = (unsigned long) __rand48_mult[0] * (unsigned long) xseed[0];
+	accu += (unsigned long) __rand48_add;
 	temp[0] = (unsigned short) accu;	/* lower 16 bits */
 	accu >>= sizeof(unsigned short) * 8;
-	accu += (unsigned long) __rand48_mult[0] * (unsigned long) xseed[1] +
-	 (unsigned long) __rand48_mult[1] * (unsigned long) xseed[0];
+	accu += (unsigned long) __rand48_mult[0] * (unsigned long) xseed[1];
+	accu += (unsigned long) __rand48_mult[1] * (unsigned long) xseed[0];
 	temp[1] = (unsigned short) accu;	/* middle 16 bits */
 	accu >>= sizeof(unsigned short) * 8;
-	accu += __rand48_mult[0] * xseed[2] + __rand48_mult[1] * xseed[1] + __rand48_mult[2] * xseed[0];
+	accu += (unsigned long) __rand48_mult[0] * (unsigned long) xseed[2];
+	accu += (unsigned long) __rand48_mult[1] * (unsigned long) xseed[1];
+	accu += (unsigned long) __rand48_mult[2] * (unsigned long) xseed[0];
 	xseed[0] = temp[0];
 	xseed[1] = temp[1];
 	xseed[2] = (unsigned short) accu;
diff --git a/libc/upstream-openbsd/android/include/openbsd-compat.h b/libc/upstream-openbsd/android/include/openbsd-compat.h
index 8206269..2fc5046 100644
--- a/libc/upstream-openbsd/android/include/openbsd-compat.h
+++ b/libc/upstream-openbsd/android/include/openbsd-compat.h
@@ -72,3 +72,7 @@
 
 __LIBC_HIDDEN__ extern char* __findenv(const char*, int, int*);
 __LIBC_HIDDEN__ extern char* _mktemp(char*);
+
+// Only OpenBSD has this at the moment, and we're more likely to just say
+// "malloc is always calloc", so we don't expose this as libc API.
+__LIBC_HIDDEN__ void* recallocarray(void*, size_t, size_t, size_t);
diff --git a/libc/upstream-openbsd/lib/libc/gen/fnmatch.c b/libc/upstream-openbsd/lib/libc/gen/fnmatch.c
index 0d0f18f..d7afd5f 100644
--- a/libc/upstream-openbsd/lib/libc/gen/fnmatch.c
+++ b/libc/upstream-openbsd/lib/libc/gen/fnmatch.c
@@ -1,8 +1,8 @@
-/*	$OpenBSD: fnmatch.c,v 1.19 2015/08/01 18:11:08 millert Exp $	*/
+/*	$OpenBSD: fnmatch.c,v 1.22 2020/03/13 03:25:45 djm Exp $	*/
 
 /* Copyright (c) 2011, VMware, Inc.
  * 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
@@ -13,7 +13,7 @@
  *     * Neither the name of the VMware, Inc. 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 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
@@ -27,7 +27,7 @@
  */
 
 /*
- * Copyright (c) 2008 Todd C. Miller <millert@openbsd.org>
+ * Copyright (c) 2008, 2016 Todd C. Miller <millert@openbsd.org>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -51,9 +51,9 @@
  * Filename pattern matches defined in section 2.13, "Pattern Matching Notation"
  * from chapter 2. "Shell Command Language"
  *   http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_13
- * where; 1. A bracket expression starting with an unquoted <circumflex> '^' 
- * character CONTINUES to specify a non-matching list; 2. an explicit <period> '.' 
- * in a bracket expression matching list, e.g. "[.abc]" does NOT match a leading 
+ * where; 1. A bracket expression starting with an unquoted <circumflex> '^'
+ * character CONTINUES to specify a non-matching list; 2. an explicit <period> '.'
+ * in a bracket expression matching list, e.g. "[.abc]" does NOT match a leading
  * <period> in a filename; 3. a <left-square-bracket> '[' which does not introduce
  * a valid bracket expression is treated as an ordinary character; 4. a differing
  * number of consecutive slashes within pattern and string will NOT match;
@@ -62,10 +62,10 @@
  * Bracket expansion defined in section 9.3.5, "RE Bracket Expression",
  * from chapter 9, "Regular Expressions"
  *   http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html#tag_09_03_05
- * with no support for collating symbols, equivalence class expressions or 
- * character class expressions.  A partial range expression with a leading 
+ * with no support for collating symbols, equivalence class expressions or
+ * character class expressions.  A partial range expression with a leading
  * hyphen following a valid range expression will match only the ordinary
- * <hyphen> and the ending character (e.g. "[a-m-z]" will match characters 
+ * <hyphen> and the ending character (e.g. "[a-m-z]" will match characters
  * 'a' through 'm', a <hyphen> '-', or a 'z').
  *
  * Supports BSD extensions FNM_LEADING_DIR to match pattern to the end of one
@@ -98,22 +98,21 @@
 static int
 classmatch(const char *pattern, char test, int foldcase, const char **ep)
 {
-	struct cclass *cc;
-	const char *colon;
-	size_t len;
-	int rval = RANGE_NOMATCH;
 	const char * const mismatch = pattern;
+	const char *colon;
+	struct cclass *cc;
+	int rval = RANGE_NOMATCH;
+	size_t len;
 
-	if (*pattern != '[' || pattern[1] != ':') {
+	if (pattern[0] != '[' || pattern[1] != ':') {
 		*ep = mismatch;
-		return(RANGE_ERROR);
+		return RANGE_ERROR;
 	}
-
 	pattern += 2;
 
 	if ((colon = strchr(pattern, ':')) == NULL || colon[1] != ']') {
 		*ep = mismatch;
-		return(RANGE_ERROR);
+		return RANGE_ERROR;
 	}
 	*ep = colon + 2;
 	len = (size_t)(colon - pattern);
@@ -132,11 +131,11 @@
 		*ep = mismatch;
 		rval = RANGE_ERROR;
 	}
-	return(rval);
+	return rval;
 }
 
 /* Most MBCS/collation/case issues handled here.  Wildcard '*' is not handled.
- * EOS '\0' and the FNM_PATHNAME '/' delimiters are not advanced over, 
+ * EOS '\0' and the FNM_PATHNAME '/' delimiters are not advanced over,
  * however the "\/" sequence is advanced to '/'.
  *
  * Both pattern and string are **char to support pointer increment of arbitrary
@@ -144,341 +143,347 @@
  */
 static int fnmatch_ch(const char **pattern, const char **string, int flags)
 {
-    const char * const mismatch = *pattern;
-    const int nocase = !!(flags & FNM_CASEFOLD);
-    const int escape = !(flags & FNM_NOESCAPE);
-    const int slash = !!(flags & FNM_PATHNAME);
-    int result = FNM_NOMATCH;
-    const char *startch;
-    int negate;
+	const char * const mismatch = *pattern;
+	const int nocase = !!(flags & FNM_CASEFOLD);
+	const int escape = !(flags & FNM_NOESCAPE);
+	const int slash = !!(flags & FNM_PATHNAME);
+	int result = FNM_NOMATCH;
+	const char *startch;
+	int negate;
 
-    if (**pattern == '[')
-    {
-        ++*pattern;
+	if (**pattern == '[') {
+		++*pattern;
 
-        /* Handle negation, either leading ! or ^ operators (never both) */
-        negate = ((**pattern == '!') || (**pattern == '^'));
-        if (negate)
-            ++*pattern;
+		/* Handle negation, either leading ! or ^ operators */
+		negate = (**pattern == '!') || (**pattern == '^');
+		if (negate)
+			++*pattern;
 
-        /* ']' is an ordinary character at the start of the range pattern */
-        if (**pattern == ']')
-            goto leadingclosebrace;
+		/* ']' is an ordinary char at the start of the range pattern */
+		if (**pattern == ']')
+			goto leadingclosebrace;
 
-        while (**pattern)
-        {
-            if (**pattern == ']') {
-                ++*pattern;
-                /* XXX: Fix for MBCS character width */
-                ++*string;
-                return (result ^ negate);
-            }
+		while (**pattern) {
+			if (**pattern == ']') {
+				++*pattern;
+				/* XXX: Fix for MBCS character width */
+				++*string;
+				return (result ^ negate);
+			}
 
-            if (escape && (**pattern == '\\')) {
-                ++*pattern;
+			if (escape && (**pattern == '\\')) {
+				++*pattern;
 
-                /* Patterns must be terminated with ']', not EOS */
-                if (!**pattern)
-                    break;
-            }
+				/* Patterns must terminate with ']', not EOS */
+				if (!**pattern)
+					break;
+			}
 
-            /* Patterns must be terminated with ']' not '/' */
-            if (slash && (**pattern == '/'))
-                break;
+			/* Patterns must terminate with ']' not '/' */
+			if (slash && (**pattern == '/'))
+				break;
 
-            /* Match character classes. */
-            if (classmatch(*pattern, **string, nocase, pattern)
-                == RANGE_MATCH) {
-                result = 0;
-                continue;
-            }
-            if (!**pattern)
-                break;
+			/* Match character classes. */
+			switch (classmatch(*pattern, **string, nocase, pattern)) {
+			case RANGE_MATCH:
+				result = 0;
+				continue;
+			case RANGE_NOMATCH:
+				/* Valid character class but no match. */
+				continue;
+			default:
+				/* Not a valid character class. */
+				break;
+			}
+			if (!**pattern)
+				break;
 
 leadingclosebrace:
-            /* Look at only well-formed range patterns; 
-             * "x-]" is not allowed unless escaped ("x-\]")
-             * XXX: Fix for locale/MBCS character width
-             */
-            if (((*pattern)[1] == '-') && ((*pattern)[2] != ']'))
-            {
-                startch = *pattern;
-                *pattern += (escape && ((*pattern)[2] == '\\')) ? 3 : 2;
+			/* Look at only well-formed range patterns;
+			 * "x-]" is not allowed unless escaped ("x-\]")
+			 * XXX: Fix for locale/MBCS character width
+			 */
+			if (((*pattern)[1] == '-') && ((*pattern)[2] != ']')) {
+				startch = *pattern;
+				*pattern += (escape && ((*pattern)[2] == '\\')) ? 3 : 2;
 
-                /* NOT a properly balanced [expr] pattern, EOS terminated 
-                 * or ranges containing a slash in FNM_PATHNAME mode pattern
-                 * fall out to to the rewind and test '[' literal code path
-                 */
-                if (!**pattern || (slash && (**pattern == '/')))
-                    break;
+				/*
+				 * NOT a properly balanced [expr] pattern, EOS
+				 * terminated or ranges containing a slash in
+				 * FNM_PATHNAME mode pattern fall out to to the
+				 * rewind and test '[' literal code path.
+				 */
+				if (!**pattern || (slash && (**pattern == '/')))
+					break;
 
-                /* XXX: handle locale/MBCS comparison, advance by MBCS char width */
-                if ((**string >= *startch) && (**string <= **pattern))
-                    result = 0;
-                else if (nocase && (isupper((unsigned char)**string) ||
-			    isupper((unsigned char)*startch) ||
-                            isupper((unsigned char)**pattern))
-                            && (tolower((unsigned char)**string) >=
-			        tolower((unsigned char)*startch)) 
-                            && (tolower((unsigned char)**string) <=
-				tolower((unsigned char)**pattern)))
-                    result = 0;
+				/* XXX: handle locale/MBCS comparison, advance by MBCS char width */
+				if ((**string >= *startch) && (**string <= **pattern))
+					result = 0;
+				else if (nocase &&
+				    (isupper((unsigned char)**string) ||
+				     isupper((unsigned char)*startch) ||
+				     isupper((unsigned char)**pattern)) &&
+				    (tolower((unsigned char)**string) >=
+				     tolower((unsigned char)*startch)) &&
+				    (tolower((unsigned char)**string) <=
+				     tolower((unsigned char)**pattern)))
+					result = 0;
 
-                ++*pattern;
-                continue;
-            }
+				++*pattern;
+				continue;
+			}
 
-            /* XXX: handle locale/MBCS comparison, advance by MBCS char width */
-            if ((**string == **pattern))
-                result = 0;
-            else if (nocase && (isupper((unsigned char)**string) ||
-			    isupper((unsigned char)**pattern))
-                            && (tolower((unsigned char)**string) ==
-				tolower((unsigned char)**pattern)))
-                result = 0;
+			/* XXX: handle locale/MBCS comparison, advance by MBCS char width */
+			if ((**string == **pattern))
+				result = 0;
+			else if (nocase && (isupper((unsigned char)**string) ||
+			    isupper((unsigned char)**pattern)) &&
+			    (tolower((unsigned char)**string) ==
+			    tolower((unsigned char)**pattern)))
+				result = 0;
 
-            ++*pattern;
-        }
+			++*pattern;
+		}
+		/*
+		 * NOT a properly balanced [expr] pattern;
+		 * Rewind and reset result to test '[' literal
+		 */
+		*pattern = mismatch;
+		result = FNM_NOMATCH;
+	} else if (**pattern == '?') {
+		/* Optimize '?' match before unescaping **pattern */
+		if (!**string || (slash && (**string == '/')))
+			return FNM_NOMATCH;
+		result = 0;
+		goto fnmatch_ch_success;
+	} else if (escape && (**pattern == '\\') && (*pattern)[1]) {
+		++*pattern;
+	}
 
-        /* NOT a properly balanced [expr] pattern; Rewind
-         * and reset result to test '[' literal
-         */
-        *pattern = mismatch;
-        result = FNM_NOMATCH;
-    }
-    else if (**pattern == '?') {
-        /* Optimize '?' match before unescaping **pattern */
-        if (!**string || (slash && (**string == '/')))
-            return FNM_NOMATCH;
-        result = 0;
-        goto fnmatch_ch_success;
-    }
-    else if (escape && (**pattern == '\\') && (*pattern)[1]) {
-        ++*pattern;
-    }
+	/* XXX: handle locale/MBCS comparison, advance by the MBCS char width */
+	if (**string == **pattern)
+		result = 0;
+	else if (nocase && (isupper((unsigned char)**string) ||
+	    isupper((unsigned char)**pattern)) &&
+	    (tolower((unsigned char)**string) ==
+	    tolower((unsigned char)**pattern)))
+		result = 0;
 
-    /* XXX: handle locale/MBCS comparison, advance by the MBCS char width */
-    if (**string == **pattern)
-        result = 0;
-    else if (nocase && (isupper((unsigned char)**string) ||
-		    isupper((unsigned char)**pattern))
-                    && (tolower((unsigned char)**string) ==
-			tolower((unsigned char)**pattern)))
-        result = 0;
-
-    /* Refuse to advance over trailing slash or nulls
-     */
-    if (!**string || !**pattern || (slash && ((**string == '/') || (**pattern == '/'))))
-        return result;
+	/* Refuse to advance over trailing slash or NULs */
+	if (**string == '\0' || **pattern == '\0' ||
+	    (slash && ((**string == '/') || (**pattern == '/'))))
+		return result;
 
 fnmatch_ch_success:
-    ++*pattern;
-    ++*string;
-    return result;
+	++*pattern;
+	++*string;
+	return result;
 }
 
 
 int fnmatch(const char *pattern, const char *string, int flags)
 {
-    static const char dummystring[2] = {' ', 0};
-    const int escape = !(flags & FNM_NOESCAPE);
-    const int slash = !!(flags & FNM_PATHNAME);
-    const int leading_dir = !!(flags & FNM_LEADING_DIR);
-    const char *strendseg;
-    const char *dummyptr;
-    const char *matchptr;
-    int wild;
-    /* For '*' wild processing only; surpress 'used before initialization'
-     * warnings with dummy initialization values;
-     */
-    const char *strstartseg = NULL;
-    const char *mismatch = NULL;
-    int matchlen = 0;
+	static const char dummystring[2] = {' ', 0};
+	const int escape = !(flags & FNM_NOESCAPE);
+	const int slash = !!(flags & FNM_PATHNAME);
+	const int leading_dir = !!(flags & FNM_LEADING_DIR);
+	const char *dummyptr, *matchptr, *strendseg;
+	int wild;
+	/* For '*' wild processing only; suppress 'used before initialization'
+	 * warnings with dummy initialization values;
+	 */
+	const char *strstartseg = NULL;
+	const char *mismatch = NULL;
+	int matchlen = 0;
 
-    if (*pattern == '*')
-        goto firstsegment;
+	if (*pattern == '*')
+		goto firstsegment;
 
-    while (*pattern && *string)
-    {
-        /* Pre-decode "\/" which has no special significance, and
-         * match balanced slashes, starting a new segment pattern
-         */
-        if (slash && escape && (*pattern == '\\') && (pattern[1] == '/'))
-            ++pattern;
-        if (slash && (*pattern == '/') && (*string == '/')) {
-            ++pattern;
-            ++string;
-        }            
+	while (*pattern && *string) {
+		/*
+		 * Pre-decode "\/" which has no special significance, and
+		 * match balanced slashes, starting a new segment pattern.
+		 */
+		if (slash && escape && (*pattern == '\\') && (pattern[1] == '/'))
+			++pattern;
+		if (slash && (*pattern == '/') && (*string == '/')) {
+			++pattern;
+			++string;
+		}
 
 firstsegment:
-        /* At the beginning of each segment, validate leading period behavior.
-         */
-        if ((flags & FNM_PERIOD) && (*string == '.'))
-        {
-            if (*pattern == '.')
-                ++pattern;
-            else if (escape && (*pattern == '\\') && (pattern[1] == '.'))
-                pattern += 2;
-            else
-                return FNM_NOMATCH;
-            ++string;
-        }
+		/*
+		 * At the beginning of each segment, validate leading period
+		 * behavior.
+		 */
+		if ((flags & FNM_PERIOD) && (*string == '.')) {
+		    if (*pattern == '.')
+			    ++pattern;
+		    else if (escape && (*pattern == '\\') && (pattern[1] == '.'))
+			    pattern += 2;
+		    else
+			    return FNM_NOMATCH;
+		    ++string;
+		}
 
-        /* Determine the end of string segment
-         *
-         * Presumes '/' character is unique, not composite in any MBCS encoding
-         */
-        if (slash) {
-            strendseg = strchr(string, '/');
-            if (!strendseg)
-                strendseg = strchr(string, '\0');
-        }
-        else {
-            strendseg = strchr(string, '\0');
-        }
+		/*
+		 * Determine the end of string segment.  Presumes '/'
+		 * character is unique, not composite in any MBCS encoding
+		 */
+		if (slash) {
+			strendseg = strchr(string, '/');
+			if (!strendseg)
+				strendseg = strchr(string, '\0');
+		} else {
+			strendseg = strchr(string, '\0');
+		}
 
-        /* Allow pattern '*' to be consumed even with no remaining string to match
-         */
-        while (*pattern)
-        {
-            if ((string > strendseg)
-                || ((string == strendseg) && (*pattern != '*')))
-                break;
+		/*
+		 * Allow pattern '*' to be consumed even with no remaining
+		 * string to match.
+		 */
+		while (*pattern) {
+			if ((string > strendseg) ||
+			    ((string == strendseg) && (*pattern != '*')))
+				break;
 
-            if (slash && ((*pattern == '/')
-                           || (escape && (*pattern == '\\')
-                                      && (pattern[1] == '/'))))
-                break;
+			if (slash && ((*pattern == '/') ||
+			    (escape && (*pattern == '\\') && (pattern[1] == '/'))))
+				break;
 
-            /* Reduce groups of '*' and '?' to n '?' matches
-             * followed by one '*' test for simplicity
-             */
-            for (wild = 0; ((*pattern == '*') || (*pattern == '?')); ++pattern)
-            {
-                if (*pattern == '*') {
-                    wild = 1;
-                }
-                else if (string < strendseg) {  /* && (*pattern == '?') */
-                    /* XXX: Advance 1 char for MBCS locale */
-                    ++string;
-                }
-                else {  /* (string >= strendseg) && (*pattern == '?') */
-                    return FNM_NOMATCH;
-                }
-            }
+			/*
+			 * Reduce groups of '*' and '?' to n '?' matches
+			 * followed by one '*' test for simplicity.
+			 */
+			for (wild = 0; (*pattern == '*') || (*pattern == '?'); ++pattern) {
+				if (*pattern == '*') {
+					wild = 1;
+				} else if (string < strendseg) {  /* && (*pattern == '?') */
+					/* XXX: Advance 1 char for MBCS locale */
+					++string;
+				}
+				else {  /* (string >= strendseg) && (*pattern == '?') */
+					return FNM_NOMATCH;
+				}
+			}
 
-            if (wild)
-            {
-                strstartseg = string;
-                mismatch = pattern;
+			if (wild) {
+				strstartseg = string;
+				mismatch = pattern;
 
-                /* Count fixed (non '*') char matches remaining in pattern
-                 * excluding '/' (or "\/") and '*'
-                 */
-                for (matchptr = pattern, matchlen = 0; 1; ++matchlen)
-                {
-                    if ((*matchptr == '\0') 
-                        || (slash && ((*matchptr == '/')
-                                      || (escape && (*matchptr == '\\')
-                                                 && (matchptr[1] == '/')))))
-                    {
-                        /* Compare precisely this many trailing string chars,
-                         * the resulting match needs no wildcard loop
-                         */
-                        /* XXX: Adjust for MBCS */
-                        if (string + matchlen > strendseg)
-                            return FNM_NOMATCH;
+				/*
+				 * Count fixed (non '*') char matches remaining
+				 * in pattern * excluding '/' (or "\/") and '*'.
+				 */
+				for (matchptr = pattern, matchlen = 0; 1; ++matchlen) {
+					if ((*matchptr == '\0') ||
+					    (slash && ((*matchptr == '/') ||
+					    (escape && (*matchptr == '\\') &&
+					    (matchptr[1] == '/'))))) {
+						/* Compare precisely this many
+						 * trailing string chars, the
+						 * resulting match needs no
+						 * wildcard loop.
+						 */
+						/* XXX: Adjust for MBCS */
+						if (string + matchlen > strendseg)
+							return FNM_NOMATCH;
 
-                        string = strendseg - matchlen;
-                        wild = 0;
-                        break;
-                    }
+						string = strendseg - matchlen;
+						wild = 0;
+						break;
+					}
 
-                    if (*matchptr == '*')
-                    {
-                        /* Ensure at least this many trailing string chars remain
-                         * for the first comparison
-                         */
-                        /* XXX: Adjust for MBCS */
-                        if (string + matchlen > strendseg)
-                            return FNM_NOMATCH;
+					if (*matchptr == '*') {
+						/*
+						 * Ensure at least this many
+						 * trailing string chars remain
+						 * for the first comparison.
+						 */
+						/* XXX: Adjust for MBCS */
+						if (string + matchlen > strendseg)
+							return FNM_NOMATCH;
 
-                        /* Begin first wild comparison at the current position */
-                        break;
-                    }
+						/*
+						 * Begin first wild comparison
+						 * at the current position.
+						 */
+						break;
+					}
 
-                    /* Skip forward in pattern by a single character match
-                     * Use a dummy fnmatch_ch() test to count one "[range]" escape
-                     */ 
-                    /* XXX: Adjust for MBCS */
-                    if (escape && (*matchptr == '\\') && matchptr[1]) {
-                        matchptr += 2;
-                    }
-                    else if (*matchptr == '[') {
-                        dummyptr = dummystring;
-                        fnmatch_ch(&matchptr, &dummyptr, flags);
-                    }
-                    else {
-                        ++matchptr;
-                    }
-                }
-            }
+					/*
+					 * Skip forward in pattern by a single
+					 * character match Use a dummy
+					 * fnmatch_ch() test to count one
+					 * "[range]" escape.
+					 */
+					/* XXX: Adjust for MBCS */
+					if (escape && (*matchptr == '\\') &&
+					    matchptr[1]) {
+						matchptr += 2;
+					} else if (*matchptr == '[') {
+						dummyptr = dummystring;
+						fnmatch_ch(&matchptr, &dummyptr,
+						    flags);
+					} else {
+						++matchptr;
+					}
+				}
+			}
 
-            /* Incrementally match string against the pattern
-             */
-            while (*pattern && (string < strendseg))
-            {
-                /* Success; begin a new wild pattern search
-                 */
-                if (*pattern == '*')
-                    break;
+			/* Incrementally match string against the pattern. */
+			while (*pattern && (string < strendseg)) {
+				/* Success; begin a new wild pattern search. */
+				if (*pattern == '*')
+					break;
 
-                if (slash && ((*string == '/')
-                              || (*pattern == '/')
-                              || (escape && (*pattern == '\\')
-                                         && (pattern[1] == '/'))))
-                    break;
+				if (slash && ((*string == '/') ||
+				    (*pattern == '/') || (escape &&
+				    (*pattern == '\\') && (pattern[1] == '/'))))
+					break;
 
-                /* Compare ch's (the pattern is advanced over "\/" to the '/',
-                 * but slashes will mismatch, and are not consumed)
-                 */
-                if (!fnmatch_ch(&pattern, &string, flags))
-                    continue;
+				/*
+				 * Compare ch's (the pattern is advanced over
+				 * "\/" to the '/', but slashes will mismatch,
+				 * and are not consumed).
+				 */
+				if (!fnmatch_ch(&pattern, &string, flags))
+					continue;
 
-                /* Failed to match, loop against next char offset of string segment 
-                 * until not enough string chars remain to match the fixed pattern
-                 */
-                if (wild) {
-                    /* XXX: Advance 1 char for MBCS locale */
-                    string = ++strstartseg;
-                    if (string + matchlen > strendseg)
-                        return FNM_NOMATCH;
+				/*
+				 * Failed to match, loop against next char
+				 * offset of string segment until not enough
+				 * string chars remain to match the fixed
+				 * pattern.
+				 */
+				if (wild) {
+					/* XXX: Advance 1 char for MBCS locale */
+					string = ++strstartseg;
+					if (string + matchlen > strendseg)
+						return FNM_NOMATCH;
 
-                    pattern = mismatch;
-                    continue;
-                }
-                else
-                    return FNM_NOMATCH;
-            }
-        }
+					pattern = mismatch;
+					continue;
+				} else
+					return FNM_NOMATCH;
+			}
+		}
 
-        if (*string && !((slash || leading_dir) && (*string == '/')))
-            return FNM_NOMATCH;
+		if (*string && !((slash || leading_dir) && (*string == '/')))
+			return FNM_NOMATCH;
 
-        if (*pattern && !(slash && ((*pattern == '/')
-                                    || (escape && (*pattern == '\\')
-                                               && (pattern[1] == '/')))))
-            return FNM_NOMATCH;
+		if (*pattern && !(slash && ((*pattern == '/') ||
+		    (escape && (*pattern == '\\') && (pattern[1] == '/')))))
+			return FNM_NOMATCH;
 
-        if (leading_dir && !*pattern && *string == '/')
-            return 0;
-    }
+		if (leading_dir && !*pattern && *string == '/')
+			return 0;
+	}
 
-    /* Where both pattern and string are at EOS, declare success
-     */
-    if (!*string && !*pattern)
-        return 0;
+	/* Where both pattern and string are at EOS, declare success.  */
+	if (!*string && !*pattern)
+		return 0;
 
-    /* pattern didn't match to the end of string */
-    return FNM_NOMATCH;
+	/* Pattern didn't match to the end of string. */
+	return FNM_NOMATCH;
 }
diff --git a/libc/upstream-openbsd/lib/libc/locale/mbtowc.c b/libc/upstream-openbsd/lib/libc/locale/mbtowc.c
index 920f4bf..4399ed8 100644
--- a/libc/upstream-openbsd/lib/libc/locale/mbtowc.c
+++ b/libc/upstream-openbsd/lib/libc/locale/mbtowc.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: mbtowc.c,v 1.2 2012/12/05 23:20:00 deraadt Exp $ */
+/*	$OpenBSD: mbtowc.c,v 1.3 2016/02/27 14:02:13 schwarze Exp $ */
 
 /*-
  * Copyright (c) 2002-2004 Tim J. Robbins.
@@ -44,7 +44,14 @@
 		return (0);
 	}
 	rval = mbrtowc(pwc, s, n, &mbs);
-	if (rval == (size_t)-1 || rval == (size_t)-2)
-		return (-1);
-	return ((int)rval);
+
+	switch (rval) {
+	case (size_t)-2:
+		errno = EILSEQ;
+		/* FALLTHROUGH */
+	case (size_t)-1:
+		return -1;
+	default:
+		return (int)rval;
+	}
 }
diff --git a/libc/upstream-openbsd/lib/libc/stdio/fgetln.c b/libc/upstream-openbsd/lib/libc/stdio/fgetln.c
index 1109cf2..903dbd6 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/fgetln.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/fgetln.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: fgetln.c,v 1.13 2015/01/05 21:58:52 millert Exp $ */
+/*	$OpenBSD: fgetln.c,v 1.17 2017/03/17 14:53:08 deraadt Exp $ */
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -46,7 +46,7 @@
 
 	if (fp->_lb._size >= newsize)
 		return (0);
-	if ((p = realloc(fp->_lb._base, newsize)) == NULL)
+	if ((p = recallocarray(fp->_lb._base, fp->_lb._size, newsize, 1)) == NULL)
 		return (-1);
 	fp->_lb._base = p;
 	fp->_lb._size = newsize;
@@ -76,7 +76,7 @@
 		goto error;
 
 	/* look for a newline in the input */
-	if ((p = memchr((void *)fp->_p, '\n', fp->_r)) != NULL) {
+	if ((p = memchr(fp->_p, '\n', fp->_r)) != NULL) {
 		/*
 		 * Found one.  Flag buffer as modified to keep fseek from
 		 * `optimising' a backward seek, in case the user stomps on
@@ -112,12 +112,14 @@
 		 */
 		if (__slbexpand(fp, len + OPTIMISTIC))
 			goto error;
-		(void)memcpy((void *)(fp->_lb._base + off), (void *)fp->_p,
-		    len - off);
+		(void)memcpy(fp->_lb._base + off, fp->_p, len - off);
 		off = len;
-		if (__srefill(fp))
-			break;	/* EOF or error: return partial line */
-		if ((p = memchr((void *)fp->_p, '\n', fp->_r)) == NULL)
+		if (__srefill(fp)) {
+			if (fp->_flags & __SEOF)
+				break;
+			goto error;
+		}
+		if ((p = memchr(fp->_p, '\n', fp->_r)) == NULL)
 			continue;
 
 		/* got it: finish up the line (like code above) */
@@ -126,8 +128,7 @@
 		len += diff;
 		if (__slbexpand(fp, len))
 			goto error;
-		(void)memcpy((void *)(fp->_lb._base + off), (void *)fp->_p,
-		    diff);
+		(void)memcpy(fp->_lb._base + off, fp->_p, diff);
 		fp->_r -= diff;
 		fp->_p = p;
 		break;
@@ -142,3 +143,4 @@
 	*lenp = 0;
 	return (NULL);
 }
+DEF_WEAK(fgetln);
diff --git a/libc/upstream-openbsd/lib/libc/stdio/fputwc.c b/libc/upstream-openbsd/lib/libc/stdio/fputwc.c
index 829c22c..e156922 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/fputwc.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/fputwc.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: fputwc.c,v 1.6 2015/10/01 02:32:07 guenther Exp $	*/
+/*	$OpenBSD: fputwc.c,v 1.7 2016/01/26 13:57:02 schwarze Exp $	*/
 /* $NetBSD: fputwc.c,v 1.3 2003/03/07 07:11:37 tshiozak Exp $ */
 
 /*-
@@ -62,7 +62,7 @@
 
 	size = wcrtomb(buf, wc, st);
 	if (size == (size_t)-1) {
-		errno = EILSEQ;
+		fp->_flags |= __SERR;
 		return WEOF;
 	}
 
diff --git a/libc/upstream-openbsd/lib/libc/stdio/fvwrite.c b/libc/upstream-openbsd/lib/libc/stdio/fvwrite.c
index 1088991..ba58f9d 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/fvwrite.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/fvwrite.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: fvwrite.c,v 1.17 2009/11/09 00:18:27 kurt Exp $ */
+/*	$OpenBSD: fvwrite.c,v 1.20 2017/03/17 16:06:33 millert Exp $ */
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -35,6 +35,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
+#include <unistd.h>
 #include "local.h"
 #include "fvwrite.h"
 
@@ -63,7 +64,7 @@
 	}
 
 #define	MIN(a, b) ((a) < (b) ? (a) : (b))
-#define	COPY(n)	  (void)memcpy((void *)fp->_p, (void *)p, (size_t)(n))
+#define	COPY(n)	  (void)memcpy(fp->_p, p, n)
 
 	iov = uio->uio_iov;
 	p = iov->iov_base;
@@ -105,15 +106,14 @@
 			if ((fp->_flags & (__SALC | __SSTR)) ==
 			    (__SALC | __SSTR) && fp->_w < len) {
 				size_t blen = fp->_p - fp->_bf._base;
+				int pgmsk = getpagesize() - 1;
 				unsigned char *_base;
 				int _size;
 
-				/* Allocate space exponentially. */
-				_size = fp->_bf._size;
-				do {
-					_size = (_size << 1) + 1;
-				} while (_size < blen + len);
-				_base = realloc(fp->_bf._base, _size + 1);
+				/* Round up to nearest page. */
+				_size = ((blen + len + 1 + pgmsk) & ~pgmsk) - 1;
+				_base = recallocarray(fp->_bf._base,
+				    fp->_bf._size + 1, _size + 1, 1);
 				if (_base == NULL)
 					goto err;
 				fp->_w += _size - fp->_bf._size;
@@ -164,7 +164,7 @@
 		do {
 			GETIOV(nlknown = 0);
 			if (!nlknown) {
-				nl = memchr((void *)p, '\n', len);
+				nl = memchr(p, '\n', len);
 				nldist = nl ? nl + 1 - p : len + 1;
 				nlknown = 1;
 			}
diff --git a/libc/upstream-openbsd/lib/libc/stdio/fwide.c b/libc/upstream-openbsd/lib/libc/stdio/fwide.c
index 27ca0f8..4b93d59 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/fwide.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/fwide.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: fwide.c,v 1.5 2015/08/31 02:53:57 guenther Exp $	*/
+/*	$OpenBSD: fwide.c,v 1.6 2019/12/03 05:03:37 asou Exp $	*/
 /* $NetBSD: fwide.c,v 1.2 2003/01/18 11:29:54 thorpej Exp $ */
 
 /*-
@@ -51,8 +51,10 @@
 
 	FLOCKFILE(fp);
 	wcio = WCIO_GET(fp);
-	if (!wcio)
+	if (!wcio) {
+		FUNLOCKFILE(fp);
 		return 0; /* XXX */
+	}
 
 	if (wcio->wcio_mode == 0 && mode != 0)
 		wcio->wcio_mode = mode;
diff --git a/libc/upstream-openbsd/lib/libc/stdio/getdelim.c b/libc/upstream-openbsd/lib/libc/stdio/getdelim.c
index 58ff0a1..d709a3d 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/getdelim.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/getdelim.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: getdelim.c,v 1.4 2015/08/31 02:53:57 guenther Exp $	*/
+/*	$OpenBSD: getdelim.c,v 1.6 2017/04/13 18:36:51 brynet Exp $	*/
 /* $NetBSD: getdelim.c,v 1.13 2011/07/22 23:12:30 joerg Exp $ */
 
 /*
@@ -73,7 +73,7 @@
 		}
 
 		/* Scan through looking for the separator */
-		p = memchr(fp->_p, sep, (size_t)fp->_r);
+		p = memchr(fp->_p, sep, fp->_r);
 		if (p == NULL)
 			len = fp->_r;
 		else
@@ -103,7 +103,7 @@
 				newlen++;
 			}
 
-			newb = realloc(*buf, newlen);
+			newb = recallocarray(*buf, *buflen, newlen, 1);
 			if (newb == NULL)
 				goto error;
 			*buf = newb;
diff --git a/libc/upstream-openbsd/lib/libc/stdio/open_memstream.c b/libc/upstream-openbsd/lib/libc/stdio/open_memstream.c
index f708acc..6ee5a5c 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/open_memstream.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/open_memstream.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: open_memstream.c,v 1.6 2015/08/31 02:53:57 guenther Exp $	*/
+/*	$OpenBSD: open_memstream.c,v 1.8 2019/05/02 08:30:10 yasuoka Exp $	*/
 
 /*
  * Copyright (c) 2011 Martin Pieuchot <mpi@openbsd.org>
@@ -50,7 +50,7 @@
 
 		if (sz < end + 1)
 			sz = end + 1;
-		p = realloc(st->string, sz);
+		p = recallocarray(st->string, st->size, sz, 1);
 		if (!p)
 			return (-1);
 		bzero(p + st->size, sz - st->size);
@@ -76,7 +76,7 @@
 memstream_seek(void *v, fpos_t off, int whence)
 {
 	struct state	*st = v;
-	ssize_t		 base = 0;
+	size_t		 base = 0;
 
 	switch (whence) {
 	case SEEK_SET:
@@ -89,7 +89,7 @@
 		break;
 	}
 
-	if (off > SIZE_MAX - base || off < -base) {
+	if ((off > 0 && off > SIZE_MAX - base) || (off < 0 && base < -off)) {
 		errno = EOVERFLOW;
 		return (-1);
 	}
diff --git a/libc/upstream-openbsd/lib/libc/stdio/vasprintf.c b/libc/upstream-openbsd/lib/libc/stdio/vasprintf.c
index 98cdb45..c2e17e7 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/vasprintf.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/vasprintf.c
@@ -1,7 +1,7 @@
-/*	$OpenBSD: vasprintf.c,v 1.19 2015/12/28 22:08:18 mmcc Exp $	*/
+/*	$OpenBSD: vasprintf.c,v 1.23 2019/01/25 00:19:25 millert Exp $	*/
 
 /*
- * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
+ * Copyright (c) 1997 Todd C. Miller <millert@openbsd.org>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -20,31 +20,40 @@
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
+#include <unistd.h>
 #include "local.h"
 
+#define	INITIAL_SIZE	128
+
 int
 vasprintf(char **str, const char *fmt, __va_list ap)
 {
 	int ret;
 	FILE f;
 	struct __sfileext fext;
-	unsigned char *_base;
+	const int pgsz = getpagesize();
 
 	_FILEEXT_SETUP(&f, &fext);
 	f._file = -1;
 	f._flags = __SWR | __SSTR | __SALC;
-	f._bf._base = f._p = malloc(128);
+	f._bf._base = f._p = malloc(INITIAL_SIZE);
 	if (f._bf._base == NULL)
 		goto err;
-	f._bf._size = f._w = 127;		/* Leave room for the NUL */
+	f._bf._size = f._w = INITIAL_SIZE - 1;	/* leave room for the NUL */
 	ret = __vfprintf(&f, fmt, ap);
 	if (ret == -1)
 		goto err;
 	*f._p = '\0';
-	_base = realloc(f._bf._base, ret + 1);
-	if (_base == NULL)
-		goto err;
-	*str = (char *)_base;
+	if (ret + 1 > INITIAL_SIZE && ret + 1 < pgsz / 2) {
+		/* midsize allocations can try to conserve memory */
+		unsigned char *_base = recallocarray(f._bf._base,
+		    f._bf._size + 1, ret + 1, 1);
+
+		if (_base == NULL)
+			goto err;
+		*str = (char *)_base;
+	} else
+		*str = (char *)f._bf._base;
 	return (ret);
 
 err:
diff --git a/libc/upstream-openbsd/lib/libc/stdio/vdprintf.c b/libc/upstream-openbsd/lib/libc/stdio/vdprintf.c
index e76fcd4..ad4ab0a 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/vdprintf.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/vdprintf.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: vdprintf.c,v 1.2 2015/08/31 02:53:57 guenther Exp $	*/
+/*	$OpenBSD: vdprintf.c,v 1.3 2019/03/03 16:41:41 semarie Exp $	*/
 /*	$FreeBSD: src/lib/libc/stdio/vdprintf.c,v 1.4 2012/11/17 01:49:40 svnexp Exp $ */
 
 /*-
@@ -69,6 +69,6 @@
 	if ((ret = __vfprintf(&f, fmt, ap)) < 0)
 		return ret;
 
-	return fflush(&f) ? EOF : ret;
+	return __sflush(&f) ? EOF : ret;
 }
 DEF_WEAK(vdprintf);
diff --git a/libc/upstream-openbsd/lib/libc/stdlib/recallocarray.c b/libc/upstream-openbsd/lib/libc/stdlib/recallocarray.c
new file mode 100644
index 0000000..a2f37fe
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/stdlib/recallocarray.c
@@ -0,0 +1,81 @@
+/*	$OpenBSD: recallocarray.c,v 1.1 2017/03/06 18:44:21 otto Exp $	*/
+/*
+ * Copyright (c) 2008, 2017 Otto Moerbeek <otto@drijf.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+
+/*
+ * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
+ * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
+ */
+#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
+
+void *
+recallocarray(void *ptr, size_t oldnmemb, size_t newnmemb, size_t size)
+{
+	size_t oldsize, newsize;
+	void *newptr;
+
+	if (ptr == NULL)
+		return calloc(newnmemb, size);
+
+	if ((newnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
+	    newnmemb > 0 && SIZE_MAX / newnmemb < size) {
+		errno = ENOMEM;
+		return NULL;
+	}
+	newsize = newnmemb * size;
+
+	if ((oldnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
+	    oldnmemb > 0 && SIZE_MAX / oldnmemb < size) {
+		errno = EINVAL;
+		return NULL;
+	}
+	oldsize = oldnmemb * size;
+	
+	/*
+	 * Don't bother too much if we're shrinking just a bit,
+	 * we do not shrink for series of small steps, oh well.
+	 */
+	if (newsize <= oldsize) {
+		size_t d = oldsize - newsize;
+
+		if (d < oldsize / 2 && d < getpagesize()) {
+			memset((char *)ptr + newsize, 0, d);
+			return ptr;
+		}
+	}
+
+	newptr = malloc(newsize);
+	if (newptr == NULL)
+		return NULL;
+
+	if (newsize > oldsize) {
+		memcpy(newptr, ptr, oldsize);
+		memset((char *)newptr + oldsize, 0, newsize - oldsize);
+	} else
+		memcpy(newptr, ptr, newsize);
+
+	explicit_bzero(ptr, oldsize);
+	free(ptr);
+
+	return newptr;
+}
+DEF_WEAK(recallocarray);
diff --git a/libc/upstream-openbsd/lib/libc/stdlib/setenv.c b/libc/upstream-openbsd/lib/libc/stdlib/setenv.c
index e55a1fe..15c550b 100644
--- a/libc/upstream-openbsd/lib/libc/stdlib/setenv.c
+++ b/libc/upstream-openbsd/lib/libc/stdlib/setenv.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: setenv.c,v 1.16 2015/09/13 08:31:47 guenther Exp $ */
+/*	$OpenBSD: setenv.c,v 1.19 2016/09/21 04:38:56 guenther Exp $ */
 /*
  * Copyright (c) 1987 Regents of the University of California.
  * All rights reserved.
@@ -32,7 +32,6 @@
 #include <stdlib.h>
 #include <string.h>
 
-extern char **environ;
 static char **lastenv;				/* last value of environ */
 
 /*
@@ -44,7 +43,7 @@
 putenv(char *str)
 {
 	char **P, *cp;
-	size_t cnt;
+	size_t cnt = 0;
 	int offset = 0;
 
 	for (cp = str; *cp && *cp != '='; ++cp)
@@ -66,13 +65,15 @@
 	}
 
 	/* create new slot for string */
-	for (P = environ; *P != NULL; P++)
-		;
-	cnt = P - environ;
+	if (environ != NULL) {
+		for (P = environ; *P != NULL; P++)
+			;
+		cnt = P - environ;
+	}
 	P = reallocarray(lastenv, cnt + 2, sizeof(char *));
 	if (!P)
 		return (-1);
-	if (lastenv != environ)
+	if (lastenv != environ && environ != NULL)
 		memcpy(P, environ, cnt * sizeof(char *));
 	lastenv = environ = P;
 	environ[cnt] = str;
@@ -123,22 +124,24 @@
 					break;
 		}
 	} else {					/* create new slot */
-		size_t cnt;
+		size_t cnt = 0;
 
-		for (P = environ; *P != NULL; P++)
-			;
-		cnt = P - environ;
+		if (environ != NULL) {
+			for (P = environ; *P != NULL; P++)
+				;
+			cnt = P - environ;
+		}
 		P = reallocarray(lastenv, cnt + 2, sizeof(char *));
 		if (!P)
 			return (-1);
-		if (lastenv != environ)
+		if (lastenv != environ && environ != NULL)
 			memcpy(P, environ, cnt * sizeof(char *));
 		lastenv = environ = P;
 		offset = cnt;
 		environ[cnt + 1] = NULL;
 	}
 	if (!(environ[offset] =			/* name + `=' + value */
-	    malloc((size_t)((int)(np - name) + l_value + 2))))
+	    malloc((int)(np - name) + l_value + 2)))
 		return (-1);
 	for (C = environ[offset]; (*C = *name++) && *C != '='; ++C)
 		;
diff --git a/libc/upstream-openbsd/lib/libc/string/memmem.c b/libc/upstream-openbsd/lib/libc/string/memmem.c
new file mode 100644
index 0000000..3b180b4
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/string/memmem.c
@@ -0,0 +1,184 @@
+/*	$OpenBSD: memmem.c,v 1.5 2020/04/16 12:39:28 claudio Exp $ */
+
+/*
+ * Copyright (c) 2005-2020 Rich Felker, et al.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <string.h>
+#include <stdint.h>
+
+static char *
+twobyte_memmem(const unsigned char *h, size_t k, const unsigned char *n)
+{
+	uint16_t nw = n[0]<<8 | n[1], hw = h[0]<<8 | h[1];
+	for (h+=2, k-=2; k; k--, hw = hw<<8 | *h++)
+		if (hw == nw) return (char *)h-2;
+	return hw == nw ? (char *)h-2 : 0;
+}
+
+static char *
+threebyte_memmem(const unsigned char *h, size_t k, const unsigned char *n)
+{
+	uint32_t nw = n[0]<<24 | n[1]<<16 | n[2]<<8;
+	uint32_t hw = h[0]<<24 | h[1]<<16 | h[2]<<8;
+	for (h+=3, k-=3; k; k--, hw = (hw|*h++)<<8)
+		if (hw == nw) return (char *)h-3;
+	return hw == nw ? (char *)h-3 : 0;
+}
+
+static char *
+fourbyte_memmem(const unsigned char *h, size_t k, const unsigned char *n)
+{
+	uint32_t nw = n[0]<<24 | n[1]<<16 | n[2]<<8 | n[3];
+	uint32_t hw = h[0]<<24 | h[1]<<16 | h[2]<<8 | h[3];
+	for (h+=4, k-=4; k; k--, hw = hw<<8 | *h++)
+		if (hw == nw) return (char *)h-4;
+	return hw == nw ? (char *)h-4 : 0;
+}
+
+#define MAX(a,b) ((a)>(b)?(a):(b))
+#define MIN(a,b) ((a)<(b)?(a):(b))
+
+#define BITOP(a,b,op) \
+ ((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a))))
+
+/*
+ * Maxime Crochemore and Dominique Perrin, Two-way string-matching,
+ * Journal of the ACM, 38(3):651-675, July 1991.
+ */
+static char *
+twoway_memmem(const unsigned char *h, const unsigned char *z,
+    const unsigned char *n, size_t l)
+{
+	size_t i, ip, jp, k, p, ms, p0, mem, mem0;
+	size_t byteset[32 / sizeof(size_t)] = { 0 };
+	size_t shift[256];
+
+	/* Computing length of needle and fill shift table */
+	for (i=0; i<l; i++)
+		BITOP(byteset, n[i], |=), shift[n[i]] = i+1;
+
+	/* Compute maximal suffix */
+	ip = -1; jp = 0; k = p = 1;
+	while (jp+k<l) {
+		if (n[ip+k] == n[jp+k]) {
+			if (k == p) {
+				jp += p;
+				k = 1;
+			} else k++;
+		} else if (n[ip+k] > n[jp+k]) {
+			jp += k;
+			k = 1;
+			p = jp - ip;
+		} else {
+			ip = jp++;
+			k = p = 1;
+		}
+	}
+	ms = ip;
+	p0 = p;
+
+	/* And with the opposite comparison */
+	ip = -1; jp = 0; k = p = 1;
+	while (jp+k<l) {
+		if (n[ip+k] == n[jp+k]) {
+			if (k == p) {
+				jp += p;
+				k = 1;
+			} else k++;
+		} else if (n[ip+k] < n[jp+k]) {
+			jp += k;
+			k = 1;
+			p = jp - ip;
+		} else {
+			ip = jp++;
+			k = p = 1;
+		}
+	}
+	if (ip+1 > ms+1) ms = ip;
+	else p = p0;
+
+	/* Periodic needle? */
+	if (memcmp(n, n+p, ms+1)) {
+		mem0 = 0;
+		p = MAX(ms, l-ms-1) + 1;
+	} else mem0 = l-p;
+	mem = 0;
+
+	/* Search loop */
+	for (;;) {
+		/* If remainder of haystack is shorter than needle, done */
+		if (z-h < l) return 0;
+
+		/* Check last byte first; advance by shift on mismatch */
+		if (BITOP(byteset, h[l-1], &)) {
+			k = l-shift[h[l-1]];
+			if (k) {
+				if (k < mem) k = mem;
+				h += k;
+				mem = 0;
+				continue;
+			}
+		} else {
+			h += l;
+			mem = 0;
+			continue;
+		}
+
+		/* Compare right half */
+		for (k=MAX(ms+1,mem); k<l && n[k] == h[k]; k++);
+		if (k < l) {
+			h += k-ms;
+			mem = 0;
+			continue;
+		}
+		/* Compare left half */
+		for (k=ms+1; k>mem && n[k-1] == h[k-1]; k--);
+		if (k <= mem) return (char *)h;
+		h += p;
+		mem = mem0;
+	}
+}
+
+void *
+memmem(const void *h0, size_t k, const void *n0, size_t l)
+{
+	const unsigned char *h = h0, *n = n0;
+
+	/* Return immediately on empty needle */
+	if (!l) return (void *)h;
+
+	/* Return immediately when needle is longer than haystack */
+	if (k<l) return 0;
+
+	/* Use faster algorithms for short needles */
+	h = memchr(h0, *n, k);
+	if (!h || l==1) return (void *)h;
+	k -= h - (const unsigned char *)h0;
+	if (k<l) return 0;
+	if (l==2) return twobyte_memmem(h, k, n);
+	if (l==3) return threebyte_memmem(h, k, n);
+	if (l==4) return fourbyte_memmem(h, k, n);
+
+	return twoway_memmem(h, h+k, n, l);
+}
+DEF_WEAK(memmem);
diff --git a/libc/upstream-openbsd/lib/libc/string/strstr.c b/libc/upstream-openbsd/lib/libc/string/strstr.c
index 079d69d..241a080 100644
--- a/libc/upstream-openbsd/lib/libc/string/strstr.c
+++ b/libc/upstream-openbsd/lib/libc/string/strstr.c
@@ -1,7 +1,7 @@
-/*	$OpenBSD: strstr.c,v 1.8 2018/04/30 07:44:56 denis Exp $ */
+/*	$OpenBSD: strstr.c,v 1.9 2020/04/16 12:37:52 claudio Exp $ */
 
 /*
- * Copyright (c) 2005-2014 Rich Felker
+ * Copyright (c) 2005-2018 Rich Felker
  *
  * Permission is hereby granted, free of charge, to any person obtaining
  * a copy of this software and associated documentation files (the
@@ -24,13 +24,8 @@
  */
 
 #include <string.h>
-#include <stdlib.h>
 #include <stdint.h>
 
-#ifdef DEBUG
-#include <stdio.h>
-#endif
-
 static char *
 twobyte_strstr(const unsigned char *h, const unsigned char *n)
 {
@@ -146,11 +141,8 @@
 		/* Check last byte first; advance by shift on mismatch */
 		if (BITOP(byteset, h[l-1], &)) {
 			k = l-shift[h[l-1]];
-#ifdef DEBUG
-			printf("adv by %zu (on %c) at [%s] (%zu;l=%zu)\n", k, h[l-1], h, shift[h[l-1]], l);
-#endif
 			if (k) {
-				if (mem0 && mem && k < p) k = l-p;
+				if (k < mem) k = mem;
 				h += k;
 				mem = 0;
 				continue;
diff --git a/libm/Android.bp b/libm/Android.bp
index 1c4fe55..6a348e1 100644
--- a/libm/Android.bp
+++ b/libm/Android.bp
@@ -1,5 +1,3 @@
-bionic_coverage = false
-
 //
 // libm.so and libm.a for target.
 //
@@ -488,7 +486,6 @@
     include_dirs: ["bionic/libc"],
     system_shared_libs: ["libc"],
 
-    native_coverage: bionic_coverage,
     sanitize: {
         address: false,
         fuzzer: false,
diff --git a/linker/ld.config.format.md b/linker/ld.config.format.md
index f9fbcde..a16efa4 100644
--- a/linker/ld.config.format.md
+++ b/linker/ld.config.format.md
@@ -80,7 +80,9 @@
 namespace.ns.links = default
 namespace.ns.link.default.shared_libs = libc.so:libdl.so:libm.so:libstdc++.so
 
-# This defines what libraries are allowed to be loaded from ns1
+# [Deprecated] This defines what libraries are allowed to be loaded from ns1
 namespace.ns1.whitelisted = libsomething.so
+# This defines what libraries are allowed to be loaded from ns1
+namespace.ns1.allowed_libs = libsomething2.so
 ```
 
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 10608f4..302e4b3 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -186,10 +186,10 @@
   return false;
 }
 
-// TODO(dimitry): The grey-list is a workaround for http://b/26394120 ---
+// TODO(dimitry): The exempt-list is a workaround for http://b/26394120 ---
 // gradually remove libraries from this list until it is gone.
-static bool is_greylisted(android_namespace_t* ns, const char* name, const soinfo* needed_by) {
-  static const char* const kLibraryGreyList[] = {
+static bool is_exempt_lib(android_namespace_t* ns, const char* name, const soinfo* needed_by) {
+  static const char* const kLibraryExemptList[] = {
     "libandroid_runtime.so",
     "libbinder.so",
     "libcrypto.so",
@@ -206,13 +206,13 @@
     nullptr
   };
 
-  // If you're targeting N, you don't get the greylist.
-  if (g_greylist_disabled || get_application_target_sdk_version() >= 24) {
+  // If you're targeting N, you don't get the exempt-list.
+  if (get_application_target_sdk_version() >= 24) {
     return false;
   }
 
   // if the library needed by a system library - implicitly assume it
-  // is greylisted unless it is in the list of shared libraries for one or
+  // is exempt unless it is in the list of shared libraries for one or
   // more linked namespaces
   if (needed_by != nullptr && is_system_library(needed_by->get_realpath())) {
     return !maybe_accessible_via_namespace_links(ns, name);
@@ -224,8 +224,8 @@
     name = basename(name);
   }
 
-  for (size_t i = 0; kLibraryGreyList[i] != nullptr; ++i) {
-    if (strcmp(name, kLibraryGreyList[i]) == 0) {
+  for (size_t i = 0; kLibraryExemptList[i] != nullptr; ++i) {
+    if (strcmp(name, kLibraryExemptList[i]) == 0) {
       return true;
     }
   }
@@ -311,6 +311,10 @@
     }
   }
 
+  if (si->has_min_version(6) && si->get_gap_size()) {
+    munmap(reinterpret_cast<void*>(si->get_gap_start()), si->get_gap_size());
+  }
+
   TRACE("name %s: freeing soinfo @ %p", si->get_realpath(), si);
 
   if (!solist_remove_soinfo(si)) {
@@ -599,6 +603,8 @@
     si_->load_bias = elf_reader.load_bias();
     si_->phnum = elf_reader.phdr_count();
     si_->phdr = elf_reader.loaded_phdr();
+    si_->set_gap_start(elf_reader.gap_start());
+    si_->set_gap_size(elf_reader.gap_size());
 
     return true;
   }
@@ -626,7 +632,7 @@
   bool close_fd_;
   off64_t file_offset_;
   std::unordered_map<const soinfo*, ElfReader>* elf_readers_map_;
-  // TODO(dimitry): needed by workaround for http://b/26394120 (the grey-list)
+  // TODO(dimitry): needed by workaround for http://b/26394120 (the exempt-list)
   bool is_dt_needed_;
   // END OF WORKAROUND
   const android_namespace_t* const start_from_;
@@ -1181,12 +1187,12 @@
   // do not check accessibility using realpath if fd is located on tmpfs
   // this enables use of memfd_create() for apps
   if ((fs_stat.f_type != TMPFS_MAGIC) && (!ns->is_accessible(realpath))) {
-    // TODO(dimitry): workaround for http://b/26394120 - the grey-list
+    // TODO(dimitry): workaround for http://b/26394120 - the exempt-list
 
     // TODO(dimitry) before O release: add a namespace attribute to have this enabled
     // only for classloader-namespaces
     const soinfo* needed_by = task->is_dt_needed() ? task->get_needed_by() : nullptr;
-    if (is_greylisted(ns, name, needed_by)) {
+    if (is_exempt_lib(ns, name, needed_by)) {
       // print warning only if needed by non-system library
       if (needed_by == nullptr || !is_system_library(needed_by->get_realpath())) {
         const soinfo* needed_or_dlopened_by = task->get_needed_by();
@@ -1440,14 +1446,14 @@
     return true;
   }
 
-  // TODO(dimitry): workaround for http://b/26394120 (the grey-list)
-  if (ns->is_greylist_enabled() && is_greylisted(ns, task->get_name(), task->get_needed_by())) {
-    // For the libs in the greylist, switch to the default namespace and then
+  // TODO(dimitry): workaround for http://b/26394120 (the exempt-list)
+  if (ns->is_exempt_list_enabled() && is_exempt_lib(ns, task->get_name(), task->get_needed_by())) {
+    // For the libs in the exempt-list, switch to the default namespace and then
     // try the load again from there. The library could be loaded from the
     // default namespace or from another namespace (e.g. runtime) that is linked
     // from the default namespace.
     LD_LOG(kLogDlopen,
-           "find_library_internal(ns=%s, task=%s): Greylisted library - trying namespace %s",
+           "find_library_internal(ns=%s, task=%s): Exempt system library - trying namespace %s",
            ns->get_name(), task->get_name(), g_default_namespace.get_name());
     ns = &g_default_namespace;
     if (load_library(ns, task, zip_archive_cache, load_tasks, rtld_flags,
@@ -1467,9 +1473,9 @@
       // Library is already loaded.
       if (task->get_soinfo() != nullptr) {
         // n.b. This code path runs when find_library_in_linked_namespace found an already-loaded
-        // library by soname. That should only be possible with a greylist lookup, where we switch
-        // the namespace, because otherwise, find_library_in_linked_namespace is duplicating the
-        // soname scan done in this function's first call to find_loaded_library_by_soname.
+        // library by soname. That should only be possible with a exempt-list lookup, where we
+        // switch the namespace, because otherwise, find_library_in_linked_namespace is duplicating
+        // the soname scan done in this function's first call to find_loaded_library_by_soname.
         return true;
       }
 
@@ -2420,7 +2426,7 @@
   android_namespace_t* ns = new (g_namespace_allocator.alloc()) android_namespace_t();
   ns->set_name(name);
   ns->set_isolated((type & ANDROID_NAMESPACE_TYPE_ISOLATED) != 0);
-  ns->set_greylist_enabled((type & ANDROID_NAMESPACE_TYPE_GREYLIST_ENABLED) != 0);
+  ns->set_exempt_list_enabled((type & ANDROID_NAMESPACE_TYPE_EXEMPT_LIST_ENABLED) != 0);
   ns->set_also_used_as_anonymous((type & ANDROID_NAMESPACE_TYPE_ALSO_USED_AS_ANONYMOUS) != 0);
 
   if ((type & ANDROID_NAMESPACE_TYPE_SHARED) != 0) {
@@ -3162,7 +3168,7 @@
   DEBUG("si->base = %p, si->strtab = %p, si->symtab = %p",
         reinterpret_cast<void*>(base), strtab_, symtab_);
 
-  // Sanity checks.
+  // Validity checks.
   if (relocating_linker && needed_count != 0) {
     DL_ERR("linker cannot have DT_NEEDED dependencies on other libraries");
     return false;
@@ -3494,7 +3500,7 @@
     ns->set_isolated(ns_config->isolated());
     ns->set_default_library_paths(ns_config->search_paths());
     ns->set_permitted_paths(ns_config->permitted_paths());
-    ns->set_whitelisted_libs(ns_config->whitelisted_libs());
+    ns->set_allowed_libs(ns_config->allowed_libs());
 
     namespaces[ns_config->name()] = ns;
     if (ns_config->visible()) {
diff --git a/linker/linker.h b/linker/linker.h
index 9b6af3b..3e851da 100644
--- a/linker/linker.h
+++ b/linker/linker.h
@@ -133,10 +133,10 @@
    */
   ANDROID_NAMESPACE_TYPE_SHARED = 2,
 
-  /* This flag instructs linker to enable grey-list workaround for the namespace.
+  /* This flag instructs linker to enable exempt-list workaround for the namespace.
    * See http://b/26394120 for details.
    */
-  ANDROID_NAMESPACE_TYPE_GREYLIST_ENABLED = 0x08000000,
+  ANDROID_NAMESPACE_TYPE_EXEMPT_LIST_ENABLED = 0x08000000,
 
   /* This flag instructs linker to use this namespace as the anonymous
    * namespace. There can be only one anonymous namespace in a process. If there
diff --git a/linker/linker_block_allocator_test.cpp b/linker/linker_block_allocator_test.cpp
index 359eefb..6fb2b26 100644
--- a/linker/linker_block_allocator_test.cpp
+++ b/linker/linker_block_allocator_test.cpp
@@ -47,14 +47,14 @@
  * this one has size below allocator cap which is 2*sizeof(void*)
  */
 struct test_struct_small {
-  char dummy_str[5];
+  char str[5];
 };
 
 /*
  * 1009 byte struct (1009 is prime)
  */
 struct test_struct_larger {
-  char dummy_str[1009];
+  char str[1009];
 };
 
 static size_t kPageSize = sysconf(_SC_PAGE_SIZE);
@@ -131,14 +131,14 @@
   allocator.protect_all(PROT_READ);
   allocator.protect_all(PROT_READ | PROT_WRITE);
   // check access
-  page2_ptr->dummy_str[23] = 27;
-  page1_ptr->dummy_str[13] = 11;
+  page2_ptr->str[23] = 27;
+  page1_ptr->str[13] = 11;
 
   allocator.protect_all(PROT_READ);
   fprintf(stderr, "trying to access protected page");
 
   // this should result in segmentation fault
-  page1_ptr->dummy_str[11] = 7;
+  page1_ptr->str[11] = 7;
 }
 
 TEST(linker_allocator, test_protect) {
diff --git a/linker/linker_config.cpp b/linker/linker_config.cpp
index aaa3a03..1771e87 100644
--- a/linker/linker_config.cpp
+++ b/linker/linker_config.cpp
@@ -326,7 +326,8 @@
           (*properties)[name].append_value(std::move(value));
         } else if (android::base::EndsWith(name, ".paths") ||
                    android::base::EndsWith(name, ".shared_libs") ||
-                   android::base::EndsWith(name, ".whitelisted")) {
+                   android::base::EndsWith(name, ".whitelisted") ||
+                   android::base::EndsWith(name, ".allowed_libs")) {
           value = ":" + value;
           (*properties)[name].append_value(std::move(value));
         } else {
@@ -564,10 +565,15 @@
     ns_config->set_isolated(properties.get_bool(property_name_prefix + ".isolated"));
     ns_config->set_visible(properties.get_bool(property_name_prefix + ".visible"));
 
-    std::string whitelisted =
+    std::string allowed_libs =
         properties.get_string(property_name_prefix + ".whitelisted", &lineno);
-    if (!whitelisted.empty()) {
-      ns_config->set_whitelisted_libs(android::base::Split(whitelisted, ":"));
+    const std::string libs = properties.get_string(property_name_prefix + ".allowed_libs", &lineno);
+    if (!allowed_libs.empty() && !libs.empty()) {
+      allowed_libs += ":";
+    }
+    allowed_libs += libs;
+    if (!allowed_libs.empty()) {
+      ns_config->set_allowed_libs(android::base::Split(allowed_libs, ":"));
     }
 
     // these are affected by is_asan flag
diff --git a/linker/linker_config.h b/linker/linker_config.h
index 6733148..fe23ec1 100644
--- a/linker/linker_config.h
+++ b/linker/linker_config.h
@@ -98,9 +98,7 @@
     return permitted_paths_;
   }
 
-  const std::vector<std::string>& whitelisted_libs() const {
-    return whitelisted_libs_;
-  }
+  const std::vector<std::string>& allowed_libs() const { return allowed_libs_; }
 
   const std::vector<NamespaceLinkConfig>& links() const {
     return namespace_links_;
@@ -127,16 +125,17 @@
     permitted_paths_ = std::move(permitted_paths);
   }
 
-  void set_whitelisted_libs(std::vector<std::string>&& whitelisted_libs) {
-    whitelisted_libs_ = std::move(whitelisted_libs);
+  void set_allowed_libs(std::vector<std::string>&& allowed_libs) {
+    allowed_libs_ = std::move(allowed_libs);
   }
+
  private:
   const std::string name_;
   bool isolated_;
   bool visible_;
   std::vector<std::string> search_paths_;
   std::vector<std::string> permitted_paths_;
-  std::vector<std::string> whitelisted_libs_;
+  std::vector<std::string> allowed_libs_;
   std::vector<NamespaceLinkConfig> namespace_links_;
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(NamespaceConfig);
diff --git a/linker/linker_config_test.cpp b/linker/linker_config_test.cpp
index 3caa4d4..acdf641 100644
--- a/linker/linker_config_test.cpp
+++ b/linker/linker_config_test.cpp
@@ -91,6 +91,8 @@
   "namespace.vndk_in_system.permitted.paths = /system/${LIB}\n"
   "namespace.vndk_in_system.whitelisted = libz.so:libyuv.so\n"
   "namespace.vndk_in_system.whitelisted += libtinyxml2.so\n"
+  "namespace.vndk_in_system.allowed_libs = libfoo.so:libbar.so\n"
+  "namespace.vndk_in_system.allowed_libs += libtinyxml3.so\n"
   "\n";
 // clang-format on
 
@@ -215,9 +217,9 @@
   ASSERT_TRUE(ns_vndk_links[0].allow_all_shared_libs());
 
   ASSERT_TRUE(ns_vndk_in_system != nullptr) << "vndk_in_system namespace was not found";
-  ASSERT_EQ(
-      std::vector<std::string>({"libz.so", "libyuv.so", "libtinyxml2.so"}),
-      ns_vndk_in_system->whitelisted_libs());
+  ASSERT_EQ(std::vector<std::string>({"libz.so", "libyuv.so", "libtinyxml2.so", "libfoo.so",
+                                      "libbar.so", "libtinyxml3.so"}),
+            ns_vndk_in_system->allowed_libs());
 }
 
 TEST(linker_config, smoke) {
diff --git a/linker/linker_logger.cpp b/linker/linker_logger.cpp
index ec07a55..165b85d 100644
--- a/linker/linker_logger.cpp
+++ b/linker/linker_logger.cpp
@@ -41,7 +41,6 @@
 #include "private/CachedProperty.h"
 
 LinkerLogger g_linker_logger;
-bool g_greylist_disabled = false;
 
 static uint32_t ParseProperty(const std::string& value) {
   if (value.empty()) {
@@ -91,15 +90,6 @@
     return;
   }
 
-  // This is a convenient place to check whether the greylist should be disabled for testing.
-  static CachedProperty greylist_disabled("debug.ld.greylist_disabled");
-  bool old_value = g_greylist_disabled;
-  g_greylist_disabled = (strcmp(greylist_disabled.Get(), "true") == 0);
-  if (g_greylist_disabled != old_value) {
-    async_safe_format_log(ANDROID_LOG_INFO, "linker", "%s greylist",
-                          g_greylist_disabled ? "Disabling" : "Enabling");
-  }
-
   flags_ = 0;
 
   // For logging, check the flag applied to all processes first.
diff --git a/linker/linker_logger.h b/linker/linker_logger.h
index fedbc05..f3820a2 100644
--- a/linker/linker_logger.h
+++ b/linker/linker_logger.h
@@ -63,7 +63,3 @@
 
 extern LinkerLogger g_linker_logger;
 extern char** g_argv;
-
-// If the system property debug.ld.greylist_disabled is true, we'll not use the greylist
-// regardless of API level.
-extern bool g_greylist_disabled;
diff --git a/linker/linker_namespaces.cpp b/linker/linker_namespaces.cpp
index b993689..5182129 100644
--- a/linker/linker_namespaces.cpp
+++ b/linker/linker_namespaces.cpp
@@ -39,10 +39,9 @@
     return true;
   }
 
-  if (!whitelisted_libs_.empty()) {
+  if (!allowed_libs_.empty()) {
     const char *lib_name = basename(file.c_str());
-    if (std::find(whitelisted_libs_.begin(), whitelisted_libs_.end(),
-                  lib_name) == whitelisted_libs_.end()) {
+    if (std::find(allowed_libs_.begin(), allowed_libs_.end(), lib_name) == allowed_libs_.end()) {
       return false;
     }
   }
diff --git a/linker/linker_namespaces.h b/linker/linker_namespaces.h
index 6843ebc..77b6622 100644
--- a/linker/linker_namespaces.h
+++ b/linker/linker_namespaces.h
@@ -76,7 +76,7 @@
  public:
   android_namespace_t() :
     is_isolated_(false),
-    is_greylist_enabled_(false),
+    is_exempt_list_enabled_(false),
     is_also_used_as_anonymous_(false) {}
 
   const char* get_name() const { return name_.c_str(); }
@@ -85,8 +85,8 @@
   bool is_isolated() const { return is_isolated_; }
   void set_isolated(bool isolated) { is_isolated_ = isolated; }
 
-  bool is_greylist_enabled() const { return is_greylist_enabled_; }
-  void set_greylist_enabled(bool enabled) { is_greylist_enabled_ = enabled; }
+  bool is_exempt_list_enabled() const { return is_exempt_list_enabled_; }
+  void set_exempt_list_enabled(bool enabled) { is_exempt_list_enabled_ = enabled; }
 
   bool is_also_used_as_anonymous() const { return is_also_used_as_anonymous_; }
   void set_also_used_as_anonymous(bool yes) { is_also_used_as_anonymous_ = yes; }
@@ -118,14 +118,12 @@
     permitted_paths_ = permitted_paths;
   }
 
-  const std::vector<std::string>& get_whitelisted_libs() const {
-    return whitelisted_libs_;
+  const std::vector<std::string>& get_allowed_libs() const { return allowed_libs_; }
+  void set_allowed_libs(std::vector<std::string>&& allowed_libs) {
+    allowed_libs_ = std::move(allowed_libs);
   }
-  void set_whitelisted_libs(std::vector<std::string>&& whitelisted_libs) {
-    whitelisted_libs_ = std::move(whitelisted_libs);
-  }
-  void set_whitelisted_libs(const std::vector<std::string>& whitelisted_libs) {
-    whitelisted_libs_ = whitelisted_libs;
+  void set_allowed_libs(const std::vector<std::string>& allowed_libs) {
+    allowed_libs_ = allowed_libs;
   }
 
   const std::vector<android_namespace_link_t>& linked_namespaces() const {
@@ -171,12 +169,12 @@
  private:
   std::string name_;
   bool is_isolated_;
-  bool is_greylist_enabled_;
+  bool is_exempt_list_enabled_;
   bool is_also_used_as_anonymous_;
   std::vector<std::string> ld_library_paths_;
   std::vector<std::string> default_library_paths_;
   std::vector<std::string> permitted_paths_;
-  std::vector<std::string> whitelisted_libs_;
+  std::vector<std::string> allowed_libs_;
   // Loader looks into linked namespace if it was not able
   // to find a library in this namespace. Note that library
   // lookup in linked namespaces are limited by the list of
diff --git a/linker/linker_phdr.cpp b/linker/linker_phdr.cpp
index 9b7a461..1e89094 100644
--- a/linker/linker_phdr.cpp
+++ b/linker/linker_phdr.cpp
@@ -520,7 +520,8 @@
 
 // Reserve a virtual address range such that if it's limits were extended to the next 2**align
 // boundary, it would not overlap with any existing mappings.
-static void* ReserveAligned(size_t size, size_t align) {
+static void* ReserveWithAlignmentPadding(size_t size, size_t align, void** out_gap_start,
+                                         size_t* out_gap_size) {
   int mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS;
   if (align == PAGE_SIZE) {
     void* mmap_ptr = mmap(nullptr, size, PROT_NONE, mmap_flags, -1, 0);
@@ -530,6 +531,15 @@
     return mmap_ptr;
   }
 
+  // Minimum alignment of shared library gap. For efficiency, this should match the second level
+  // page size of the platform.
+#if defined(__LP64__)
+  constexpr size_t kGapAlignment = 1ul << 21;  // 2MB
+#else
+  constexpr size_t kGapAlignment = 0;
+#endif
+  // Maximum gap size, in the units of kGapAlignment.
+  constexpr size_t kMaxGapUnits = 32;
   // Allocate enough space so that the end of the desired region aligned up is still inside the
   // mapping.
   size_t mmap_size = align_up(size, align) + align - PAGE_SIZE;
@@ -538,16 +548,49 @@
   if (mmap_ptr == MAP_FAILED) {
     return nullptr;
   }
+  size_t gap_size = 0;
+  size_t first_byte = reinterpret_cast<size_t>(align_up(mmap_ptr, align));
+  size_t last_byte = reinterpret_cast<size_t>(align_down(mmap_ptr + mmap_size, align) - 1);
+  if (kGapAlignment && first_byte / kGapAlignment != last_byte / kGapAlignment) {
+    // This library crosses a 2MB boundary and will fragment a new huge page.
+    // Lets take advantage of that and insert a random number of inaccessible huge pages before that
+    // to improve address randomization and make it harder to locate this library code by probing.
+    munmap(mmap_ptr, mmap_size);
+    align = std::max(align, kGapAlignment);
+    gap_size =
+        kGapAlignment * (is_first_stage_init() ? 1 : arc4random_uniform(kMaxGapUnits - 1) + 1);
+    mmap_size = align_up(size + gap_size, align) + align - PAGE_SIZE;
+    mmap_ptr = reinterpret_cast<uint8_t*>(mmap(nullptr, mmap_size, PROT_NONE, mmap_flags, -1, 0));
+    if (mmap_ptr == MAP_FAILED) {
+      return nullptr;
+    }
+  }
+
+  uint8_t *gap_end, *gap_start;
+  if (gap_size) {
+    gap_end = align_down(mmap_ptr + mmap_size, kGapAlignment);
+    gap_start = gap_end - gap_size;
+  } else {
+    gap_start = gap_end = mmap_ptr + mmap_size;
+  }
 
   uint8_t* first = align_up(mmap_ptr, align);
-  uint8_t* last = align_down(mmap_ptr + mmap_size, align) - size;
+  uint8_t* last = align_down(gap_start, align) - size;
 
   // arc4random* is not available in first stage init because /dev/urandom hasn't yet been
   // created. Don't randomize then.
   size_t n = is_first_stage_init() ? 0 : arc4random_uniform((last - first) / PAGE_SIZE + 1);
   uint8_t* start = first + n * PAGE_SIZE;
+  // Unmap the extra space around the allocation.
+  // Keep it mapped PROT_NONE on 64-bit targets where address space is plentiful to make it harder
+  // to defeat ASLR by probing for readable memory mappings.
   munmap(mmap_ptr, start - mmap_ptr);
-  munmap(start + size, mmap_ptr + mmap_size - (start + size));
+  munmap(start + size, gap_start - (start + size));
+  if (gap_end != mmap_ptr + mmap_size) {
+    munmap(gap_end, mmap_ptr + mmap_size - gap_end);
+  }
+  *out_gap_start = gap_start;
+  *out_gap_size = gap_size;
   return start;
 }
 
@@ -571,13 +614,15 @@
              load_size_ - address_space->reserved_size, load_size_, name_.c_str());
       return false;
     }
-    start = ReserveAligned(load_size_, kLibraryAlignment);
+    start = ReserveWithAlignmentPadding(load_size_, kLibraryAlignment, &gap_start_, &gap_size_);
     if (start == nullptr) {
       DL_ERR("couldn't reserve %zd bytes of address space for \"%s\"", load_size_, name_.c_str());
       return false;
     }
   } else {
     start = address_space->start_addr;
+    gap_start_ = nullptr;
+    gap_size_ = 0;
     mapped_by_caller_ = true;
 
     // Update the reserved address space to subtract the space used by this library.
diff --git a/linker/linker_phdr.h b/linker/linker_phdr.h
index 5d1cfc2..4cb48f5 100644
--- a/linker/linker_phdr.h
+++ b/linker/linker_phdr.h
@@ -49,6 +49,8 @@
   size_t phdr_count() const { return phdr_num_; }
   ElfW(Addr) load_start() const { return reinterpret_cast<ElfW(Addr)>(load_start_); }
   size_t load_size() const { return load_size_; }
+  ElfW(Addr) gap_start() const { return reinterpret_cast<ElfW(Addr)>(gap_start_); }
+  size_t gap_size() const { return gap_size_; }
   ElfW(Addr) load_bias() const { return load_bias_; }
   const ElfW(Phdr)* loaded_phdr() const { return loaded_phdr_; }
   const ElfW(Dyn)* dynamic() const { return dynamic_; }
@@ -96,6 +98,10 @@
   void* load_start_;
   // Size in bytes of reserved address space.
   size_t load_size_;
+  // First page of inaccessible gap mapping reserved for this DSO.
+  void* gap_start_;
+  // Size in bytes of the gap mapping.
+  size_t gap_size_;
   // Load bias.
   ElfW(Addr) load_bias_;
 
diff --git a/linker/linker_soinfo.cpp b/linker/linker_soinfo.cpp
index 4f67003..60fd242 100644
--- a/linker/linker_soinfo.cpp
+++ b/linker/linker_soinfo.cpp
@@ -900,6 +900,24 @@
   g_soinfo_handles_map[handle_] = this;
 }
 
+void soinfo::set_gap_start(ElfW(Addr) gap_start) {
+  CHECK(has_min_version(6));
+  gap_start_ = gap_start;
+}
+ElfW(Addr) soinfo::get_gap_start() const {
+  CHECK(has_min_version(6));
+  return gap_start_;
+}
+
+void soinfo::set_gap_size(size_t gap_size) {
+  CHECK(has_min_version(6));
+  gap_size_ = gap_size;
+}
+size_t soinfo::get_gap_size() const {
+  CHECK(has_min_version(6));
+  return gap_size_;
+}
+
 // TODO(dimitry): Move SymbolName methods to a separate file.
 
 uint32_t calculate_elf_hash(const char* name) {
diff --git a/linker/linker_soinfo.h b/linker/linker_soinfo.h
index e1a3c30..7372a51 100644
--- a/linker/linker_soinfo.h
+++ b/linker/linker_soinfo.h
@@ -66,7 +66,7 @@
 #define FLAG_PRELINKED        0x00000400 // prelink_image has successfully processed this soinfo
 #define FLAG_NEW_SOINFO       0x40000000 // new soinfo format
 
-#define SOINFO_VERSION 5
+#define SOINFO_VERSION 6
 
 ElfW(Addr) call_ifunc_resolver(ElfW(Addr) resolver_addr);
 
@@ -345,6 +345,12 @@
 
   SymbolLookupLib get_lookup_lib();
 
+  void set_gap_start(ElfW(Addr) gap_start);
+  ElfW(Addr) get_gap_start() const;
+
+  void set_gap_size(size_t gap_size);
+  size_t get_gap_size() const;
+
  private:
   bool is_image_linked() const;
   void set_image_linked();
@@ -423,6 +429,10 @@
   // version >= 5
   std::unique_ptr<soinfo_tls> tls_;
   std::vector<TlsDynamicResolverArg> tlsdesc_args_;
+
+  // version >= 6
+  ElfW(Addr) gap_start_;
+  size_t gap_size_;
 };
 
 // This function is used by dlvsym() to calculate hash of sym_ver
diff --git a/linker/linker_tls.cpp b/linker/linker_tls.cpp
index d2edbb3..97892f4 100644
--- a/linker/linker_tls.cpp
+++ b/linker/linker_tls.cpp
@@ -128,6 +128,8 @@
 void linker_finalize_static_tls() {
   g_static_tls_finished = true;
   __libc_shared_globals()->static_tls_layout.finish_layout();
+  TlsModules& modules = __libc_shared_globals()->tls_modules;
+  modules.static_module_count = modules.module_count;
 }
 
 void register_soinfo_tls(soinfo* si) {
diff --git a/tests/Android.bp b/tests/Android.bp
index 598865b..586ef34 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -72,6 +72,217 @@
 }
 
 // -----------------------------------------------------------------------------
+// Prebuilt shared libraries for use in tests.
+// -----------------------------------------------------------------------------
+
+cc_prebuilt_test_library_shared {
+    name: "libtest_invalid-rw_load_segment",
+    strip: {
+        none: true,
+    },
+    check_elf_files: false,
+    relative_install_path: "bionic-loader-test-libs/prebuilt-elf-files",
+    arch: {
+        arm: {
+            srcs: ["prebuilt-elf-files/arm/libtest_invalid-rw_load_segment.so"],
+        },
+        arm64: {
+            srcs: ["prebuilt-elf-files/arm64/libtest_invalid-rw_load_segment.so"],
+        },
+        x86: {
+            srcs: ["prebuilt-elf-files/x86/libtest_invalid-rw_load_segment.so"],
+        },
+        x86_64: {
+            srcs: ["prebuilt-elf-files/x86_64/libtest_invalid-rw_load_segment.so"],
+        },
+    },
+}
+
+cc_prebuilt_test_library_shared {
+    name: "libtest_invalid-unaligned_shdr_offset",
+    strip: {
+        none: true,
+    },
+    check_elf_files: false,
+    relative_install_path: "bionic-loader-test-libs/prebuilt-elf-files",
+    arch: {
+        arm: {
+            srcs: ["prebuilt-elf-files/arm/libtest_invalid-unaligned_shdr_offset.so"],
+        },
+        arm64: {
+            srcs: ["prebuilt-elf-files/arm64/libtest_invalid-unaligned_shdr_offset.so"],
+        },
+        x86: {
+            srcs: ["prebuilt-elf-files/x86/libtest_invalid-unaligned_shdr_offset.so"],
+        },
+        x86_64: {
+            srcs: ["prebuilt-elf-files/x86_64/libtest_invalid-unaligned_shdr_offset.so"],
+        },
+    },
+}
+
+cc_prebuilt_test_library_shared {
+    name: "libtest_invalid-zero_shentsize",
+    strip: {
+        none: true,
+    },
+    check_elf_files: false,
+    relative_install_path: "bionic-loader-test-libs/prebuilt-elf-files",
+    arch: {
+        arm: {
+            srcs: ["prebuilt-elf-files/arm/libtest_invalid-zero_shentsize.so"],
+        },
+        arm64: {
+            srcs: ["prebuilt-elf-files/arm64/libtest_invalid-zero_shentsize.so"],
+        },
+        x86: {
+            srcs: ["prebuilt-elf-files/x86/libtest_invalid-zero_shentsize.so"],
+        },
+        x86_64: {
+            srcs: ["prebuilt-elf-files/x86_64/libtest_invalid-zero_shentsize.so"],
+        },
+    },
+}
+
+cc_prebuilt_test_library_shared {
+    name: "libtest_invalid-zero_shstrndx",
+    strip: {
+        none: true,
+    },
+    check_elf_files: false,
+    relative_install_path: "bionic-loader-test-libs/prebuilt-elf-files",
+    arch: {
+        arm: {
+            srcs: ["prebuilt-elf-files/arm/libtest_invalid-zero_shstrndx.so"],
+        },
+        arm64: {
+            srcs: ["prebuilt-elf-files/arm64/libtest_invalid-zero_shstrndx.so"],
+        },
+        x86: {
+            srcs: ["prebuilt-elf-files/x86/libtest_invalid-zero_shstrndx.so"],
+        },
+        x86_64: {
+            srcs: ["prebuilt-elf-files/x86_64/libtest_invalid-zero_shstrndx.so"],
+        },
+    },
+}
+
+cc_prebuilt_test_library_shared {
+    name: "libtest_invalid-empty_shdr_table",
+    strip: {
+        none: true,
+    },
+    check_elf_files: false,
+    relative_install_path: "bionic-loader-test-libs/prebuilt-elf-files",
+    arch: {
+        arm: {
+            srcs: ["prebuilt-elf-files/arm/libtest_invalid-empty_shdr_table.so"],
+        },
+        arm64: {
+            srcs: ["prebuilt-elf-files/arm64/libtest_invalid-empty_shdr_table.so"],
+        },
+        x86: {
+            srcs: ["prebuilt-elf-files/x86/libtest_invalid-empty_shdr_table.so"],
+        },
+        x86_64: {
+            srcs: ["prebuilt-elf-files/x86_64/libtest_invalid-empty_shdr_table.so"],
+        },
+    },
+}
+
+cc_prebuilt_test_library_shared {
+    name: "libtest_invalid-zero_shdr_table_offset",
+    strip: {
+        none: true,
+    },
+    check_elf_files: false,
+    relative_install_path: "bionic-loader-test-libs/prebuilt-elf-files",
+    arch: {
+        arm: {
+            srcs: ["prebuilt-elf-files/arm/libtest_invalid-zero_shdr_table_offset.so"],
+        },
+        arm64: {
+            srcs: ["prebuilt-elf-files/arm64/libtest_invalid-zero_shdr_table_offset.so"],
+        },
+        x86: {
+            srcs: ["prebuilt-elf-files/x86/libtest_invalid-zero_shdr_table_offset.so"],
+        },
+        x86_64: {
+            srcs: ["prebuilt-elf-files/x86_64/libtest_invalid-zero_shdr_table_offset.so"],
+        },
+    },
+}
+
+cc_prebuilt_test_library_shared {
+    name: "libtest_invalid-zero_shdr_table_content",
+    strip: {
+        none: true,
+    },
+    check_elf_files: false,
+    relative_install_path: "bionic-loader-test-libs/prebuilt-elf-files",
+    arch: {
+        arm: {
+            srcs: ["prebuilt-elf-files/arm/libtest_invalid-zero_shdr_table_content.so"],
+        },
+        arm64: {
+            srcs: ["prebuilt-elf-files/arm64/libtest_invalid-zero_shdr_table_content.so"],
+        },
+        x86: {
+            srcs: ["prebuilt-elf-files/x86/libtest_invalid-zero_shdr_table_content.so"],
+        },
+        x86_64: {
+            srcs: ["prebuilt-elf-files/x86_64/libtest_invalid-zero_shdr_table_content.so"],
+        },
+    },
+}
+
+cc_prebuilt_test_library_shared {
+    name: "libtest_invalid-textrels",
+    strip: {
+        none: true,
+    },
+    check_elf_files: false,
+    relative_install_path: "bionic-loader-test-libs/prebuilt-elf-files",
+    arch: {
+        arm: {
+            srcs: ["prebuilt-elf-files/arm/libtest_invalid-textrels.so"],
+        },
+        arm64: {
+            srcs: ["prebuilt-elf-files/arm64/libtest_invalid-textrels.so"],
+        },
+        x86: {
+            srcs: ["prebuilt-elf-files/x86/libtest_invalid-textrels.so"],
+        },
+        x86_64: {
+            srcs: ["prebuilt-elf-files/x86_64/libtest_invalid-textrels.so"],
+        },
+    },
+}
+
+cc_prebuilt_test_library_shared {
+    name: "libtest_invalid-textrels2",
+    strip: {
+        none: true,
+    },
+    check_elf_files: false,
+    relative_install_path: "bionic-loader-test-libs/prebuilt-elf-files",
+    arch: {
+        arm: {
+            srcs: ["prebuilt-elf-files/arm/libtest_invalid-textrels2.so"],
+        },
+        arm64: {
+            srcs: ["prebuilt-elf-files/arm64/libtest_invalid-textrels2.so"],
+        },
+        x86: {
+            srcs: ["prebuilt-elf-files/x86/libtest_invalid-textrels2.so"],
+        },
+        x86_64: {
+            srcs: ["prebuilt-elf-files/x86_64/libtest_invalid-textrels2.so"],
+        },
+    },
+}
+
+// -----------------------------------------------------------------------------
 // All standard tests.
 // -----------------------------------------------------------------------------
 
@@ -211,6 +422,7 @@
         "sys_uio_test.cpp",
         "sys_un_test.cpp",
         "sys_vfs_test.cpp",
+        "sys_wait_test.cpp",
         "sys_xattr_test.cpp",
         "system_properties_test.cpp",
         "system_properties_test2.cpp",
@@ -736,15 +948,15 @@
         "libtest_with_dependency_loop",
         "libtest_with_dependency",
         "libtest_indirect_thread_local_dtor",
-        "libtest_invalid-empty_shdr_table.so",
-        "libtest_invalid-rw_load_segment.so",
-        "libtest_invalid-unaligned_shdr_offset.so",
-        "libtest_invalid-zero_shdr_table_content.so",
-        "libtest_invalid-zero_shdr_table_offset.so",
-        "libtest_invalid-zero_shentsize.so",
-        "libtest_invalid-zero_shstrndx.so",
-        "libtest_invalid-textrels.so",
-        "libtest_invalid-textrels2.so",
+        "libtest_invalid-empty_shdr_table",
+        "libtest_invalid-rw_load_segment",
+        "libtest_invalid-unaligned_shdr_offset",
+        "libtest_invalid-zero_shdr_table_content",
+        "libtest_invalid-zero_shdr_table_offset",
+        "libtest_invalid-zero_shentsize",
+        "libtest_invalid-zero_shstrndx",
+        "libtest_invalid-textrels",
+        "libtest_invalid-textrels2",
         "libtest_thread_local_dtor",
         "libtest_thread_local_dtor2",
         "preinit_getauxval_test_helper",
diff --git a/tests/Android.build.prebuilt.mk b/tests/Android.build.prebuilt.mk
deleted file mode 100644
index de8f5e6..0000000
--- a/tests/Android.build.prebuilt.mk
+++ /dev/null
@@ -1,30 +0,0 @@
-#
-# Copyright (C) 2016 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 $(CLEAR_VARS)
-LOCAL_MULTILIB := both
-LOCAL_MODULE := $(bionic_tests_module)
-LOCAL_MODULE_PATH_32 := $($(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_DATA_NATIVE_TESTS)/bionic-loader-test-libs/prebuilt-elf-files
-LOCAL_MODULE_PATH_64 := $(TARGET_OUT_DATA_NATIVE_TESTS)/bionic-loader-test-libs/prebuilt-elf-files
-LOCAL_MODULE_CLASS := EXECUTABLES
-
-LOCAL_SRC_FILES_arm := prebuilt-elf-files/arm/$(bionic_tests_module)
-LOCAL_SRC_FILES_arm64 := prebuilt-elf-files/arm64/$(bionic_tests_module)
-LOCAL_SRC_FILES_x86 := prebuilt-elf-files/x86/$(bionic_tests_module)
-LOCAL_SRC_FILES_x86_64 := prebuilt-elf-files/x86_64/$(bionic_tests_module)
-include $(BUILD_PREBUILT)
-bionic-loader-test-libs-target: $(LOCAL_MODULE)
-.PHONY: bionic-loader-test-libs-target
diff --git a/tests/Android.mk b/tests/Android.mk
index b5571e3..5ad4045 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -16,43 +16,6 @@
 
 LOCAL_PATH := $(call my-dir)
 
-# TODO(dimitry): replace with define once https://android-review.googlesource.com/247466 is reverted
-# https://github.com/google/kati/issues/83 is currently blocking it.
-
-# Move prebuilt test elf-files to $(TARGET_OUT_NATIVE_TESTS)
-bionic_tests_module := libtest_invalid-rw_load_segment.so
-include $(LOCAL_PATH)/Android.build.prebuilt.mk
-
-bionic_tests_module := libtest_invalid-unaligned_shdr_offset.so
-include $(LOCAL_PATH)/Android.build.prebuilt.mk
-
-bionic_tests_module := libtest_invalid-zero_shentsize.so
-include $(LOCAL_PATH)/Android.build.prebuilt.mk
-
-bionic_tests_module := libtest_invalid-zero_shstrndx.so
-include $(LOCAL_PATH)/Android.build.prebuilt.mk
-
-bionic_tests_module := libtest_invalid-empty_shdr_table.so
-include $(LOCAL_PATH)/Android.build.prebuilt.mk
-
-bionic_tests_module := libtest_invalid-zero_shdr_table_offset.so
-include $(LOCAL_PATH)/Android.build.prebuilt.mk
-
-bionic_tests_module := libtest_invalid-zero_shdr_table_content.so
-include $(LOCAL_PATH)/Android.build.prebuilt.mk
-
-bionic_tests_module := libtest_invalid-textrels.so
-include $(LOCAL_PATH)/Android.build.prebuilt.mk
-
-bionic_tests_module := libtest_invalid-textrels2.so
-include $(LOCAL_PATH)/Android.build.prebuilt.mk
-
-ifeq ($(HOST_OS)-$(HOST_ARCH),$(filter $(HOST_OS)-$(HOST_ARCH),linux-x86 linux-x86_64))
-build_host := true
-else
-build_host := false
-endif
-
 ifeq ($(HOST_OS)-$(HOST_ARCH),$(filter $(HOST_OS)-$(HOST_ARCH),linux-x86 linux-x86_64))
 
 # -----------------------------------------------------------------------------
diff --git a/tests/bionic_allocator_test.cpp b/tests/bionic_allocator_test.cpp
index f710907..fdcf868 100644
--- a/tests/bionic_allocator_test.cpp
+++ b/tests/bionic_allocator_test.cpp
@@ -42,19 +42,19 @@
  * this one has size below allocator cap which is 2*sizeof(void*)
  */
 struct test_struct_small {
-  char dummy_str[5];
+  char str[5];
 };
 
 struct test_struct_large {
-  char dummy_str[1009];
+  char str[1009];
 };
 
 struct test_struct_huge {
-  char dummy_str[73939];
+  char str[73939];
 };
 
 struct test_struct_512 {
-  char dummy_str[503];
+  char str[503];
 };
 
 };
diff --git a/tests/cfi_test.cpp b/tests/cfi_test.cpp
index 792f917..e0ae3af 100644
--- a/tests/cfi_test.cpp
+++ b/tests/cfi_test.cpp
@@ -95,9 +95,6 @@
   EXPECT_EQ(get_global_address(), get_last_address());
   EXPECT_EQ(c, get_count());
 
-  // CFI check for a stack address. This is always invalid and gets the process killed.
-  EXPECT_DEATH(__cfi_slowpath(45, reinterpret_cast<void*>(&c)), "");
-
   // CFI check for a heap address.
   // It's possible that this allocation could wind up in the same CFI granule as
   // an unchecked library, which means the below might not crash. To force a
diff --git a/tests/clang_fortify_tests.cpp b/tests/clang_fortify_tests.cpp
index 715f9c8..0d17284 100644
--- a/tests/clang_fortify_tests.cpp
+++ b/tests/clang_fortify_tests.cpp
@@ -18,17 +18,24 @@
 #error "Non-clang isn't supported"
 #endif
 
+//
 // Clang compile-time and run-time tests for Bionic's FORTIFY.
 //
-// This file is compiled in two configurations ways to give us a sane set of tests for clang's
-// FORTIFY implementation.
+
+// This file is compiled in two configurations to give us reasonable coverage of clang's
+// FORTIFY implementation:
 //
-// One configuration uses clang's diagnostic consumer
+// 1. For compile-time checks, we use clang's diagnostic consumer
 // (https://clang.llvm.org/doxygen/classclang_1_1VerifyDiagnosticConsumer.html#details)
 // to check diagnostics (e.g. the expected-* comments everywhere).
 //
-// Please note that this test does things like leaking memory. That's WAI.
+// 2. For run-time checks, we build and run as regular gtests.
 
+// Note that these tests do things like leaking memory. That's WAI.
+
+//
+// Configuration for the compile-time checks. (These comments have side effects!)
+//
 // Silence all "from 'diagnose_if'" `note`s from anywhere, including headers; they're uninteresting
 // for this test case, and their line numbers may change over time.
 // expected-note@* 0+{{from 'diagnose_if'}}
@@ -39,8 +46,8 @@
 // And finally, all explicitly-unavailable-here complaints from headers are
 // uninteresting
 // expected-note@* 0+{{has been explicitly marked unavailable here}}
-
-// Note that some of these diags come from clang itself, while others come from
+//
+// Note that some of these diagnostics come from clang itself, while others come from
 // `diagnose_if`s sprinkled throughout Bionic.
 
 #ifndef _FORTIFY_SOURCE
diff --git a/tests/dirent_test.cpp b/tests/dirent_test.cpp
index 378aea4..56929d1 100644
--- a/tests/dirent_test.cpp
+++ b/tests/dirent_test.cpp
@@ -113,6 +113,18 @@
   ASSERT_EQ(unsorted_name_list, unsorted_name_list_at64);
 }
 
+static int is_version_filter(const dirent* de) {
+  return !strcmp(de->d_name, "version");
+}
+
+TEST(dirent, scandir_filter) {
+  dirent** entries;
+  errno = 0;
+  ASSERT_EQ(1, scandir("/proc", &entries, is_version_filter, nullptr));
+  ASSERT_STREQ("version", entries[0]->d_name);
+  free(entries);
+}
+
 TEST(dirent, scandir_ENOENT) {
   dirent** entries;
   errno = 0;
diff --git a/tests/dlext_private.h b/tests/dlext_private.h
index b338ae0..262af4c 100644
--- a/tests/dlext_private.h
+++ b/tests/dlext_private.h
@@ -56,10 +56,10 @@
    */
   ANDROID_NAMESPACE_TYPE_SHARED = 2,
 
-  /* This flag instructs linker to enable grey-list workaround for the namespace.
+  /* This flag instructs linker to enable exempt-list workaround for the namespace.
    * See http://b/26394120 for details.
    */
-  ANDROID_NAMESPACE_TYPE_GREYLIST_ENABLED = 0x08000000,
+  ANDROID_NAMESPACE_TYPE_EXEMPT_LIST_ENABLED = 0x08000000,
 
   ANDROID_NAMESPACE_TYPE_SHARED_ISOLATED = ANDROID_NAMESPACE_TYPE_SHARED |
                                            ANDROID_NAMESPACE_TYPE_ISOLATED,
diff --git a/tests/dlext_test.cpp b/tests/dlext_test.cpp
index 1139e53..01bf8ab 100644
--- a/tests/dlext_test.cpp
+++ b/tests/dlext_test.cpp
@@ -1228,7 +1228,7 @@
             dlerror());
 }
 
-TEST(dlext, ns_greylist_enabled) {
+TEST(dlext, ns_exempt_list_enabled) {
   ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
 
   const std::string ns_search_path = GetTestlibRoot() + "/private_namespace_libs";
@@ -1237,7 +1237,7 @@
           android_create_namespace("namespace",
                                    nullptr,
                                    ns_search_path.c_str(),
-                                   ANDROID_NAMESPACE_TYPE_ISOLATED | ANDROID_NAMESPACE_TYPE_GREYLIST_ENABLED,
+                                   ANDROID_NAMESPACE_TYPE_ISOLATED | ANDROID_NAMESPACE_TYPE_EXEMPT_LIST_ENABLED,
                                    nullptr,
                                    nullptr);
 
@@ -1247,26 +1247,26 @@
   extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
   extinfo.library_namespace = ns;
 
-  // An app targeting M can open libnativehelper.so because it's on the greylist.
+  // An app targeting M can open libnativehelper.so because it's on the exempt-list.
   android_set_application_target_sdk_version(23);
   void* handle = android_dlopen_ext("libnativehelper.so", RTLD_NOW, &extinfo);
   ASSERT_TRUE(handle != nullptr) << dlerror();
 
-  // Check that loader did not load another copy of libdl.so while loading greylisted library.
+  // Check that loader did not load another copy of libdl.so while loading exempted library.
   void* dlsym_ptr = dlsym(handle, "dlsym");
   ASSERT_TRUE(dlsym_ptr != nullptr) << dlerror();
   ASSERT_EQ(&dlsym, dlsym_ptr);
 
   dlclose(handle);
 
-  // An app targeting N no longer has the greylist.
+  // An app targeting N no longer has the exempt-list.
   android_set_application_target_sdk_version(24);
   handle = android_dlopen_ext("libnativehelper.so", RTLD_NOW, &extinfo);
   ASSERT_TRUE(handle == nullptr);
   ASSERT_STREQ("dlopen failed: library \"libnativehelper.so\" not found", dlerror());
 }
 
-TEST(dlext, ns_greylist_disabled_by_default) {
+TEST(dlext, ns_exempt_list_disabled_by_default) {
   ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
 
   const std::string ns_search_path = GetTestlibRoot() + "/private_namespace_libs";
@@ -2022,7 +2022,7 @@
     }
   }
 
-  // some sanity checks..
+  // Some validity checks.
   ASSERT_TRUE(addr_start > 0);
   ASSERT_TRUE(addr_end > 0);
   ASSERT_TRUE(maps_to_copy.size() > 0);
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index d7b9bae..35e12eb 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -1623,9 +1623,7 @@
 #endif //  defined(__arm__)
 
 TEST(dlfcn, dlopen_invalid_rw_load_segment) {
-  const std::string libpath = GetTestlibRoot() +
-                              "/" + kPrebuiltElfDir +
-                              "/libtest_invalid-rw_load_segment.so";
+  const std::string libpath = GetPrebuiltElfDir() + "/libtest_invalid-rw_load_segment.so";
   void* handle = dlopen(libpath.c_str(), RTLD_NOW);
   ASSERT_TRUE(handle == nullptr);
   std::string expected_dlerror = std::string("dlopen failed: \"") + libpath + "\": W+E load segments are not allowed";
@@ -1633,9 +1631,7 @@
 }
 
 TEST(dlfcn, dlopen_invalid_unaligned_shdr_offset) {
-  const std::string libpath = GetTestlibRoot() +
-                              "/" + kPrebuiltElfDir +
-                              "/libtest_invalid-unaligned_shdr_offset.so";
+  const std::string libpath = GetPrebuiltElfDir() + "/libtest_invalid-unaligned_shdr_offset.so";
 
   void* handle = dlopen(libpath.c_str(), RTLD_NOW);
   ASSERT_TRUE(handle == nullptr);
@@ -1644,9 +1640,7 @@
 }
 
 TEST(dlfcn, dlopen_invalid_zero_shentsize) {
-  const std::string libpath = GetTestlibRoot() +
-                              "/" + kPrebuiltElfDir +
-                              "/libtest_invalid-zero_shentsize.so";
+  const std::string libpath = GetPrebuiltElfDir() + "/libtest_invalid-zero_shentsize.so";
 
   void* handle = dlopen(libpath.c_str(), RTLD_NOW);
   ASSERT_TRUE(handle == nullptr);
@@ -1655,9 +1649,7 @@
 }
 
 TEST(dlfcn, dlopen_invalid_zero_shstrndx) {
-  const std::string libpath = GetTestlibRoot() +
-                              "/" + kPrebuiltElfDir +
-                              "/libtest_invalid-zero_shstrndx.so";
+  const std::string libpath = GetPrebuiltElfDir() + "/libtest_invalid-zero_shstrndx.so";
 
   void* handle = dlopen(libpath.c_str(), RTLD_NOW);
   ASSERT_TRUE(handle == nullptr);
@@ -1666,9 +1658,7 @@
 }
 
 TEST(dlfcn, dlopen_invalid_empty_shdr_table) {
-  const std::string libpath = GetTestlibRoot() +
-                              "/" + kPrebuiltElfDir +
-                              "/libtest_invalid-empty_shdr_table.so";
+  const std::string libpath = GetPrebuiltElfDir() + "/libtest_invalid-empty_shdr_table.so";
 
   void* handle = dlopen(libpath.c_str(), RTLD_NOW);
   ASSERT_TRUE(handle == nullptr);
@@ -1677,9 +1667,7 @@
 }
 
 TEST(dlfcn, dlopen_invalid_zero_shdr_table_offset) {
-  const std::string libpath = GetTestlibRoot() +
-                              "/" + kPrebuiltElfDir +
-                              "/libtest_invalid-zero_shdr_table_offset.so";
+  const std::string libpath = GetPrebuiltElfDir() + "/libtest_invalid-zero_shdr_table_offset.so";
 
   void* handle = dlopen(libpath.c_str(), RTLD_NOW);
   ASSERT_TRUE(handle == nullptr);
@@ -1688,9 +1676,7 @@
 }
 
 TEST(dlfcn, dlopen_invalid_zero_shdr_table_content) {
-  const std::string libpath = GetTestlibRoot() +
-                              "/" + kPrebuiltElfDir +
-                              "/libtest_invalid-zero_shdr_table_content.so";
+  const std::string libpath = GetPrebuiltElfDir() + "/libtest_invalid-zero_shdr_table_content.so";
 
   void* handle = dlopen(libpath.c_str(), RTLD_NOW);
   ASSERT_TRUE(handle == nullptr);
@@ -1699,9 +1685,7 @@
 }
 
 TEST(dlfcn, dlopen_invalid_textrels) {
-  const std::string libpath = GetTestlibRoot() +
-                              "/" + kPrebuiltElfDir +
-                              "/libtest_invalid-textrels.so";
+  const std::string libpath = GetPrebuiltElfDir() + "/libtest_invalid-textrels.so";
 
   void* handle = dlopen(libpath.c_str(), RTLD_NOW);
   ASSERT_TRUE(handle == nullptr);
@@ -1710,9 +1694,7 @@
 }
 
 TEST(dlfcn, dlopen_invalid_textrels2) {
-  const std::string libpath = GetTestlibRoot() +
-                              "/" + kPrebuiltElfDir +
-                              "/libtest_invalid-textrels2.so";
+  const std::string libpath = GetPrebuiltElfDir() + "/libtest_invalid-textrels2.so";
 
   void* handle = dlopen(libpath.c_str(), RTLD_NOW);
   ASSERT_TRUE(handle == nullptr);
diff --git a/tests/fortify_test.cpp b/tests/fortify_test.cpp
index 9a4b781..6907abe 100644
--- a/tests/fortify_test.cpp
+++ b/tests/fortify_test.cpp
@@ -14,14 +14,6 @@
  * limitations under the License.
  */
 
-// -Werror is on whether we like it or not, and we're intentionally doing awful
-// things in this file. GCC is dumb and doesn't have a specific error class for
-// the fortify failures (it's just -Werror), so we can't use anything more
-// constrained than disabling all the warnings in the file :( It also won't let
-// us use system_header in a .cpp file, so we have to #include this from
-// fortify_test_main.cpp.
-#pragma GCC system_header
-
 #include <gtest/gtest.h>
 #include "BionicDeathTest.h"
 
diff --git a/tests/ftw_test.cpp b/tests/ftw_test.cpp
index dfc4d72..200ed4b 100644
--- a/tests/ftw_test.cpp
+++ b/tests/ftw_test.cpp
@@ -49,7 +49,7 @@
   ASSERT_EQ(0, close(fd));
 }
 
-void sanity_check_ftw(const char* fpath, const struct stat* sb, int tflag) {
+void smoke_test_ftw(const char* fpath, const struct stat* sb, int tflag) {
   ASSERT_TRUE(fpath != nullptr);
   ASSERT_TRUE(sb != nullptr);
 
@@ -75,28 +75,28 @@
   }
 }
 
-void sanity_check_nftw(const char* fpath, const struct stat* sb, int tflag, FTW* ftwbuf) {
-  sanity_check_ftw(fpath, sb, tflag);
+void smoke_test_nftw(const char* fpath, const struct stat* sb, int tflag, FTW* ftwbuf) {
+  smoke_test_ftw(fpath, sb, tflag);
   ASSERT_EQ('/', fpath[ftwbuf->base - 1]) << fpath;
 }
 
 int check_ftw(const char* fpath, const struct stat* sb, int tflag) {
-  sanity_check_ftw(fpath, sb, tflag);
+  smoke_test_ftw(fpath, sb, tflag);
   return 0;
 }
 
 int check_ftw64(const char* fpath, const struct stat64* sb, int tflag) {
-  sanity_check_ftw(fpath, reinterpret_cast<const struct stat*>(sb), tflag);
+  smoke_test_ftw(fpath, reinterpret_cast<const struct stat*>(sb), tflag);
   return 0;
 }
 
 int check_nftw(const char* fpath, const struct stat* sb, int tflag, FTW* ftwbuf) {
-  sanity_check_nftw(fpath, sb, tflag, ftwbuf);
+  smoke_test_nftw(fpath, sb, tflag, ftwbuf);
   return 0;
 }
 
 int check_nftw64(const char* fpath, const struct stat64* sb, int tflag, FTW* ftwbuf) {
-  sanity_check_nftw(fpath, reinterpret_cast<const struct stat*>(sb), tflag, ftwbuf);
+  smoke_test_nftw(fpath, reinterpret_cast<const struct stat*>(sb), tflag, ftwbuf);
   return 0;
 }
 
diff --git a/tests/grp_pwd_test.cpp b/tests/grp_pwd_test.cpp
index 9b23921..bf65720 100644
--- a/tests/grp_pwd_test.cpp
+++ b/tests/grp_pwd_test.cpp
@@ -75,7 +75,11 @@
     EXPECT_STREQ("/", pwd->pw_dir);
   }
 
-  EXPECT_STREQ("/bin/sh", pwd->pw_shell);
+  // This has changed over time and that causes new GSI + old vendor images testing to fail.
+  // This parameter doesn't matter on Android, so simply ignore its value for older vendor images.
+  if (android::base::GetIntProperty("ro.product.first_api_level", 0) >= 30) {
+    EXPECT_STREQ("/bin/sh", pwd->pw_shell);
+  }
 }
 
 static void check_getpwuid(const char* username, uid_t uid, uid_type_t uid_type,
@@ -816,6 +820,24 @@
 #endif
 }
 
+TEST(grp, getgrouplist) {
+#if defined(__BIONIC__)
+  // Query the number of groups.
+  int ngroups = 0;
+  ASSERT_EQ(-1, getgrouplist("root", 123, nullptr, &ngroups));
+  ASSERT_EQ(1, ngroups);
+
+  // Query the specific groups (just the one you pass in on Android).
+  ngroups = 8;
+  gid_t groups[ngroups];
+  ASSERT_EQ(1, getgrouplist("root", 123, groups, &ngroups));
+  ASSERT_EQ(1, ngroups);
+  ASSERT_EQ(123u, groups[0]);
+#else
+  GTEST_SKIP() << "bionic-only test (groups too unpredictable)";
+#endif
+}
+
 #if defined(__BIONIC__)
 static void TestAidNamePrefix(const std::string& file_path) {
   std::string file_contents;
diff --git a/tests/gtest_globals.cpp b/tests/gtest_globals.cpp
index 4160237..5b5ede8 100644
--- a/tests/gtest_globals.cpp
+++ b/tests/gtest_globals.cpp
@@ -24,8 +24,9 @@
 #include <string>
 
 std::string GetTestlibRoot() {
-  // Calculate ANDROID_DATA assuming the binary is in "$ANDROID_DATA/somedir/binary-dir/binary"
-  std::string path = android::base::Dirname(android::base::GetExecutablePath()) + "/..";
+  // Typically the executable is /data/nativetest[64]/bionic-unit-tests/bionic-unit-tests, and the
+  // test libraries are in /data/nativetest[64]/bionic-loader-test-libs.
+  std::string path = android::base::GetExecutableDirectory() + "/..";
 
   std::string out_path;
   if (!android::base::Realpath(path.c_str(), &out_path)) {
diff --git a/tests/gtest_globals.h b/tests/gtest_globals.h
index b3c7b10..1bebb70 100644
--- a/tests/gtest_globals.h
+++ b/tests/gtest_globals.h
@@ -19,8 +19,10 @@
 
 #include <string>
 
-constexpr const char* kPrebuiltElfDir = "prebuilt-elf-files";
-
 std::string GetTestlibRoot();
 
+inline std::string GetPrebuiltElfDir() {
+  return GetTestlibRoot() + "/prebuilt-elf-files";
+}
+
 #endif  // _BIONIC_TESTS_GTEST_GLOBALS_H
diff --git a/tests/libs/Android.bp b/tests/libs/Android.bp
index c427282..ef4fddd 100644
--- a/tests/libs/Android.bp
+++ b/tests/libs/Android.bp
@@ -79,6 +79,22 @@
     shared_libs: ["libtest_elftls_shared_var"],
 }
 
+cc_test {
+   name: "thread_exit_cb_helper.cpp",
+   defaults: ["bionic_testlib_defaults"],
+   srcs: ["thread_exit_cb_helper.cpp"],
+   cflags: ["-fno-emulated-tls"],
+}
+
+cc_test {
+   name: "tls_properties_helper",
+   defaults: ["bionic_testlib_defaults"],
+   srcs: ["tls_properties_helper.cpp"],
+   cflags: ["-fno-emulated-tls"],
+   shared_libs: ["libtest_elftls_shared_var"],
+}
+
+
 cc_test_library {
     name: "libtest_elftls_dynamic_filler_1",
     defaults: ["bionic_testlib_defaults"],
@@ -1268,6 +1284,7 @@
     name: "libtest_check_rtld_next_from_library",
     defaults: ["bionic_testlib_defaults"],
     srcs: ["check_rtld_next_from_library.cpp"],
+    native_coverage: false,
 }
 
 // -----------------------------------------------------------------------------
diff --git a/tests/libs/dlopen_b.cpp b/tests/libs/dlopen_b.cpp
index cd81e16..092c96c 100644
--- a/tests/libs/dlopen_b.cpp
+++ b/tests/libs/dlopen_b.cpp
@@ -1,15 +1,14 @@
 #include <dlfcn.h>
 extern "C" void *dlopen_b() {
-  // TODO (dimitry): this is to work around http://b/20049306
-  // remove once it is fixed
-  static int dummy = 0;
+  // Work around for http://b/20049306, which isn't going to be fixed.
+  static int defeat_sibling_call_optimization = 0;
 
   // This is supposed to succeed because this library has DT_RUNPATH
   // for libtest_dt_runpath_x.so which should be taken into account
   // by dlopen.
   void *handle = dlopen("libtest_dt_runpath_x.so", RTLD_NOW);
   if (handle != nullptr) {
-    dummy++;
+    defeat_sibling_call_optimization++;
     return handle;
   }
   return nullptr;
diff --git a/tests/libs/elftls_dynamic.cpp b/tests/libs/elftls_dynamic.cpp
index 6da2f6f..2500484 100644
--- a/tests/libs/elftls_dynamic.cpp
+++ b/tests/libs/elftls_dynamic.cpp
@@ -41,8 +41,8 @@
 // section, but does not have an entry in the dynsym table and whose
 // solib-relative address appears to overlap with the large TLS variable.
 extern "C" void* get_local_addr() {
-  static char dummy[1024];
-  return &dummy[512];
+  static char buf[1024];
+  return &buf[512];
 }
 
 // This variable comes from libtest_elftls_shared_var.so, which is part of
diff --git a/tests/libs/segment_gap_outer.cpp b/tests/libs/segment_gap_outer.cpp
index 18aa3ee..3ba90d0 100644
--- a/tests/libs/segment_gap_outer.cpp
+++ b/tests/libs/segment_gap_outer.cpp
@@ -2,8 +2,8 @@
 #include <dlfcn.h>
 #include <stdlib.h>
 
-extern "C" void text_before_start_of_gap() {}
-char end_of_gap[0x1000];
+extern "C" void __attribute__((section(".custom_text"))) text_before_start_of_gap() {}
+char __attribute__((section(".custom_bss"))) end_of_gap[0x1000];
 
 extern "C" void* get_inner() {
   android_dlextinfo info = {};
diff --git a/tests/libs/segment_gap_outer.lds b/tests/libs/segment_gap_outer.lds
index 0f175af..527f29e 100644
--- a/tests/libs/segment_gap_outer.lds
+++ b/tests/libs/segment_gap_outer.lds
@@ -2,25 +2,25 @@
   # This starts off fairly normal: rodata, text, dynamic, data, bss with
   # appropriate alignment between them.
   . = SIZEOF_HEADERS;
-  .rodata : {}
+  .rodata : {*(.rodata .rodata.*)}
   . = ALIGN(0x1000);
-  .text : {}
+  .text : {*(.text .text.*)}
   . = ALIGN(0x1000);
-  .dynamic : {}
+  .dynamic : {*(.dynamic)}
   . = ALIGN(0x1000);
-  .data : {}
-  .bss : {}
+  .data : {*(.data .data.*)}
+  .bss : {*(.bss .bss.*)}
 
   # Now create the gap. We need a text segment first to prevent the linker from
-  # merging .bss with .bss.end_of_gap.
+  # merging .bss with .custom_bss.
   . = ALIGN(0x1000);
-  .text.text_before_start_of_gap : {
-    *(.text.text_before_start_of_gap);
+  .custom_text : {
+    *(.custom_text);
   }
 
-  # Place end_of_gap at the end of the gap.
+  # Place custom_bss at the end of the gap.
   . = 0x1000000;
-  .bss.end_of_gap : {
-    *(.bss.*end_of_gap*);
+  .custom_bss : {
+    *(.custom_bss);
   }
 }
diff --git a/libc/bionic/pututline.c b/tests/libs/thread_exit_cb_helper.cpp
similarity index 61%
copy from libc/bionic/pututline.c
copy to tests/libs/thread_exit_cb_helper.cpp
index 8cbf470..8ec1398 100644
--- a/libc/bionic/pututline.c
+++ b/tests/libs/thread_exit_cb_helper.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2019 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -25,40 +25,42 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
-#include <string.h>
+
+// Prevent tests from being compiled with glibc because thread_properties.h
+// only exists in Bionic.
+#if defined(__BIONIC__)
+
 #include <stdio.h>
-#include <utmp.h>
+#include <sys/thread_properties.h>
 
+// Helper binary for testing thread_exit_cb registration.
 
-void pututline(struct utmp* utmp)
-{
-    FILE* f;
-    struct utmp u;
-    long i;
-
-    if (!(f = fopen(_PATH_UTMP, "w+e")))
-        return;
-
-    while (fread(&u, sizeof(struct utmp), 1, f) == 1)
-    {
-        if (!strncmp(utmp->ut_line, u.ut_line, sizeof(u.ut_line) -1))
-        {
-            if ((i = ftell(f)) < 0)
-                goto ret;
-            if (fseek(f, i - sizeof(struct utmp), SEEK_SET) < 0)
-                goto ret;
-            fwrite(utmp, sizeof(struct utmp), 1, f);
-            goto ret;
-        }
-    }
-
-
-    fclose(f);
-
-    if (!(f = fopen(_PATH_UTMP, "w+e")))
-        return;
-    fwrite(utmp, sizeof(struct utmp), 1, f);
-
-ret:
-    fclose(f);
+void exit_cb_1() {
+  printf("exit_cb_1 called ");
 }
+
+void exit_cb_2() {
+  printf("exit_cb_2 called ");
+}
+
+void exit_cb_3() {
+  printf("exit_cb_3 called");
+}
+
+void test_register_thread_exit_cb() {
+  // Register the exit-cb in reverse order (3,2,1)
+  // so that they'd be called in 1,2,3 order.
+  __libc_register_thread_exit_callback(&exit_cb_3);
+  __libc_register_thread_exit_callback(&exit_cb_2);
+  __libc_register_thread_exit_callback(&exit_cb_1);
+}
+
+int main() {
+  test_register_thread_exit_cb();
+  return 0;
+}
+#else
+int main() {
+  return 0;
+}
+#endif  // __BIONIC__
diff --git a/tests/libs/tls_properties_helper.cpp b/tests/libs/tls_properties_helper.cpp
new file mode 100644
index 0000000..93f5e9f
--- /dev/null
+++ b/tests/libs/tls_properties_helper.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+// Prevent tests from being compiled with glibc because thread_properties.h
+// only exists in Bionic.
+#if defined(__BIONIC__)
+
+#include <sys/thread_properties.h>
+
+#include <dlfcn.h>
+#include <stdio.h>
+#include <unistd.h>  // for gettid
+
+// Helper binary to use TLS-related functions in thread_properties
+
+// Tests __get_static_tls_bound.
+void test_static_tls_bounds() {
+  void* start_addr;
+  void* end_addr;
+
+  __libc_get_static_tls_bounds(reinterpret_cast<void**>(&start_addr),
+                               reinterpret_cast<void**>(&end_addr));
+  printf("done_get_static_tls_bounds\n");
+}
+
+// Tests iterate_dynamic tls chunks.
+// Export a var from the shared so.
+__thread char large_tls_var[4 * 1024 * 1024];
+void test_iter_tls() {
+  void* lib = dlopen("libtest_elftls_dynamic.so", RTLD_LOCAL | RTLD_NOW);
+
+  int i = 0;
+  auto cb = [&](void* dtls_begin, void* dtls_end, size_t dso_id, void* arg) {
+    printf("iterate_cb i = %d\n", i++);
+  };
+  __libc_iterate_dynamic_tls(gettid(), cb, nullptr);
+  printf("done_iterate_dynamic_tls\n");
+}
+
+int main() {
+  test_static_tls_bounds();
+  test_iter_tls();
+  return 0;
+}
+
+#else
+int main() {
+  return 0;
+}
+#endif  // __BIONIC__
diff --git a/tests/link_test.cpp b/tests/link_test.cpp
index 75bb4d6..127a3d9 100644
--- a/tests/link_test.cpp
+++ b/tests/link_test.cpp
@@ -258,7 +258,7 @@
   ASSERT_TRUE(entries != nullptr);
   ASSERT_GT(count, 0);
 
-  // Sanity checks
+  // Validity checks.
   uintptr_t func = reinterpret_cast<uintptr_t>(read_exidx_func);
   bool found = false;
   for (int i = 0; i < count; ++i) {
diff --git a/tests/malloc_test.cpp b/tests/malloc_test.cpp
index 47a9033..55bd149 100644
--- a/tests/malloc_test.cpp
+++ b/tests/malloc_test.cpp
@@ -662,6 +662,46 @@
 #endif
 }
 
+#if defined(__BIONIC__)
+static void GetAllocatorVersion(bool* allocator_scudo) {
+  TemporaryFile tf;
+  ASSERT_TRUE(tf.fd != -1);
+  FILE* fp = fdopen(tf.fd, "w+");
+  tf.release();
+  ASSERT_TRUE(fp != nullptr);
+  ASSERT_EQ(0, malloc_info(0, fp));
+  ASSERT_EQ(0, fclose(fp));
+
+  std::string contents;
+  ASSERT_TRUE(android::base::ReadFileToString(tf.path, &contents));
+
+  tinyxml2::XMLDocument doc;
+  ASSERT_EQ(tinyxml2::XML_SUCCESS, doc.Parse(contents.c_str()));
+
+  auto root = doc.FirstChildElement();
+  ASSERT_NE(nullptr, root);
+  ASSERT_STREQ("malloc", root->Name());
+  std::string version(root->Attribute("version"));
+  *allocator_scudo = (version == "scudo-1");
+}
+#endif
+
+TEST(malloc, mallopt_scudo_only_options) {
+#if defined(__BIONIC__)
+  SKIP_WITH_HWASAN << "hwasan does not implement mallopt";
+  bool allocator_scudo;
+  GetAllocatorVersion(&allocator_scudo);
+  if (!allocator_scudo) {
+    GTEST_SKIP() << "scudo allocator only test";
+  }
+  ASSERT_EQ(1, mallopt(M_CACHE_COUNT_MAX, 100));
+  ASSERT_EQ(1, mallopt(M_CACHE_SIZE_MAX, 1024 * 1024 * 2));
+  ASSERT_EQ(1, mallopt(M_TSDS_COUNT_MAX, 8));
+#else
+  GTEST_SKIP() << "bionic-only test";
+#endif
+}
+
 TEST(malloc, reallocarray_overflow) {
 #if HAVE_REALLOCARRAY
   // Values that cause overflow to a result small enough (8 on LP64) that malloc would "succeed".
diff --git a/tests/netinet_ether_test.cpp b/tests/netinet_ether_test.cpp
index faa3db4..af020ec 100644
--- a/tests/netinet_ether_test.cpp
+++ b/tests/netinet_ether_test.cpp
@@ -34,7 +34,7 @@
 TEST(netinet_ether, ether_aton_r__ether_ntoa_r) {
   ether_addr addr;
   memset(&addr, 0, sizeof(addr));
-  ether_addr* a = ether_aton_r("12:34:56:78:9a:bc", &addr);
+  ether_addr* a = ether_aton_r("12:34:56:78:9a:Bc", &addr);
   ASSERT_EQ(&addr, a);
   ASSERT_EQ(0x12, addr.ether_addr_octet[0]);
   ASSERT_EQ(0x34, addr.ether_addr_octet[1]);
@@ -49,3 +49,11 @@
   ASSERT_EQ(buf, p);
   ASSERT_STREQ("12:34:56:78:9a:bc", buf);
 }
+
+TEST(netinet_ether, ether_aton_r_failures) {
+  ether_addr addr;
+  ASSERT_TRUE(ether_aton_r("12:34:56:78:9a;bc", &addr) == nullptr);
+  ASSERT_TRUE(ether_aton_r("12:34:56:78:9a:bc ", &addr) == nullptr);
+  ASSERT_TRUE(ether_aton_r("g2:34:56:78:9a:bc ", &addr) == nullptr);
+  ASSERT_TRUE(ether_aton_r("1G:34:56:78:9a:bc ", &addr) == nullptr);
+}
diff --git a/tests/netinet_in_test.cpp b/tests/netinet_in_test.cpp
index 2606082..437e180 100644
--- a/tests/netinet_in_test.cpp
+++ b/tests/netinet_in_test.cpp
@@ -31,8 +31,15 @@
 static constexpr uint64_t be64 = 0xf0debc9a78563412;
 
 TEST(netinet_in, bindresvport) {
-  // This isn't something we can usually test, so just check the symbol's there.
+  // This isn't something we can usually test (because you need to be root),
+  // so just check the symbol's there.
   ASSERT_EQ(-1, bindresvport(-1, nullptr));
+
+  // Only AF_INET is supported.
+  sockaddr_in sin = {.sin_family = AF_INET6};
+  errno = 0;
+  ASSERT_EQ(-1, bindresvport(-1, &sin));
+  ASSERT_EQ(EPFNOSUPPORT, errno);
 }
 
 TEST(netinet_in, in6addr_any) {
diff --git a/tests/pty_test.cpp b/tests/pty_test.cpp
index 29f86f1..d5d8994 100644
--- a/tests/pty_test.cpp
+++ b/tests/pty_test.cpp
@@ -28,34 +28,34 @@
 #include "utils.h"
 
 TEST(pty, openpty) {
-  int master, slave;
+  int pty, tty;
   char name[32];
   struct winsize w = { 123, 456, 9999, 999 };
-  ASSERT_EQ(0, openpty(&master, &slave, name, nullptr, &w));
-  ASSERT_NE(-1, master);
-  ASSERT_NE(-1, slave);
-  ASSERT_NE(master, slave);
+  ASSERT_EQ(0, openpty(&pty, &tty, name, nullptr, &w));
+  ASSERT_NE(-1, pty);
+  ASSERT_NE(-1, tty);
+  ASSERT_NE(pty, tty);
 
   char tty_name[32];
-  ASSERT_EQ(0, ttyname_r(slave, tty_name, sizeof(tty_name)));
+  ASSERT_EQ(0, ttyname_r(tty, tty_name, sizeof(tty_name)));
   ASSERT_STREQ(tty_name, name);
 
   struct winsize w_actual;
-  ASSERT_EQ(0, ioctl(slave, TIOCGWINSZ, &w_actual));
+  ASSERT_EQ(0, ioctl(tty, TIOCGWINSZ, &w_actual));
   ASSERT_EQ(w_actual.ws_row, w.ws_row);
   ASSERT_EQ(w_actual.ws_col, w.ws_col);
   ASSERT_EQ(w_actual.ws_xpixel, w.ws_xpixel);
   ASSERT_EQ(w_actual.ws_ypixel, w.ws_ypixel);
 
-  close(master);
-  close(slave);
+  close(pty);
+  close(tty);
 }
 
 TEST(pty, forkpty) {
   pid_t sid = getsid(0);
 
-  int master;
-  pid_t pid = forkpty(&master, nullptr, nullptr, nullptr);
+  int pty;
+  pid_t pid = forkpty(&pty, nullptr, nullptr, nullptr);
   ASSERT_NE(-1, pid);
 
   if (pid == 0) {
@@ -68,12 +68,12 @@
 
   AssertChildExited(pid, 0);
 
-  close(master);
+  close(pty);
 }
 
 struct PtyReader_28979140_Arg {
   int main_cpu_id;
-  int slave_fd;
+  int fd;
   uint32_t data_count;
   bool finished;
   std::atomic<bool> matched;
@@ -90,7 +90,7 @@
   while (counter <= arg->data_count) {
     char buf[4096];  // Use big buffer to read to hit the bug more easily.
     size_t to_read = std::min(sizeof(buf), (arg->data_count + 1 - counter) * sizeof(uint32_t));
-    ASSERT_TRUE(android::base::ReadFully(arg->slave_fd, buf, to_read));
+    ASSERT_TRUE(android::base::ReadFully(arg->fd, buf, to_read));
     size_t num_of_value = to_read / sizeof(uint32_t);
     uint32_t* p = reinterpret_cast<uint32_t*>(buf);
     while (num_of_value-- > 0) {
@@ -99,7 +99,7 @@
       }
     }
   }
-  close(arg->slave_fd);
+  close(arg->fd);
   arg->finished = true;
 }
 
@@ -114,16 +114,16 @@
   constexpr uint32_t TEST_DATA_COUNT = 2000000;
 
   // 1. Open raw pty.
-  int master;
-  int slave;
-  ASSERT_EQ(0, openpty(&master, &slave, nullptr, nullptr, nullptr));
+  int pty;
+  int tty;
+  ASSERT_EQ(0, openpty(&pty, &tty, nullptr, nullptr, nullptr));
   termios tattr;
-  ASSERT_EQ(0, tcgetattr(slave, &tattr));
+  ASSERT_EQ(0, tcgetattr(tty, &tattr));
   cfmakeraw(&tattr);
-  ASSERT_EQ(0, tcsetattr(slave, TCSADRAIN, &tattr));
+  ASSERT_EQ(0, tcsetattr(tty, TCSADRAIN, &tattr));
 
-  // 2. Make master thread and slave thread running on different cpus:
-  // master thread uses first available cpu, and slave thread uses other cpus.
+  // 2. Make two threads running on different cpus:
+  // pty thread uses first available cpu, and tty thread uses other cpus.
   PtyReader_28979140_Arg arg;
   arg.main_cpu_id = -1;
   for (int i = 0; i < CPU_SETSIZE; i++) {
@@ -134,9 +134,9 @@
   }
   ASSERT_GE(arg.main_cpu_id, 0);
 
-  // 3. Create thread for slave reader.
+  // 3. Create thread for tty reader.
   pthread_t thread;
-  arg.slave_fd = slave;
+  arg.fd = tty;
   arg.data_count = TEST_DATA_COUNT;
   arg.matched = true;
   ASSERT_EQ(0, pthread_create(&thread, nullptr,
@@ -147,7 +147,7 @@
   CPU_SET(arg.main_cpu_id, &cpus);
   ASSERT_EQ(0, sched_setaffinity(0, sizeof(cpu_set_t), &cpus));
 
-  // 4. Send data to slave.
+  // 4. Send data to tty reader.
   // Send a bunch of data at a time, so it is easier to catch the bug that some data isn't seen
   // by the reader thread on another cpu.
   uint32_t counter_buf[100];
@@ -156,11 +156,11 @@
     for (size_t i = 0; i < sizeof(counter_buf) / sizeof(counter_buf[0]); ++i) {
       counter_buf[i] = counter++;
     }
-    ASSERT_TRUE(android::base::WriteFully(master, &counter_buf, sizeof(counter_buf)));
+    ASSERT_TRUE(android::base::WriteFully(pty, &counter_buf, sizeof(counter_buf)));
     ASSERT_TRUE(arg.matched) << "failed at count = " << counter;
   }
   ASSERT_EQ(0, pthread_join(thread, nullptr));
   ASSERT_TRUE(arg.finished);
   ASSERT_TRUE(arg.matched);
-  close(master);
+  close(pty);
 }
diff --git a/tests/sched_test.cpp b/tests/sched_test.cpp
index 9309a7f..03e8062 100644
--- a/tests/sched_test.cpp
+++ b/tests/sched_test.cpp
@@ -301,3 +301,7 @@
   // don't behave as POSIX specifies. http://b/26203902.
   ASSERT_EQ(0, sched_setscheduler(getpid(), original_policy, &p));
 }
+
+TEST(sched, sched_getaffinity_failure) {
+  ASSERT_EQ(-1, sched_getaffinity(getpid(), 0, nullptr));
+}
diff --git a/tests/search_test.cpp b/tests/search_test.cpp
index 1509199..8b8359d 100644
--- a/tests/search_test.cpp
+++ b/tests/search_test.cpp
@@ -114,6 +114,11 @@
   ASSERT_EQ(3U, g_free_calls);
 }
 
+TEST(search, tdestroy_null) {
+  // It's okay to pass a null node, and your callback will not be called.
+  tdestroy(nullptr, nullptr);
+}
+
 struct pod_node {
   explicit pod_node(int i) : i(i) {}
   int i;
@@ -285,3 +290,26 @@
   AssertEntry(e, "a", "B");
   hdestroy_r(&h2);
 }
+
+TEST(search, hsearch_resizing) {
+  ASSERT_NE(0, hcreate(1));
+
+  std::vector<char*> entries;
+  // Add enough entries to ensure that we've had to resize.
+  for (char ch = ' '; ch <= '~'; ++ch) {
+    char* p;
+    asprintf(&p, "%c", ch);
+    ENTRY e;
+    e.data = e.key = p;
+    ASSERT_TRUE(hsearch(e, ENTER) != nullptr);
+    entries.push_back(p);
+  }
+
+  // Check they're all there.
+  for (auto& p : entries) {
+    ENTRY* e = hsearch(ENTRY{.key = p, .data = nullptr}, FIND);
+    AssertEntry(e, p, p);
+  }
+
+  for (auto& p : entries) free(p);
+}
diff --git a/tests/stdatomic_test.cpp b/tests/stdatomic_test.cpp
index 11d41b4..7b98df2 100644
--- a/tests/stdatomic_test.cpp
+++ b/tests/stdatomic_test.cpp
@@ -192,7 +192,7 @@
   atomic_uint_least32_t z;
 };
 
-// Very simple acquire/release memory ordering sanity check.
+// Very simple acquire/release memory ordering smoke test.
 static void* writer(void* arg) {
   three_atomics* a = reinterpret_cast<three_atomics*>(arg);
   for (uint_least32_t i = 0; i <= BIG; i+=2) {
@@ -239,7 +239,7 @@
 }
 
 TEST(stdatomic, ordering) {
-  // Run a memory ordering sanity test.
+  // Run a memory ordering smoke test.
   void* result;
   three_atomics a;
   atomic_init(&a.x, 0ul);
diff --git a/tests/stdio_test.cpp b/tests/stdio_test.cpp
index f6eca05..c21c3b8 100644
--- a/tests/stdio_test.cpp
+++ b/tests/stdio_test.cpp
@@ -371,6 +371,11 @@
 #endif
 }
 
+TEST(STDIO_TEST, snprintf_measure) {
+  char buf[16];
+  ASSERT_EQ(11, snprintf(buf, 0, "Hello %s", "world"));
+}
+
 TEST(STDIO_TEST, snprintf_smoke) {
   char buf[BUFSIZ];
 
@@ -1155,7 +1160,6 @@
   free(p1);
 }
 
-
 TEST(STDIO_TEST, sscanf_mlc) {
   // This is so useless that clang doesn't even believe it exists...
 #pragma clang diagnostic push
@@ -1189,7 +1193,6 @@
 #pragma clang diagnostic pop
 }
 
-
 TEST(STDIO_TEST, sscanf_ms) {
   CheckScanfM(sscanf, "hello", "%ms", 1, "hello");
   CheckScanfM(sscanf, "hello", "%4ms", 1, "hell");
@@ -2533,6 +2536,16 @@
   eth.Run([&]() { exit(puts("a b c")); }, 0, "a b c\n");
 }
 
+TEST(STDIO_TEST, putchar) {
+  ExecTestHelper eth;
+  eth.Run([&]() { exit(putchar('A')); }, 65, "A");
+}
+
+TEST(STDIO_TEST, putchar_unlocked) {
+  ExecTestHelper eth;
+  eth.Run([&]() { exit(putchar('B')); }, 66, "B");
+}
+
 TEST(STDIO_TEST, unlocked) {
   TemporaryFile tf;
 
@@ -2733,3 +2746,73 @@
  ASSERT_NE(0, RENAME_WHITEOUT);
 #endif
 }
+
+TEST(STDIO_TEST, fdopen_failures) {
+  FILE* fp;
+  int fd = open("/proc/version", O_RDONLY);
+  ASSERT_TRUE(fd != -1);
+
+  // Nonsense mode.
+  errno = 0;
+  fp = fdopen(fd, "nonsense");
+  ASSERT_TRUE(fp == nullptr);
+  ASSERT_EQ(EINVAL, errno);
+
+  // Mode that isn't a subset of the fd's actual mode.
+  errno = 0;
+  fp = fdopen(fd, "w");
+  ASSERT_TRUE(fp == nullptr);
+  ASSERT_EQ(EINVAL, errno);
+
+  // Can't set append on the underlying fd.
+  errno = 0;
+  fp = fdopen(fd, "a");
+  ASSERT_TRUE(fp == nullptr);
+  ASSERT_EQ(EINVAL, errno);
+
+  // Bad fd.
+  errno = 0;
+  fp = fdopen(-1, "re");
+  ASSERT_TRUE(fp == nullptr);
+  ASSERT_EQ(EBADF, errno);
+
+  close(fd);
+}
+
+TEST(STDIO_TEST, fmemopen_invalid_mode) {
+  errno = 0;
+  FILE* fp = fmemopen(nullptr, 16, "nonsense");
+  ASSERT_TRUE(fp == nullptr);
+  ASSERT_EQ(EINVAL, errno);
+}
+
+TEST(STDIO_TEST, fopen_invalid_mode) {
+  errno = 0;
+  FILE* fp = fopen("/proc/version", "nonsense");
+  ASSERT_TRUE(fp == nullptr);
+  ASSERT_EQ(EINVAL, errno);
+}
+
+TEST(STDIO_TEST, freopen_invalid_mode) {
+  FILE* fp = fopen("/proc/version", "re");
+  ASSERT_TRUE(fp != nullptr);
+
+  errno = 0;
+  fp = freopen("/proc/version", "nonsense", fp);
+  ASSERT_TRUE(fp == nullptr);
+  ASSERT_EQ(EINVAL, errno);
+}
+
+TEST(STDIO_TEST, asprintf_smoke) {
+  char* p = nullptr;
+  ASSERT_EQ(11, asprintf(&p, "hello %s", "world"));
+  ASSERT_STREQ("hello world", p);
+  free(p);
+}
+
+TEST(STDIO_TEST, fopen_ENOENT) {
+  errno = 0;
+  FILE* fp = fopen("/proc/does-not-exist", "re");
+  ASSERT_TRUE(fp == nullptr);
+  ASSERT_EQ(ENOENT, errno);
+}
diff --git a/tests/stdlib_test.cpp b/tests/stdlib_test.cpp
index 3f1ec86..c7b2ad8 100644
--- a/tests/stdlib_test.cpp
+++ b/tests/stdlib_test.cpp
@@ -800,10 +800,25 @@
   ASSERT_EQ(T(0), fn("123", &end_p, 37));
   ASSERT_EQ(EINVAL, errno);
 
+  // Both leading + or - are always allowed (even for the strtou* family).
+  ASSERT_EQ(T(-123), fn("-123", &end_p, 10));
+  ASSERT_EQ(T(123), fn("+123", &end_p, 10));
+
   // If we see "0x" *not* followed by a hex digit, we shouldn't swallow the 'x'.
   ASSERT_EQ(T(0), fn("0xy", &end_p, 16));
   ASSERT_EQ('x', *end_p);
 
+  // Hexadecimal (both the 0x and the digits) is case-insensitive.
+  ASSERT_EQ(T(0xab), fn("0xab", &end_p, 0));
+  ASSERT_EQ(T(0xab), fn("0Xab", &end_p, 0));
+  ASSERT_EQ(T(0xab), fn("0xAB", &end_p, 0));
+  ASSERT_EQ(T(0xab), fn("0XAB", &end_p, 0));
+  ASSERT_EQ(T(0xab), fn("0xAb", &end_p, 0));
+  ASSERT_EQ(T(0xab), fn("0XAb", &end_p, 0));
+
+  // Octal lives! (Sadly.)
+  ASSERT_EQ(T(0666), fn("0666", &end_p, 0));
+
   if (std::numeric_limits<T>::is_signed) {
     // Minimum (such as -128).
     std::string min{std::to_string(std::numeric_limits<T>::min())};
@@ -878,6 +893,18 @@
   CheckStrToInt(strtoumax);
 }
 
+TEST(stdlib, atoi) {
+  // Implemented using strtol in bionic, so extensive testing unnecessary.
+  ASSERT_EQ(123, atoi("123four"));
+  ASSERT_EQ(0, atoi("hello"));
+}
+
+TEST(stdlib, atol) {
+  // Implemented using strtol in bionic, so extensive testing unnecessary.
+  ASSERT_EQ(123L, atol("123four"));
+  ASSERT_EQ(0L, atol("hello"));
+}
+
 TEST(stdlib, abs) {
   ASSERT_EQ(INT_MAX, abs(-INT_MAX));
   ASSERT_EQ(INT_MAX, abs(INT_MAX));
diff --git a/tests/string_test.cpp b/tests/string_test.cpp
index 0ed0598f..22be852 100644
--- a/tests/string_test.cpp
+++ b/tests/string_test.cpp
@@ -64,6 +64,11 @@
   ASSERT_STREQ("Unknown error 134", strerror(EHWPOISON + 1));
 }
 
+TEST(STRING_TEST, strerror_l) {
+  // bionic just forwards to strerror(3).
+  ASSERT_STREQ("Success", strerror_l(0, LC_GLOBAL_LOCALE));
+}
+
 #if defined(__BIONIC__)
 static void* ConcurrentStrErrorFn(void*) {
   bool equal = (strcmp("Unknown error 2002", strerror(2002)) == 0);
@@ -1538,13 +1543,31 @@
 }
 
 TEST(STRING_TEST, memmem_smoke) {
-  const char haystack[] = "big\0daddy\0giant\0haystacks";
-  ASSERT_EQ(haystack, memmem(haystack, sizeof(haystack), "", 0));
-  ASSERT_EQ(haystack + 3, memmem(haystack, sizeof(haystack), "", 1));
+  const char haystack[] = "big\0daddy/giant\0haystacks!";
+
+  // The current memmem() implementation has special cases for needles of
+  // lengths 0, 1, 2, 3, and 4, plus a long needle case. We test matches at the
+  // beginning, middle, and end of the haystack.
+
+  ASSERT_EQ(haystack + 0, memmem(haystack, sizeof(haystack), "", 0));
+
   ASSERT_EQ(haystack + 0, memmem(haystack, sizeof(haystack), "b", 1));
-  ASSERT_EQ(haystack + 1, memmem(haystack, sizeof(haystack), "i", 1));
-  ASSERT_EQ(haystack + 4, memmem(haystack, sizeof(haystack), "da", 2));
-  ASSERT_EQ(haystack + 8, memmem(haystack, sizeof(haystack), "y\0g", 3));
+  ASSERT_EQ(haystack + 0, memmem(haystack, sizeof(haystack), "bi", 2));
+  ASSERT_EQ(haystack + 0, memmem(haystack, sizeof(haystack), "big", 3));
+  ASSERT_EQ(haystack + 0, memmem(haystack, sizeof(haystack), "big\0", 4));
+  ASSERT_EQ(haystack + 0, memmem(haystack, sizeof(haystack), "big\0d", 5));
+
+  ASSERT_EQ(haystack + 2, memmem(haystack, sizeof(haystack), "g", 1));
+  ASSERT_EQ(haystack + 10, memmem(haystack, sizeof(haystack), "gi", 2));
+  ASSERT_EQ(haystack + 10, memmem(haystack, sizeof(haystack), "gia", 3));
+  ASSERT_EQ(haystack + 10, memmem(haystack, sizeof(haystack), "gian", 4));
+  ASSERT_EQ(haystack + 10, memmem(haystack, sizeof(haystack), "giant", 5));
+
+  ASSERT_EQ(haystack + 25, memmem(haystack, sizeof(haystack), "!", 1));
+  ASSERT_EQ(haystack + 24, memmem(haystack, sizeof(haystack), "s!", 2));
+  ASSERT_EQ(haystack + 23, memmem(haystack, sizeof(haystack), "ks!", 3));
+  ASSERT_EQ(haystack + 22, memmem(haystack, sizeof(haystack), "cks!", 4));
+  ASSERT_EQ(haystack + 21, memmem(haystack, sizeof(haystack), "acks!", 5));
 }
 
 TEST(STRING_TEST, strstr_smoke) {
@@ -1589,16 +1612,44 @@
   ASSERT_TRUE(strcoll("aac", "aab") > 0);
 }
 
+TEST(STRING_TEST, strcoll_l_smoke) {
+  // bionic just forwards to strcoll(3).
+  ASSERT_TRUE(strcoll_l("aab", "aac", LC_GLOBAL_LOCALE) < 0);
+  ASSERT_TRUE(strcoll_l("aab", "aab", LC_GLOBAL_LOCALE) == 0);
+  ASSERT_TRUE(strcoll_l("aac", "aab", LC_GLOBAL_LOCALE) > 0);
+}
+
 TEST(STRING_TEST, strxfrm_smoke) {
   const char* src1 = "aab";
   char dst1[16] = {};
-  ASSERT_GT(strxfrm(dst1, src1, sizeof(dst1)), 0U);
+  // Dry run.
+  ASSERT_EQ(strxfrm(dst1, src1, 0), 3U);
+  ASSERT_STREQ(dst1, "");
+  // Really do it.
+  ASSERT_EQ(strxfrm(dst1, src1, sizeof(dst1)), 3U);
+
   const char* src2 = "aac";
   char dst2[16] = {};
-  ASSERT_GT(strxfrm(dst2, src2, sizeof(dst2)), 0U);
+  // Dry run.
+  ASSERT_EQ(strxfrm(dst2, src2, 0), 3U);
+  ASSERT_STREQ(dst2, "");
+  // Really do it.
+  ASSERT_EQ(strxfrm(dst2, src2, sizeof(dst2)), 3U);
+
+  // The "transform" of two different strings should cause different outputs.
   ASSERT_TRUE(strcmp(dst1, dst2) < 0);
 }
 
+TEST(STRING_TEST, strxfrm_l_smoke) {
+  // bionic just forwards to strxfrm(3), so this is a subset of the
+  // strxfrm test.
+  const char* src1 = "aab";
+  char dst1[16] = {};
+  ASSERT_EQ(strxfrm_l(dst1, src1, 0, LC_GLOBAL_LOCALE), 3U);
+  ASSERT_STREQ(dst1, "");
+  ASSERT_EQ(strxfrm_l(dst1, src1, sizeof(dst1), LC_GLOBAL_LOCALE), 3U);
+}
+
 TEST(STRING_TEST, memccpy_smoke) {
   char dst[32];
 
diff --git a/tests/sys_thread_properties_test.cpp b/tests/sys_thread_properties_test.cpp
new file mode 100644
index 0000000..cf1a6ba
--- /dev/null
+++ b/tests/sys_thread_properties_test.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2020 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 <gtest/gtest.h>
+
+#include "gtest_globals.h"
+#include "utils.h"
+
+TEST(thread_properties_test, iterate_dts) {
+#if defined(__BIONIC__)
+  const char expected_out[] =
+      "got test_static_tls_bounds\niterate_cb i = 0\ndone_iterate_dynamic_tls\n";
+  std::string helper = GetTestLibRoot() + "tls_properties_helper/tls_properties_helper";
+  chmod(helper.c_str(), 0755);  // TODO: "x" lost in CTS, b/34945607
+
+  ExecTestHelper eth;
+  eth.SetArgs({helper.c_str(), nullptr});
+  eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, 0, expected_out);
+#endif
+}
+
+TEST(thread_properties_test, thread_exit_cb) {
+#if defined(__BIONIC__)
+  // tests/libs/thread_exit_cb_helper.cpp
+  const char expected_out[] = "exit_cb_1 called exit_cb_2 called exit_cb_3 called";
+  std::string helper = GetTestLibRoot() + "thread_exit_cb_helper/thread_exit_cb_helper";
+  chmod(helper.c_str(), 0755);  // TODO: "x" lost in CTS, b/34945607
+
+  ExecTestHelper eth;
+  eth.SetArgs({helper.c_str(), nullptr});
+  eth.Run([&]() { execve(helper.c_str(), eth.GetArgs(), eth.GetEnv()); }, 0, expected_out);
+
+#endif
+}
diff --git a/tests/sys_vfs_test.cpp b/tests/sys_vfs_test.cpp
index a521967..f82f505 100644
--- a/tests/sys_vfs_test.cpp
+++ b/tests/sys_vfs_test.cpp
@@ -44,12 +44,26 @@
   Check(sb);
 }
 
+TEST(sys_vfs, statfs_failure) {
+  struct statfs sb;
+  errno = 0;
+  ASSERT_EQ(-1, statfs("/does-not-exist", &sb));
+  ASSERT_EQ(ENOENT, errno);
+}
+
 TEST(sys_vfs, statfs64) {
   struct statfs64 sb;
   ASSERT_EQ(0, statfs64("/proc", &sb));
   Check(sb);
 }
 
+TEST(sys_vfs, statfs64_failure) {
+  struct statfs64 sb;
+  errno = 0;
+  ASSERT_EQ(-1, statfs64("/does-not-exist", &sb));
+  ASSERT_EQ(ENOENT, errno);
+}
+
 TEST(sys_vfs, fstatfs) {
   struct statfs sb;
   int fd = open("/proc", O_RDONLY);
@@ -58,6 +72,13 @@
   Check(sb);
 }
 
+TEST(sys_vfs, fstatfs_failure) {
+  struct statfs sb;
+  errno = 0;
+  ASSERT_EQ(-1, fstatfs(-1, &sb));
+  ASSERT_EQ(EBADF, errno);
+}
+
 TEST(sys_vfs, fstatfs64) {
   struct statfs64 sb;
   int fd = open("/proc", O_RDONLY);
@@ -65,3 +86,10 @@
   close(fd);
   Check(sb);
 }
+
+TEST(sys_vfs, fstatfs64_failure) {
+  struct statfs sb;
+  errno = 0;
+  ASSERT_EQ(-1, fstatfs(-1, &sb));
+  ASSERT_EQ(EBADF, errno);
+}
diff --git a/libc/bionic/pututline.c b/tests/sys_wait_test.cpp
similarity index 63%
copy from libc/bionic/pututline.c
copy to tests/sys_wait_test.cpp
index 8cbf470..c006972 100644
--- a/libc/bionic/pututline.c
+++ b/tests/sys_wait_test.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2020 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -25,40 +25,20 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
-#include <string.h>
-#include <stdio.h>
-#include <utmp.h>
 
+#include <gtest/gtest.h>
 
-void pututline(struct utmp* utmp)
-{
-    FILE* f;
-    struct utmp u;
-    long i;
+#include <sys/wait.h>
 
-    if (!(f = fopen(_PATH_UTMP, "w+e")))
-        return;
+TEST(sys_wait, waitid) {
+  pid_t pid = fork();
+  ASSERT_NE(pid, -1);
 
-    while (fread(&u, sizeof(struct utmp), 1, f) == 1)
-    {
-        if (!strncmp(utmp->ut_line, u.ut_line, sizeof(u.ut_line) -1))
-        {
-            if ((i = ftell(f)) < 0)
-                goto ret;
-            if (fseek(f, i - sizeof(struct utmp), SEEK_SET) < 0)
-                goto ret;
-            fwrite(utmp, sizeof(struct utmp), 1, f);
-            goto ret;
-        }
-    }
+  if (pid == 0) _exit(66);
 
-
-    fclose(f);
-
-    if (!(f = fopen(_PATH_UTMP, "w+e")))
-        return;
-    fwrite(utmp, sizeof(struct utmp), 1, f);
-
-ret:
-    fclose(f);
+  siginfo_t si = {};
+  ASSERT_EQ(0, waitid(P_PID, pid, &si, WEXITED));
+  ASSERT_EQ(pid, si.si_pid);
+  ASSERT_EQ(66, si.si_status);
+  ASSERT_EQ(CLD_EXITED, si.si_code);
 }
diff --git a/tests/time_test.cpp b/tests/time_test.cpp
index 74d691d..3d745ea 100644
--- a/tests/time_test.cpp
+++ b/tests/time_test.cpp
@@ -142,7 +142,7 @@
   t.tm_mday = 10;
 
 #if !defined(__LP64__)
-  // 32-bit bionic stupidly had a signed 32-bit time_t.
+  // 32-bit bionic has a signed 32-bit time_t.
   ASSERT_EQ(-1, mktime(&t));
   ASSERT_EQ(EOVERFLOW, errno);
 #else
@@ -1008,4 +1008,5 @@
 
 TEST(time, difftime) {
   ASSERT_EQ(1.0, difftime(1, 0));
+  ASSERT_EQ(-1.0, difftime(0, 1));
 }
diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp
index 6b28561..43d50f8 100644
--- a/tests/unistd_test.cpp
+++ b/tests/unistd_test.cpp
@@ -1350,6 +1350,11 @@
   ASSERT_EQ(EACCES, errno);
 }
 
+static void append_llvm_cov_env_var(std::string& env_str) {
+  if (getenv("LLVM_PROFILE_FILE") != nullptr)
+    env_str.append("__LLVM_PROFILE_RT_INIT_ONCE=__LLVM_PROFILE_RT_INIT_ONCE\n");
+}
+
 TEST(UNISTD_TEST, execve_args) {
   // int execve(const char* path, char* argv[], char* envp[]);
 
@@ -1361,7 +1366,12 @@
   // Test environment variable setting too.
   eth.SetArgs({"printenv", nullptr});
   eth.SetEnv({"A=B", nullptr});
-  eth.Run([&]() { execve(BIN_DIR "printenv", eth.GetArgs(), eth.GetEnv()); }, 0, "A=B\n");
+
+  std::string expected_output("A=B\n");
+  append_llvm_cov_env_var(expected_output);
+
+  eth.Run([&]() { execve(BIN_DIR "printenv", eth.GetArgs(), eth.GetEnv()); }, 0,
+          expected_output.c_str());
 }
 
 TEST(UNISTD_TEST, execl_failure) {
@@ -1386,8 +1396,13 @@
 TEST(UNISTD_TEST, execle) {
   ExecTestHelper eth;
   eth.SetEnv({"A=B", nullptr});
+
+  std::string expected_output("A=B\n");
+  append_llvm_cov_env_var(expected_output);
+
   // int execle(const char* path, const char* arg, ..., char* envp[]);
-  eth.Run([&]() { execle(BIN_DIR "printenv", "printenv", nullptr, eth.GetEnv()); }, 0, "A=B\n");
+  eth.Run([&]() { execle(BIN_DIR "printenv", "printenv", nullptr, eth.GetEnv()); }, 0,
+          expected_output.c_str());
 }
 
 TEST(UNISTD_TEST, execv_failure) {
@@ -1450,7 +1465,11 @@
   // Test environment variable setting too.
   eth.SetArgs({"printenv", nullptr});
   eth.SetEnv({"A=B", nullptr});
-  eth.Run([&]() { execvpe("printenv", eth.GetArgs(), eth.GetEnv()); }, 0, "A=B\n");
+
+  std::string expected_output("A=B\n");
+  append_llvm_cov_env_var(expected_output);
+
+  eth.Run([&]() { execvpe("printenv", eth.GetArgs(), eth.GetEnv()); }, 0, expected_output.c_str());
 }
 
 TEST(UNISTD_TEST, execvpe_ENOEXEC) {
@@ -1538,7 +1557,11 @@
   ASSERT_NE(-1, printenv_fd);
   eth.SetArgs({"printenv", nullptr});
   eth.SetEnv({"A=B", nullptr});
-  eth.Run([&]() { fexecve(printenv_fd, eth.GetArgs(), eth.GetEnv()); }, 0, "A=B\n");
+
+  std::string expected_output("A=B\n");
+  append_llvm_cov_env_var(expected_output);
+
+  eth.Run([&]() { fexecve(printenv_fd, eth.GetArgs(), eth.GetEnv()); }, 0, expected_output.c_str());
   close(printenv_fd);
 }
 
diff --git a/tests/utmp_test.cpp b/tests/utmp_test.cpp
index 0fa55c7..6d0d6f1 100644
--- a/tests/utmp_test.cpp
+++ b/tests/utmp_test.cpp
@@ -24,8 +24,10 @@
   ASSERT_EQ(-1, login_tty(-1));
 }
 
-TEST(utmp, setutent_getutent_endutent) {
+TEST(utmp, smoke) {
+  ASSERT_EQ(-1, utmpname("hello"));
   setutent();
-  getutent();
+  ASSERT_EQ(NULL, getutent());
   endutent();
+  ASSERT_EQ(NULL, pututline(NULL));
 }
diff --git a/tools/versioner/src/DeclarationDatabase.cpp b/tools/versioner/src/DeclarationDatabase.cpp
index b41c865..ec2e38d 100644
--- a/tools/versioner/src/DeclarationDatabase.cpp
+++ b/tools/versioner/src/DeclarationDatabase.cpp
@@ -190,8 +190,8 @@
     auto symbol_it = database.symbols.find(declaration_name);
     if (symbol_it == database.symbols.end()) {
       Symbol symbol = {.name = declaration_name };
-      bool dummy;
-      std::tie(symbol_it, dummy) = database.symbols.insert({ declaration_name, symbol });
+      bool unused;
+      std::tie(symbol_it, unused) = database.symbols.insert({declaration_name, symbol});
     }
 
     auto expansion_range = src_manager.getExpansionRange(range);
diff --git a/tools/versioner/src/Preprocessor.cpp b/tools/versioner/src/Preprocessor.cpp
index 7a5b502..eb88c46 100644
--- a/tools/versioner/src/Preprocessor.cpp
+++ b/tools/versioner/src/Preprocessor.cpp
@@ -237,7 +237,7 @@
   return "("s + Join(expressions, ") || (") + ")";
 }
 
-// Assumes that nothing crazy is happening (e.g. having the semicolon be in a macro)
+// Assumes that nothing weird is happening (e.g. having the semicolon be in a macro).
 static FileLocation findNextSemicolon(const std::deque<std::string>& lines, FileLocation start) {
   unsigned current_line = start.line;
   unsigned current_column = start.column;
@@ -373,8 +373,8 @@
 
     guard_map.erase(current);
     guard_map.erase(next);
-    bool dummy;
-    std::tie(current, dummy) = guard_map.insert(std::make_pair(merged, avail));
+    bool unused;
+    std::tie(current, unused) = guard_map.insert(std::make_pair(merged, avail));
     next = current;
     ++next;
   }
diff --git a/tools/versioner/src/Utils.cpp b/tools/versioner/src/Utils.cpp
index ca186a4..dc6b5dd 100644
--- a/tools/versioner/src/Utils.cpp
+++ b/tools/versioner/src/Utils.cpp
@@ -64,7 +64,7 @@
 
     if (ent->fts_info & FTS_D) {
       if (ignored_directories.count(ent->fts_path) != 0) {
-        // fts_read guarantees that `ent` is valid and sane to hold on to until
+        // fts_read guarantees that `ent` is valid and okay to hold on to until
         // after it's returned with FTS_DP set.
         skipping = ent;
       }
diff --git a/tools/versioner/src/versioner.cpp b/tools/versioner/src/versioner.cpp
index 99228dd..c818197 100644
--- a/tools/versioner/src/versioner.cpp
+++ b/tools/versioner/src/versioner.cpp
@@ -276,7 +276,7 @@
   return intersection;
 }
 
-// Perform a sanity check on a symbol's declarations, enforcing the following invariants:
+// Perform a validity check on a symbol's declarations, enforcing the following invariants:
 //   1. At most one inline definition of the function exists (overloaded inline functions for
 //      _FORTIFY_SOURCE do not count because they are usually introduced to intercept the original
 //      functions or usually have enable_if attributes).
@@ -334,7 +334,7 @@
   return true;
 }
 
-static bool sanityCheck(const HeaderDatabase* database) {
+static bool validityCheck(const HeaderDatabase* database) {
   bool error = false;
   std::string cwd = getWorkingDir() + "/";
 
@@ -676,8 +676,8 @@
   if (dump) {
     declaration_database->dump(location.header_path + "/");
   } else {
-    if (!sanityCheck(declaration_database.get())) {
-      printf("versioner: sanity check failed\n");
+    if (!validityCheck(declaration_database.get())) {
+      printf("versioner: validity check failed\n");
       failed = true;
     }
 
diff --git a/tools/versioner/tests/multiple_decl_mismatch/expected_fail b/tools/versioner/tests/multiple_decl_mismatch/expected_fail
index 1d1f266..30e7233 100644
--- a/tools/versioner/tests/multiple_decl_mismatch/expected_fail
+++ b/tools/versioner/tests/multiple_decl_mismatch/expected_fail
@@ -5,4 +5,4 @@
       obsoleted = 12
     extern declaration @ headers/foo.h:5:1
       obsoleted = 9
-versioner: sanity check failed
+versioner: validity check failed
diff --git a/tools/versioner/tests/multiple_definition/expected_fail b/tools/versioner/tests/multiple_definition/expected_fail
index cb4acc6..5abb833 100644
--- a/tools/versioner/tests/multiple_definition/expected_fail
+++ b/tools/versioner/tests/multiple_definition/expected_fail
@@ -4,4 +4,4 @@
       no availability
     static definition @ headers/bar.h:5:1
       no availability
-versioner: sanity check failed
+versioner: validity check failed
diff --git a/tools/versioner/tests/version_mismatch/expected_fail b/tools/versioner/tests/version_mismatch/expected_fail
index f2143a3..95d284b 100644
--- a/tools/versioner/tests/version_mismatch/expected_fail
+++ b/tools/versioner/tests/version_mismatch/expected_fail
@@ -5,4 +5,4 @@
       introduced = 9
     extern declaration @ headers/foo.h:8:1
       introduced = 10
-versioner: sanity check failed
+versioner: validity check failed