Merge "Make vendor_ramdisk_available."
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..5bf078a 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -36,6 +36,9 @@
     },
     key: "com.android.runtime.key",
     certificate: ":com.android.runtime.certificate",
+    prebuilts: [
+        "bionic-linker-config",
+    ],
 }
 
 sdk {
@@ -65,10 +68,20 @@
 
 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"],
+        },
+    },
+}
+
+linker_config {
+    name: "bionic-linker-config",
+    src: "linker.config.json",
+    installable: false,
 }
diff --git a/apex/linker.config.json b/apex/linker.config.json
new file mode 100644
index 0000000..67c076e
--- /dev/null
+++ b/apex/linker.config.json
@@ -0,0 +1,3 @@
+{
+    "visible": true
+}
diff --git a/benchmarks/README.md b/benchmarks/README.md
index fe447d1..1fd17a1 100644
--- a/benchmarks/README.md
+++ b/benchmarks/README.md
@@ -184,5 +184,5 @@
 Some devices have a `perf-setup.sh` script that locks CPU and GPU frequencies. Some TradeFed
 benchmarks appear to be using the script. For more information:
  * run `get_build_var BOARD_PERFSETUP_SCRIPT`
- * run `m perf-setup.sh` to install the script into `${OUT}/data/local/tmp/perf-setup.sh`
+ * run `m perf-setup` to install the script into `${OUT}/data/local/tmp/perf-setup.sh`
  * see: https://android.googlesource.com/platform/platform_testing/+/refs/heads/master/scripts/perf-setup/
diff --git a/benchmarks/get_heap_size_benchmark.cpp b/benchmarks/get_heap_size_benchmark.cpp
index c3680dc..47d5b18 100644
--- a/benchmarks/get_heap_size_benchmark.cpp
+++ b/benchmarks/get_heap_size_benchmark.cpp
@@ -30,8 +30,6 @@
 #include <benchmark/benchmark.h>
 #include "util.h"
 
-static volatile size_t sink;
-
 static constexpr int NTHREADS = 5;
 
 static std::atomic<int> thread_count;
@@ -57,7 +55,7 @@
     sched_yield();
   }
   for (auto _ : state) {
-    sink = mallinfo().uordblks;
+    benchmark::DoNotOptimize(mallinfo().uordblks);
   }
   for (int i = 0; i < 5; i++) {
     int res = pthread_join(t[i], NULL);
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/benchmarks/spawn/Android.bp b/benchmarks/spawn/Android.bp
index 2276d2e..689e7c9 100644
--- a/benchmarks/spawn/Android.bp
+++ b/benchmarks/spawn/Android.bp
@@ -68,6 +68,7 @@
 
     // Install these binaries in the same directory as the main benchmark binary.
     data: [
+        ":bench_cxa_atexit",
         ":bench_noop",
         ":bench_noop_nostl",
         ":bench_noop_static",
@@ -75,7 +76,7 @@
 }
 
 cc_defaults {
-    name: "noop_binary_defaults",
+    name: "bionic_spawn_benchmark_binary",
     defaults: ["bionic_spawn_benchmark_targets"],
 
     compile_multilib: "both",
@@ -87,16 +88,11 @@
             suffix: "64",
         },
     },
-}
-
-cc_binary {
-    defaults: ["noop_binary_defaults"],
-    name: "bench_noop",
-    srcs: ["noop.cpp"],
 
     // When this binary is installed to host/linux-x86/bin, its runpath is ${ORIGIN}/../lib64, which
     // is fine for finding host/linux-x86/lib64/libc++.so. When it's installed to
-    // host/linux-x86/benchmarktest64/bionic-spawn-benchmarks, the runpath needs an extra "..".
+    // host/linux-x86/benchmarktest64/bionic-spawn-benchmarks, the runpath needs an extra "..". This
+    // argument has no effect when a static executable is produced.
     target: {
         linux_glibc_x86_64: {
             ldflags: [
@@ -107,14 +103,26 @@
 }
 
 cc_binary {
-    defaults: ["noop_binary_defaults"],
+    defaults: ["bionic_spawn_benchmark_binary"],
+    name: "bench_cxa_atexit",
+    srcs: ["bench_cxa_atexit.cpp"],
+}
+
+cc_binary {
+    defaults: ["bionic_spawn_benchmark_binary"],
+    name: "bench_noop",
+    srcs: ["noop.cpp"],
+}
+
+cc_binary {
+    defaults: ["bionic_spawn_benchmark_binary"],
     name: "bench_noop_nostl",
     srcs: ["noop.cpp"],
     stl: "none",
 }
 
 cc_binary {
-    defaults: ["noop_binary_defaults"],
+    defaults: ["bionic_spawn_benchmark_binary"],
     name: "bench_noop_static",
     srcs: ["noop.cpp"],
     static_executable: true,
diff --git a/benchmarks/spawn/bench_cxa_atexit.cpp b/benchmarks/spawn/bench_cxa_atexit.cpp
new file mode 100644
index 0000000..95849f4
--- /dev/null
+++ b/benchmarks/spawn/bench_cxa_atexit.cpp
@@ -0,0 +1,67 @@
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+
+#include <string>
+
+extern "C" int __cxa_atexit(void (*func)(void*), void* arg, void* dso);
+
+extern void* __dso_handle;
+
+static void dtor_func(void*) {}
+
+// Prevent the compiler from optimizing out the __cxa_atexit call.
+void (*volatile g_pdtor_func)(void*) = dtor_func;
+
+int main(int argc, char* argv[]) {
+  auto usage = [&argv]() {
+    fprintf(stderr, "usage: %s COUNT MODE\n", argv[0]);
+    fprintf(stderr, "MODE is one of '_Exit' or 'exit'.\n");
+    exit(1);
+  };
+
+  if (argc != 3) usage();
+
+  int count = atoi(argv[1]);
+
+  // Two modes: "_Exit" ==> exit early w/o calling dtors, "exit" ==> call dtors on exit.
+  std::string mode = argv[2];
+  if (mode != "_Exit" && mode != "exit") usage();
+
+  for (int i = 0; i < count; ++i) {
+    __cxa_atexit(g_pdtor_func, nullptr, &__dso_handle);
+  }
+
+  if (mode == "_Exit") {
+    _Exit(0);
+  } else {
+    exit(0);
+  }
+}
diff --git a/benchmarks/spawn/spawn_benchmarks.cpp b/benchmarks/spawn/spawn_benchmarks.cpp
index 931a8be..18dacf9 100644
--- a/benchmarks/spawn/spawn_benchmarks.cpp
+++ b/benchmarks/spawn/spawn_benchmarks.cpp
@@ -31,6 +31,8 @@
 SPAWN_BENCHMARK(noop, test_program("bench_noop").c_str());
 SPAWN_BENCHMARK(noop_nostl, test_program("bench_noop_nostl").c_str());
 SPAWN_BENCHMARK(noop_static, test_program("bench_noop_static").c_str());
+SPAWN_BENCHMARK(bench_cxa_atexit, test_program("bench_cxa_atexit").c_str(), "100000", "_Exit");
+SPAWN_BENCHMARK(bench_cxa_atexit_full, test_program("bench_cxa_atexit").c_str(), "100000", "exit");
 
 // Android has a /bin -> /system/bin symlink, but use /system/bin explicitly so we can more easily
 // compare Bionic-vs-glibc on a Linux desktop machine.
diff --git a/benchmarks/stdio_benchmark.cpp b/benchmarks/stdio_benchmark.cpp
index 037bbd9..03f3f29 100644
--- a/benchmarks/stdio_benchmark.cpp
+++ b/benchmarks/stdio_benchmark.cpp
@@ -155,9 +155,8 @@
   while (state.KeepRunning()) {
     FILE* fp = fopen("/dev/zero", "re");
     if (no_locking) __fsetlocking(fp, FSETLOCKING_BYCALLER);
-    volatile int c __attribute__((unused));
     for (size_t i = 0; i < nbytes; ++i) {
-      c = fgetc(fp);
+      benchmark::DoNotOptimize(fgetc(fp));
     }
     fclose(fp);
   }
diff --git a/benchmarks/stdlib_benchmark.cpp b/benchmarks/stdlib_benchmark.cpp
index 45b953f..b6ea58d 100644
--- a/benchmarks/stdlib_benchmark.cpp
+++ b/benchmarks/stdlib_benchmark.cpp
@@ -189,9 +189,8 @@
         buf[l++] = i, buf[l++] = j, buf[l++] = 0x80, buf[l++] = k;
   buf[l++] = 0;
 
-  volatile size_t c __attribute__((unused)) = 0;
   for (auto _ : state) {
-    c = mbstowcs(widebuf_aligned, buf_aligned, 500000);
+    benchmark::DoNotOptimize(mbstowcs(widebuf_aligned, buf_aligned, 500000));
   }
 
   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(500000));
diff --git a/benchmarks/string_benchmark.cpp b/benchmarks/string_benchmark.cpp
index d176675..9be54c7 100644
--- a/benchmarks/string_benchmark.cpp
+++ b/benchmarks/string_benchmark.cpp
@@ -31,9 +31,8 @@
   char* src_aligned = GetAlignedPtrFilled(&src, src_alignment, nbytes, 'x');
   char* dst_aligned = GetAlignedPtrFilled(&dst, dst_alignment, nbytes, 'x');
 
-  volatile int c __attribute__((unused)) = 0;
   while (state.KeepRunning()) {
-    c += memcmp(dst_aligned, src_aligned, nbytes);
+    benchmark::DoNotOptimize(memcmp(dst_aligned, src_aligned, nbytes));
   }
 
   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
@@ -129,9 +128,8 @@
   char* buf_aligned = GetAlignedPtrFilled(&buf, alignment, nbytes + 1, 'x');
   buf_aligned[nbytes - 1] = '\0';
 
-  volatile int c __attribute__((unused)) = 0;
   while (state.KeepRunning()) {
-    c += strlen(buf_aligned);
+    benchmark::DoNotOptimize(strlen(buf_aligned));
   }
 
   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
@@ -239,9 +237,8 @@
   s1_aligned[nbytes - 1] = '\0';
   s2_aligned[nbytes - 1] = '\0';
 
-  volatile int c __attribute__((unused));
   while (state.KeepRunning()) {
-    c = strcmp(s1_aligned, s2_aligned);
+    benchmark::DoNotOptimize(strcmp(s1_aligned, s2_aligned));
   }
 
   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
@@ -258,9 +255,8 @@
   char* s1_aligned = GetAlignedPtrFilled(&s1, s1_alignment, nbytes, 'x');
   char* s2_aligned = GetAlignedPtrFilled(&s2, s2_alignment, nbytes, 'x');
 
-  volatile int c __attribute__((unused));
   for (auto _ : state) {
-    c = strncmp(s1_aligned, s2_aligned, nbytes);
+    benchmark::DoNotOptimize(strncmp(s1_aligned, s2_aligned, nbytes));
   }
 
   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
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/fdtrack.md b/docs/fdtrack.md
new file mode 100644
index 0000000..5bc9860
--- /dev/null
+++ b/docs/fdtrack.md
@@ -0,0 +1,66 @@
+## fdtrack
+
+fdtrack consists of two parts: a set of hooks in bionic to register a callback
+that's invoked on file descriptor operations, and a library that implements a
+hook to perform and store backtraces for file descriptor creation.
+
+### bionic hooks
+bionic provides a header in the `bionic_libc_platform_headers` header_lib at <[bionic/fdtrack.h](https://android.googlesource.com/platform/bionic/+/refs/heads/master/libc/platform/bionic/fdtrack.h)>.
+Register a callback with `android_fdtrack_compare_exchange_hook` to receive
+callbacks upon file descriptor creation and destruction. This function can be
+called at any point in order to start capturing events, but be sure to properly
+handle unbalanced closes. This callback may be called from an async signal safe
+context, but not vfork (bionic tracks whether a thread is vforked, and chooses
+not to call callbacks when this is the case).
+
+### libfdtrack
+[libfdtrack](https://android.googlesource.com/platform/bionic/+/refs/heads/master/libfdtrack)
+implements a library that uses libunwindstack to unwind and store fd creation backtraces.
+
+
+#### Using libfdtrack
+libfdtrack registers its hook upon being loaded, so to start capturing
+backtraces, `dlopen("libfdtrack.so", RTLD_GLOBAL)` is all that's needed. To dump
+its output to logcat, either use `fdtrack_dump`, or send the signal
+`BIONIC_SIGNAL_FDTRACK` (available from `<bionic/reserved_signals.h>`) to the
+process. If you wish to iterate through the results programmatically,
+`fdtrack_iterate` can be used (warning: this interface is currently unstable,
+don't use it in code that can be used on multiple platform versions.)
+
+libfdtrack adds a significant amount of overhead, so for processes that are
+latency-critical like system_server, it's not feasible to always capture
+backtraces. Instead, if you can detect that an fd leak is ongoing, turning on
+backtraces for a while and then triggering a dump can be sufficient.
+system_server [implements this approach](https://android.googlesource.com/platform/frameworks/base/+/679f3e4242b8e018eb7df90ef433f81088a64fff%5E%21/),
+spawning a thread that regularly checks the count of fds in the process, turns
+on fdtrack when it hits a threshold, and then aborts after another threshold.
+This dumps the output to logcat, which will be available in both the tombstone
+and logcat from bugreports.
+
+#### Implementation details
+There are multiple methods to unwind in Android:
+
+ * libunwindstack
+   * Pros
+     * Primary method on the platform
+     * Able to unwind through ART
+   * Cons
+     * Uses malloc internally: unsafe unless a separate allocator is
+       statically-linked and steps are taken to prevent the unwind from being
+       interrupted by a signal
+     * Slow - infeasible to be used always in latency-sensitive processes
+ * `android_unsafe_frame_pointer_chase`
+   * Pros
+     * Definitely async signal safe
+     * Fast
+   * Cons
+     * Unable to unwind through ART because it doesn't maintain the frame pointer
+     * Requires -fno-omit-frame-pointer to be used on all code being unwound
+       through, which currently isn't the case on Android
+     * Frame layout is a mess on 32-bit ARM: the ARM standard, clang, and GCC
+       [all disagree](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92172)
+     * Chasing the frame pointer will often result in multiple frames inside the
+       same function
+
+libfdtrack chooses to use libunwindstack for now, since unwinding through ART
+is critical to being useful for the initial user, system_server.
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 a4edfbb..c6bd6fa 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",
@@ -63,6 +62,9 @@
     cppflags: [],
     include_dirs: [
         "bionic/libc/async_safe/include",
+        "bionic/libc/platform",
+        // For android_filesystem_config.h.
+        "system/core/libcutils/include",
     ],
 
     header_libs: [
@@ -81,7 +83,6 @@
         // TODO(b/132640749): Fix broken fuzzer support.
         fuzzer: false,
     },
-    native_coverage: false,
     ramdisk_available: true,
     vendor_ramdisk_available: true,
     recovery_available: true,
@@ -101,6 +102,9 @@
         malloc_pattern_fill_contents: {
             cflags: ["-DSCUDO_PATTERN_FILL_CONTENTS"],
         },
+        malloc_not_svelte: {
+            cflags: ["-DUSE_SCUDO"],
+        },
     },
 }
 
@@ -390,7 +394,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",
@@ -526,6 +529,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",
@@ -567,6 +571,7 @@
     srcs: [
         "stdio/vfprintf.cpp",
         "stdio/vfwprintf.cpp",
+        "upstream-openbsd/lib/libc/string/memmem.c",
         "upstream-openbsd/lib/libc/string/strstr.c",
     ],
     cflags: [
@@ -1010,7 +1015,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",
@@ -1075,7 +1079,7 @@
         "bionic/mblen.cpp",
         "bionic/mbrtoc16.cpp",
         "bionic/mbrtoc32.cpp",
-        "bionic/memmem.cpp",
+        "bionic/memory_mitigation_state.cpp",
         "bionic/mempcpy.cpp",
         "bionic/mkdir.cpp",
         "bionic/mkfifo.cpp",
@@ -1153,6 +1157,7 @@
         "bionic/umount.cpp",
         "bionic/unlink.cpp",
         "bionic/usleep.cpp",
+        "bionic/utmp.cpp",
         "bionic/wait.cpp",
         "bionic/wchar.cpp",
         "bionic/wchar_l.cpp",
@@ -1177,7 +1182,9 @@
             cflags: ["-DTREBLE_LINKER_NAMESPACES"],
         },
     },
-    whole_static_libs: ["libsystemproperties"],
+    whole_static_libs: [
+        "libsystemproperties",
+    ],
     cppflags: ["-Wold-style-cast"],
     local_include_dirs: ["stdio"],
     include_dirs: ["bionic/libstdc++/include"],
@@ -1186,6 +1193,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
@@ -1220,6 +1242,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.
@@ -1583,6 +1606,7 @@
     ],
     name: "libc",
     static_ndk_lib: true,
+    llndk_stubs: "libc.llndk",
     product_variables: {
         platform_sdk_version: {
             asflags: ["-DPLATFORM_SDK_VERSION=%d"],
@@ -1707,7 +1731,7 @@
         versions: [
             "29",
             "R",
-            "10000",
+            "current",
         ],
     },
 
@@ -1719,6 +1743,10 @@
     // Sorting bss symbols by size usually results in less dirty pages at run
     // time, because small symbols are grouped together.
     sort_bss_symbols_by_size: true,
+
+    lto: {
+        never: true,
+    },
 }
 
 genrule {
@@ -1766,8 +1794,9 @@
         "//external/perfetto:__subpackages__",
         "//external/scudo:__subpackages__",
         "//system/core/debuggerd:__subpackages__",
-        "//system/core/libunwindstack:__subpackages__",
+        "//system/core/libcutils:__subpackages__",
         "//system/memory/libmemunreachable:__subpackages__",
+        "//system/unwinding/libunwindstack:__subpackages__",
         "//tools/security/sanitizer-status:__subpackages__",
     ],
     vendor_available: true,
@@ -1782,11 +1811,10 @@
     stl: "none",
     sdk_version: "current",
 
+    min_sdk_version: "29",
     apex_available: [
         "//apex_available:platform",
-        "com.android.runtime",
-        "com.android.art.release", // from libdexfile_external
-        "com.android.art.debug", // from libdexfile_external
+        "//apex_available:anyapex",
     ],
 }
 
@@ -1988,8 +2016,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",
@@ -2193,7 +2223,7 @@
 }
 
 llndk_library {
-    name: "libc",
+    name: "libc.llndk",
     symbol_file: "libc.map.txt",
     export_headers_as_system: true,
     export_preprocessed_headers: ["include"],
diff --git a/libc/NOTICE b/libc/NOTICE
index 2fd674b..58d6679 100644
--- a/libc/NOTICE
+++ b/libc/NOTICE
@@ -1040,6 +1040,22 @@
 -------------------------------------------------------------------
 
 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.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2020 The Android Open Source Project
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -3004,7 +3020,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 +3472,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 +4231,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 +4612,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-arm64/bionic/__bionic_clone.S b/libc/arch-arm64/bionic/__bionic_clone.S
index c3ff0e5..e9932ad 100644
--- a/libc/arch-arm64/bionic/__bionic_clone.S
+++ b/libc/arch-arm64/bionic/__bionic_clone.S
@@ -57,3 +57,5 @@
     ldp     x0, x1, [sp], #16
     b       __start_thread
 END(__bionic_clone)
+
+NOTE_GNU_PROPERTY()
diff --git a/libc/arch-arm64/bionic/_exit_with_stack_teardown.S b/libc/arch-arm64/bionic/_exit_with_stack_teardown.S
index 6a7b1e5..c53a1f4 100644
--- a/libc/arch-arm64/bionic/_exit_with_stack_teardown.S
+++ b/libc/arch-arm64/bionic/_exit_with_stack_teardown.S
@@ -39,3 +39,5 @@
   svc #0
   // The exit syscall does not return.
 END(_exit_with_stack_teardown)
+
+NOTE_GNU_PROPERTY()
diff --git a/libc/arch-arm64/bionic/setjmp.S b/libc/arch-arm64/bionic/setjmp.S
index a2b2370..07270c9 100644
--- a/libc/arch-arm64/bionic/setjmp.S
+++ b/libc/arch-arm64/bionic/setjmp.S
@@ -118,6 +118,8 @@
 // int sigsetjmp(sigjmp_buf env, int save_signal_mask);
 ENTRY(sigsetjmp)
 __BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(sigsetjmp)
+  hint #25 // paciasp
+  .cfi_negate_ra_state
   stp x0, x30, [sp, #-16]!
   .cfi_def_cfa_offset 16
   .cfi_rel_offset x0, 0
@@ -184,6 +186,8 @@
 #endif
 
   mov w0, #0
+  hint #29 // autiasp
+  .cfi_negate_ra_state
   ret
 END(sigsetjmp)
 
@@ -250,7 +254,9 @@
 1:
   // Restore core registers.
   bic x2, x2, #1
+  // x30 was saved with PAC to jmp_buf in sigsetjmp().
   ldp x30, x10, [x0, #(_JB_X30_SP  * 8)]
+  .cfi_negate_ra_state
   ldp x28, x29, [x0, #(_JB_X28_X29 * 8)]
   ldp x26, x27, [x0, #(_JB_X26_X27 * 8)]
   ldp x24, x25, [x0, #(_JB_X24_X25 * 8)]
@@ -290,6 +296,8 @@
   // Set return value.
   cmp w1, wzr
   csinc w0, w1, wzr, ne
+  hint #29 // autiasp
+  .cfi_negate_ra_state
   ret
 END(siglongjmp)
 
@@ -297,3 +305,5 @@
 __BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(longjmp)
 ALIAS_SYMBOL(_longjmp, siglongjmp)
 __BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(_longjmp)
+
+NOTE_GNU_PROPERTY()
diff --git a/libc/arch-arm64/bionic/syscall.S b/libc/arch-arm64/bionic/syscall.S
index 8389f98..9e6f68a 100644
--- a/libc/arch-arm64/bionic/syscall.S
+++ b/libc/arch-arm64/bionic/syscall.S
@@ -47,3 +47,5 @@
 
     ret
 END(syscall)
+
+NOTE_GNU_PROPERTY()
diff --git a/libc/arch-arm64/bionic/vfork.S b/libc/arch-arm64/bionic/vfork.S
index 5cfb8b0..81b84a3 100644
--- a/libc/arch-arm64/bionic/vfork.S
+++ b/libc/arch-arm64/bionic/vfork.S
@@ -67,6 +67,8 @@
 
     // Clean up stack shadow in the parent process.
     // https://github.com/google/sanitizers/issues/925
+    hint #25 // paciasp
+    .cfi_negate_ra_state
     stp x0, x30, [sp, #-16]!
     .cfi_adjust_cfa_offset 16
     .cfi_rel_offset x0, 0
@@ -79,9 +81,13 @@
     .cfi_adjust_cfa_offset -16
     .cfi_restore x0
     .cfi_restore x30
+    hint #29 // autiasp
+    .cfi_negate_ra_state
 
 #endif
 
 .L_exit:
     ret
 END(vfork)
+
+NOTE_GNU_PROPERTY()
diff --git a/libc/arch-arm64/generic/bionic/__memcpy_chk.S b/libc/arch-arm64/generic/bionic/__memcpy_chk.S
index a6eeca4..a8e9e83 100644
--- a/libc/arch-arm64/generic/bionic/__memcpy_chk.S
+++ b/libc/arch-arm64/generic/bionic/__memcpy_chk.S
@@ -43,3 +43,5 @@
 
   bl __memcpy_chk_fail
 END(__memcpy_chk)
+
+NOTE_GNU_PROPERTY()
diff --git a/libc/arch-arm64/generic/bionic/memcpy.S b/libc/arch-arm64/generic/bionic/memcpy.S
index baadb92..bc1945c 100644
--- a/libc/arch-arm64/generic/bionic/memcpy.S
+++ b/libc/arch-arm64/generic/bionic/memcpy.S
@@ -33,3 +33,5 @@
 ENTRY(__memcpy)
   #include "memcpy_base.S"
 END(__memcpy)
+
+NOTE_GNU_PROPERTY()
diff --git a/libc/arch-arm64/generic/bionic/memmove.S b/libc/arch-arm64/generic/bionic/memmove.S
index 335b7d6..0f752ea 100644
--- a/libc/arch-arm64/generic/bionic/memmove.S
+++ b/libc/arch-arm64/generic/bionic/memmove.S
@@ -153,3 +153,5 @@
 
 ALIAS_SYMBOL(memcpy, memmove)
 #endif
+
+NOTE_GNU_PROPERTY()
diff --git a/libc/arch-arm64/generic/bionic/memset.S b/libc/arch-arm64/generic/bionic/memset.S
index 12fc09d..19d3510 100644
--- a/libc/arch-arm64/generic/bionic/memset.S
+++ b/libc/arch-arm64/generic/bionic/memset.S
@@ -249,3 +249,5 @@
 	b	L(tail64)
 
 END(memset)
+
+NOTE_GNU_PROPERTY()
diff --git a/libc/arch-arm64/generic/bionic/wmemmove.S b/libc/arch-arm64/generic/bionic/wmemmove.S
index e4f67f7..b130530 100644
--- a/libc/arch-arm64/generic/bionic/wmemmove.S
+++ b/libc/arch-arm64/generic/bionic/wmemmove.S
@@ -28,3 +28,5 @@
 #define WMEMMOVE
 #include "memmove.S"
 #undef WMEMMOVE
+
+NOTE_GNU_PROPERTY()
diff --git a/libc/arch-arm64/static_function_dispatch.S b/libc/arch-arm64/static_function_dispatch.S
index 65a1492..161ece8 100644
--- a/libc/arch-arm64/static_function_dispatch.S
+++ b/libc/arch-arm64/static_function_dispatch.S
@@ -42,3 +42,5 @@
 FUNCTION_DELEGATE(strlen, __strlen_aarch64_mte)
 FUNCTION_DELEGATE(strrchr, __strrchr_aarch64_mte)
 FUNCTION_DELEGATE(strncmp, __strncmp_aarch64_mte)
+
+NOTE_GNU_PROPERTY()
diff --git a/libc/arch-common/bionic/crtbegin.c b/libc/arch-common/bionic/crtbegin.c
index b7043dc..1f8dfd2 100644
--- a/libc/arch-common/bionic/crtbegin.c
+++ b/libc/arch-common/bionic/crtbegin.c
@@ -49,7 +49,7 @@
 #define POST "; .size _start, .-_start"
 
 #if defined(__aarch64__)
-__asm__(PRE "mov x0,sp; b _start_main" POST);
+__asm__(PRE "/* BTI J */ hint #36; mov x0,sp; b _start_main" POST);
 #elif defined(__arm__)
 __asm__(PRE "mov r0,sp; b _start_main" POST);
 #elif defined(__i386__)
diff --git a/libc/arch-common/bionic/crtbrand.S b/libc/arch-common/bionic/crtbrand.S
index 34d6480..3d80d73 100644
--- a/libc/arch-common/bionic/crtbrand.S
+++ b/libc/arch-common/bionic/crtbrand.S
@@ -26,6 +26,12 @@
  * SUCH DAMAGE.
  */
 
+#if defined(__aarch64__)
+#include <private/bionic_asm_arm64.h>
+
+__bionic_asm_custom_note_gnu_section()
+#endif
+
   .section .note.android.ident,"a",%note
   .balign 4
   .type abitag, %object
diff --git a/libc/arch-common/bionic/crtend.S b/libc/arch-common/bionic/crtend.S
index 87d1120..9676db8 100644
--- a/libc/arch-common/bionic/crtend.S
+++ b/libc/arch-common/bionic/crtend.S
@@ -28,6 +28,12 @@
 
 #include "asm_multiarch.h"
 
+#if defined(__aarch64__)
+#include <private/bionic_asm_arm64.h>
+
+__bionic_asm_custom_note_gnu_section()
+#endif
+
 	.section .preinit_array, "aw"
 	ASM_ALIGN_TO_PTR_SIZE
 	ASM_PTR_SIZE(0)
@@ -43,11 +49,9 @@
 #if defined(__linux__) && defined(__ELF__)
 	.section .note.GNU-stack,"",%progbits
 #endif
-#if defined(__i386__) || defined(__x86_64__)
+#if !defined(__arm__)
 	.section	.eh_frame,"a",@progbits
-#if defined(__i386__)
 	.balign 4
-#endif
 	.type	__FRAME_END__, @object
 	.size	__FRAME_END__, 4
 __FRAME_END__:
diff --git a/libc/arch-common/bionic/crtend_so.S b/libc/arch-common/bionic/crtend_so.S
index e7b8cac..5875acb 100644
--- a/libc/arch-common/bionic/crtend_so.S
+++ b/libc/arch-common/bionic/crtend_so.S
@@ -26,14 +26,18 @@
  * SUCH DAMAGE.
  */
 
+#if defined(__aarch64__)
+#include <private/bionic_asm_arm64.h>
+
+__bionic_asm_custom_note_gnu_section()
+#endif
+
 #if defined(__linux__) && defined(__ELF__)
 	.section .note.GNU-stack,"",%progbits
 #endif
-#if defined(__i386__) || defined(__x86_64__)
+#if !defined(__arm__)
 	.section	.eh_frame,"a",@progbits
-#if defined(__i386__)
 	.balign 4
-#endif
 	.type	__FRAME_END__, @object
 	.size	__FRAME_END__, 4
 __FRAME_END__:
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/arch-x86/bionic/__restore.S b/libc/arch-x86/bionic/__restore.S
index cb18fd0..5977eab 100644
--- a/libc/arch-x86/bionic/__restore.S
+++ b/libc/arch-x86/bionic/__restore.S
@@ -27,14 +27,7 @@
  */
 
 #include <private/bionic_asm.h>
-
-// DWARF constants.
-#define DW_CFA_def_cfa_expression 0x0f
-#define DW_CFA_expression 0x10
-#define DW_EH_PE_pcrel 0x10
-#define DW_EH_PE_sdata4 0x0b
-#define DW_OP_breg4 0x74
-#define DW_OP_deref 0x06
+#include <private/bionic_asm_dwarf_exprs.h>
 
 // Offsets into struct sigcontext.
 #define OFFSET_EDI 16
@@ -52,84 +45,47 @@
 #define DW_x86_REG_ECX 1
 #define DW_x86_REG_EDX 2
 #define DW_x86_REG_EBX 3
+#define DW_x86_REG_ESP 4
 #define DW_x86_REG_EBP 5
 #define DW_x86_REG_ESI 6
 #define DW_x86_REG_EDI 7
 #define DW_x86_REG_EIP 8
 
-#define cfi_signal_frame_start(f) \
-.section .eh_frame,"a",@progbits; \
-.L ## f ## _START_EH_FRAME: \
-  .long 2f - 1f; /* CIE length. */ \
-1:.long 0;       /* CIE ID. */ \
-  .byte 1;       /* Version. */ \
-  .string "zRS"; /* Augmentation string. */ \
-  .uleb128 1;    /* Code alignment factor. */ \
-  .sleb128 -4;   /* Data alignment factor. */ \
-  .uleb128 DW_x86_REG_EIP;    /* Return address register. */ \
-  .uleb128 1;    /* 1 byte of augmentation data. */ \
-  .byte (DW_EH_PE_pcrel|DW_EH_PE_sdata4); /* FDE encoding. */ \
-  .align 8; \
-2: \
-  .long .L ## f ## _END_FDE - .L ## f ## _START_FDE;   /* FDE length. */ \
-.L ## f ## _START_FDE: \
-  .long .L ## f ## _START_FDE - .L ## f ## _START_EH_FRAME; /* CIE location. */ \
-  .long (.L ## f ## _START - 1) - .;                   /* pcrel start address (see FDE encoding above). */ \
-  .long .L ## f ## _END - (.L ## f ## _START - 1);     /* Function this FDE applies to. */ \
-  .uleb128 0;                                          /* FDE augmentation length. */ \
+#define RESTORE_GPR(reg, extra_offset)                    \
+    m_cfi_breg_offset DW_x86_REG_ ## reg,                 \
+                      DW_x86_REG_ESP,                     \
+                      (OFFSET_ ## reg + (extra_offset));
 
-#define cfi_signal_frame_end(f) \
-.L ## f ## _END_FDE: \
+// Restoring ESP is unnecessary as the unwinder simply uses the CFA value.
+#define RESTORE_GPRS(extra_offset)                                      \
+    m_cfi_def_cfa_deref DW_x86_REG_ESP, (OFFSET_ESP + (extra_offset));  \
+    RESTORE_GPR(EDI, extra_offset)                                      \
+    RESTORE_GPR(ESI, extra_offset)                                      \
+    RESTORE_GPR(EBP, extra_offset)                                      \
+    RESTORE_GPR(EBX, extra_offset)                                      \
+    RESTORE_GPR(EDX, extra_offset)                                      \
+    RESTORE_GPR(ECX, extra_offset)                                      \
+    RESTORE_GPR(EAX, extra_offset)                                      \
+    RESTORE_GPR(EIP, extra_offset)                                      \
 
-#define cfi_def_cfa(offset) \
-  .byte DW_CFA_def_cfa_expression; \
-  .uleb128 2f-1f; \
-1:.byte DW_OP_breg4; \
-  .sleb128 offset; \
-  .byte DW_OP_deref; \
-2: \
+  .text
 
-#define cfi_offset(reg_number,offset) \
-  .byte DW_CFA_expression; \
-  .uleb128 reg_number; \
-  .uleb128 2f-1f; \
-1:.byte DW_OP_breg4; \
-  .sleb128 offset; \
-2: \
-
-ENTRY_PRIVATE(__restore)
-.L__restore_START:
+  .cfi_startproc
+  .cfi_signal_frame
+  RESTORE_GPRS(4)
+  nop   // See comment in libc/arch-x86_64/bionic/__restore_rt.S about this nop.
+ENTRY_PRIVATE_NO_DWARF(__restore)
   popl %eax
+  RESTORE_GPRS(0)
   movl $__NR_sigreturn, %eax
   int $0x80
-.L__restore_END:
 END(__restore)
-cfi_signal_frame_start(__restore)
-  cfi_def_cfa(OFFSET_ESP + 4)
-  cfi_offset(DW_x86_REG_EDI, OFFSET_EDI + 4)
-  cfi_offset(DW_x86_REG_ESI, OFFSET_ESI + 4)
-  cfi_offset(DW_x86_REG_EBP, OFFSET_EBP + 4)
-  cfi_offset(DW_x86_REG_EBX, OFFSET_EBX + 4)
-  cfi_offset(DW_x86_REG_EDX, OFFSET_EDX + 4)
-  cfi_offset(DW_x86_REG_ECX, OFFSET_ECX + 4)
-  cfi_offset(DW_x86_REG_EAX, OFFSET_EAX + 4)
-  cfi_offset(DW_x86_REG_EIP, OFFSET_EIP + 4)
-cfi_signal_frame_end(__restore)
 
-ENTRY_PRIVATE(__restore_rt)
-.L__restore_rt_START:
+  .cfi_startproc
+  .cfi_signal_frame
+  RESTORE_GPRS(160)
+  nop   // See comment in libc/arch-x86_64/bionic/__restore_rt.S about this nop.
+ENTRY_PRIVATE_NO_DWARF(__restore_rt)
   movl $__NR_rt_sigreturn, %eax
   int $0x80
-.L__restore_rt_END:
 END(__restore_rt)
-cfi_signal_frame_start(__restore_rt)
-  cfi_def_cfa(OFFSET_ESP + 160)
-  cfi_offset(DW_x86_REG_EDI, OFFSET_EDI + 160)
-  cfi_offset(DW_x86_REG_ESI, OFFSET_ESI + 160)
-  cfi_offset(DW_x86_REG_EBP, OFFSET_EBP + 160)
-  cfi_offset(DW_x86_REG_EBX, OFFSET_EBX + 160)
-  cfi_offset(DW_x86_REG_EDX, OFFSET_EDX + 160)
-  cfi_offset(DW_x86_REG_ECX, OFFSET_ECX + 160)
-  cfi_offset(DW_x86_REG_EAX, OFFSET_EAX + 160)
-  cfi_offset(DW_x86_REG_EIP, OFFSET_EIP + 160)
-cfi_signal_frame_end(__restore_rt)
diff --git a/libc/arch-x86_64/bionic/__restore_rt.S b/libc/arch-x86_64/bionic/__restore_rt.S
index 785b3b3..f3e4012 100644
--- a/libc/arch-x86_64/bionic/__restore_rt.S
+++ b/libc/arch-x86_64/bionic/__restore_rt.S
@@ -27,15 +27,9 @@
  */
 
 #include <private/bionic_asm.h>
+#include <private/bionic_asm_dwarf_exprs.h>
 
-// DWARF constants.
-#define DW_CFA_def_cfa_expression 0x0f
-#define DW_CFA_expression 0x10
-#define DW_EH_PE_pcrel 0x10
-#define DW_EH_PE_sdata4 0x0b
-#define DW_OP_breg4 0x74
-#define DW_OP_breg7 0x77
-#define DW_OP_deref 0x06
+// In the signal trampoline frame, rsp points to a ucontext_t struct.
 
 // Offsets into struct ucontext_t of uc_mcontext.gregs[x].
 #define OFFSET_R8 40
@@ -49,11 +43,11 @@
 #define OFFSET_RDI 104
 #define OFFSET_RSI 112
 #define OFFSET_RBP 120
-#define OFFSET_RSP 160
 #define OFFSET_RBX 128
 #define OFFSET_RDX 136
 #define OFFSET_RAX 144
 #define OFFSET_RCX 152
+#define OFFSET_RSP 160
 #define OFFSET_RIP 168
 
 // Non-standard DWARF constants for the x86-64 registers.
@@ -75,69 +69,47 @@
 #define DW_x86_64_R15 15
 #define DW_x86_64_RIP 16
 
-#define cfi_signal_frame_start(f) \
-.section .eh_frame,"a",@progbits; \
-.L ## f ## _START_EH_FRAME: \
-  .long 2f - 1f; /* CIE length. */ \
-1:.long 0;       /* CIE ID. */ \
-  .byte 1;       /* Version. */ \
-  .string "zRS"; /* Augmentation string. */ \
-  .uleb128 1;    /* Code alignment factor. */ \
-  .sleb128 -8;   /* Data alignment factor. */ \
-  .uleb128 DW_x86_64_RIP;   /* Return address register. */ \
-  .uleb128 1;    /* 1 byte of augmentation data. */ \
-  .byte (DW_EH_PE_pcrel | DW_EH_PE_sdata4); /* FDE encoding. */ \
-  .align 8; \
-2: \
-  .long .L ## f ## _END_FDE - .L ## f ## _START_FDE;   /* FDE length. */ \
-.L ## f ## _START_FDE: \
-  .long .L ## f ## _START_FDE - .L ## f ## _START_EH_FRAME; /* CIE location. */ \
-  .long (.L ## f ## _START - 1) - .;                   /* pcrel start address (see FDE encoding above). */ \
-  .long .L ## f ## _END - (.L ## f ## _START - 1);     /* Function this FDE applies to. */ \
-  .uleb128 0;                                          /* FDE augmentation length. */ \
+// Insert a nop between .cfi_startproc and the trampoline symbol so that unwinders can find the FDE.
+// A function's last instruction can be a call instruction (e.g. to __cxa_throw), in which case the
+// return address (e.g. from __cxa_throw to the caller) will be just after the function. This
+// address may also be the start of the next function, so to avoid ambiguity, unwinders assume that
+// a return address PC can refer to the address just after a function, but never to the start of a
+// function. (This is implemented by subtracting 1 from the return address PC before looking it up.)
+// This is fine for ordinary functions, but breaks on trampolines. Inserting a nop fixes it.
+//
+// N.B. Unwinders have two other strategies for recognizing the signal trampoline:
+//  - Read the instructions that the return address PC points at and look for a sigreturn syscall.
+//    (Hence, the instructions must not change at all.)
+//  - Do a symbol table lookup and check that against the PC (e.g. LLDB looks for
+//    __kernel_rt_sigreturn and __restore_rt.)
+// Either way, the nop is needed to avoid ambiguity if the function before the trampoline could end
+// with a call.
 
-#define cfi_signal_frame_end(f) \
-.L ## f ## _END_FDE: \
+#define RESTORE_GPR(reg) m_cfi_breg_offset DW_x86_64_ ## reg, DW_x86_64_RSP, OFFSET_ ## reg;
 
-#define cfi_def_cfa(offset) \
-  .byte DW_CFA_def_cfa_expression; \
-  .uleb128 2f-1f; \
-1:.byte DW_OP_breg7; \
-  .sleb128 offset; \
-  .byte DW_OP_deref; \
-2: \
-
-#define cfi_offset(reg_number,offset) \
-  .byte DW_CFA_expression; \
-  .uleb128 reg_number; \
-  .uleb128 2f-1f; \
-1:.byte DW_OP_breg7; \
-  .sleb128 offset; \
-2: \
-
-ENTRY_PRIVATE(__restore_rt)
-.L__restore_rt_START:
+  .text
+  .cfi_startproc
+  .cfi_signal_frame
+  m_cfi_def_cfa_deref DW_x86_64_RSP, OFFSET_RSP
+  RESTORE_GPR(R8)
+  RESTORE_GPR(R9)
+  RESTORE_GPR(R10)
+  RESTORE_GPR(R11)
+  RESTORE_GPR(R12)
+  RESTORE_GPR(R13)
+  RESTORE_GPR(R14)
+  RESTORE_GPR(R15)
+  RESTORE_GPR(RDI)
+  RESTORE_GPR(RSI)
+  RESTORE_GPR(RBP)
+  RESTORE_GPR(RBX)
+  RESTORE_GPR(RDX)
+  RESTORE_GPR(RAX)
+  RESTORE_GPR(RCX)
+  // Restoring RSP is unnecessary as the unwinder simply uses the CFA value.
+  RESTORE_GPR(RIP)
+  nop
+ENTRY_PRIVATE_NO_DWARF(__restore_rt)
   mov $__NR_rt_sigreturn, %rax
   syscall
-.L__restore_rt_END:
 END(__restore_rt)
-cfi_signal_frame_start(__restore_rt)
-  cfi_def_cfa(OFFSET_RSP)
-  cfi_offset(DW_x86_64_R8, OFFSET_R8)
-  cfi_offset(DW_x86_64_R9, OFFSET_R9)
-  cfi_offset(DW_x86_64_R10, OFFSET_R10)
-  cfi_offset(DW_x86_64_R11, OFFSET_R11)
-  cfi_offset(DW_x86_64_R12, OFFSET_R12)
-  cfi_offset(DW_x86_64_R13, OFFSET_R13)
-  cfi_offset(DW_x86_64_R14, OFFSET_R14)
-  cfi_offset(DW_x86_64_R15, OFFSET_R15)
-  cfi_offset(DW_x86_64_RDI, OFFSET_RDI)
-  cfi_offset(DW_x86_64_RSI, OFFSET_RSI)
-  cfi_offset(DW_x86_64_RBP, OFFSET_RBP)
-  cfi_offset(DW_x86_64_RSP, OFFSET_RSP)
-  cfi_offset(DW_x86_64_RBX, OFFSET_RBX)
-  cfi_offset(DW_x86_64_RDX, OFFSET_RDX)
-  cfi_offset(DW_x86_64_RAX, OFFSET_RAX)
-  cfi_offset(DW_x86_64_RCX, OFFSET_RCX)
-  cfi_offset(DW_x86_64_RIP, OFFSET_RIP)
-cfi_signal_frame_end(__restore_rt)
diff --git a/libc/async_safe/Android.bp b/libc/async_safe/Android.bp
index a808dde..90cff0d 100644
--- a/libc/async_safe/Android.bp
+++ b/libc/async_safe/Android.bp
@@ -22,8 +22,8 @@
     apex_available: [
         "//apex_available:platform",
         "com.android.runtime",
+        "com.android.art",
         "com.android.art.debug",
-        "com.android.art.release",
         "com.android.media",
         "com.android.media.swcodec",
     ],
diff --git a/libc/async_safe/async_safe_log.cpp b/libc/async_safe/async_safe_log.cpp
index 207035a..8b2a32b 100644
--- a/libc/async_safe/async_safe_log.cpp
+++ b/libc/async_safe/async_safe_log.cpp
@@ -30,6 +30,7 @@
 #include <ctype.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <linux/net.h>
 #include <pthread.h>
 #include <stdarg.h>
 #include <stddef.h>
@@ -51,12 +52,22 @@
 #include "private/ErrnoRestorer.h"
 #include "private/ScopedPthreadMutexLocker.h"
 
-// Don't call libc's close, since it might call back into us as a result of fdsan.
+// Don't call libc's close or socket, since it might call back into us as a result of fdsan/fdtrack.
 #pragma GCC poison close
 static int __close(int fd) {
   return syscall(__NR_close, fd);
 }
 
+static int __socket(int domain, int type, int protocol) {
+#if defined(__i386__)
+  unsigned long args[3] = {static_cast<unsigned long>(domain), static_cast<unsigned long>(type),
+                           static_cast<unsigned long>(protocol)};
+  return syscall(__NR_socketcall, SYS_SOCKET, &args);
+#else
+  return syscall(__NR_socket, domain, type, protocol);
+#endif
+}
+
 // Must be kept in sync with frameworks/base/core/java/android/util/EventLog.java.
 enum AndroidEventLogType {
   EVENT_TYPE_INT = 0,
@@ -460,7 +471,7 @@
   // found that all logd crashes thus far have had no problem stuffing
   // the UNIX domain socket and moving on so not critical *today*.
 
-  int log_fd = TEMP_FAILURE_RETRY(socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0));
+  int log_fd = TEMP_FAILURE_RETRY(__socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0));
   if (log_fd == -1) {
     return -1;
   }
diff --git a/libc/bionic/__bionic_get_shell_path.cpp b/libc/bionic/__bionic_get_shell_path.cpp
index 7aeed18..c087b35 100644
--- a/libc/bionic/__bionic_get_shell_path.cpp
+++ b/libc/bionic/__bionic_get_shell_path.cpp
@@ -36,6 +36,10 @@
 #define VENDOR_PREFIX "/vendor/"
 
 static const char* init_sh_path() {
+#if !defined(__ANDROID__)
+  // For the host Bionic, use the standard /bin/sh
+  return "/bin/sh";
+#else
   /* If the device is not treble enabled, return the path to the system shell.
    * Vendor code, on non-treble enabled devices could use system() / popen()
    * with relative paths for executables on /system. Since /system will not be
@@ -51,6 +55,7 @@
   }
 #endif
   return "/system/bin/sh";
+#endif  // if !defined(__ANDROID__)
 }
 
 const char* __bionic_get_shell_path() {
diff --git a/libc/bionic/__libc_init_main_thread.cpp b/libc/bionic/__libc_init_main_thread.cpp
index 56a8488..95f46e9 100644
--- a/libc/bionic/__libc_init_main_thread.cpp
+++ b/libc/bionic/__libc_init_main_thread.cpp
@@ -101,6 +101,19 @@
   __set_tcb_dtv(tcb, const_cast<TlsDtv*>(&zero_dtv));
 }
 
+// This is public so that the zygote can call it too. It is not expected
+// to be useful otherwise.
+//
+// Note in particular that it is not possible to return from any existing
+// stack frame with stack protector enabled after this function is called.
+extern "C" void android_reset_stack_guards() {
+  // The TLS stack guard is set from the global, so ensure that we've initialized the global
+  // before we initialize the TLS. Dynamic executables will initialize their copy of the global
+  // stack protector from the one in the main thread's TLS.
+  __libc_safe_arc4random_buf(&__stack_chk_guard, sizeof(__stack_chk_guard));
+  __init_tcb_stack_guard(__get_bionic_tcb());
+}
+
 // Finish initializing the main thread.
 __BIONIC_WEAK_FOR_NATIVE_BRIDGE
 extern "C" void __libc_init_main_thread_late() {
@@ -119,11 +132,7 @@
   // User code should never see this; we'll compute it when asked.
   pthread_attr_setstacksize(&main_thread.attr, 0);
 
-  // The TLS stack guard is set from the global, so ensure that we've initialized the global
-  // before we initialize the TLS. Dynamic executables will initialize their copy of the global
-  // stack protector from the one in the main thread's TLS.
-  __libc_safe_arc4random_buf(&__stack_chk_guard, sizeof(__stack_chk_guard));
-  __init_tcb_stack_guard(__get_bionic_tcb());
+  android_reset_stack_guards();
 
   __init_thread(&main_thread);
 
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/atexit.cpp b/libc/bionic/atexit.cpp
index df306af..5dbf322 100644
--- a/libc/bionic/atexit.cpp
+++ b/libc/bionic/atexit.cpp
@@ -73,50 +73,42 @@
   // restart concurrent __cxa_finalize passes.
   uint64_t total_appends_;
 
-  static size_t round_up_to_page_bytes(size_t capacity) {
-    return PAGE_END(capacity * sizeof(AtexitEntry));
-  }
-
-  static size_t next_capacity(size_t capacity) {
-    // Double the capacity each time.
-    size_t result = round_up_to_page_bytes(MAX(1, capacity * 2)) / sizeof(AtexitEntry);
-    CHECK(result > capacity);
-    return result;
-  }
+  static size_t page_start_of_index(size_t idx) { return PAGE_START(idx * sizeof(AtexitEntry)); }
+  static size_t page_end_of_index(size_t idx) { return PAGE_END(idx * sizeof(AtexitEntry)); }
 
   // Recompact the array if it will save at least one page of memory at the end.
-  bool needs_recompaction() {
-    return round_up_to_page_bytes(size_ - extracted_count_) < round_up_to_page_bytes(size_);
+  bool needs_recompaction() const {
+    return page_end_of_index(size_ - extracted_count_) < page_end_of_index(size_);
   }
 
-  void set_writable(bool writable);
+  void set_writable(bool writable, size_t start_idx, size_t num_entries);
+  static bool next_capacity(size_t capacity, size_t* result);
   bool expand_capacity();
 };
 
 }  // anonymous namespace
 
 bool AtexitArray::append_entry(const AtexitEntry& entry) {
-  bool result = false;
+  if (size_ >= capacity_ && !expand_capacity()) return false;
 
-  set_writable(true);
-  if (size_ < capacity_ || expand_capacity()) {
-    array_[size_++] = entry;
-    ++total_appends_;
-    result = true;
-  }
-  set_writable(false);
+  size_t idx = size_++;
 
-  return result;
+  set_writable(true, idx, 1);
+  array_[idx] = entry;
+  ++total_appends_;
+  set_writable(false, idx, 1);
+
+  return true;
 }
 
 // Extract an entry and return it.
 AtexitEntry AtexitArray::extract_entry(size_t idx) {
   AtexitEntry result = array_[idx];
 
-  set_writable(true);
+  set_writable(true, idx, 1);
   array_[idx] = {};
   ++extracted_count_;
-  set_writable(false);
+  set_writable(false, idx, 1);
 
   return result;
 }
@@ -124,7 +116,7 @@
 void AtexitArray::recompact() {
   if (!needs_recompaction()) return;
 
-  set_writable(true);
+  set_writable(true, 0, size_);
 
   // Optimization: quickly skip over the initial non-null entries.
   size_t src = 0, dst = 0;
@@ -143,51 +135,79 @@
   }
 
   // If the table uses fewer pages, clean the pages at the end.
-  size_t old_bytes = round_up_to_page_bytes(size_);
-  size_t new_bytes = round_up_to_page_bytes(dst);
+  size_t old_bytes = page_end_of_index(size_);
+  size_t new_bytes = page_end_of_index(dst);
   if (new_bytes < old_bytes) {
     madvise(reinterpret_cast<char*>(array_) + new_bytes, old_bytes - new_bytes, MADV_DONTNEED);
   }
 
+  set_writable(false, 0, size_);
+
   size_ = dst;
   extracted_count_ = 0;
-
-  set_writable(false);
 }
 
 // Use mprotect to make the array writable or read-only. Returns true on success. Making the array
 // read-only could protect against either unintentional or malicious corruption of the array.
-void AtexitArray::set_writable(bool writable) {
+void AtexitArray::set_writable(bool writable, size_t start_idx, size_t num_entries) {
   if (array_ == nullptr) return;
+
+  const size_t start_byte = page_start_of_index(start_idx);
+  const size_t stop_byte = page_end_of_index(start_idx + num_entries);
+  const size_t byte_len = stop_byte - start_byte;
+
   const int prot = PROT_READ | (writable ? PROT_WRITE : 0);
-  if (mprotect(array_, round_up_to_page_bytes(capacity_), prot) != 0) {
+  if (mprotect(reinterpret_cast<char*>(array_) + start_byte, byte_len, prot) != 0) {
     async_safe_fatal("mprotect failed on atexit array: %s", strerror(errno));
   }
 }
 
-bool AtexitArray::expand_capacity() {
-  const size_t new_capacity = next_capacity(capacity_);
-  const size_t new_capacity_bytes = round_up_to_page_bytes(new_capacity);
+// Approximately double the capacity. Returns true if successful (no overflow). AtexitEntry is
+// smaller than a page, but this function should still be correct even if AtexitEntry were larger
+// than one.
+bool AtexitArray::next_capacity(size_t capacity, size_t* result) {
+  if (capacity == 0) {
+    *result = PAGE_END(sizeof(AtexitEntry)) / sizeof(AtexitEntry);
+    return true;
+  }
+  size_t num_bytes;
+  if (__builtin_mul_overflow(page_end_of_index(capacity), 2, &num_bytes)) {
+    async_safe_format_log(ANDROID_LOG_WARN, "libc", "__cxa_atexit: capacity calculation overflow");
+    return false;
+  }
+  *result = num_bytes / sizeof(AtexitEntry);
+  return true;
+}
 
+bool AtexitArray::expand_capacity() {
+  size_t new_capacity;
+  if (!next_capacity(capacity_, &new_capacity)) return false;
+  const size_t new_capacity_bytes = page_end_of_index(new_capacity);
+
+  set_writable(true, 0, capacity_);
+
+  bool result = false;
   void* new_pages;
   if (array_ == nullptr) {
     new_pages = mmap(nullptr, new_capacity_bytes, PROT_READ | PROT_WRITE,
                      MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
   } else {
-    new_pages =
-        mremap(array_, round_up_to_page_bytes(capacity_), new_capacity_bytes, MREMAP_MAYMOVE);
+    // mremap fails if the source buffer crosses a boundary between two VMAs. When a single array
+    // element is modified, the kernel should split then rejoin the buffer's VMA.
+    new_pages = mremap(array_, page_end_of_index(capacity_), new_capacity_bytes, MREMAP_MAYMOVE);
   }
   if (new_pages == MAP_FAILED) {
     async_safe_format_log(ANDROID_LOG_WARN, "libc",
                           "__cxa_atexit: mmap/mremap failed to allocate %zu bytes: %s",
                           new_capacity_bytes, strerror(errno));
-    return false;
+  } else {
+    result = true;
+    prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, new_pages, new_capacity_bytes, "atexit handlers");
+    array_ = static_cast<AtexitEntry*>(new_pages);
+    capacity_ = new_capacity;
   }
-
-  prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, new_pages, new_capacity_bytes, "atexit handlers");
-  array_ = static_cast<AtexitEntry*>(new_pages);
-  capacity_ = new_capacity;
-  return true;
+  set_writable(false, 0, capacity_);
+  return result;
 }
 
 static AtexitArray g_array;
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/bionic_systrace.cpp b/libc/bionic/bionic_systrace.cpp
index fd97712..0de51c5 100644
--- a/libc/bionic/bionic_systrace.cpp
+++ b/libc/bionic/bionic_systrace.cpp
@@ -14,52 +14,50 @@
  * limitations under the License.
  */
 
+#include "private/bionic_systrace.h"
+
 #include <errno.h>
 #include <fcntl.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
-#include "private/bionic_lock.h"
-#include "private/bionic_systrace.h"
-#include "private/CachedProperty.h"
-
 #include <async_safe/log.h>
 #include <cutils/trace.h> // For ATRACE_TAG_BIONIC.
 
+#include "private/CachedProperty.h"
+#include "private/bionic_lock.h"
+
 #define WRITE_OFFSET   32
 
 static Lock g_lock;
-static CachedProperty g_debug_atrace_tags_enableflags("debug.atrace.tags.enableflags");
-static uint64_t g_tags;
-static int g_trace_marker_fd = -1;
 
-static bool should_trace() {
+bool should_trace(const uint64_t enable_tags) {
+  static uint64_t tags_val;
+  static CachedProperty tags_prop(kTraceTagsProp);
   g_lock.lock();
-  if (g_debug_atrace_tags_enableflags.DidChange()) {
-    g_tags = strtoull(g_debug_atrace_tags_enableflags.Get(), nullptr, 0);
+  if (tags_prop.DidChange()) {
+    tags_val = strtoull(tags_prop.Get(), nullptr, 0);
   }
   g_lock.unlock();
-  return ((g_tags & ATRACE_TAG_BIONIC) != 0);
+  return tags_val & enable_tags;
 }
 
-static int get_trace_marker_fd() {
+int get_trace_marker_fd() {
+  static int opened_trace_marker_fd = -1;
   g_lock.lock();
-  if (g_trace_marker_fd == -1) {
-    g_trace_marker_fd = open("/sys/kernel/tracing/trace_marker", O_CLOEXEC | O_WRONLY);
-    if (g_trace_marker_fd == -1) {
-      g_trace_marker_fd = open("/sys/kernel/debug/tracing/trace_marker", O_CLOEXEC | O_WRONLY);
+  if (opened_trace_marker_fd == -1) {
+    opened_trace_marker_fd = open("/sys/kernel/tracing/trace_marker", O_CLOEXEC | O_WRONLY);
+    if (opened_trace_marker_fd == -1) {
+      opened_trace_marker_fd = open("/sys/kernel/debug/tracing/trace_marker", O_CLOEXEC | O_WRONLY);
     }
   }
   g_lock.unlock();
-  return g_trace_marker_fd;
+  return opened_trace_marker_fd;
 }
 
-void bionic_trace_begin(const char* message) {
-  if (!should_trace()) {
-    return;
-  }
-
+// event could be 'B' for begin or 'E' for end.
+void output_trace(const char* message, const char event) {
   int trace_marker_fd = get_trace_marker_fd();
   if (trace_marker_fd == -1) {
     return;
@@ -69,13 +67,22 @@
   // kernel trace_marker.
   int length = strlen(message);
   char buf[length + WRITE_OFFSET];
-  size_t len = async_safe_format_buffer(buf, length + WRITE_OFFSET, "B|%d|%s", getpid(), message);
+  size_t len =
+      async_safe_format_buffer(buf, length + WRITE_OFFSET, "%c|%d|%s", event, getpid(), message);
 
   // Tracing may stop just after checking property and before writing the message.
   // So the write is acceptable to fail. See b/20666100.
   TEMP_FAILURE_RETRY(write(trace_marker_fd, buf, len));
 }
 
+void bionic_trace_begin(const char* message) {
+  if (!should_trace()) {
+    return;
+  }
+
+  output_trace(message);
+}
+
 void bionic_trace_end() {
   if (!should_trace()) {
     return;
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..8c5cf2b 100644
--- a/libc/bionic/fork.cpp
+++ b/libc/bionic/fork.cpp
@@ -33,7 +33,7 @@
 #include "private/bionic_defs.h"
 #include "pthread_internal.h"
 
-__BIONIC_WEAK_FOR_NATIVE_BRIDGE
+__BIONIC_WEAK_FOR_NATIVE_BRIDGE_INLINE
 int __clone_for_fork() {
   pthread_internal_t* self = __get_thread();
 
@@ -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/icu.cpp b/libc/bionic/icu.cpp
index 72dac9b..c11b9d6 100644
--- a/libc/bionic/icu.cpp
+++ b/libc/bionic/icu.cpp
@@ -36,12 +36,12 @@
 
 #include <async_safe/log.h>
 
-static void* g_libicuuc_handle = nullptr;
+static void* g_libicu_handle = nullptr;
 
 static bool __find_icu() {
-  g_libicuuc_handle = dlopen("libandroidicu.so", RTLD_LOCAL);
-  if (g_libicuuc_handle == nullptr) {
-    async_safe_format_log(ANDROID_LOG_ERROR, "bionic-icu", "couldn't open libandroidicu.so: %s",
+  g_libicu_handle = dlopen("libicu.so", RTLD_LOCAL);
+  if (g_libicu_handle == nullptr) {
+    async_safe_format_log(ANDROID_LOG_ERROR, "bionic-icu", "couldn't open libicu.so: %s",
                           dlerror());
     return false;
   }
@@ -53,14 +53,9 @@
   static bool found_icu = __find_icu();
   if (!found_icu) return nullptr;
 
-  char versioned_symbol_name[strlen(symbol_name) + strlen("_android") + 1];
-  snprintf(versioned_symbol_name, sizeof(versioned_symbol_name), "%s_android",
-           symbol_name);
-
-  void* symbol = dlsym(g_libicuuc_handle, versioned_symbol_name);
+  void* symbol = dlsym(g_libicu_handle, symbol_name);
   if (symbol == nullptr) {
-    async_safe_format_log(ANDROID_LOG_ERROR, "bionic-icu", "couldn't find %s",
-                          versioned_symbol_name);
+    async_safe_format_log(ANDROID_LOG_ERROR, "bionic-icu", "couldn't find %s", symbol_name);
   }
   return symbol;
 }
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..80adbbe 100644
--- a/libc/bionic/libc_init_common.cpp
+++ b/libc/bionic/libc_init_common.cpp
@@ -58,6 +58,7 @@
 __LIBC_HIDDEN__ WriteProtected<libc_globals> __libc_globals;
 
 // Not public, but well-known in the BSDs.
+__BIONIC_WEAK_VARIABLE_FOR_NATIVE_BRIDGE
 const char* __progname;
 
 void __libc_init_globals() {
@@ -86,11 +87,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 +363,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 +375,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/malloc_common.cpp b/libc/bionic/malloc_common.cpp
index ed5537f..6b7006d 100644
--- a/libc/bionic/malloc_common.cpp
+++ b/libc/bionic/malloc_common.cpp
@@ -46,6 +46,7 @@
 #include "malloc_common.h"
 #include "malloc_limit.h"
 #include "malloc_tagged_pointers.h"
+#include "memory_mitigation_state.h"
 
 // =============================================================================
 // Global variables instantations.
@@ -326,6 +327,9 @@
       return MaybeInitGwpAsan(globals, *reinterpret_cast<bool*>(arg));
     });
   }
+  if (opcode == M_DISABLE_MEMORY_MITIGATIONS) {
+    return DisableMemoryMitigations(arg, arg_size);
+  }
   errno = ENOTSUP;
   return false;
 }
diff --git a/libc/bionic/malloc_common_dynamic.cpp b/libc/bionic/malloc_common_dynamic.cpp
index 6a82ae3..eeeaff9 100644
--- a/libc/bionic/malloc_common_dynamic.cpp
+++ b/libc/bionic/malloc_common_dynamic.cpp
@@ -70,6 +70,7 @@
 #include "malloc_common_dynamic.h"
 #include "malloc_heapprofd.h"
 #include "malloc_limit.h"
+#include "memory_mitigation_state.h"
 
 // =============================================================================
 // Global variables instantations.
@@ -533,6 +534,9 @@
       return MaybeInitGwpAsan(globals, *reinterpret_cast<bool*>(arg));
     });
   }
+  if (opcode == M_DISABLE_MEMORY_MITIGATIONS) {
+    return DisableMemoryMitigations(arg, arg_size);
+  }
   // Try heapprofd's mallopt, as it handles options not covered here.
   return HeapprofdMallopt(opcode, arg, arg_size);
 }
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/memory_mitigation_state.cpp b/libc/bionic/memory_mitigation_state.cpp
new file mode 100644
index 0000000..82b0b7b
--- /dev/null
+++ b/libc/bionic/memory_mitigation_state.cpp
@@ -0,0 +1,86 @@
+/*
+ * 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 "memory_mitigation_state.h"
+
+#include <dirent.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <stdatomic.h>
+#include <stdlib.h>
+#include <sys/prctl.h>
+#include <sys/types.h>
+
+#include <bionic/mte.h>
+#include <bionic/reserved_signals.h>
+
+#include "private/ScopedRWLock.h"
+#include "pthread_internal.h"
+
+extern "C" void scudo_malloc_set_zero_contents(int zero_contents);
+extern "C" void scudo_malloc_disable_memory_tagging();
+
+#ifdef ANDROID_EXPERIMENTAL_MTE
+static bool set_tcf_on_all_threads(int tcf) {
+  static int g_tcf;
+  g_tcf = tcf;
+
+  return android_run_on_all_threads(
+      [](void*) {
+        int tagged_addr_ctrl = prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0);
+        if (tagged_addr_ctrl < 0) {
+          return false;
+        }
+
+        tagged_addr_ctrl = (tagged_addr_ctrl & ~PR_MTE_TCF_MASK) | g_tcf;
+        if (prctl(PR_SET_TAGGED_ADDR_CTRL, tagged_addr_ctrl, 0, 0, 0) < 0) {
+          return false;
+        }
+        return true;
+      },
+      nullptr);
+}
+#endif
+
+bool DisableMemoryMitigations(void* arg, size_t arg_size) {
+  if (arg || arg_size) {
+    return false;
+  }
+
+#ifdef USE_SCUDO
+  scudo_malloc_set_zero_contents(0);
+
+#ifdef ANDROID_EXPERIMENTAL_MTE
+  if (mte_supported() && set_tcf_on_all_threads(PR_MTE_TCF_NONE)) {
+    scudo_malloc_disable_memory_tagging();
+  }
+#endif
+#endif
+
+  return true;
+}
diff --git a/libc/bionic/pututline.c b/libc/bionic/memory_mitigation_state.h
similarity index 63%
copy from libc/bionic/pututline.c
copy to libc/bionic/memory_mitigation_state.h
index 8cbf470..ffa1912 100644
--- a/libc/bionic/pututline.c
+++ b/libc/bionic/memory_mitigation_state.h
@@ -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,9 @@
  * 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 <stddef.h>
 
-    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);
-}
+bool DisableMemoryMitigations(void* arg, size_t arg_size);
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_cond.cpp b/libc/bionic/pthread_cond.cpp
index e857069..793dcd9 100644
--- a/libc/bionic/pthread_cond.cpp
+++ b/libc/bionic/pthread_cond.cpp
@@ -116,7 +116,8 @@
   }
 
 #if defined(__LP64__)
-  char __reserved[44];
+  atomic_uint waiters;
+  char __reserved[40];
 #endif
 };
 
@@ -141,6 +142,10 @@
   }
   atomic_init(&cond->state, init_state);
 
+#if defined(__LP64__)
+  atomic_init(&cond->waiters, 0);
+#endif
+
   return 0;
 }
 
@@ -163,6 +168,12 @@
   // not be called. That's why pthread_wait/signal pair can't be used as a method for memory
   // synchronization. And it doesn't help even if we use any fence here.
 
+#if defined(__LP64__)
+  if (atomic_load_explicit(&cond->waiters, memory_order_relaxed) == 0) {
+    return 0;
+  }
+#endif
+
   // The increase of value should leave flags alone, even if the value can overflows.
   atomic_fetch_add_explicit(&cond->state, COND_COUNTER_STEP, memory_order_relaxed);
 
@@ -178,9 +189,19 @@
   }
 
   unsigned int old_state = atomic_load_explicit(&cond->state, memory_order_relaxed);
+
+#if defined(__LP64__)
+  atomic_fetch_add_explicit(&cond->waiters, 1, memory_order_relaxed);
+#endif
+
   pthread_mutex_unlock(mutex);
   int status = __futex_wait_ex(&cond->state, cond->process_shared(), old_state,
                                use_realtime_clock, abs_timeout_or_null);
+
+#if defined(__LP64__)
+  atomic_fetch_sub_explicit(&cond->waiters, 1, memory_order_relaxed);
+#endif
+
   pthread_mutex_lock(mutex);
 
   if (status == -ETIMEDOUT) {
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index d4a8bef..206d5fd 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -39,6 +39,7 @@
 
 #include <async_safe/log.h>
 
+#include "private/ScopedRWLock.h"
 #include "private/bionic_constants.h"
 #include "private/bionic_defs.h"
 #include "private/bionic_globals.h"
@@ -350,13 +351,14 @@
   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*) {
   return nullptr;
 }
 
+pthread_rwlock_t g_thread_creation_lock = PTHREAD_RWLOCK_INITIALIZER;
 
 __BIONIC_WEAK_FOR_NATIVE_BRIDGE
 int pthread_create(pthread_t* thread_out, pthread_attr_t const* attr,
@@ -406,6 +408,8 @@
   tls = &tls_descriptor;
 #endif
 
+  ScopedReadLock locker(&g_thread_creation_lock);
+
   sigset64_t block_all_mask;
   sigfillset64(&block_all_mask);
   __rt_sigprocmask(SIG_SETMASK, &block_all_mask, &thread->start_mask, sizeof(thread->start_mask));
diff --git a/libc/bionic/pthread_exit.cpp b/libc/bionic/pthread_exit.cpp
index 3b873b3..bde95ec 100644
--- a/libc/bionic/pthread_exit.cpp
+++ b/libc/bionic/pthread_exit.cpp
@@ -35,6 +35,7 @@
 
 #include "private/bionic_constants.h"
 #include "private/bionic_defs.h"
+#include "private/ScopedRWLock.h"
 #include "private/ScopedSignalBlocker.h"
 #include "pthread_internal.h"
 
@@ -103,16 +104,24 @@
          !atomic_compare_exchange_weak(&thread->join_state, &old_state, THREAD_EXITED_NOT_JOINED)) {
   }
 
-  // We don't want to take a signal after unmapping the stack, the shadow call
-  // stack, or dynamic TLS memory.
-  ScopedSignalBlocker ssb;
+  // android_run_on_all_threads() needs to see signals blocked atomically with setting the
+  // terminating flag, so take the creation lock while doing these operations.
+  {
+    ScopedReadLock locker(&g_thread_creation_lock);
+    atomic_store(&thread->terminating, true);
+
+    // We don't want to take a signal after unmapping the stack, the shadow call stack, or dynamic
+    // TLS memory.
+    sigset64_t set;
+    sigfillset64(&set);
+    __rt_sigprocmask(SIG_BLOCK, &set, nullptr, sizeof(sigset64_t));
+  }
 
 #ifdef __aarch64__
   // Free the shadow call stack and guard pages.
   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 +137,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 +145,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/pthread_internal.cpp b/libc/bionic/pthread_internal.cpp
index e091158..6a7ee2f 100644
--- a/libc/bionic/pthread_internal.cpp
+++ b/libc/bionic/pthread_internal.cpp
@@ -29,12 +29,15 @@
 #include "pthread_internal.h"
 
 #include <errno.h>
+#include <semaphore.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/mman.h>
 
 #include <async_safe/log.h>
+#include <bionic/reserved_signals.h>
 
+#include "private/ErrnoRestorer.h"
 #include "private/ScopedRWLock.h"
 #include "private/bionic_futex.h"
 #include "private/bionic_tls.h"
@@ -115,3 +118,76 @@
   }
   return nullptr;
 }
+
+bool android_run_on_all_threads(bool (*func)(void*), void* arg) {
+  // Take the locks in this order to avoid inversion (pthread_create ->
+  // __pthread_internal_add).
+  ScopedWriteLock creation_locker(&g_thread_creation_lock);
+  ScopedReadLock list_locker(&g_thread_list_lock);
+
+  // Call the function directly for the current thread so that we don't need to worry about
+  // the consequences of synchronizing with ourselves.
+  if (!func(arg)) {
+    return false;
+  }
+
+  static sem_t g_sem;
+  if (sem_init(&g_sem, 0, 0) != 0) {
+    return false;
+  }
+
+  static bool (*g_func)(void*);
+  static void *g_arg;
+  g_func = func;
+  g_arg = arg;
+
+  static _Atomic(bool) g_retval;
+  atomic_init(&g_retval, true);
+
+  auto handler = [](int, siginfo_t*, void*) {
+    ErrnoRestorer restorer;
+    if (!g_func(g_arg)) {
+      atomic_store(&g_retval, false);
+    }
+    sem_post(&g_sem);
+  };
+
+  struct sigaction act = {}, oldact;
+  act.sa_flags = SA_SIGINFO;
+  act.sa_sigaction = handler;
+  sigfillset(&act.sa_mask);
+  if (sigaction(BIONIC_SIGNAL_RUN_ON_ALL_THREADS, &act, &oldact) != 0) {
+    sem_destroy(&g_sem);
+    return false;
+  }
+
+  pid_t my_pid = getpid();
+  size_t num_tids = 0;
+  for (pthread_internal_t* t = g_thread_list; t != nullptr; t = t->next) {
+    // The function is called directly for the current thread above, so no need to send a signal to
+    // ourselves to call it here.
+    if (t == __get_thread()) continue;
+
+    // If a thread is terminating (has blocked signals) or has already terminated, our signal will
+    // never be received, so we need to check for that condition and skip the thread if it is the
+    // case.
+    if (atomic_load(&t->terminating)) continue;
+
+    if (tgkill(my_pid, t->tid, BIONIC_SIGNAL_RUN_ON_ALL_THREADS) == 0) {
+      ++num_tids;
+    } else {
+      atomic_store(&g_retval, false);
+    }
+  }
+
+  for (size_t i = 0; i != num_tids; ++i) {
+    if (TEMP_FAILURE_RETRY(sem_wait(&g_sem)) != 0) {
+      atomic_store(&g_retval, false);
+      break;
+    }
+  }
+
+  sigaction(BIONIC_SIGNAL_RUN_ON_ALL_THREADS, &oldact, 0);
+  sem_destroy(&g_sem);
+  return atomic_load(&g_retval);
+}
diff --git a/libc/bionic/pthread_internal.h b/libc/bionic/pthread_internal.h
index 1f055f5..071a5bc 100644
--- a/libc/bionic/pthread_internal.h
+++ b/libc/bionic/pthread_internal.h
@@ -132,6 +132,11 @@
   // top of the stack quickly, which would otherwise require special logic for the main thread.
   uintptr_t stack_top;
 
+  // Whether the thread is in the process of terminating (has blocked signals), or has already
+  // terminated. This is used by android_run_on_all_threads() to avoid sending a signal to a thread
+  // that will never receive it.
+  _Atomic(bool) terminating;
+
   Lock startup_handshake_lock;
 
   void* mmap_base;
@@ -242,3 +247,7 @@
 __LIBC_HIDDEN__ extern void __bionic_atfork_run_prepare();
 __LIBC_HIDDEN__ extern void __bionic_atfork_run_child();
 __LIBC_HIDDEN__ extern void __bionic_atfork_run_parent();
+
+extern "C" bool android_run_on_all_threads(bool (*func)(void*), void* arg);
+
+extern pthread_rwlock_t g_thread_creation_lock;
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..d1a73b7
--- /dev/null
+++ b/libc/bionic/sys_thread_properties.cpp
@@ -0,0 +1,152 @@
+/*
+ * 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>
+
+#if defined(__i386__)
+#include <asm/ldt.h>
+#endif
+
+#include "private/ErrnoRestorer.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__)
+  {
+    ErrnoRestorer errno_restorer;
+    errno = 0;
+    uintptr_t fs_base = ptrace(PTRACE_PEEKUSER, tid, offsetof(user_regs_struct, fs_base), nullptr);
+    if (errno == 0) {
+      tp_reg = reinterpret_cast<void**>(fs_base);
+    }
+  }
+#elif 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) {
+    struct user_desc u_info;
+    u_info.entry_number = regs.xgs >> 3;
+    if (ptrace(PTRACE_GET_THREAD_AREA, tid, u_info.entry_number, &u_info) == 0) {
+      tp_reg = reinterpret_cast<void**>(u_info.base_addr);
+    }
+  }
+#elif defined(__aarch64__)
+  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);
+  }
+#elif defined(__arm__)
+  if (ptrace(PTRACE_GET_THREAD_AREA, tid, nullptr, &tp_reg) != 0) {
+    // Reset the tp_reg if ptrace was unsuccessful.
+    tp_reg = nullptr;
+  }
+#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/system_property_set.cpp b/libc/bionic/system_property_set.cpp
index 212aafc..6823b6a 100644
--- a/libc/bionic/system_property_set.cpp
+++ b/libc/bionic/system_property_set.cpp
@@ -41,12 +41,13 @@
 #include <sys/_system_properties.h>
 #include <unistd.h>
 
-#include <async_safe/log.h>
 #include <async_safe/CHECK.h>
+#include <async_safe/log.h>
+#include <system_properties/prop_trace.h>
 
-#include "private/bionic_defs.h"
 #include "platform/bionic/macros.h"
 #include "private/ScopedFd.h"
+#include "private/bionic_defs.h"
 
 static const char property_service_socket[] = "/dev/socket/" PROP_SERVICE_NAME;
 static const char* kServiceVersionPropertyName = "ro.property_service.version";
@@ -249,6 +250,8 @@
   if (key == nullptr) return -1;
   if (value == nullptr) value = "";
 
+  SyspropTrace trace(key, value, nullptr /* prop_info */, PropertyAction::kPropertySet);
+
   if (g_propservice_protocol_version == 0) {
     detect_protocol_version();
   }
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/dns/net/gethnamaddr.c b/libc/dns/net/gethnamaddr.c
index 7e18840..84942f8 100644
--- a/libc/dns/net/gethnamaddr.c
+++ b/libc/dns/net/gethnamaddr.c
@@ -90,6 +90,8 @@
 
 #include "hostent.h"
 
+#include "private/bionic_defs.h"
+
 #define maybe_ok(res, nm, ok) (((res)->options & RES_NOCHECKNAME) != 0U || \
                                (ok)(nm) != 0)
 #define maybe_hnok(res, hn) maybe_ok((res), (hn), res_hnok)
@@ -1533,6 +1535,7 @@
  * Non-reentrant versions.
  */
 
+__BIONIC_WEAK_FOR_NATIVE_BRIDGE
 struct hostent *
 gethostbyname(const char *name)
 {
@@ -1590,6 +1593,7 @@
 	return hp;
 }
 
+__BIONIC_WEAK_FOR_NATIVE_BRIDGE
 struct hostent *
 gethostbyaddr(const void *addr, socklen_t len, int af)
 {
diff --git a/libc/dns/net/getnameinfo.c b/libc/dns/net/getnameinfo.c
index 31d07c5..413b37e 100644
--- a/libc/dns/net/getnameinfo.c
+++ b/libc/dns/net/getnameinfo.c
@@ -68,6 +68,8 @@
 #include <stddef.h>
 #include <string.h>
 
+#include "private/bionic_defs.h"
+
 /* This macro is modelled after the ones in <netinet/in6.h>. */
 /* RFC 6052, section 2.1 */
 #define IN6_IS_ADDR_WKP(a) \
@@ -110,6 +112,7 @@
  * Top-level getnameinfo() code.  Look at the address family, and pick an
  * appropriate function to call.
  */
+__BIONIC_WEAK_FOR_NATIVE_BRIDGE
 int getnameinfo(const struct sockaddr* sa, socklen_t salen, char* host, size_t hostlen,
 		char* serv, size_t servlen, int flags)
 {
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/elf_arm64.h b/libc/include/bits/elf_arm64.h
index 6bb8384..9330d7b 100644
--- a/libc/include/bits/elf_arm64.h
+++ b/libc/include/bits/elf_arm64.h
@@ -89,4 +89,9 @@
 #define R_AARCH64_TLSDESC               1031    /* 16-byte descriptor: resolver func + arg. */
 #define R_AARCH64_IRELATIVE             1032
 
+/* Dynamic array tags */
+#define DT_AARCH64_BTI_PLT              0x70000001
+#define DT_AARCH64_PAC_PLT              0x70000003
+#define DT_AARCH64_VARIANT_PCS          0x70000005
+
 #endif /* _AARCH64_ELF_MACHDEP_H_ */
diff --git a/libc/include/bits/glibc-syscalls.h b/libc/include/bits/glibc-syscalls.h
index 0e3014d..1decafd 100644
--- a/libc/include/bits/glibc-syscalls.h
+++ b/libc/include/bits/glibc-syscalls.h
@@ -120,6 +120,9 @@
 #if defined(__NR_close)
   #define SYS_close __NR_close
 #endif
+#if defined(__NR_close_range)
+  #define SYS_close_range __NR_close_range
+#endif
 #if defined(__NR_connect)
   #define SYS_connect __NR_connect
 #endif
@@ -186,6 +189,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..a237254 100644
--- a/libc/include/malloc.h
+++ b/libc/include/malloc.h
@@ -170,6 +170,38 @@
  * Available since API level 28.
  */
 #define M_PURGE (-101)
+/*
+ * mallopt() option for per-thread memory initialization tuning.
+ * The value argument should be one of:
+ * 1: Disable automatic heap initialization and, where possible, memory tagging,
+ *    on this thread.
+ * 0: Normal behavior.
+ *
+ * Available since API level 31.
+ */
+#define M_THREAD_DISABLE_MEM_INIT (-103)
+/**
+ * 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/math.h b/libc/include/math.h
index 7efc83a..8c084b2 100644
--- a/libc/include/math.h
+++ b/libc/include/math.h
@@ -10,12 +10,10 @@
  */
 
 /*
- * from: @(#)fdlibm.h 5.1 93/09/24
- * $FreeBSD$
+ * Originally based on fdlibm.h 5.1 via FreeBSD.
  */
 
-#ifndef _MATH_H_
-#define _MATH_H_
+#pragma once
 
 #include <sys/cdefs.h>
 #include <limits.h>
@@ -408,5 +406,3 @@
 #endif
 
 __END_DECLS
-
-#endif
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/procfs.h b/libc/include/sys/procfs.h
index 75a1e98..a082e97 100644
--- a/libc/include/sys/procfs.h
+++ b/libc/include/sys/procfs.h
@@ -26,16 +26,24 @@
  * SUCH DAMAGE.
  */
 
-#ifndef _SYS_PROCFS_H_
-#define _SYS_PROCFS_H_
+#pragma once
 
 #include <sys/cdefs.h>
+#include <sys/ptrace.h>
 #include <sys/ucontext.h>
 
 __BEGIN_DECLS
 
+#if defined(__arm__)
+#define ELF_NGREG (sizeof(struct user_regs) / sizeof(elf_greg_t))
+#elif defined(__aarch64__)
+#define ELF_NGREG (sizeof(struct user_pt_regs) / sizeof(elf_greg_t))
+#else
+#define ELF_NGREG (sizeof(struct user_regs_struct) / sizeof(elf_greg_t))
+#endif
+
 typedef unsigned long elf_greg_t;
-typedef elf_greg_t elf_gregset_t[NGREG];
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
 
 typedef fpregset_t elf_fpregset_t;
 
@@ -58,5 +66,3 @@
 #define ELF_PRARGSZ 80
 
 __END_DECLS
-
-#endif
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..6e7faec 100644
--- a/libc/kernel/uapi/asm-arm/asm/unistd-common.h
+++ b/libc/kernel/uapi/asm-arm/asm/unistd-common.h
@@ -407,6 +407,8 @@
 #define __NR_fspick (__NR_SYSCALL_BASE + 433)
 #define __NR_pidfd_open (__NR_SYSCALL_BASE + 434)
 #define __NR_clone3 (__NR_SYSCALL_BASE + 435)
+#define __NR_close_range (__NR_SYSCALL_BASE + 436)
 #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..07fe6e7 100644
--- a/libc/kernel/uapi/asm-generic/unistd.h
+++ b/libc/kernel/uapi/asm-generic/unistd.h
@@ -396,10 +396,12 @@
 #ifdef __ARCH_WANT_SYS_CLONE3
 #define __NR_clone3 435
 #endif
+#define __NR_close_range 436
 #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/hwcap2.h b/libc/kernel/uapi/asm-x86/asm/hwcap2.h
index 9015dee..a6dbfb9 100644
--- a/libc/kernel/uapi/asm-x86/asm/hwcap2.h
+++ b/libc/kernel/uapi/asm-x86/asm/hwcap2.h
@@ -19,4 +19,5 @@
 #ifndef _ASM_X86_HWCAP2_H
 #define _ASM_X86_HWCAP2_H
 #define HWCAP2_RING3MWAIT (1 << 0)
+#define HWCAP2_FSGSBASE BIT(1)
 #endif
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..ff83a82 100644
--- a/libc/kernel/uapi/asm-x86/asm/unistd_32.h
+++ b/libc/kernel/uapi/asm-x86/asm/unistd_32.h
@@ -443,6 +443,8 @@
 #define __NR_fspick 433
 #define __NR_pidfd_open 434
 #define __NR_clone3 435
+#define __NR_close_range 436
 #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..40986b8 100644
--- a/libc/kernel/uapi/asm-x86/asm/unistd_64.h
+++ b/libc/kernel/uapi/asm-x86/asm/unistd_64.h
@@ -365,6 +365,8 @@
 #define __NR_fspick 433
 #define __NR_pidfd_open 434
 #define __NR_clone3 435
+#define __NR_close_range 436
 #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..283828b 100644
--- a/libc/kernel/uapi/asm-x86/asm/unistd_x32.h
+++ b/libc/kernel/uapi/asm-x86/asm/unistd_x32.h
@@ -318,8 +318,10 @@
 #define __NR_fspick (__X32_SYSCALL_BIT + 433)
 #define __NR_pidfd_open (__X32_SYSCALL_BIT + 434)
 #define __NR_clone3 (__X32_SYSCALL_BIT + 435)
+#define __NR_close_range (__X32_SYSCALL_BIT + 436)
 #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..794a9e9 100644
--- a/libc/kernel/uapi/drm/drm_fourcc.h
+++ b/libc/kernel/uapi/drm/drm_fourcc.h
@@ -111,10 +111,13 @@
 #define DRM_FORMAT_NV61 fourcc_code('N', 'V', '6', '1')
 #define DRM_FORMAT_NV24 fourcc_code('N', 'V', '2', '4')
 #define DRM_FORMAT_NV42 fourcc_code('N', 'V', '4', '2')
+#define DRM_FORMAT_NV15 fourcc_code('N', 'V', '1', '5')
 #define DRM_FORMAT_P210 fourcc_code('P', '2', '1', '0')
 #define DRM_FORMAT_P010 fourcc_code('P', '0', '1', '0')
 #define DRM_FORMAT_P012 fourcc_code('P', '0', '1', '2')
 #define DRM_FORMAT_P016 fourcc_code('P', '0', '1', '6')
+#define DRM_FORMAT_Q410 fourcc_code('Q', '4', '1', '0')
+#define DRM_FORMAT_Q401 fourcc_code('Q', '4', '0', '1')
 #define DRM_FORMAT_YUV410 fourcc_code('Y', 'U', 'V', '9')
 #define DRM_FORMAT_YVU410 fourcc_code('Y', 'V', 'U', '9')
 #define DRM_FORMAT_YUV411 fourcc_code('Y', 'U', '1', '1')
@@ -136,8 +139,10 @@
 #define DRM_FORMAT_MOD_VENDOR_BROADCOM 0x07
 #define DRM_FORMAT_MOD_VENDOR_ARM 0x08
 #define DRM_FORMAT_MOD_VENDOR_ALLWINNER 0x09
+#define DRM_FORMAT_MOD_VENDOR_AMLOGIC 0x0a
 #define DRM_FORMAT_RESERVED ((1ULL << 56) - 1)
 #define fourcc_mod_code(vendor,val) ((((__u64) DRM_FORMAT_MOD_VENDOR_ ##vendor) << 56) | ((val) & 0x00ffffffffffffffULL))
+#define DRM_FORMAT_MOD_GENERIC_16_16_TILE DRM_FORMAT_MOD_SAMSUNG_16_16_TILE
 #define DRM_FORMAT_MOD_INVALID fourcc_mod_code(NONE, DRM_FORMAT_RESERVED)
 #define DRM_FORMAT_MOD_LINEAR fourcc_mod_code(NONE, 0)
 #define I915_FORMAT_MOD_X_TILED fourcc_mod_code(INTEL, 1)
@@ -150,21 +155,19 @@
 #define DRM_FORMAT_MOD_SAMSUNG_64_32_TILE fourcc_mod_code(SAMSUNG, 1)
 #define DRM_FORMAT_MOD_SAMSUNG_16_16_TILE fourcc_mod_code(SAMSUNG, 2)
 #define DRM_FORMAT_MOD_QCOM_COMPRESSED fourcc_mod_code(QCOM, 1)
-#define DRM_FORMAT_MOD_QCOM_DX fourcc_mod_code(QCOM, 0x2)
-#define DRM_FORMAT_MOD_QCOM_TIGHT fourcc_mod_code(QCOM, 0x4)
-#define DRM_FORMAT_MOD_QCOM_TILE fourcc_mod_code(QCOM, 0x8)
 #define DRM_FORMAT_MOD_VIVANTE_TILED fourcc_mod_code(VIVANTE, 1)
 #define DRM_FORMAT_MOD_VIVANTE_SUPER_TILED fourcc_mod_code(VIVANTE, 2)
 #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))
@@ -197,8 +200,16 @@
 #define AFBC_FORMAT_MOD_SC (1ULL << 9)
 #define AFBC_FORMAT_MOD_DB (1ULL << 10)
 #define AFBC_FORMAT_MOD_BCH (1ULL << 11)
+#define AFBC_FORMAT_MOD_USM (1ULL << 12)
 #define DRM_FORMAT_MOD_ARM_16X16_BLOCK_U_INTERLEAVED DRM_FORMAT_MOD_ARM_CODE(DRM_FORMAT_MOD_ARM_TYPE_MISC, 1ULL)
 #define DRM_FORMAT_MOD_ALLWINNER_TILED fourcc_mod_code(ALLWINNER, 1)
+#define __fourcc_mod_amlogic_layout_mask 0xf
+#define __fourcc_mod_amlogic_options_shift 8
+#define __fourcc_mod_amlogic_options_mask 0xf
+#define DRM_FORMAT_MOD_AMLOGIC_FBC(__layout,__options) fourcc_mod_code(AMLOGIC, ((__layout) & __fourcc_mod_amlogic_layout_mask) | (((__options) & __fourcc_mod_amlogic_options_mask) << __fourcc_mod_amlogic_options_shift))
+#define AMLOGIC_FBC_LAYOUT_BASIC (1ULL)
+#define AMLOGIC_FBC_LAYOUT_SCATTER (2ULL)
+#define AMLOGIC_FBC_OPTION_MEM_SAVING (1ULL << 0)
 #ifdef __cplusplus
 }
 #endif
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..2c18e07 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
@@ -247,6 +248,7 @@
 #define AUDIT_STATUS_BACKLOG_LIMIT 0x0010
 #define AUDIT_STATUS_BACKLOG_WAIT_TIME 0x0020
 #define AUDIT_STATUS_LOST 0x0040
+#define AUDIT_STATUS_BACKLOG_WAIT_TIME_ACTUAL 0x0080
 #define AUDIT_FEATURE_BITMAP_BACKLOG_LIMIT 0x00000001
 #define AUDIT_FEATURE_BITMAP_BACKLOG_WAIT_TIME 0x00000002
 #define AUDIT_FEATURE_BITMAP_EXECUTABLE_PATH 0x00000004
@@ -341,6 +343,7 @@
     __u32 feature_bitmap;
   };
   __u32 backlog_wait_time;
+  __u32 backlog_wait_time_actual;
 };
 struct audit_features {
 #define AUDIT_FEATURE_VERSION 1
diff --git a/libc/kernel/uapi/linux/bcache.h b/libc/kernel/uapi/linux/bcache.h
index 5e5377e..09335c8 100644
--- a/libc/kernel/uapi/linux/bcache.h
+++ b/libc/kernel/uapi/linux/bcache.h
@@ -54,7 +54,9 @@
 #define BCACHE_SB_VERSION_BDEV 1
 #define BCACHE_SB_VERSION_CDEV_WITH_UUID 3
 #define BCACHE_SB_VERSION_BDEV_WITH_OFFSET 4
-#define BCACHE_SB_MAX_VERSION 4
+#define BCACHE_SB_VERSION_CDEV_WITH_FEATURES 5
+#define BCACHE_SB_VERSION_BDEV_WITH_FEATURES 6
+#define BCACHE_SB_MAX_VERSION 6
 #define SB_SECTOR 8
 #define SB_OFFSET (SB_SECTOR << SECTOR_SHIFT)
 #define SB_SIZE 4096
@@ -75,7 +77,10 @@
   __u8 label[SB_LABEL_SIZE];
   __le64 flags;
   __le64 seq;
-  __le64 pad[8];
+  __le64 feature_compat;
+  __le64 feature_incompat;
+  __le64 feature_ro_compat;
+  __le64 pad[5];
   union {
     struct {
       __le64 nbuckets;
@@ -95,9 +100,9 @@
     __le16 keys;
   };
   __le64 d[SB_JOURNAL_BUCKETS];
+  __le16 bucket_size_hi;
 };
 struct cache_sb {
-  __u64 csum;
   __u64 offset;
   __u64 version;
   __u8 magic[16];
@@ -109,14 +114,16 @@
   __u8 label[SB_LABEL_SIZE];
   __u64 flags;
   __u64 seq;
-  __u64 pad[8];
+  __u64 feature_compat;
+  __u64 feature_incompat;
+  __u64 feature_ro_compat;
   union {
     struct {
       __u64 nbuckets;
       __u16 block_size;
-      __u16 bucket_size;
       __u16 nr_in_set;
       __u16 nr_this_dev;
+      __u32 bucket_size;
     };
     struct {
       __u64 data_offset;
diff --git a/libc/kernel/uapi/linux/blkzoned.h b/libc/kernel/uapi/linux/blkzoned.h
index 0b8ddd6..b551e8b 100644
--- a/libc/kernel/uapi/linux/blkzoned.h
+++ b/libc/kernel/uapi/linux/blkzoned.h
@@ -35,6 +35,9 @@
   BLK_ZONE_COND_FULL = 0xE,
   BLK_ZONE_COND_OFFLINE = 0xF,
 };
+enum blk_zone_report_flags {
+  BLK_ZONE_REP_CAPACITY = (1 << 0),
+};
 struct blk_zone {
   __u64 start;
   __u64 len;
@@ -43,12 +46,14 @@
   __u8 cond;
   __u8 non_seq;
   __u8 reset;
-  __u8 reserved[36];
+  __u8 resv[4];
+  __u64 capacity;
+  __u8 reserved[24];
 };
 struct blk_zone_report {
   __u64 sector;
   __u32 nr_zones;
-  __u8 reserved[4];
+  __u32 flags;
   struct blk_zone zones[0];
 };
 struct blk_zone_range {
diff --git a/libc/kernel/uapi/linux/bpf.h b/libc/kernel/uapi/linux/bpf.h
index 815fd6a..816871a 100644
--- a/libc/kernel/uapi/linux/bpf.h
+++ b/libc/kernel/uapi/linux/bpf.h
@@ -70,6 +70,11 @@
   __u64 cgroup_inode_id;
   __u32 attach_type;
 };
+union bpf_iter_link_info {
+  struct {
+    __u32 map_fd;
+  } map;
+};
 enum bpf_cmd {
   BPF_MAP_CREATE,
   BPF_MAP_LOOKUP_ELEM,
@@ -101,6 +106,11 @@
   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,
+  BPF_LINK_DETACH,
 };
 enum bpf_map_type {
   BPF_MAP_TYPE_UNSPEC,
@@ -130,6 +140,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,
@@ -162,6 +173,7 @@
   BPF_PROG_TYPE_STRUCT_OPS,
   BPF_PROG_TYPE_EXT,
   BPF_PROG_TYPE_LSM,
+  BPF_PROG_TYPE_SK_LOOKUP,
 };
 enum bpf_attach_type {
   BPF_CGROUP_INET_INGRESS,
@@ -192,9 +204,29 @@
   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,
+  BPF_CGROUP_INET_SOCK_RELEASE,
+  BPF_XDP_CPUMAP,
+  BPF_SK_LOOKUP,
+  BPF_XDP,
   __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,
+  BPF_LINK_TYPE_XDP = 6,
+  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 +257,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 +365,7 @@
       __u32 prog_id;
       __u32 map_id;
       __u32 btf_id;
+      __u32 link_id;
     };
     __u32 next_id;
     __u32 open_flags;
@@ -371,9 +407,14 @@
   } task_fd_query;
   struct {
     __u32 prog_fd;
-    __u32 target_fd;
+    union {
+      __u32 target_fd;
+      __u32 target_ifindex;
+    };
     __u32 attach_type;
     __u32 flags;
+    __aligned_u64 iter_info;
+    __u32 iter_info_len;
   } link_create;
   struct {
     __u32 link_fd;
@@ -381,8 +422,18 @@
     __u32 flags;
     __u32 old_prog_fd;
   } link_update;
+  struct {
+    __u32 link_fd;
+  } link_detach;
+  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), FN(skc_to_tcp6_sock), FN(skc_to_tcp_sock), FN(skc_to_tcp_timewait_sock), FN(skc_to_tcp_request_sock), FN(skc_to_udp6_sock), FN(get_task_stack),
 #define __BPF_ENUM_FN(x) BPF_FUNC_ ##x
 enum bpf_func_id {
   __BPF_FUNC_MAPPER(__BPF_ENUM_FN) __BPF_FUNC_MAX_ID,
@@ -427,11 +478,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 +505,25 @@
 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_SK_LOOKUP_F_REPLACE = (1ULL << 0),
+  BPF_SK_LOOKUP_F_NO_REUSEPORT = (1ULL << 1),
+};
 enum bpf_adj_room_mode {
   BPF_ADJ_ROOM_NET,
   BPF_ADJ_ROOM_MAC,
@@ -537,6 +614,7 @@
   __u32 dst_ip4;
   __u32 dst_ip6[4];
   __u32 state;
+  __s32 rx_queue_mapping;
 };
 struct bpf_tcp_sock {
   __u32 snd_cwnd;
@@ -599,6 +677,21 @@
   __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;
+};
+struct bpf_cpumap_val {
+  __u32 qsize;
+  union {
+    int fd;
+    __u32 id;
+  } bpf_prog;
 };
 enum sk_action {
   SK_DROP = 0,
@@ -615,6 +708,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 +778,31 @@
   __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;
+    struct {
+      __u32 ifindex;
+    } xdp;
+  };
+} __attribute__((aligned(8)));
 struct bpf_sock_addr {
   __u32 user_family;
   __u32 user_ip4;
@@ -910,4 +1029,15 @@
   __u32 pid;
   __u32 tgid;
 };
+struct bpf_sk_lookup {
+  __bpf_md_ptr(struct bpf_sock *, sk);
+  __u32 family;
+  __u32 protocol;
+  __u32 remote_ip4;
+  __u32 remote_ip6[4];
+  __u32 remote_port;
+  __u32 local_ip4;
+  __u32 local_ip6[4];
+  __u32 local_port;
+};
 #endif
diff --git a/libc/kernel/uapi/linux/btrfs.h b/libc/kernel/uapi/linux/btrfs.h
index 45e5572..cfeef2a 100644
--- a/libc/kernel/uapi/linux/btrfs.h
+++ b/libc/kernel/uapi/linux/btrfs.h
@@ -156,6 +156,9 @@
   __u64 unused[379];
   __u8 path[BTRFS_DEVICE_PATH_NAME_MAX];
 };
+#define BTRFS_FS_INFO_FLAG_CSUM_INFO (1 << 0)
+#define BTRFS_FS_INFO_FLAG_GENERATION (1 << 1)
+#define BTRFS_FS_INFO_FLAG_METADATA_UUID (1 << 2)
 struct btrfs_ioctl_fs_info_args {
   __u64 max_id;
   __u64 num_devices;
@@ -163,8 +166,12 @@
   __u32 nodesize;
   __u32 sectorsize;
   __u32 clone_alignment;
-  __u32 reserved32;
-  __u64 reserved[122];
+  __u16 csum_type;
+  __u16 csum_size;
+  __u64 flags;
+  __u64 generation;
+  __u8 metadata_uuid[BTRFS_FSID_SIZE];
+  __u8 reserved[944];
 };
 #define BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE (1ULL << 0)
 #define BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE_VALID (1ULL << 1)
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..958e6ab 100644
--- a/libc/kernel/uapi/linux/capability.h
+++ b/libc/kernel/uapi/linux/capability.h
@@ -105,7 +105,10 @@
 #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_CHECKPOINT_RESTORE 40
+#define CAP_LAST_CAP CAP_CHECKPOINT_RESTORE
 #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/close_range.h b/libc/kernel/uapi/linux/close_range.h
new file mode 100644
index 0000000..de4135e
--- /dev/null
+++ b/libc/kernel/uapi/linux/close_range.h
@@ -0,0 +1,22 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   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_CLOSE_RANGE_H
+#define _UAPI_LINUX_CLOSE_RANGE_H
+#define CLOSE_RANGE_UNSHARE (1U << 1)
+#endif
diff --git a/libc/kernel/uapi/linux/coresight-stm.h b/libc/kernel/uapi/linux/coresight-stm.h
index 9d89dd6..86d80ca 100644
--- a/libc/kernel/uapi/linux/coresight-stm.h
+++ b/libc/kernel/uapi/linux/coresight-stm.h
@@ -20,6 +20,7 @@
 #define __UAPI_CORESIGHT_STM_H_
 #include <linux/const.h>
 #define STM_FLAG_TIMESTAMPED _BITUL(3)
+#define STM_FLAG_MARKED _BITUL(4)
 #define STM_FLAG_GUARANTEED _BITUL(7)
 enum {
   STM_OPTION_GUARANTEED = 0,
diff --git a/libc/kernel/uapi/linux/devlink.h b/libc/kernel/uapi/linux/devlink.h
index 18f7da5..9b4d104 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,
@@ -321,6 +323,10 @@
   DEVLINK_ATTR_TRAP_POLICER_ID,
   DEVLINK_ATTR_TRAP_POLICER_RATE,
   DEVLINK_ATTR_TRAP_POLICER_BURST,
+  DEVLINK_ATTR_PORT_FUNCTION,
+  DEVLINK_ATTR_INFO_BOARD_SERIAL_NUMBER,
+  DEVLINK_ATTR_PORT_LANES,
+  DEVLINK_ATTR_PORT_SPLITTABLE,
   __DEVLINK_ATTR_MAX,
   DEVLINK_ATTR_MAX = __DEVLINK_ATTR_MAX - 1
 };
@@ -351,4 +357,10 @@
 enum devlink_resource_unit {
   DEVLINK_RESOURCE_UNIT_ENTRY,
 };
+enum devlink_port_function_attr {
+  DEVLINK_PORT_FUNCTION_ATTR_UNSPEC,
+  DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR,
+  __DEVLINK_PORT_FUNCTION_ATTR_MAX,
+  DEVLINK_PORT_FUNCTION_ATTR_MAX = __DEVLINK_PORT_FUNCTION_ATTR_MAX - 1
+};
 #endif
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/elfcore.h b/libc/kernel/uapi/linux/elfcore.h
deleted file mode 100644
index a1df1ff..0000000
--- a/libc/kernel/uapi/linux/elfcore.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/****************************************************************************
- ****************************************************************************
- ***
- ***   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_ELFCORE_H
-#define _UAPI_LINUX_ELFCORE_H
-#include <linux/types.h>
-#include <linux/signal.h>
-#include <linux/time.h>
-#include <linux/ptrace.h>
-#include <linux/elf.h>
-#include <linux/fs.h>
-struct elf_siginfo {
-  int si_signo;
-  int si_code;
-  int si_errno;
-};
-typedef elf_greg_t greg_t;
-typedef elf_gregset_t gregset_t;
-typedef elf_fpregset_t fpregset_t;
-typedef elf_fpxregset_t fpxregset_t;
-#define NGREG ELF_NGREG
-struct elf_prstatus {
-  struct elf_siginfo pr_info;
-  short pr_cursig;
-  unsigned long pr_sigpend;
-  unsigned long pr_sighold;
-  pid_t pr_pid;
-  pid_t pr_ppid;
-  pid_t pr_pgrp;
-  pid_t pr_sid;
-  struct timeval pr_utime;
-  struct timeval pr_stime;
-  struct timeval pr_cutime;
-  struct timeval pr_cstime;
-  elf_gregset_t pr_reg;
-  int pr_fpvalid;
-};
-#define ELF_PRARGSZ (80)
-struct elf_prpsinfo {
-  char pr_state;
-  char pr_sname;
-  char pr_zomb;
-  char pr_nice;
-  unsigned long pr_flag;
-  __kernel_uid_t pr_uid;
-  __kernel_gid_t pr_gid;
-  pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid;
-  char pr_fname[16];
-  char pr_psargs[ELF_PRARGSZ];
-};
-typedef struct elf_prstatus prstatus_t;
-typedef struct elf_prpsinfo prpsinfo_t;
-#define PRARGSZ ELF_PRARGSZ
-#endif
diff --git a/libc/kernel/uapi/linux/errqueue.h b/libc/kernel/uapi/linux/errqueue.h
index 7959d2b..e93bad2 100644
--- a/libc/kernel/uapi/linux/errqueue.h
+++ b/libc/kernel/uapi/linux/errqueue.h
@@ -20,6 +20,11 @@
 #define _UAPI_LINUX_ERRQUEUE_H
 #include <linux/types.h>
 #include <linux/time_types.h>
+struct sock_ee_data_rfc4884 {
+  __u16 len;
+  __u8 flags;
+  __u8 reserved;
+};
 struct sock_extended_err {
   __u32 ee_errno;
   __u8 ee_origin;
@@ -27,7 +32,10 @@
   __u8 ee_code;
   __u8 ee_pad;
   __u32 ee_info;
-  __u32 ee_data;
+  union {
+    __u32 ee_data;
+    struct sock_ee_data_rfc4884 ee_rfc4884;
+  };
 };
 #define SO_EE_ORIGIN_NONE 0
 #define SO_EE_ORIGIN_LOCAL 1
@@ -41,6 +49,7 @@
 #define SO_EE_CODE_ZEROCOPY_COPIED 1
 #define SO_EE_CODE_TXTIME_INVALID_PARAM 1
 #define SO_EE_CODE_TXTIME_MISSED 2
+#define SO_EE_RFC4884_FLAG_INVALID 1
 struct scm_timestamping {
   struct timespec ts[3];
 };
diff --git a/libc/kernel/uapi/linux/ethtool.h b/libc/kernel/uapi/linux/ethtool.h
index 8733bca..3a2737a 100644
--- a/libc/kernel/uapi/linux/ethtool.h
+++ b/libc/kernel/uapi/linux/ethtool.h
@@ -196,6 +196,47 @@
   __u32 rx_pause;
   __u32 tx_pause;
 };
+enum ethtool_link_ext_state {
+  ETHTOOL_LINK_EXT_STATE_AUTONEG,
+  ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE,
+  ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH,
+  ETHTOOL_LINK_EXT_STATE_BAD_SIGNAL_INTEGRITY,
+  ETHTOOL_LINK_EXT_STATE_NO_CABLE,
+  ETHTOOL_LINK_EXT_STATE_CABLE_ISSUE,
+  ETHTOOL_LINK_EXT_STATE_EEPROM_ISSUE,
+  ETHTOOL_LINK_EXT_STATE_CALIBRATION_FAILURE,
+  ETHTOOL_LINK_EXT_STATE_POWER_BUDGET_EXCEEDED,
+  ETHTOOL_LINK_EXT_STATE_OVERHEAT,
+};
+enum ethtool_link_ext_substate_autoneg {
+  ETHTOOL_LINK_EXT_SUBSTATE_AN_NO_PARTNER_DETECTED = 1,
+  ETHTOOL_LINK_EXT_SUBSTATE_AN_ACK_NOT_RECEIVED,
+  ETHTOOL_LINK_EXT_SUBSTATE_AN_NEXT_PAGE_EXCHANGE_FAILED,
+  ETHTOOL_LINK_EXT_SUBSTATE_AN_NO_PARTNER_DETECTED_FORCE_MODE,
+  ETHTOOL_LINK_EXT_SUBSTATE_AN_FEC_MISMATCH_DURING_OVERRIDE,
+  ETHTOOL_LINK_EXT_SUBSTATE_AN_NO_HCD,
+};
+enum ethtool_link_ext_substate_link_training {
+  ETHTOOL_LINK_EXT_SUBSTATE_LT_KR_FRAME_LOCK_NOT_ACQUIRED = 1,
+  ETHTOOL_LINK_EXT_SUBSTATE_LT_KR_LINK_INHIBIT_TIMEOUT,
+  ETHTOOL_LINK_EXT_SUBSTATE_LT_KR_LINK_PARTNER_DID_NOT_SET_RECEIVER_READY,
+  ETHTOOL_LINK_EXT_SUBSTATE_LT_REMOTE_FAULT,
+};
+enum ethtool_link_ext_substate_link_logical_mismatch {
+  ETHTOOL_LINK_EXT_SUBSTATE_LLM_PCS_DID_NOT_ACQUIRE_BLOCK_LOCK = 1,
+  ETHTOOL_LINK_EXT_SUBSTATE_LLM_PCS_DID_NOT_ACQUIRE_AM_LOCK,
+  ETHTOOL_LINK_EXT_SUBSTATE_LLM_PCS_DID_NOT_GET_ALIGN_STATUS,
+  ETHTOOL_LINK_EXT_SUBSTATE_LLM_FC_FEC_IS_NOT_LOCKED,
+  ETHTOOL_LINK_EXT_SUBSTATE_LLM_RS_FEC_IS_NOT_LOCKED,
+};
+enum ethtool_link_ext_substate_bad_signal_integrity {
+  ETHTOOL_LINK_EXT_SUBSTATE_BSI_LARGE_NUMBER_OF_PHYSICAL_ERRORS = 1,
+  ETHTOOL_LINK_EXT_SUBSTATE_BSI_UNSUPPORTED_RATE,
+};
+enum ethtool_link_ext_substate_cable_issue {
+  ETHTOOL_LINK_EXT_SUBSTATE_CI_UNSUPPORTED_CABLE = 1,
+  ETHTOOL_LINK_EXT_SUBSTATE_CI_CABLE_TEST_FAILURE,
+};
 #define ETH_GSTRING_LEN 32
 enum ethtool_stringset {
   ETH_SS_TEST = 0,
@@ -213,6 +254,7 @@
   ETH_SS_SOF_TIMESTAMPING,
   ETH_SS_TS_TX_TYPES,
   ETH_SS_TS_RX_FILTERS,
+  ETH_SS_UDP_TUNNEL_TYPES,
   ETH_SS_COUNT
 };
 struct ethtool_gstrings {
@@ -625,6 +667,21 @@
   ETHTOOL_LINK_MODE_400000baseDR8_Full_BIT = 72,
   ETHTOOL_LINK_MODE_400000baseCR8_Full_BIT = 73,
   ETHTOOL_LINK_MODE_FEC_LLRS_BIT = 74,
+  ETHTOOL_LINK_MODE_100000baseKR_Full_BIT = 75,
+  ETHTOOL_LINK_MODE_100000baseSR_Full_BIT = 76,
+  ETHTOOL_LINK_MODE_100000baseLR_ER_FR_Full_BIT = 77,
+  ETHTOOL_LINK_MODE_100000baseCR_Full_BIT = 78,
+  ETHTOOL_LINK_MODE_100000baseDR_Full_BIT = 79,
+  ETHTOOL_LINK_MODE_200000baseKR2_Full_BIT = 80,
+  ETHTOOL_LINK_MODE_200000baseSR2_Full_BIT = 81,
+  ETHTOOL_LINK_MODE_200000baseLR2_ER2_FR2_Full_BIT = 82,
+  ETHTOOL_LINK_MODE_200000baseDR2_Full_BIT = 83,
+  ETHTOOL_LINK_MODE_200000baseCR2_Full_BIT = 84,
+  ETHTOOL_LINK_MODE_400000baseKR4_Full_BIT = 85,
+  ETHTOOL_LINK_MODE_400000baseSR4_Full_BIT = 86,
+  ETHTOOL_LINK_MODE_400000baseLR4_ER4_FR4_Full_BIT = 87,
+  ETHTOOL_LINK_MODE_400000baseDR4_Full_BIT = 88,
+  ETHTOOL_LINK_MODE_400000baseCR4_Full_BIT = 89,
   __ETHTOOL_LINK_MODE_MASK_NBITS
 };
 #define __ETHTOOL_LINK_MODE_LEGACY_MASK(base_name) (1UL << (ETHTOOL_LINK_MODE_ ##base_name ##_BIT))
@@ -709,6 +766,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 +876,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..da4fb46 100644
--- a/libc/kernel/uapi/linux/ethtool_netlink.h
+++ b/libc/kernel/uapi/linux/ethtool_netlink.h
@@ -46,6 +46,9 @@
   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_TUNNEL_INFO_GET,
   __ETHTOOL_MSG_USER_CNT,
   ETHTOOL_MSG_USER_MAX = __ETHTOOL_MSG_USER_CNT - 1
 };
@@ -77,6 +80,9 @@
   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_TUNNEL_INFO_GET_REPLY,
   __ETHTOOL_MSG_KERNEL_CNT,
   ETHTOOL_MSG_KERNEL_MAX = __ETHTOOL_MSG_KERNEL_CNT - 1
 };
@@ -169,6 +175,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 +184,10 @@
   ETHTOOL_A_LINKSTATE_UNSPEC,
   ETHTOOL_A_LINKSTATE_HEADER,
   ETHTOOL_A_LINKSTATE_LINK,
+  ETHTOOL_A_LINKSTATE_SQI,
+  ETHTOOL_A_LINKSTATE_SQI_MAX,
+  ETHTOOL_A_LINKSTATE_EXT_STATE,
+  ETHTOOL_A_LINKSTATE_EXT_SUBSTATE,
   __ETHTOOL_A_LINKSTATE_CNT,
   ETHTOOL_A_LINKSTATE_MAX = __ETHTOOL_A_LINKSTATE_CNT - 1
 };
@@ -298,6 +310,146 @@
   __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
+};
+enum {
+  ETHTOOL_UDP_TUNNEL_TYPE_VXLAN,
+  ETHTOOL_UDP_TUNNEL_TYPE_GENEVE,
+  ETHTOOL_UDP_TUNNEL_TYPE_VXLAN_GPE,
+  __ETHTOOL_UDP_TUNNEL_TYPE_CNT
+};
+enum {
+  ETHTOOL_A_TUNNEL_UDP_ENTRY_UNSPEC,
+  ETHTOOL_A_TUNNEL_UDP_ENTRY_PORT,
+  ETHTOOL_A_TUNNEL_UDP_ENTRY_TYPE,
+  __ETHTOOL_A_TUNNEL_UDP_ENTRY_CNT,
+  ETHTOOL_A_TUNNEL_UDP_ENTRY_MAX = (__ETHTOOL_A_TUNNEL_UDP_ENTRY_CNT - 1)
+};
+enum {
+  ETHTOOL_A_TUNNEL_UDP_TABLE_UNSPEC,
+  ETHTOOL_A_TUNNEL_UDP_TABLE_SIZE,
+  ETHTOOL_A_TUNNEL_UDP_TABLE_TYPES,
+  ETHTOOL_A_TUNNEL_UDP_TABLE_ENTRY,
+  __ETHTOOL_A_TUNNEL_UDP_TABLE_CNT,
+  ETHTOOL_A_TUNNEL_UDP_TABLE_MAX = (__ETHTOOL_A_TUNNEL_UDP_TABLE_CNT - 1)
+};
+enum {
+  ETHTOOL_A_TUNNEL_UDP_UNSPEC,
+  ETHTOOL_A_TUNNEL_UDP_TABLE,
+  __ETHTOOL_A_TUNNEL_UDP_CNT,
+  ETHTOOL_A_TUNNEL_UDP_MAX = (__ETHTOOL_A_TUNNEL_UDP_CNT - 1)
+};
+enum {
+  ETHTOOL_A_TUNNEL_INFO_UNSPEC,
+  ETHTOOL_A_TUNNEL_INFO_HEADER,
+  ETHTOOL_A_TUNNEL_INFO_UDP_PORTS,
+  __ETHTOOL_A_TUNNEL_INFO_CNT,
+  ETHTOOL_A_TUNNEL_INFO_MAX = (__ETHTOOL_A_TUNNEL_INFO_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/fanotify.h b/libc/kernel/uapi/linux/fanotify.h
index 8f9bea6..c63d058 100644
--- a/libc/kernel/uapi/linux/fanotify.h
+++ b/libc/kernel/uapi/linux/fanotify.h
@@ -36,7 +36,6 @@
 #define FAN_OPEN_PERM 0x00010000
 #define FAN_ACCESS_PERM 0x00020000
 #define FAN_OPEN_EXEC_PERM 0x00040000
-#define FAN_DIR_MODIFY 0x00080000
 #define FAN_EVENT_ON_CHILD 0x08000000
 #define FAN_ONDIR 0x40000000
 #define FAN_CLOSE (FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE)
@@ -52,6 +51,9 @@
 #define FAN_ENABLE_AUDIT 0x00000040
 #define FAN_REPORT_TID 0x00000100
 #define FAN_REPORT_FID 0x00000200
+#define FAN_REPORT_DIR_FID 0x00000400
+#define FAN_REPORT_NAME 0x00000800
+#define FAN_REPORT_DFID_NAME (FAN_REPORT_DIR_FID | FAN_REPORT_NAME)
 #define FAN_ALL_INIT_FLAGS (FAN_CLOEXEC | FAN_NONBLOCK | FAN_ALL_CLASS_BITS | FAN_UNLIMITED_QUEUE | FAN_UNLIMITED_MARKS)
 #define FAN_MARK_ADD 0x00000001
 #define FAN_MARK_REMOVE 0x00000002
@@ -79,6 +81,7 @@
 };
 #define FAN_EVENT_INFO_TYPE_FID 1
 #define FAN_EVENT_INFO_TYPE_DFID_NAME 2
+#define FAN_EVENT_INFO_TYPE_DFID 3
 struct fanotify_event_info_header {
   __u8 info_type;
   __u8 pad;
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/fpga-dfl.h b/libc/kernel/uapi/linux/fpga-dfl.h
index 8712e4c..54b93d0 100644
--- a/libc/kernel/uapi/linux/fpga-dfl.h
+++ b/libc/kernel/uapi/linux/fpga-dfl.h
@@ -63,6 +63,15 @@
   __u64 iova;
 };
 #define DFL_FPGA_PORT_DMA_UNMAP _IO(DFL_FPGA_MAGIC, DFL_PORT_BASE + 4)
+struct dfl_fpga_irq_set {
+  __u32 start;
+  __u32 count;
+  __s32 evtfds[];
+};
+#define DFL_FPGA_PORT_ERR_GET_IRQ_NUM _IOR(DFL_FPGA_MAGIC, DFL_PORT_BASE + 5, __u32)
+#define DFL_FPGA_PORT_ERR_SET_IRQ _IOW(DFL_FPGA_MAGIC, DFL_PORT_BASE + 6, struct dfl_fpga_irq_set)
+#define DFL_FPGA_PORT_UINT_GET_IRQ_NUM _IOR(DFL_FPGA_MAGIC, DFL_PORT_BASE + 7, __u32)
+#define DFL_FPGA_PORT_UINT_SET_IRQ _IOW(DFL_FPGA_MAGIC, DFL_PORT_BASE + 8, struct dfl_fpga_irq_set)
 struct dfl_fpga_fme_port_pr {
   __u32 argsz;
   __u32 flags;
@@ -73,4 +82,6 @@
 #define DFL_FPGA_FME_PORT_PR _IO(DFL_FPGA_MAGIC, DFL_FME_BASE + 0)
 #define DFL_FPGA_FME_PORT_RELEASE _IOW(DFL_FPGA_MAGIC, DFL_FME_BASE + 1, int)
 #define DFL_FPGA_FME_PORT_ASSIGN _IOW(DFL_FPGA_MAGIC, DFL_FME_BASE + 2, int)
+#define DFL_FPGA_FME_ERR_GET_IRQ_NUM _IOR(DFL_FPGA_MAGIC, DFL_FME_BASE + 3, __u32)
+#define DFL_FPGA_FME_ERR_SET_IRQ _IOW(DFL_FPGA_MAGIC, DFL_FME_BASE + 4, struct dfl_fpga_irq_set)
 #endif
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/icmp.h b/libc/kernel/uapi/linux/icmp.h
index 03aa087..5892d12 100644
--- a/libc/kernel/uapi/linux/icmp.h
+++ b/libc/kernel/uapi/linux/icmp.h
@@ -19,6 +19,7 @@
 #ifndef _UAPI_LINUX_ICMP_H
 #define _UAPI_LINUX_ICMP_H
 #include <linux/types.h>
+#include <asm/byteorder.h>
 #define ICMP_ECHOREPLY 0
 #define ICMP_DEST_UNREACH 3
 #define ICMP_SOURCE_QUENCH 4
@@ -77,4 +78,20 @@
 struct icmp_filter {
   __u32 data;
 };
+struct icmp_ext_hdr {
+#ifdef __LITTLE_ENDIAN_BITFIELD
+  __u8 reserved1 : 4, version : 4;
+#elif defined(__BIG_ENDIAN_BITFIELD)
+  __u8 version : 4, reserved1 : 4;
+#else
+#error "Please fix <asm/byteorder.h>"
+#endif
+  __u8 reserved2;
+  __sum16 checksum;
+};
+struct icmp_extobj_hdr {
+  __be16 length;
+  __u8 class_num;
+  __u8 class_type;
+};
 #endif
diff --git a/libc/kernel/uapi/linux/icmpv6.h b/libc/kernel/uapi/linux/icmpv6.h
index 798a945..38c30cf 100644
--- a/libc/kernel/uapi/linux/icmpv6.h
+++ b/libc/kernel/uapi/linux/icmpv6.h
@@ -59,6 +59,7 @@
 #define icmp6_mtu icmp6_dataun.un_data32[0]
 #define icmp6_unused icmp6_dataun.un_data32[0]
 #define icmp6_maxdelay icmp6_dataun.un_data16[0]
+#define icmp6_datagram_len icmp6_dataun.un_data8[0]
 #define icmp6_router icmp6_dataun.u_nd_advt.router
 #define icmp6_solicited icmp6_dataun.u_nd_advt.solicited
 #define icmp6_override icmp6_dataun.u_nd_advt.override
diff --git a/libc/kernel/uapi/linux/idxd.h b/libc/kernel/uapi/linux/idxd.h
index 9565ff7..74cdabd 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;
@@ -170,6 +172,10 @@
   uint32_t bytes_completed;
   uint64_t fault_addr;
   union {
+    struct {
+      uint32_t invalid_flags : 24;
+      uint32_t rsvd2 : 8;
+    };
     uint16_t delta_rec_size;
     uint16_t crc_val;
     struct {
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..aa12dea 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,147 @@
   __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_INFO,
+  IFLA_BRIDGE_MRP_IN_ROLE,
+  IFLA_BRIDGE_MRP_IN_STATE,
+  IFLA_BRIDGE_MRP_START_IN_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)
+enum {
+  IFLA_BRIDGE_MRP_INFO_UNSPEC,
+  IFLA_BRIDGE_MRP_INFO_RING_ID,
+  IFLA_BRIDGE_MRP_INFO_P_IFINDEX,
+  IFLA_BRIDGE_MRP_INFO_S_IFINDEX,
+  IFLA_BRIDGE_MRP_INFO_PRIO,
+  IFLA_BRIDGE_MRP_INFO_RING_STATE,
+  IFLA_BRIDGE_MRP_INFO_RING_ROLE,
+  IFLA_BRIDGE_MRP_INFO_TEST_INTERVAL,
+  IFLA_BRIDGE_MRP_INFO_TEST_MAX_MISS,
+  IFLA_BRIDGE_MRP_INFO_TEST_MONITOR,
+  IFLA_BRIDGE_MRP_INFO_I_IFINDEX,
+  IFLA_BRIDGE_MRP_INFO_IN_STATE,
+  IFLA_BRIDGE_MRP_INFO_IN_ROLE,
+  IFLA_BRIDGE_MRP_INFO_IN_TEST_INTERVAL,
+  IFLA_BRIDGE_MRP_INFO_IN_TEST_MAX_MISS,
+  __IFLA_BRIDGE_MRP_INFO_MAX,
+};
+#define IFLA_BRIDGE_MRP_INFO_MAX (__IFLA_BRIDGE_MRP_INFO_MAX - 1)
+enum {
+  IFLA_BRIDGE_MRP_IN_STATE_UNSPEC,
+  IFLA_BRIDGE_MRP_IN_STATE_IN_ID,
+  IFLA_BRIDGE_MRP_IN_STATE_STATE,
+  __IFLA_BRIDGE_MRP_IN_STATE_MAX,
+};
+#define IFLA_BRIDGE_MRP_IN_STATE_MAX (__IFLA_BRIDGE_MRP_IN_STATE_MAX - 1)
+enum {
+  IFLA_BRIDGE_MRP_IN_ROLE_UNSPEC,
+  IFLA_BRIDGE_MRP_IN_ROLE_RING_ID,
+  IFLA_BRIDGE_MRP_IN_ROLE_IN_ID,
+  IFLA_BRIDGE_MRP_IN_ROLE_ROLE,
+  IFLA_BRIDGE_MRP_IN_ROLE_I_IFINDEX,
+  __IFLA_BRIDGE_MRP_IN_ROLE_MAX,
+};
+#define IFLA_BRIDGE_MRP_IN_ROLE_MAX (__IFLA_BRIDGE_MRP_IN_ROLE_MAX - 1)
+enum {
+  IFLA_BRIDGE_MRP_START_IN_TEST_UNSPEC,
+  IFLA_BRIDGE_MRP_START_IN_TEST_IN_ID,
+  IFLA_BRIDGE_MRP_START_IN_TEST_INTERVAL,
+  IFLA_BRIDGE_MRP_START_IN_TEST_MAX_MISS,
+  IFLA_BRIDGE_MRP_START_IN_TEST_PERIOD,
+  __IFLA_BRIDGE_MRP_START_IN_TEST_MAX,
+};
+#define IFLA_BRIDGE_MRP_START_IN_TEST_MAX (__IFLA_BRIDGE_MRP_START_IN_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 br_mrp_in_state {
+  __u32 in_state;
+  __u16 in_id;
+};
+struct br_mrp_in_role {
+  __u32 ring_id;
+  __u32 in_role;
+  __u32 i_ifindex;
+  __u16 in_id;
+};
+struct br_mrp_start_in_test {
+  __u32 interval;
+  __u32 max_miss;
+  __u32 period;
+  __u16 in_id;
+};
 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..1b4683e 100644
--- a/libc/kernel/uapi/linux/if_link.h
+++ b/libc/kernel/uapi/linux/if_link.h
@@ -147,9 +147,17 @@
   IFLA_PROP_LIST,
   IFLA_ALT_IFNAME,
   IFLA_PERM_ADDRESS,
+  IFLA_PROTO_DOWN_REASON,
   __IFLA_MAX
 };
 #define IFLA_MAX (__IFLA_MAX - 1)
+enum {
+  IFLA_PROTO_DOWN_REASON_UNSPEC,
+  IFLA_PROTO_DOWN_REASON_MASK,
+  IFLA_PROTO_DOWN_REASON_VALUE,
+  __IFLA_PROTO_DOWN_REASON_CNT,
+  IFLA_PROTO_DOWN_REASON_MAX = __IFLA_PROTO_DOWN_REASON_CNT - 1
+};
 #define IFLA_RTA(r) ((struct rtattr *) (((char *) (r)) + NLMSG_ALIGN(sizeof(struct ifinfomsg))))
 #define IFLA_PAYLOAD(n) NLMSG_PAYLOAD(n, sizeof(struct ifinfomsg))
 enum {
@@ -272,6 +280,8 @@
   IFLA_BRPORT_NEIGH_SUPPRESS,
   IFLA_BRPORT_ISOLATED,
   IFLA_BRPORT_BACKUP_PORT,
+  IFLA_BRPORT_MRP_RING_OPEN,
+  IFLA_BRPORT_MRP_IN_OPEN,
   __IFLA_BRPORT_MAX
 };
 #define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1)
@@ -720,6 +730,11 @@
 };
 #define IFLA_IPOIB_MAX (__IFLA_IPOIB_MAX - 1)
 enum {
+  HSR_PROTOCOL_HSR,
+  HSR_PROTOCOL_PRP,
+  HSR_PROTOCOL_MAX,
+};
+enum {
   IFLA_HSR_UNSPEC,
   IFLA_HSR_SLAVE1,
   IFLA_HSR_SLAVE2,
@@ -727,6 +742,7 @@
   IFLA_HSR_SUPERVISION_ADDR,
   IFLA_HSR_SEQ_NR,
   IFLA_HSR_VERSION,
+  IFLA_HSR_PROTOCOL,
   __IFLA_HSR_MAX,
 };
 #define IFLA_HSR_MAX (__IFLA_HSR_MAX - 1)
diff --git a/libc/kernel/uapi/linux/if_xdp.h b/libc/kernel/uapi/linux/if_xdp.h
index 3615edb..d2b6bfd 100644
--- a/libc/kernel/uapi/linux/if_xdp.h
+++ b/libc/kernel/uapi/linux/if_xdp.h
@@ -63,6 +63,9 @@
   __u64 rx_dropped;
   __u64 rx_invalid_descs;
   __u64 tx_invalid_descs;
+  __u64 rx_ring_full;
+  __u64 rx_fill_ring_empty_descs;
+  __u64 tx_ring_empty_descs;
 };
 struct xdp_options {
   __u32 flags;
diff --git a/libc/kernel/uapi/linux/in.h b/libc/kernel/uapi/linux/in.h
index 99b54cc..e5437ca 100644
--- a/libc/kernel/uapi/linux/in.h
+++ b/libc/kernel/uapi/linux/in.h
@@ -112,6 +112,7 @@
 #define IP_CHECKSUM 23
 #define IP_BIND_ADDRESS_NO_PORT 24
 #define IP_RECVFRAGSIZE 25
+#define IP_RECVERR_RFC4884 26
 #define IP_PMTUDISC_DONT 0
 #define IP_PMTUDISC_WANT 1
 #define IP_PMTUDISC_DO 2
diff --git a/libc/kernel/uapi/linux/in6.h b/libc/kernel/uapi/linux/in6.h
index 2eb64d0..8dd3238 100644
--- a/libc/kernel/uapi/linux/in6.h
+++ b/libc/kernel/uapi/linux/in6.h
@@ -134,6 +134,7 @@
 #define IPV6_LEAVE_ANYCAST 28
 #define IPV6_MULTICAST_ALL 29
 #define IPV6_ROUTER_ALERT_ISOLATE 30
+#define IPV6_RECVERR_RFC4884 31
 #define IPV6_PMTUDISC_DONT 0
 #define IPV6_PMTUDISC_WANT 1
 #define IPV6_PMTUDISC_DO 2
diff --git a/libc/kernel/uapi/linux/incrementalfs.h b/libc/kernel/uapi/linux/incrementalfs.h
index cfaee52..3dea328 100644
--- a/libc/kernel/uapi/linux/incrementalfs.h
+++ b/libc/kernel/uapi/linux/incrementalfs.h
@@ -23,13 +23,14 @@
 #include <linux/types.h>
 #include <linux/xattr.h>
 #define INCFS_NAME "incremental-fs"
-#define INCFS_MAGIC_NUMBER (0x5346434e49ul)
+#define INCFS_MAGIC_NUMBER (unsigned long) (0x5346434e49ul)
 #define INCFS_DATA_FILE_BLOCK_SIZE 4096
 #define INCFS_HEADER_VER 1
 #define INCFS_MAX_HASH_SIZE 32
 #define INCFS_MAX_FILE_ATTR_SIZE 512
 #define INCFS_PENDING_READS_FILENAME ".pending_reads"
 #define INCFS_LOG_FILENAME ".log"
+#define INCFS_BLOCKS_WRITTEN_FILENAME ".blocks_written"
 #define INCFS_XATTR_ID_NAME (XATTR_USER_PREFIX "incfs.id")
 #define INCFS_XATTR_SIZE_NAME (XATTR_USER_PREFIX "incfs.size")
 #define INCFS_XATTR_METADATA_NAME (XATTR_USER_PREFIX "incfs.metadata")
@@ -42,6 +43,12 @@
 #define INCFS_IOC_FILL_BLOCKS _IOR(INCFS_IOCTL_BASE_CODE, 32, struct incfs_fill_blocks)
 #define INCFS_IOC_PERMIT_FILL _IOW(INCFS_IOCTL_BASE_CODE, 33, struct incfs_permit_fill)
 #define INCFS_IOC_GET_FILLED_BLOCKS _IOR(INCFS_IOCTL_BASE_CODE, 34, struct incfs_get_filled_blocks_args)
+#define INCFS_IOC_CREATE_MAPPED_FILE _IOWR(INCFS_IOCTL_BASE_CODE, 35, struct incfs_create_mapped_file_args)
+#define INCFS_IOC_GET_BLOCK_COUNT _IOR(INCFS_IOCTL_BASE_CODE, 36, struct incfs_get_block_count_args)
+#define INCFS_IOC_GET_READ_TIMEOUTS _IOR(INCFS_IOCTL_BASE_CODE, 37, struct incfs_get_read_timeouts_args)
+#define INCFS_IOC_SET_READ_TIMEOUTS _IOW(INCFS_IOCTL_BASE_CODE, 38, struct incfs_set_read_timeouts_args)
+#define INCFS_FEATURE_FLAG_COREFS "corefs"
+#define INCFS_FEATURE_FLAG_REPORT_UID "report_uid"
 enum incfs_compression_alg {
   COMPRESSION_NONE = 0,
   COMPRESSION_LZ4 = 1
@@ -59,6 +66,14 @@
   __u32 block_index;
   __u32 serial_number;
 };
+struct incfs_pending_read_info2 {
+  incfs_uuid_t file_id;
+  __aligned_u64 timestamp_us;
+  __u32 block_index;
+  __u32 serial_number;
+  __u32 uid;
+  __u32 reserved;
+};
 struct incfs_fill_block {
   __u32 block_index;
   __u32 data_len;
@@ -114,4 +129,35 @@
   __u32 range_buffer_size_out;
   __u32 index_out;
 };
+struct incfs_create_mapped_file_args {
+  __aligned_u64 size;
+  __u16 mode;
+  __u16 reserved1;
+  __u32 reserved2;
+  __aligned_u64 directory_path;
+  __aligned_u64 file_name;
+  incfs_uuid_t source_file_id;
+  __aligned_u64 source_offset;
+};
+struct incfs_get_block_count_args {
+  __u32 total_data_blocks_out;
+  __u32 filled_data_blocks_out;
+  __u32 total_hash_blocks_out;
+  __u32 filled_hash_blocks_out;
+};
+struct incfs_per_uid_read_timeouts {
+  __u32 uid;
+  __u32 min_time_ms;
+  __u32 min_pending_time_ms;
+  __u32 max_pending_time_ms;
+};
+struct incfs_get_read_timeouts_args {
+  __aligned_u64 timeouts_array;
+  __u32 timeouts_array_size;
+  __u32 timeouts_array_size_out;
+};
+struct incfs_set_read_timeouts_args {
+  __aligned_u64 timeouts_array;
+  __u32 timeouts_array_size;
+};
 #endif
diff --git a/libc/kernel/uapi/linux/inet_diag.h b/libc/kernel/uapi/linux/inet_diag.h
index fedbd85..350781c 100644
--- a/libc/kernel/uapi/linux/inet_diag.h
+++ b/libc/kernel/uapi/linux/inet_diag.h
@@ -60,6 +60,7 @@
   INET_DIAG_REQ_NONE,
   INET_DIAG_REQ_BYTECODE,
   INET_DIAG_REQ_SK_BPF_STORAGES,
+  INET_DIAG_REQ_PROTOCOL,
   __INET_DIAG_REQ_MAX,
 };
 #define INET_DIAG_REQ_MAX (__INET_DIAG_REQ_MAX - 1)
@@ -82,6 +83,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 +129,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..5d54090 100644
--- a/libc/kernel/uapi/linux/io_uring.h
+++ b/libc/kernel/uapi/linux/io_uring.h
@@ -38,6 +38,7 @@
     __kernel_rwf_t rw_flags;
     __u32 fsync_flags;
     __u16 poll_events;
+    __u32 poll32_events;
     __u32 sync_range_flags;
     __u32 msg_flags;
     __u32 timeout_flags;
@@ -115,6 +116,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 +146,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 +154,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 {
@@ -173,6 +179,7 @@
 #define IORING_FEAT_RW_CUR_POS (1U << 3)
 #define IORING_FEAT_CUR_PERSONALITY (1U << 4)
 #define IORING_FEAT_FAST_POLL (1U << 5)
+#define IORING_FEAT_POLL_32BITS (1U << 6)
 #define IORING_REGISTER_BUFFERS 0
 #define IORING_UNREGISTER_BUFFERS 1
 #define IORING_REGISTER_FILES 2
diff --git a/libc/kernel/uapi/linux/iommu.h b/libc/kernel/uapi/linux/iommu.h
index 54452c3..a3817b1 100644
--- a/libc/kernel/uapi/linux/iommu.h
+++ b/libc/kernel/uapi/linux/iommu.h
@@ -53,6 +53,7 @@
 #define IOMMU_FAULT_PAGE_REQUEST_PASID_VALID (1 << 0)
 #define IOMMU_FAULT_PAGE_REQUEST_LAST_PAGE (1 << 1)
 #define IOMMU_FAULT_PAGE_REQUEST_PRIV_DATA (1 << 2)
+#define IOMMU_FAULT_PAGE_RESPONSE_NEEDS_PASID (1 << 3)
   __u32 flags;
   __u32 pasid;
   __u32 grpid;
@@ -133,6 +134,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..85e6938 100644
--- a/libc/kernel/uapi/linux/kfd_ioctl.h
+++ b/libc/kernel/uapi/linux/kfd_ioctl.h
@@ -21,7 +21,7 @@
 #include <drm/drm.h>
 #include <linux/ioctl.h>
 #define KFD_IOCTL_MAJOR_VERSION 1
-#define KFD_IOCTL_MINOR_VERSION 1
+#define KFD_IOCTL_MINOR_VERSION 3
 struct kfd_ioctl_get_version_args {
   __u32 major_version;
   __u32 minor_version;
@@ -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;
@@ -281,6 +287,11 @@
   __u32 gpu_id;
   __u32 dmabuf_fd;
 };
+#define KFD_SMI_EVENT_VMFAULT 0x0000000000000001
+struct kfd_ioctl_smi_events_args {
+  __u32 gpuid;
+  __u32 anon_fd;
+};
 enum kfd_mmio_remap {
   KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL = 0,
   KFD_MMIO_REMAP_HDP_REG_FLUSH_CNTL = 4,
@@ -319,6 +330,8 @@
 #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_IOC_SMI_EVENTS AMDKFD_IOWR(0x1F, struct kfd_ioctl_smi_events_args)
 #define AMDKFD_COMMAND_START 0x01
-#define AMDKFD_COMMAND_END 0x1E
+#define AMDKFD_COMMAND_END 0x20
 #endif
diff --git a/libc/kernel/uapi/linux/kvm.h b/libc/kernel/uapi/linux/kvm.h
index ea6bca5..21fba77 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
@@ -207,6 +219,7 @@
     } hw;
     struct {
       __u64 hardware_entry_failure_reason;
+      __u32 cpu;
     } fail_entry;
     struct {
       __u32 exception;
@@ -583,8 +596,9 @@
 #define KVM_VM_S390_UCONTROL 1
 #define KVM_VM_PPC_HV 1
 #define KVM_VM_PPC_PR 2
-#define KVM_VM_MIPS_TE 0
+#define KVM_VM_MIPS_AUTO 0
 #define KVM_VM_MIPS_VZ 1
+#define KVM_VM_MIPS_TE 2
 #define KVM_S390_SIE_PAGE_OFFSET 1
 #define KVM_VM_TYPE_ARM_IPA_SIZE_MASK 0xffULL
 #define KVM_VM_TYPE_ARM_IPA_SIZE(x) ((x) & KVM_VM_TYPE_ARM_IPA_SIZE_MASK)
@@ -796,6 +810,12 @@
 #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
+#define KVM_CAP_LAST_CPU 184
+#define KVM_CAP_SMALLER_MAXPHYADDR 185
+#define KVM_CAP_S390_DIAG318 186
+#define KVM_CAP_STEAL_TIME 187
 #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/mdio.h b/libc/kernel/uapi/linux/mdio.h
index 3bbe433..a38cbfc 100644
--- a/libc/kernel/uapi/linux/mdio.h
+++ b/libc/kernel/uapi/linux/mdio.h
@@ -246,4 +246,28 @@
 #define MDIO_PHY_ID_PRTAD 0x03e0
 #define MDIO_PHY_ID_DEVAD 0x001f
 #define MDIO_PHY_ID_C45_MASK (MDIO_PHY_ID_C45 | MDIO_PHY_ID_PRTAD | MDIO_PHY_ID_DEVAD)
+#define MDIO_USXGMII_EEE_CLK_STP 0x0080
+#define MDIO_USXGMII_EEE 0x0100
+#define MDIO_USXGMII_SPD_MASK 0x0e00
+#define MDIO_USXGMII_FULL_DUPLEX 0x1000
+#define MDIO_USXGMII_DPX_SPD_MASK 0x1e00
+#define MDIO_USXGMII_10 0x0000
+#define MDIO_USXGMII_10HALF 0x0000
+#define MDIO_USXGMII_10FULL 0x1000
+#define MDIO_USXGMII_100 0x0200
+#define MDIO_USXGMII_100HALF 0x0200
+#define MDIO_USXGMII_100FULL 0x1200
+#define MDIO_USXGMII_1000 0x0400
+#define MDIO_USXGMII_1000HALF 0x0400
+#define MDIO_USXGMII_1000FULL 0x1400
+#define MDIO_USXGMII_10G 0x0600
+#define MDIO_USXGMII_10GHALF 0x0600
+#define MDIO_USXGMII_10GFULL 0x1600
+#define MDIO_USXGMII_2500 0x0800
+#define MDIO_USXGMII_2500HALF 0x0800
+#define MDIO_USXGMII_2500FULL 0x1800
+#define MDIO_USXGMII_5000 0x0a00
+#define MDIO_USXGMII_5000HALF 0x0a00
+#define MDIO_USXGMII_5000FULL 0x1a00
+#define MDIO_USXGMII_LINK 0x8000
 #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/mptcp.h b/libc/kernel/uapi/linux/mptcp.h
index 43702f3..deaa1bf 100644
--- a/libc/kernel/uapi/linux/mptcp.h
+++ b/libc/kernel/uapi/linux/mptcp.h
@@ -81,4 +81,19 @@
   MPTCP_PM_CMD_GET_LIMITS,
   __MPTCP_PM_CMD_AFTER_LAST
 };
+#define MPTCP_INFO_FLAG_FALLBACK _BITUL(0)
+#define MPTCP_INFO_FLAG_REMOTE_KEY_RECEIVED _BITUL(1)
+struct mptcp_info {
+  __u8 mptcpi_subflows;
+  __u8 mptcpi_add_addr_signal;
+  __u8 mptcpi_add_addr_accepted;
+  __u8 mptcpi_subflows_max;
+  __u8 mptcpi_add_addr_signal_max;
+  __u8 mptcpi_add_addr_accepted_max;
+  __u32 mptcpi_flags;
+  __u32 mptcpi_token;
+  __u64 mptcpi_write_seq;
+  __u64 mptcpi_snd_una;
+  __u64 mptcpi_rcv_nxt;
+};
 #endif
diff --git a/libc/kernel/uapi/linux/mrp_bridge.h b/libc/kernel/uapi/linux/mrp_bridge.h
new file mode 100644
index 0000000..ea4a7e3
--- /dev/null
+++ b/libc/kernel/uapi/linux/mrp_bridge.h
@@ -0,0 +1,150 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   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_in_role_type {
+  BR_MRP_IN_ROLE_DISABLED,
+  BR_MRP_IN_ROLE_MIC,
+  BR_MRP_IN_ROLE_MIM,
+};
+enum br_mrp_ring_state_type {
+  BR_MRP_RING_STATE_OPEN,
+  BR_MRP_RING_STATE_CLOSED,
+};
+enum br_mrp_in_state_type {
+  BR_MRP_IN_STATE_OPEN,
+  BR_MRP_IN_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,
+  BR_MRP_PORT_ROLE_INTER,
+};
+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_IN_TEST = 0x6,
+  BR_MRP_TLV_HEADER_IN_TOPO = 0x7,
+  BR_MRP_TLV_HEADER_IN_LINK_DOWN = 0x8,
+  BR_MRP_TLV_HEADER_IN_LINK_UP = 0x9,
+  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];
+};
+struct br_mrp_in_test_hdr {
+  __be16 id;
+  __u8 sa[ETH_ALEN];
+  __be16 port_role;
+  __be16 state;
+  __be16 transitions;
+  __be32 timestamp;
+};
+struct br_mrp_in_topo_hdr {
+  __u8 sa[ETH_ALEN];
+  __be16 id;
+  __be16 interval;
+};
+struct br_mrp_in_link_hdr {
+  __u8 sa[ETH_ALEN];
+  __be16 port_role;
+  __be16 id;
+  __be16 interval;
+};
+#endif
diff --git a/libc/kernel/uapi/linux/ndctl.h b/libc/kernel/uapi/linux/ndctl.h
index e47091f..53f8ba4 100644
--- a/libc/kernel/uapi/linux/ndctl.h
+++ b/libc/kernel/uapi/linux/ndctl.h
@@ -158,5 +158,10 @@
 #define NVDIMM_FAMILY_HPE2 2
 #define NVDIMM_FAMILY_MSFT 3
 #define NVDIMM_FAMILY_HYPERV 4
+#define NVDIMM_FAMILY_PAPR 5
+#define NVDIMM_FAMILY_MAX NVDIMM_FAMILY_PAPR
+#define NVDIMM_BUS_FAMILY_NFIT 0
+#define NVDIMM_BUS_FAMILY_INTEL 1
+#define NVDIMM_BUS_FAMILY_MAX NVDIMM_BUS_FAMILY_INTEL
 #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..e0e84aa 100644
--- a/libc/kernel/uapi/linux/neighbour.h
+++ b/libc/kernel/uapi/linux/neighbour.h
@@ -43,6 +43,8 @@
   NDA_LINK_NETNSID,
   NDA_SRC_VNI,
   NDA_PROTOCOL,
+  NDA_NH_ID,
+  NDA_FDB_EXT_ATTRS,
   __NDA_MAX
 };
 #define NDA_MAX (__NDA_MAX - 1)
@@ -135,4 +137,15 @@
   __NDTA_MAX
 };
 #define NDTA_MAX (__NDTA_MAX - 1)
+enum {
+  FDB_NOTIFY_BIT = (1 << 0),
+  FDB_NOTIFY_INACTIVE_BIT = (1 << 1)
+};
+enum {
+  NFEA_UNSPEC,
+  NFEA_ACTIVITY_NOTIFY,
+  NFEA_DONT_REFRESH,
+  __NFEA_MAX
+};
+#define NFEA_MAX (__NFEA_MAX - 1)
 #endif
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/nf_tables.h b/libc/kernel/uapi/linux/netfilter/nf_tables.h
index 6d3ec0a..abb35d2 100644
--- a/libc/kernel/uapi/linux/netfilter/nf_tables.h
+++ b/libc/kernel/uapi/linux/netfilter/nf_tables.h
@@ -89,7 +89,7 @@
   NFT_MSG_MAX,
 };
 enum nft_list_attributes {
-  NFTA_LIST_UNPEC,
+  NFTA_LIST_UNSPEC,
   NFTA_LIST_ELEM,
   __NFTA_LIST_MAX
 };
@@ -116,6 +116,12 @@
   __NFTA_TABLE_MAX
 };
 #define NFTA_TABLE_MAX (__NFTA_TABLE_MAX - 1)
+enum nft_chain_flags {
+  NFT_CHAIN_BASE = (1 << 0),
+  NFT_CHAIN_HW_OFFLOAD = (1 << 1),
+  NFT_CHAIN_BINDING = (1 << 2),
+};
+#define NFT_CHAIN_FLAGS (NFT_CHAIN_BASE | NFT_CHAIN_HW_OFFLOAD | NFT_CHAIN_BINDING)
 enum nft_chain_attributes {
   NFTA_CHAIN_UNSPEC,
   NFTA_CHAIN_TABLE,
@@ -128,6 +134,7 @@
   NFTA_CHAIN_COUNTERS,
   NFTA_CHAIN_PAD,
   NFTA_CHAIN_FLAGS,
+  NFTA_CHAIN_ID,
   __NFTA_CHAIN_MAX
 };
 #define NFTA_CHAIN_MAX (__NFTA_CHAIN_MAX - 1)
@@ -143,6 +150,7 @@
   NFTA_RULE_PAD,
   NFTA_RULE_ID,
   NFTA_RULE_POSITION_ID,
+  NFTA_RULE_CHAIN_ID,
   __NFTA_RULE_MAX
 };
 #define NFTA_RULE_MAX (__NFTA_RULE_MAX - 1)
@@ -250,6 +258,7 @@
   NFTA_VERDICT_UNSPEC,
   NFTA_VERDICT_CODE,
   NFTA_VERDICT_CHAIN,
+  NFTA_VERDICT_CHAIN_ID,
   __NFTA_VERDICT_MAX
 };
 #define NFTA_VERDICT_MAX (__NFTA_VERDICT_MAX - 1)
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/nfs4.h b/libc/kernel/uapi/linux/nfs4.h
index e6118a6..bc3e002 100644
--- a/libc/kernel/uapi/linux/nfs4.h
+++ b/libc/kernel/uapi/linux/nfs4.h
@@ -35,6 +35,9 @@
 #define NFS4_ACCESS_EXTEND 0x0008
 #define NFS4_ACCESS_DELETE 0x0010
 #define NFS4_ACCESS_EXECUTE 0x0020
+#define NFS4_ACCESS_XAREAD 0x0040
+#define NFS4_ACCESS_XAWRITE 0x0080
+#define NFS4_ACCESS_XALIST 0x0100
 #define NFS4_FH_PERSISTENT 0x0000
 #define NFS4_FH_NOEXPIRE_WITH_OPEN 0x0001
 #define NFS4_FH_VOLATILE_ANY 0x0002
diff --git a/libc/kernel/uapi/linux/nfs_fs.h b/libc/kernel/uapi/linux/nfs_fs.h
index 8ff9305..f8228ec 100644
--- a/libc/kernel/uapi/linux/nfs_fs.h
+++ b/libc/kernel/uapi/linux/nfs_fs.h
@@ -49,5 +49,6 @@
 #define NFSDBG_PNFS 0x1000
 #define NFSDBG_PNFS_LD 0x2000
 #define NFSDBG_STATE 0x4000
+#define NFSDBG_XATTRCACHE 0x8000
 #define NFSDBG_ALL 0xFFFF
 #endif
diff --git a/libc/kernel/uapi/linux/nl80211.h b/libc/kernel/uapi/linux/nl80211.h
index 7f8b45f..e794bec 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
@@ -654,6 +661,7 @@
   NL80211_STA_INFO_AIRTIME_WEIGHT,
   NL80211_STA_INFO_AIRTIME_LINK_METRIC,
   NL80211_STA_INFO_ASSOC_AT_BOOTTIME,
+  NL80211_STA_INFO_CONNECTED_TO_AS,
   __NL80211_STA_INFO_AFTER_LAST,
   NL80211_STA_INFO_MAX = __NL80211_STA_INFO_AFTER_LAST - 1
 };
@@ -713,6 +721,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 +772,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
 };
@@ -920,6 +930,8 @@
   NL80211_MESHCONF_AWAKE_WINDOW,
   NL80211_MESHCONF_PLINK_TIMEOUT,
   NL80211_MESHCONF_CONNECTED_TO_GATE,
+  NL80211_MESHCONF_NOLEARN,
+  NL80211_MESHCONF_CONNECTED_TO_AS,
   __NL80211_MESHCONF_ATTR_AFTER_LAST,
   NL80211_MESHCONF_ATTR_MAX = __NL80211_MESHCONF_ATTR_AFTER_LAST - 1
 };
@@ -978,11 +990,18 @@
   NL80211_CHAN_WIDTH_160,
   NL80211_CHAN_WIDTH_5,
   NL80211_CHAN_WIDTH_10,
+  NL80211_CHAN_WIDTH_1,
+  NL80211_CHAN_WIDTH_2,
+  NL80211_CHAN_WIDTH_4,
+  NL80211_CHAN_WIDTH_8,
+  NL80211_CHAN_WIDTH_16,
 };
 enum nl80211_bss_scan_width {
   NL80211_BSS_CHAN_WIDTH_20,
   NL80211_BSS_CHAN_WIDTH_10,
   NL80211_BSS_CHAN_WIDTH_5,
+  NL80211_BSS_CHAN_WIDTH_1,
+  NL80211_BSS_CHAN_WIDTH_2,
 };
 enum nl80211_bss {
   __NL80211_BSS_INVALID,
@@ -1005,6 +1024,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
 };
@@ -1087,6 +1107,7 @@
   NL80211_BAND_5GHZ,
   NL80211_BAND_60GHZ,
   NL80211_BAND_6GHZ,
+  NL80211_BAND_S1GHZ,
   NUM_NL80211_BANDS,
 };
 enum nl80211_ps_state {
@@ -1121,6 +1142,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 +1159,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 +1291,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 +1410,12 @@
   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,
+  NL80211_EXT_FEATURE_OPERATING_CHANNEL_VALIDATION,
+  NL80211_EXT_FEATURE_4WAY_HANDSHAKE_AP_PSK,
   NUM_NL80211_EXT_FEATURES,
   MAX_NL80211_EXT_FEATURES = NUM_NL80211_EXT_FEATURES - 1
 };
@@ -1411,6 +1449,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/openvswitch.h b/libc/kernel/uapi/linux/openvswitch.h
index 5dba4e6..b043dd8 100644
--- a/libc/kernel/uapi/linux/openvswitch.h
+++ b/libc/kernel/uapi/linux/openvswitch.h
@@ -42,6 +42,7 @@
   OVS_DP_ATTR_MEGAFLOW_STATS,
   OVS_DP_ATTR_USER_FEATURES,
   OVS_DP_ATTR_PAD,
+  OVS_DP_ATTR_MASKS_CACHE_SIZE,
   __OVS_DP_ATTR_MAX
 };
 #define OVS_DP_ATTR_MAX (__OVS_DP_ATTR_MAX - 1)
@@ -55,8 +56,8 @@
   __u64 n_mask_hit;
   __u32 n_masks;
   __u32 pad0;
+  __u64 n_cache_hit;
   __u64 pad1;
-  __u64 pad2;
 };
 struct ovs_vport_stats {
   __u64 rx_packets;
diff --git a/libc/kernel/uapi/linux/perf_event.h b/libc/kernel/uapi/linux/perf_event.h
index b996adb..8349f61 100644
--- a/libc/kernel/uapi/linux/perf_event.h
+++ b/libc/kernel/uapi/linux/perf_event.h
@@ -203,7 +203,7 @@
   };
   __u64 sample_type;
   __u64 read_format;
-  __u64 disabled : 1, inherit : 1, pinned : 1, exclusive : 1, exclude_user : 1, exclude_kernel : 1, exclude_hv : 1, exclude_idle : 1, mmap : 1, comm : 1, freq : 1, inherit_stat : 1, enable_on_exec : 1, task : 1, watermark : 1, precise_ip : 2, mmap_data : 1, sample_id_all : 1, exclude_host : 1, exclude_guest : 1, exclude_callchain_kernel : 1, exclude_callchain_user : 1, mmap2 : 1, comm_exec : 1, use_clockid : 1, context_switch : 1, write_backward : 1, namespaces : 1, ksymbol : 1, bpf_event : 1, aux_output : 1, cgroup : 1, __reserved_1 : 31;
+  __u64 disabled : 1, inherit : 1, pinned : 1, exclusive : 1, exclude_user : 1, exclude_kernel : 1, exclude_hv : 1, exclude_idle : 1, mmap : 1, comm : 1, freq : 1, inherit_stat : 1, enable_on_exec : 1, task : 1, watermark : 1, precise_ip : 2, mmap_data : 1, sample_id_all : 1, exclude_host : 1, exclude_guest : 1, exclude_callchain_kernel : 1, exclude_callchain_user : 1, mmap2 : 1, comm_exec : 1, use_clockid : 1, context_switch : 1, write_backward : 1, namespaces : 1, ksymbol : 1, bpf_event : 1, aux_output : 1, cgroup : 1, text_poke : 1, __reserved_1 : 30;
   union {
     __u32 wakeup_events;
     __u32 wakeup_watermark;
@@ -263,7 +263,7 @@
   union {
     __u64 capabilities;
     struct {
-      __u64 cap_bit0 : 1, cap_bit0_is_deprecated : 1, cap_user_rdpmc : 1, cap_user_time : 1, cap_user_time_zero : 1, cap_____res : 59;
+      __u64 cap_bit0 : 1, cap_bit0_is_deprecated : 1, cap_user_rdpmc : 1, cap_user_time : 1, cap_user_time_zero : 1, cap_user_time_short : 1, cap_____res : 58;
     };
   };
   __u16 pmc_width;
@@ -272,7 +272,10 @@
   __u64 time_offset;
   __u64 time_zero;
   __u32 size;
-  __u8 __reserved[118 * 8 + 4];
+  __u32 __reserved_1;
+  __u64 time_cycles;
+  __u64 time_mask;
+  __u8 __reserved[116 * 8];
   __u64 data_head;
   __u64 data_tail;
   __u64 data_offset;
@@ -336,11 +339,13 @@
   PERF_RECORD_KSYMBOL = 17,
   PERF_RECORD_BPF_EVENT = 18,
   PERF_RECORD_CGROUP = 19,
+  PERF_RECORD_TEXT_POKE = 20,
   PERF_RECORD_MAX,
 };
 enum perf_record_ksymbol_type {
   PERF_RECORD_KSYMBOL_TYPE_UNKNOWN = 0,
   PERF_RECORD_KSYMBOL_TYPE_BPF = 1,
+  PERF_RECORD_KSYMBOL_TYPE_OOL = 2,
   PERF_RECORD_KSYMBOL_TYPE_MAX
 };
 #define PERF_RECORD_KSYMBOL_FLAGS_UNREGISTER (1 << 0)
diff --git a/libc/kernel/uapi/linux/pkt_cls.h b/libc/kernel/uapi/linux/pkt_cls.h
index d77d46e..62c2274 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,9 @@
   TCA_FLOWER_KEY_CT_MARK_MASK,
   TCA_FLOWER_KEY_CT_LABELS,
   TCA_FLOWER_KEY_CT_LABELS_MASK,
+  TCA_FLOWER_KEY_MPLS_OPTS,
+  TCA_FLOWER_KEY_HASH,
+  TCA_FLOWER_KEY_HASH_MASK,
   __TCA_FLOWER_MAX,
 };
 #define TCA_FLOWER_MAX (__TCA_FLOWER_MAX - 1)
@@ -491,6 +495,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..7c16d3c 100644
--- a/libc/kernel/uapi/linux/pkt_sched.h
+++ b/libc/kernel/uapi/linux/pkt_sched.h
@@ -168,6 +168,8 @@
   TCA_RED_STAB,
   TCA_RED_MAX_P,
   TCA_RED_FLAGS,
+  TCA_RED_EARLY_DROP_BLOCK,
+  TCA_RED_MARK_BLOCK,
   __TCA_RED_MAX,
 };
 #define TCA_RED_MAX (__TCA_RED_MAX - 1)
@@ -669,6 +671,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 +690,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..ca6f3c3 100644
--- a/libc/kernel/uapi/linux/ptp_clock.h
+++ b/libc/kernel/uapi/linux/ptp_clock.h
@@ -28,7 +28,9 @@
 #define PTP_EXTTS_VALID_FLAGS (PTP_ENABLE_FEATURE | PTP_RISING_EDGE | PTP_FALLING_EDGE | PTP_STRICT_FLAGS)
 #define PTP_EXTTS_V1_VALID_FLAGS (PTP_ENABLE_FEATURE | PTP_RISING_EDGE | PTP_FALLING_EDGE)
 #define PTP_PEROUT_ONE_SHOT (1 << 0)
-#define PTP_PEROUT_VALID_FLAGS (PTP_PEROUT_ONE_SHOT)
+#define PTP_PEROUT_DUTY_CYCLE (1 << 1)
+#define PTP_PEROUT_PHASE (1 << 2)
+#define PTP_PEROUT_VALID_FLAGS (PTP_PEROUT_ONE_SHOT | PTP_PEROUT_DUTY_CYCLE | PTP_PEROUT_PHASE)
 #define PTP_PEROUT_V1_VALID_FLAGS (0)
 struct ptp_clock_time {
   __s64 sec;
@@ -43,7 +45,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;
@@ -51,11 +54,17 @@
   unsigned int rsv[2];
 };
 struct ptp_perout_request {
-  struct ptp_clock_time start;
+  union {
+    struct ptp_clock_time start;
+    struct ptp_clock_time phase;
+  };
   struct ptp_clock_time period;
   unsigned int index;
   unsigned int flags;
-  unsigned int rsv[4];
+  union {
+    struct ptp_clock_time on;
+    unsigned int rsv[4];
+  };
 };
 #define PTP_MAX_SAMPLES 25
 struct ptp_sys_offset {
diff --git a/libc/kernel/uapi/linux/raw.h b/libc/kernel/uapi/linux/raw.h
index 86aea2b..bb45c3d 100644
--- a/libc/kernel/uapi/linux/raw.h
+++ b/libc/kernel/uapi/linux/raw.h
@@ -26,5 +26,4 @@
   __u64 block_major;
   __u64 block_minor;
 };
-#define MAX_RAW_MINORS CONFIG_MAX_RAW_DEVS
 #endif
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/remoteproc_cdev.h b/libc/kernel/uapi/linux/remoteproc_cdev.h
new file mode 100644
index 0000000..a10ff01
--- /dev/null
+++ b/libc/kernel/uapi/linux/remoteproc_cdev.h
@@ -0,0 +1,26 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   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_REMOTEPROC_CDEV_H_
+#define _UAPI_REMOTEPROC_CDEV_H_
+#include <linux/ioctl.h>
+#include <linux/types.h>
+#define RPROC_MAGIC 0xB7
+#define RPROC_SET_SHUTDOWN_ON_RELEASE _IOW(RPROC_MAGIC, 1, __s32)
+#define RPROC_GET_SHUTDOWN_ON_RELEASE _IOR(RPROC_MAGIC, 2, __s32)
+#endif
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..6f50bb5 100644
--- a/libc/kernel/uapi/linux/rtnetlink.h
+++ b/libc/kernel/uapi/linux/rtnetlink.h
@@ -217,6 +217,7 @@
 #define RTPROT_NTK 15
 #define RTPROT_DHCP 16
 #define RTPROT_MROUTED 17
+#define RTPROT_KEEPALIVED 18
 #define RTPROT_BABEL 42
 #define RTPROT_BGP 186
 #define RTPROT_ISIS 187
@@ -444,9 +445,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 {
@@ -573,4 +576,5 @@
 #define RTEXT_FILTER_BRVLAN (1 << 1)
 #define RTEXT_FILTER_BRVLAN_COMPRESSED (1 << 2)
 #define RTEXT_FILTER_SKIP_STATS (1 << 3)
+#define RTEXT_FILTER_MRP (1 << 4)
 #endif
diff --git a/libc/kernel/uapi/linux/rxrpc.h b/libc/kernel/uapi/linux/rxrpc.h
index 1690111..16207dd 100644
--- a/libc/kernel/uapi/linux/rxrpc.h
+++ b/libc/kernel/uapi/linux/rxrpc.h
@@ -46,11 +46,11 @@
   RXRPC_BUSY = 6,
   RXRPC_LOCAL_ERROR = 7,
   RXRPC_NEW_CALL = 8,
-  RXRPC_ACCEPT = 9,
   RXRPC_EXCLUSIVE_CALL = 10,
   RXRPC_UPGRADE_SERVICE = 11,
   RXRPC_TX_LENGTH = 12,
   RXRPC_SET_CALL_TIMEOUT = 13,
+  RXRPC_CHARGE_ACCEPT = 14,
   RXRPC__SUPPORTED
 };
 #define RXRPC_SECURITY_PLAIN 0
diff --git a/libc/kernel/uapi/linux/seccomp.h b/libc/kernel/uapi/linux/seccomp.h
index d535f50..0ae0e12 100644
--- a/libc/kernel/uapi/linux/seccomp.h
+++ b/libc/kernel/uapi/linux/seccomp.h
@@ -68,6 +68,14 @@
   __s32 error;
   __u32 flags;
 };
+#define SECCOMP_ADDFD_FLAG_SETFD (1UL << 0)
+struct seccomp_notif_addfd {
+  __u64 id;
+  __u32 flags;
+  __u32 srcfd;
+  __u32 newfd;
+  __u32 newfd_flags;
+};
 #define SECCOMP_IOC_MAGIC '!'
 #define SECCOMP_IO(nr) _IO(SECCOMP_IOC_MAGIC, nr)
 #define SECCOMP_IOR(nr,type) _IOR(SECCOMP_IOC_MAGIC, nr, type)
@@ -75,5 +83,6 @@
 #define SECCOMP_IOWR(nr,type) _IOWR(SECCOMP_IOC_MAGIC, nr, type)
 #define SECCOMP_IOCTL_NOTIF_RECV SECCOMP_IOWR(0, struct seccomp_notif)
 #define SECCOMP_IOCTL_NOTIF_SEND SECCOMP_IOWR(1, struct seccomp_notif_resp)
-#define SECCOMP_IOCTL_NOTIF_ID_VALID SECCOMP_IOR(2, __u64)
+#define SECCOMP_IOCTL_NOTIF_ID_VALID SECCOMP_IOW(2, __u64)
+#define SECCOMP_IOCTL_NOTIF_ADDFD SECCOMP_IOW(3, struct seccomp_notif_addfd)
 #endif
diff --git a/libc/kernel/uapi/linux/serial_core.h b/libc/kernel/uapi/linux/serial_core.h
index 37dfc16..b2c3253 100644
--- a/libc/kernel/uapi/linux/serial_core.h
+++ b/libc/kernel/uapi/linux/serial_core.h
@@ -19,20 +19,6 @@
 #ifndef _UAPILINUX_SERIAL_CORE_H
 #define _UAPILINUX_SERIAL_CORE_H
 #include <linux/serial.h>
-#define PORT_UNKNOWN 0
-#define PORT_8250 1
-#define PORT_16450 2
-#define PORT_16550 3
-#define PORT_16550A 4
-#define PORT_CIRRUS 5
-#define PORT_16650 6
-#define PORT_16650V2 7
-#define PORT_16750 8
-#define PORT_STARTECH 9
-#define PORT_16C950 10
-#define PORT_16654 11
-#define PORT_16850 12
-#define PORT_RSA 13
 #define PORT_NS16550A 14
 #define PORT_XSCALE 15
 #define PORT_RM9000 16
diff --git a/libc/kernel/uapi/linux/snmp.h b/libc/kernel/uapi/linux/snmp.h
index c114544..8d63a3c 100644
--- a/libc/kernel/uapi/linux/snmp.h
+++ b/libc/kernel/uapi/linux/snmp.h
@@ -254,6 +254,8 @@
   LINUX_MIB_TCPFASTOPENPASSIVEALTKEY,
   LINUX_MIB_TCPTIMEOUTREHASH,
   LINUX_MIB_TCPDUPLICATEDATAREHASH,
+  LINUX_MIB_TCPDSACKRECVSEGS,
+  LINUX_MIB_TCPDSACKIGNOREDDUBIOUS,
   __LINUX_MIB_MAX
 };
 enum {
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/target_core_user.h b/libc/kernel/uapi/linux/target_core_user.h
index 7c997d1..e0b9f22 100644
--- a/libc/kernel/uapi/linux/target_core_user.h
+++ b/libc/kernel/uapi/linux/target_core_user.h
@@ -25,6 +25,7 @@
 #define ALIGN_SIZE 64
 #define TCMU_MAILBOX_FLAG_CAP_OOOC (1 << 0)
 #define TCMU_MAILBOX_FLAG_CAP_READ_LEN (1 << 1)
+#define TCMU_MAILBOX_FLAG_CAP_TMR (1 << 2)
 struct tcmu_mailbox {
   __u16 version;
   __u16 flags;
@@ -36,6 +37,7 @@
 enum tcmu_opcode {
   TCMU_OP_PAD = 0,
   TCMU_OP_CMD,
+  TCMU_OP_TMR,
 };
 struct tcmu_cmd_entry_hdr {
   __u32 len_op;
@@ -68,6 +70,25 @@
     } rsp;
   };
 } __packed;
+struct tcmu_tmr_entry {
+  struct tcmu_cmd_entry_hdr hdr;
+#define TCMU_TMR_UNKNOWN 0
+#define TCMU_TMR_ABORT_TASK 1
+#define TCMU_TMR_ABORT_TASK_SET 2
+#define TCMU_TMR_CLEAR_ACA 3
+#define TCMU_TMR_CLEAR_TASK_SET 4
+#define TCMU_TMR_LUN_RESET 5
+#define TCMU_TMR_TARGET_WARM_RESET 6
+#define TCMU_TMR_TARGET_COLD_RESET 7
+#define TCMU_TMR_LUN_RESET_PRO 128
+  __u8 tmr_type;
+  __u8 __pad1;
+  __u16 __pad2;
+  __u32 cmd_cnt;
+  __u64 __pad3;
+  __u64 __pad4;
+  __u16 cmd_ids[0];
+} __packed;
 #define TCMU_OP_ALIGN_SIZE sizeof(__u64)
 enum tcmu_genl_cmd {
   TCMU_CMD_UNSPEC,
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/tcp.h b/libc/kernel/uapi/linux/tcp.h
index e38e462..e05e3ad 100644
--- a/libc/kernel/uapi/linux/tcp.h
+++ b/libc/kernel/uapi/linux/tcp.h
@@ -219,6 +219,7 @@
   TCP_NLA_SRTT,
   TCP_NLA_TIMEOUT_REHASH,
   TCP_NLA_BYTES_NOTSENT,
+  TCP_NLA_EDT,
 };
 #define TCP_MD5SIG_MAXKEYLEN 80
 #define TCP_MD5SIG_FLAG_PREFIX 0x1
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/thermal.h b/libc/kernel/uapi/linux/thermal.h
index c78f17e..72ea378 100644
--- a/libc/kernel/uapi/linux/thermal.h
+++ b/libc/kernel/uapi/linux/thermal.h
@@ -19,24 +19,75 @@
 #ifndef _UAPI_LINUX_THERMAL_H
 #define _UAPI_LINUX_THERMAL_H
 #define THERMAL_NAME_LENGTH 20
-#define THERMAL_GENL_FAMILY_NAME "thermal_event"
-#define THERMAL_GENL_VERSION 0x01
-#define THERMAL_GENL_MCAST_GROUP_NAME "thermal_mc_grp"
-enum events {
-  THERMAL_AUX0,
-  THERMAL_AUX1,
-  THERMAL_CRITICAL,
-  THERMAL_DEV_FAULT,
+enum thermal_device_mode {
+  THERMAL_DEVICE_DISABLED = 0,
+  THERMAL_DEVICE_ENABLED,
 };
-enum {
+enum thermal_trip_type {
+  THERMAL_TRIP_ACTIVE = 0,
+  THERMAL_TRIP_PASSIVE,
+  THERMAL_TRIP_HOT,
+  THERMAL_TRIP_CRITICAL,
+};
+#define THERMAL_GENL_FAMILY_NAME "thermal"
+#define THERMAL_GENL_VERSION 0x01
+#define THERMAL_GENL_SAMPLING_GROUP_NAME "sampling"
+#define THERMAL_GENL_EVENT_GROUP_NAME "event"
+enum thermal_genl_attr {
   THERMAL_GENL_ATTR_UNSPEC,
-  THERMAL_GENL_ATTR_EVENT,
+  THERMAL_GENL_ATTR_TZ,
+  THERMAL_GENL_ATTR_TZ_ID,
+  THERMAL_GENL_ATTR_TZ_TEMP,
+  THERMAL_GENL_ATTR_TZ_TRIP,
+  THERMAL_GENL_ATTR_TZ_TRIP_ID,
+  THERMAL_GENL_ATTR_TZ_TRIP_TYPE,
+  THERMAL_GENL_ATTR_TZ_TRIP_TEMP,
+  THERMAL_GENL_ATTR_TZ_TRIP_HYST,
+  THERMAL_GENL_ATTR_TZ_MODE,
+  THERMAL_GENL_ATTR_TZ_NAME,
+  THERMAL_GENL_ATTR_TZ_CDEV_WEIGHT,
+  THERMAL_GENL_ATTR_TZ_GOV,
+  THERMAL_GENL_ATTR_TZ_GOV_NAME,
+  THERMAL_GENL_ATTR_CDEV,
+  THERMAL_GENL_ATTR_CDEV_ID,
+  THERMAL_GENL_ATTR_CDEV_CUR_STATE,
+  THERMAL_GENL_ATTR_CDEV_MAX_STATE,
+  THERMAL_GENL_ATTR_CDEV_NAME,
+  THERMAL_GENL_ATTR_GOV_NAME,
   __THERMAL_GENL_ATTR_MAX,
 };
 #define THERMAL_GENL_ATTR_MAX (__THERMAL_GENL_ATTR_MAX - 1)
-enum {
+enum thermal_genl_sampling {
+  THERMAL_GENL_SAMPLING_TEMP,
+  __THERMAL_GENL_SAMPLING_MAX,
+};
+#define THERMAL_GENL_SAMPLING_MAX (__THERMAL_GENL_SAMPLING_MAX - 1)
+enum thermal_genl_event {
+  THERMAL_GENL_EVENT_UNSPEC,
+  THERMAL_GENL_EVENT_TZ_CREATE,
+  THERMAL_GENL_EVENT_TZ_DELETE,
+  THERMAL_GENL_EVENT_TZ_DISABLE,
+  THERMAL_GENL_EVENT_TZ_ENABLE,
+  THERMAL_GENL_EVENT_TZ_TRIP_UP,
+  THERMAL_GENL_EVENT_TZ_TRIP_DOWN,
+  THERMAL_GENL_EVENT_TZ_TRIP_CHANGE,
+  THERMAL_GENL_EVENT_TZ_TRIP_ADD,
+  THERMAL_GENL_EVENT_TZ_TRIP_DELETE,
+  THERMAL_GENL_EVENT_CDEV_ADD,
+  THERMAL_GENL_EVENT_CDEV_DELETE,
+  THERMAL_GENL_EVENT_CDEV_STATE_UPDATE,
+  THERMAL_GENL_EVENT_TZ_GOV_CHANGE,
+  __THERMAL_GENL_EVENT_MAX,
+};
+#define THERMAL_GENL_EVENT_MAX (__THERMAL_GENL_EVENT_MAX - 1)
+enum thermal_genl_cmd {
   THERMAL_GENL_CMD_UNSPEC,
-  THERMAL_GENL_CMD_EVENT,
+  THERMAL_GENL_CMD_TZ_GET_ID,
+  THERMAL_GENL_CMD_TZ_GET_TRIP,
+  THERMAL_GENL_CMD_TZ_GET_TEMP,
+  THERMAL_GENL_CMD_TZ_GET_GOV,
+  THERMAL_GENL_CMD_TZ_GET_MODE,
+  THERMAL_GENL_CMD_CDEV_GET,
   __THERMAL_GENL_CMD_MAX,
 };
 #define THERMAL_GENL_CMD_MAX (__THERMAL_GENL_CMD_MAX - 1)
diff --git a/libc/kernel/uapi/linux/usb/ch9.h b/libc/kernel/uapi/linux/usb/ch9.h
index 2d69abd..43d2f4b 100644
--- a/libc/kernel/uapi/linux/usb/ch9.h
+++ b/libc/kernel/uapi/linux/usb/ch9.h
@@ -74,11 +74,11 @@
 #define USB_DEVICE_A_HNP_SUPPORT 4
 #define USB_DEVICE_A_ALT_HNP_SUPPORT 5
 #define USB_DEVICE_DEBUG_MODE 6
-#define TEST_J 1
-#define TEST_K 2
-#define TEST_SE0_NAK 3
-#define TEST_PACKET 4
-#define TEST_FORCE_EN 5
+#define USB_TEST_J 1
+#define USB_TEST_K 2
+#define USB_TEST_SE0_NAK 3
+#define USB_TEST_PACKET 4
+#define USB_TEST_FORCE_ENABLE 5
 #define USB_STATUS_TYPE_STANDARD 0
 #define USB_STATUS_TYPE_PTM 1
 #define USB_DEVICE_U1_ENABLE 48
@@ -176,6 +176,10 @@
 #define USB_CLASS_CONTENT_SEC 0x0d
 #define USB_CLASS_VIDEO 0x0e
 #define USB_CLASS_WIRELESS_CONTROLLER 0xe0
+#define USB_CLASS_PERSONAL_HEALTHCARE 0x0f
+#define USB_CLASS_AUDIO_VIDEO 0x10
+#define USB_CLASS_BILLBOARD 0x11
+#define USB_CLASS_USB_TYPE_C_BRIDGE 0x12
 #define USB_CLASS_MISC 0xef
 #define USB_CLASS_APP_SPEC 0xfe
 #define USB_CLASS_VENDOR_SPEC 0xff
@@ -195,6 +199,7 @@
 #define USB_CONFIG_ATT_SELFPOWER (1 << 6)
 #define USB_CONFIG_ATT_WAKEUP (1 << 5)
 #define USB_CONFIG_ATT_BATTERY (1 << 4)
+#define USB_MAX_STRING_LEN 126
 struct usb_string_descriptor {
   __u8 bLength;
   __u8 bDescriptorType;
diff --git a/libc/kernel/uapi/linux/v4l2-controls.h b/libc/kernel/uapi/linux/v4l2-controls.h
index e38620d..7f965a3 100644
--- a/libc/kernel/uapi/linux/v4l2-controls.h
+++ b/libc/kernel/uapi/linux/v4l2-controls.h
@@ -278,6 +278,7 @@
 enum v4l2_mpeg_video_bitrate_mode {
   V4L2_MPEG_VIDEO_BITRATE_MODE_VBR = 0,
   V4L2_MPEG_VIDEO_BITRATE_MODE_CBR = 1,
+  V4L2_MPEG_VIDEO_BITRATE_MODE_CQ = 2,
 };
 #define V4L2_CID_MPEG_VIDEO_BITRATE (V4L2_CID_MPEG_BASE + 207)
 #define V4L2_CID_MPEG_VIDEO_BITRATE_PEAK (V4L2_CID_MPEG_BASE + 208)
@@ -537,6 +538,23 @@
   V4L2_MPEG_VIDEO_VP9_PROFILE_2 = 2,
   V4L2_MPEG_VIDEO_VP9_PROFILE_3 = 3,
 };
+#define V4L2_CID_MPEG_VIDEO_VP9_LEVEL (V4L2_CID_MPEG_BASE + 513)
+enum v4l2_mpeg_video_vp9_level {
+  V4L2_MPEG_VIDEO_VP9_LEVEL_1_0 = 0,
+  V4L2_MPEG_VIDEO_VP9_LEVEL_1_1 = 1,
+  V4L2_MPEG_VIDEO_VP9_LEVEL_2_0 = 2,
+  V4L2_MPEG_VIDEO_VP9_LEVEL_2_1 = 3,
+  V4L2_MPEG_VIDEO_VP9_LEVEL_3_0 = 4,
+  V4L2_MPEG_VIDEO_VP9_LEVEL_3_1 = 5,
+  V4L2_MPEG_VIDEO_VP9_LEVEL_4_0 = 6,
+  V4L2_MPEG_VIDEO_VP9_LEVEL_4_1 = 7,
+  V4L2_MPEG_VIDEO_VP9_LEVEL_5_0 = 8,
+  V4L2_MPEG_VIDEO_VP9_LEVEL_5_1 = 9,
+  V4L2_MPEG_VIDEO_VP9_LEVEL_5_2 = 10,
+  V4L2_MPEG_VIDEO_VP9_LEVEL_6_0 = 11,
+  V4L2_MPEG_VIDEO_VP9_LEVEL_6_1 = 12,
+  V4L2_MPEG_VIDEO_VP9_LEVEL_6_2 = 13,
+};
 #define V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP (V4L2_CID_MPEG_BASE + 600)
 #define V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP (V4L2_CID_MPEG_BASE + 601)
 #define V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP (V4L2_CID_MPEG_BASE + 602)
@@ -626,6 +644,13 @@
 #define V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L6_BR (V4L2_CID_MPEG_BASE + 642)
 #define V4L2_CID_MPEG_VIDEO_REF_NUMBER_FOR_PFRAMES (V4L2_CID_MPEG_BASE + 643)
 #define V4L2_CID_MPEG_VIDEO_PREPEND_SPSPPS_TO_IDR (V4L2_CID_MPEG_BASE + 644)
+#define V4L2_CID_MPEG_VIDEO_CONSTANT_QUALITY (V4L2_CID_MPEG_BASE + 645)
+#define V4L2_CID_MPEG_VIDEO_FRAME_SKIP_MODE (V4L2_CID_MPEG_BASE + 646)
+enum v4l2_mpeg_video_frame_skip_mode {
+  V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_DISABLED = 0,
+  V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT = 1,
+  V4L2_MPEG_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT = 2,
+};
 #define V4L2_CID_MPEG_CX2341X_BASE (V4L2_CTRL_CLASS_MPEG | 0x1000)
 #define V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE (V4L2_CID_MPEG_CX2341X_BASE + 0)
 enum v4l2_mpeg_cx2341x_video_spatial_filter_mode {
@@ -781,6 +806,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/vbox_vmmdev_types.h b/libc/kernel/uapi/linux/vbox_vmmdev_types.h
index 3b27029..009f9a6 100644
--- a/libc/kernel/uapi/linux/vbox_vmmdev_types.h
+++ b/libc/kernel/uapi/linux/vbox_vmmdev_types.h
@@ -48,6 +48,7 @@
   VMMDEVREQ_SET_GUEST_CAPABILITIES = 56,
   VMMDEVREQ_VIDEMODE_SUPPORTED2 = 57,
   VMMDEVREQ_GET_DISPLAY_CHANGE_REQEX = 80,
+  VMMDEVREQ_GET_DISPLAY_CHANGE_REQ_MULTI = 81,
   VMMDEVREQ_HGCM_CONNECT = 60,
   VMMDEVREQ_HGCM_DISCONNECT = 61,
   VMMDEVREQ_HGCM_CALL32 = 62,
@@ -77,6 +78,8 @@
   VMMDEVREQ_WRITE_COREDUMP = 218,
   VMMDEVREQ_GUEST_HEARTBEAT = 219,
   VMMDEVREQ_HEARTBEAT_CONFIGURE = 220,
+  VMMDEVREQ_NT_BUG_CHECK = 221,
+  VMMDEVREQ_VIDEO_UPDATE_MONITOR_POSITIONS = 222,
   VMMDEVREQ_SIZEHACK = 0x7fffffff
 };
 #if __BITS_PER_LONG == 64
diff --git a/libc/kernel/uapi/linux/vboxguest.h b/libc/kernel/uapi/linux/vboxguest.h
index 2eb80ef..342c020 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 {
@@ -124,6 +124,19 @@
   } u;
 };
 #define VBG_IOCTL_CHANGE_FILTER_MASK _IOWR('V', 12, struct vbg_ioctl_change_filter)
+struct vbg_ioctl_acquire_guest_caps {
+  struct vbg_ioctl_hdr hdr;
+  union {
+    struct {
+      __u32 flags;
+      __u32 or_mask;
+      __u32 not_mask;
+    } in;
+  } u;
+};
+#define VBGL_IOC_AGC_FLAGS_CONFIG_ACQUIRE_MODE 0x00000001
+#define VBGL_IOC_AGC_FLAGS_VALID_MASK 0x00000001
+#define VBG_IOCTL_ACQUIRE_GUEST_CAPABILITIES _IOWR('V', 13, struct vbg_ioctl_acquire_guest_caps)
 struct vbg_ioctl_set_guest_caps {
   struct vbg_ioctl_hdr hdr;
   union {
diff --git a/libc/kernel/uapi/linux/version.h b/libc/kernel/uapi/linux/version.h
index 5da4041..54d59c2 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 329984
 #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..a844ec8 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)
@@ -43,6 +44,7 @@
 #define VHOST_SET_VRING_BUSYLOOP_TIMEOUT _IOW(VHOST_VIRTIO, 0x23, struct vhost_vring_state)
 #define VHOST_GET_VRING_BUSYLOOP_TIMEOUT _IOW(VHOST_VIRTIO, 0x24, struct vhost_vring_state)
 #define VHOST_BACKEND_F_IOTLB_MSG_V2 0x1
+#define VHOST_BACKEND_F_IOTLB_BATCH 0x2
 #define VHOST_SET_BACKEND_FEATURES _IOW(VHOST_VIRTIO, 0x25, __u64)
 #define VHOST_GET_BACKEND_FEATURES _IOR(VHOST_VIRTIO, 0x26, __u64)
 #define VHOST_NET_SET_BACKEND _IOW(VHOST_VIRTIO, 0x30, struct vhost_vring_file)
@@ -60,4 +62,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/vhost_types.h b/libc/kernel/uapi/linux/vhost_types.h
index 1288cf6..8c0e487 100644
--- a/libc/kernel/uapi/linux/vhost_types.h
+++ b/libc/kernel/uapi/linux/vhost_types.h
@@ -51,6 +51,8 @@
 #define VHOST_IOTLB_UPDATE 2
 #define VHOST_IOTLB_INVALIDATE 3
 #define VHOST_IOTLB_ACCESS_FAIL 4
+#define VHOST_IOTLB_BATCH_BEGIN 5
+#define VHOST_IOTLB_BATCH_END 6
   __u8 type;
 };
 #define VHOST_IOTLB_MSG 0x1
diff --git a/libc/kernel/uapi/linux/videodev2.h b/libc/kernel/uapi/linux/videodev2.h
index 1209fb7..da57468 100644
--- a/libc/kernel/uapi/linux/videodev2.h
+++ b/libc/kernel/uapi/linux/videodev2.h
@@ -65,6 +65,7 @@
 };
 #define V4L2_TYPE_IS_MULTIPLANAR(type) ((type) == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE || (type) == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
 #define V4L2_TYPE_IS_OUTPUT(type) ((type) == V4L2_BUF_TYPE_VIDEO_OUTPUT || (type) == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE || (type) == V4L2_BUF_TYPE_VIDEO_OVERLAY || (type) == V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY || (type) == V4L2_BUF_TYPE_VBI_OUTPUT || (type) == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT || (type) == V4L2_BUF_TYPE_SDR_OUTPUT || (type) == V4L2_BUF_TYPE_META_OUTPUT)
+#define V4L2_TYPE_IS_CAPTURE(type) (! V4L2_TYPE_IS_OUTPUT(type))
 enum v4l2_tuner_type {
   V4L2_TUNER_RADIO = 1,
   V4L2_TUNER_ANALOG_TV = 2,
@@ -188,6 +189,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,12 +422,14 @@
   __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
 #define V4L2_FMT_FLAG_CONTINUOUS_BYTESTREAM 0x0004
 #define V4L2_FMT_FLAG_DYN_RESOLUTION 0x0008
+#define V4L2_FMT_FLAG_ENC_CAP_FRAME_INTERVAL 0x0010
 enum v4l2_frmsizetypes {
   V4L2_FRMSIZE_TYPE_DISCRETE = 1,
   V4L2_FRMSIZE_TYPE_CONTINUOUS = 2,
@@ -521,6 +525,7 @@
 #define V4L2_BUF_CAP_SUPPORTS_REQUESTS (1 << 3)
 #define V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS (1 << 4)
 #define V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF (1 << 5)
+#define V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS (1 << 6)
 struct v4l2_plane {
   __u32 bytesused;
   __u32 length;
diff --git a/libc/kernel/uapi/linux/virtio_9p.h b/libc/kernel/uapi/linux/virtio_9p.h
index f593353..1d9dfb1 100644
--- a/libc/kernel/uapi/linux/virtio_9p.h
+++ b/libc/kernel/uapi/linux/virtio_9p.h
@@ -18,12 +18,12 @@
  ****************************************************************************/
 #ifndef _LINUX_VIRTIO_9P_H
 #define _LINUX_VIRTIO_9P_H
-#include <linux/types.h>
+#include <linux/virtio_types.h>
 #include <linux/virtio_ids.h>
 #include <linux/virtio_config.h>
 #define VIRTIO_9P_MOUNT_TAG 0
 struct virtio_9p_config {
-  __u16 tag_len;
+  __virtio16 tag_len;
   __u8 tag[0];
 } __attribute__((packed));
 #endif
diff --git a/libc/kernel/uapi/linux/virtio_balloon.h b/libc/kernel/uapi/linux/virtio_balloon.h
index 80affd8..d145caa 100644
--- a/libc/kernel/uapi/linux/virtio_balloon.h
+++ b/libc/kernel/uapi/linux/virtio_balloon.h
@@ -32,13 +32,13 @@
 #define VIRTIO_BALLOON_CMD_ID_STOP 0
 #define VIRTIO_BALLOON_CMD_ID_DONE 1
 struct virtio_balloon_config {
-  __u32 num_pages;
-  __u32 actual;
+  __le32 num_pages;
+  __le32 actual;
   union {
-    __u32 free_page_hint_cmd_id;
-    __u32 free_page_report_cmd_id;
+    __le32 free_page_hint_cmd_id;
+    __le32 free_page_report_cmd_id;
   };
-  __u32 poison_val;
+  __le32 poison_val;
 };
 #define VIRTIO_BALLOON_S_SWAP_IN 0
 #define VIRTIO_BALLOON_S_SWAP_OUT 1
diff --git a/libc/kernel/uapi/linux/virtio_blk.h b/libc/kernel/uapi/linux/virtio_blk.h
index 5197434..f2f0381 100644
--- a/libc/kernel/uapi/linux/virtio_blk.h
+++ b/libc/kernel/uapi/linux/virtio_blk.h
@@ -40,27 +40,27 @@
 #endif
 #define VIRTIO_BLK_ID_BYTES 20
 struct virtio_blk_config {
-  __u64 capacity;
-  __u32 size_max;
-  __u32 seg_max;
+  __virtio64 capacity;
+  __virtio32 size_max;
+  __virtio32 seg_max;
   struct virtio_blk_geometry {
-    __u16 cylinders;
+    __virtio16 cylinders;
     __u8 heads;
     __u8 sectors;
   } geometry;
-  __u32 blk_size;
+  __virtio32 blk_size;
   __u8 physical_block_exp;
   __u8 alignment_offset;
-  __u16 min_io_size;
-  __u32 opt_io_size;
+  __virtio16 min_io_size;
+  __virtio32 opt_io_size;
   __u8 wce;
   __u8 unused;
-  __u16 num_queues;
-  __u32 max_discard_sectors;
-  __u32 max_discard_seg;
-  __u32 discard_sector_alignment;
-  __u32 max_write_zeroes_sectors;
-  __u32 max_write_zeroes_seg;
+  __virtio16 num_queues;
+  __virtio32 max_discard_sectors;
+  __virtio32 max_discard_seg;
+  __virtio32 discard_sector_alignment;
+  __virtio32 max_write_zeroes_sectors;
+  __virtio32 max_write_zeroes_seg;
   __u8 write_zeroes_may_unmap;
   __u8 unused1[3];
 } __attribute__((packed));
diff --git a/libc/kernel/uapi/linux/virtio_config.h b/libc/kernel/uapi/linux/virtio_config.h
index c9ec83f..6198fd1 100644
--- a/libc/kernel/uapi/linux/virtio_config.h
+++ b/libc/kernel/uapi/linux/virtio_config.h
@@ -32,7 +32,8 @@
 #define VIRTIO_F_ANY_LAYOUT 27
 #endif
 #define VIRTIO_F_VERSION_1 32
-#define VIRTIO_F_IOMMU_PLATFORM 33
+#define VIRTIO_F_ACCESS_PLATFORM 33
+#define VIRTIO_F_IOMMU_PLATFORM VIRTIO_F_ACCESS_PLATFORM
 #define VIRTIO_F_RING_PACKED 34
 #define VIRTIO_F_ORDER_PLATFORM 36
 #define VIRTIO_F_SR_IOV 37
diff --git a/libc/kernel/uapi/linux/virtio_console.h b/libc/kernel/uapi/linux/virtio_console.h
index bf9888a..6eb4d2a 100644
--- a/libc/kernel/uapi/linux/virtio_console.h
+++ b/libc/kernel/uapi/linux/virtio_console.h
@@ -27,10 +27,10 @@
 #define VIRTIO_CONSOLE_F_EMERG_WRITE 2
 #define VIRTIO_CONSOLE_BAD_ID (~(__u32) 0)
 struct virtio_console_config {
-  __u16 cols;
-  __u16 rows;
-  __u32 max_nr_ports;
-  __u32 emerg_wr;
+  __virtio16 cols;
+  __virtio16 rows;
+  __virtio32 max_nr_ports;
+  __virtio32 emerg_wr;
 } __attribute__((packed));
 struct virtio_console_control {
   __virtio32 id;
diff --git a/libc/kernel/uapi/linux/virtio_crypto.h b/libc/kernel/uapi/linux/virtio_crypto.h
index 03727dc..2ce760f 100644
--- a/libc/kernel/uapi/linux/virtio_crypto.h
+++ b/libc/kernel/uapi/linux/virtio_crypto.h
@@ -273,19 +273,19 @@
 #define VIRTIO_CRYPTO_INVSESS 4
 #define VIRTIO_CRYPTO_S_HW_READY (1 << 0)
 struct virtio_crypto_config {
-  __u32 status;
-  __u32 max_dataqueues;
-  __u32 crypto_services;
-  __u32 cipher_algo_l;
-  __u32 cipher_algo_h;
-  __u32 hash_algo;
-  __u32 mac_algo_l;
-  __u32 mac_algo_h;
-  __u32 aead_algo;
-  __u32 max_cipher_key_len;
-  __u32 max_auth_key_len;
-  __u32 reserve;
-  __u64 max_size;
+  __le32 status;
+  __le32 max_dataqueues;
+  __le32 crypto_services;
+  __le32 cipher_algo_l;
+  __le32 cipher_algo_h;
+  __le32 hash_algo;
+  __le32 mac_algo_l;
+  __le32 mac_algo_h;
+  __le32 aead_algo;
+  __le32 max_cipher_key_len;
+  __le32 max_auth_key_len;
+  __le32 reserve;
+  __le64 max_size;
 };
 struct virtio_crypto_inhdr {
   __u8 status;
diff --git a/libc/kernel/uapi/linux/virtio_fs.h b/libc/kernel/uapi/linux/virtio_fs.h
index 41946e7..b64965f 100644
--- a/libc/kernel/uapi/linux/virtio_fs.h
+++ b/libc/kernel/uapi/linux/virtio_fs.h
@@ -24,6 +24,6 @@
 #include <linux/virtio_types.h>
 struct virtio_fs_config {
   __u8 tag[36];
-  __u32 num_request_queues;
+  __le32 num_request_queues;
 } __attribute__((packed));
 #endif
diff --git a/libc/kernel/uapi/linux/virtio_gpu.h b/libc/kernel/uapi/linux/virtio_gpu.h
index 0ac7495..b320280 100644
--- a/libc/kernel/uapi/linux/virtio_gpu.h
+++ b/libc/kernel/uapi/linux/virtio_gpu.h
@@ -223,10 +223,10 @@
 };
 #define VIRTIO_GPU_EVENT_DISPLAY (1 << 0)
 struct virtio_gpu_config {
-  __u32 events_read;
-  __u32 events_clear;
-  __u32 num_scanouts;
-  __u32 num_capsets;
+  __le32 events_read;
+  __le32 events_clear;
+  __le32 num_scanouts;
+  __le32 num_capsets;
 };
 enum virtio_gpu_formats {
   VIRTIO_GPU_FORMAT_B8G8R8A8_UNORM = 1,
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_input.h b/libc/kernel/uapi/linux/virtio_input.h
index e1fc3e5..188b0bb 100644
--- a/libc/kernel/uapi/linux/virtio_input.h
+++ b/libc/kernel/uapi/linux/virtio_input.h
@@ -29,17 +29,17 @@
   VIRTIO_INPUT_CFG_ABS_INFO = 0x12,
 };
 struct virtio_input_absinfo {
-  __u32 min;
-  __u32 max;
-  __u32 fuzz;
-  __u32 flat;
-  __u32 res;
+  __le32 min;
+  __le32 max;
+  __le32 fuzz;
+  __le32 flat;
+  __le32 res;
 };
 struct virtio_input_devids {
-  __u16 bustype;
-  __u16 vendor;
-  __u16 product;
-  __u16 version;
+  __le16 bustype;
+  __le16 vendor;
+  __le16 product;
+  __le16 version;
 };
 struct virtio_input_config {
   __u8 select;
diff --git a/libc/kernel/uapi/linux/virtio_iommu.h b/libc/kernel/uapi/linux/virtio_iommu.h
index b156ea3..b08de57 100644
--- a/libc/kernel/uapi/linux/virtio_iommu.h
+++ b/libc/kernel/uapi/linux/virtio_iommu.h
@@ -26,18 +26,18 @@
 #define VIRTIO_IOMMU_F_PROBE 4
 #define VIRTIO_IOMMU_F_MMIO 5
 struct virtio_iommu_range_64 {
-  __u64 start;
-  __u64 end;
+  __le64 start;
+  __le64 end;
 };
 struct virtio_iommu_range_32 {
-  __u32 start;
-  __u32 end;
+  __le32 start;
+  __le32 end;
 };
 struct virtio_iommu_config {
-  __u64 page_size_mask;
+  __le64 page_size_mask;
   struct virtio_iommu_range_64 input_range;
   struct virtio_iommu_range_32 domain_range;
-  __u32 probe_size;
+  __le32 probe_size;
 };
 #define VIRTIO_IOMMU_T_ATTACH 0x01
 #define VIRTIO_IOMMU_T_DETACH 0x02
diff --git a/libc/kernel/uapi/linux/virtio_mem.h b/libc/kernel/uapi/linux/virtio_mem.h
new file mode 100644
index 0000000..d6542b7
--- /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 {
+  __le64 block_size;
+  __le16 node_id;
+  __u8 padding[6];
+  __le64 addr;
+  __le64 region_size;
+  __le64 usable_region_size;
+  __le64 plugged_size;
+  __le64 requested_size;
+};
+#endif
diff --git a/libc/kernel/uapi/linux/virtio_net.h b/libc/kernel/uapi/linux/virtio_net.h
index cd53e16..2d92904 100644
--- a/libc/kernel/uapi/linux/virtio_net.h
+++ b/libc/kernel/uapi/linux/virtio_net.h
@@ -66,10 +66,10 @@
 #define VIRTIO_NET_RSS_HASH_TYPE_UDP_EX (1 << 8)
 struct virtio_net_config {
   __u8 mac[ETH_ALEN];
-  __u16 status;
-  __u16 max_virtqueue_pairs;
-  __u16 mtu;
-  __u32 speed;
+  __virtio16 status;
+  __virtio16 max_virtqueue_pairs;
+  __virtio16 mtu;
+  __le32 speed;
   __u8 duplex;
   __u8 rss_max_key_size;
   __le16 rss_max_indirection_table_length;
diff --git a/libc/kernel/uapi/linux/virtio_pmem.h b/libc/kernel/uapi/linux/virtio_pmem.h
index 38740f3..838f9d6 100644
--- a/libc/kernel/uapi/linux/virtio_pmem.h
+++ b/libc/kernel/uapi/linux/virtio_pmem.h
@@ -22,8 +22,8 @@
 #include <linux/virtio_ids.h>
 #include <linux/virtio_config.h>
 struct virtio_pmem_config {
-  __u64 start;
-  __u64 size;
+  __le64 start;
+  __le64 size;
 };
 #define VIRTIO_PMEM_REQ_TYPE_FLUSH 0
 struct virtio_pmem_resp {
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/virtio_scsi.h b/libc/kernel/uapi/linux/virtio_scsi.h
index b809e08..74e6ac8 100644
--- a/libc/kernel/uapi/linux/virtio_scsi.h
+++ b/libc/kernel/uapi/linux/virtio_scsi.h
@@ -77,16 +77,16 @@
   __virtio32 reason;
 } __attribute__((packed));
 struct virtio_scsi_config {
-  __u32 num_queues;
-  __u32 seg_max;
-  __u32 max_sectors;
-  __u32 cmd_per_lun;
-  __u32 event_info_size;
-  __u32 sense_size;
-  __u32 cdb_size;
-  __u16 max_channel;
-  __u16 max_target;
-  __u32 max_lun;
+  __virtio32 num_queues;
+  __virtio32 seg_max;
+  __virtio32 max_sectors;
+  __virtio32 cmd_per_lun;
+  __virtio32 event_info_size;
+  __virtio32 sense_size;
+  __virtio32 cdb_size;
+  __virtio16 max_channel;
+  __virtio16 max_target;
+  __virtio32 max_lun;
 } __attribute__((packed));
 #define VIRTIO_SCSI_F_INOUT 0
 #define VIRTIO_SCSI_F_HOTPLUG 1
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/linux/xdp_diag.h b/libc/kernel/uapi/linux/xdp_diag.h
index f7d203f..1fe9d49 100644
--- a/libc/kernel/uapi/linux/xdp_diag.h
+++ b/libc/kernel/uapi/linux/xdp_diag.h
@@ -38,6 +38,7 @@
 #define XDP_SHOW_RING_CFG (1 << 1)
 #define XDP_SHOW_UMEM (1 << 2)
 #define XDP_SHOW_MEMINFO (1 << 3)
+#define XDP_SHOW_STATS (1 << 4)
 enum {
   XDP_DIAG_NONE,
   XDP_DIAG_INFO,
@@ -48,6 +49,7 @@
   XDP_DIAG_UMEM_FILL_RING,
   XDP_DIAG_UMEM_COMPLETION_RING,
   XDP_DIAG_MEMINFO,
+  XDP_DIAG_STATS,
   __XDP_DIAG_MAX,
 };
 #define XDP_DIAG_MAX (__XDP_DIAG_MAX - 1)
@@ -70,4 +72,12 @@
   __u32 flags;
   __u32 refs;
 };
+struct xdp_diag_stats {
+  __u64 n_rx_dropped;
+  __u64 n_rx_invalid;
+  __u64 n_rx_full;
+  __u64 n_fill_ring_empty;
+  __u64 n_tx_invalid;
+  __u64 n_tx_ring_empty;
+};
 #endif
diff --git a/libc/kernel/uapi/linux/xfrm.h b/libc/kernel/uapi/linux/xfrm.h
index ea0ef5e..b0e930c 100644
--- a/libc/kernel/uapi/linux/xfrm.h
+++ b/libc/kernel/uapi/linux/xfrm.h
@@ -328,6 +328,7 @@
 #define XFRM_STATE_ESN 128
 };
 #define XFRM_SA_XFLAG_DONT_ENCAP_DSCP 1
+#define XFRM_SA_XFLAG_OSEQ_MAY_WRAP 2
 struct xfrm_usersa_id {
   xfrm_address_t daddr;
   __be32 spi;
diff --git a/libc/kernel/uapi/misc/habanalabs.h b/libc/kernel/uapi/misc/habanalabs.h
index 91849ec..b235f51 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,8 @@
 #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_CS_COUNTERS 11
 #define HL_INFO_VERSION_MAX_LEN 128
 #define HL_INFO_CARD_NAME_MAX_LEN 16
 struct hl_info_hw_ip_info {
@@ -79,7 +233,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 +270,20 @@
   __u32 hard_reset_cnt;
   __u32 soft_reset_cnt;
 };
+struct hl_info_time_sync {
+  __u64 device_time;
+  __u64 host_time;
+};
+struct hl_cs_counters {
+  __u64 out_of_mem_drop_cnt;
+  __u64 parsing_drop_cnt;
+  __u64 queue_full_drop_cnt;
+  __u64 device_in_reset_drop_cnt;
+};
+struct hl_info_cs_counters {
+  struct hl_cs_counters cs_counters;
+  struct hl_cs_counters ctx_cs_counters;
+};
 struct hl_info_args {
   __u64 return_pointer;
   __u32 return_size;
@@ -127,7 +296,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 +312,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/efa-abi.h b/libc/kernel/uapi/rdma/efa-abi.h
index 39fd55b..86cfac6 100644
--- a/libc/kernel/uapi/rdma/efa-abi.h
+++ b/libc/kernel/uapi/rdma/efa-abi.h
@@ -20,6 +20,14 @@
 #define EFA_ABI_USER_H
 #include <linux/types.h>
 #define EFA_UVERBS_ABI_VERSION 1
+enum {
+  EFA_ALLOC_UCONTEXT_CMD_COMP_TX_BATCH = 1 << 0,
+  EFA_ALLOC_UCONTEXT_CMD_COMP_MIN_SQ_WR = 1 << 1,
+};
+struct efa_ibv_alloc_ucontext_cmd {
+  __u32 comp_mask;
+  __u8 reserved_20[4];
+};
 enum efa_ibv_user_cmds_supp_udata {
   EFA_USER_CMDS_SUPP_UDATA_QUERY_DEVICE = 1 << 0,
   EFA_USER_CMDS_SUPP_UDATA_CREATE_AH = 1 << 1,
@@ -30,6 +38,9 @@
   __u16 sub_cqs_per_cq;
   __u16 inline_buf_size;
   __u32 max_llq_size;
+  __u16 max_tx_batch;
+  __u16 min_sq_wr;
+  __u8 reserved_a0[4];
 };
 struct efa_ibv_alloc_pd_resp {
   __u32 comp_mask;
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..22be9fd 100644
--- a/libc/kernel/uapi/rdma/ib_user_ioctl_cmds.h
+++ b/libc/kernel/uapi/rdma/ib_user_ioctl_cmds.h
@@ -50,6 +50,7 @@
   UVERBS_METHOD_INFO_HANDLES,
   UVERBS_METHOD_QUERY_PORT,
   UVERBS_METHOD_GET_CONTEXT,
+  UVERBS_METHOD_QUERY_CONTEXT,
 };
 enum uverbs_attrs_invoke_write_cmd_attr_ids {
   UVERBS_ATTR_CORE_IN,
@@ -64,6 +65,10 @@
   UVERBS_ATTR_GET_CONTEXT_NUM_COMP_VECTORS,
   UVERBS_ATTR_GET_CONTEXT_CORE_SUPPORT,
 };
+enum uverbs_attrs_query_context_attr_ids {
+  UVERBS_ATTR_QUERY_CONTEXT_NUM_COMP_VECTORS,
+  UVERBS_ATTR_QUERY_CONTEXT_CORE_SUPPORT,
+};
 enum uverbs_attrs_create_cq_cmd_attr_ids {
   UVERBS_ATTR_CREATE_CQ_HANDLE,
   UVERBS_ATTR_CREATE_CQ_CQE,
@@ -72,6 +77,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 +97,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,
@@ -126,6 +203,7 @@
   UVERBS_METHOD_DM_MR_REG,
   UVERBS_METHOD_MR_DESTROY,
   UVERBS_METHOD_ADVISE_MR,
+  UVERBS_METHOD_QUERY_MR,
 };
 enum uverbs_attrs_mr_destroy_ids {
   UVERBS_ATTR_DESTROY_MR_HANDLE,
@@ -136,6 +214,13 @@
   UVERBS_ATTR_ADVISE_MR_FLAGS,
   UVERBS_ATTR_ADVISE_MR_SGE_LIST,
 };
+enum uverbs_attrs_query_mr_cmd_attr_ids {
+  UVERBS_ATTR_QUERY_MR_HANDLE,
+  UVERBS_ATTR_QUERY_MR_RESP_LKEY,
+  UVERBS_ATTR_QUERY_MR_RESP_RKEY,
+  UVERBS_ATTR_QUERY_MR_RESP_LENGTH,
+  UVERBS_ATTR_QUERY_MR_RESP_IOVA,
+};
 enum uverbs_attrs_create_counters_cmd_attr_ids {
   UVERBS_ATTR_CREATE_COUNTERS_HANDLE,
 };
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..d46121a 100644
--- a/libc/kernel/uapi/rdma/mlx5_user_ioctl_cmds.h
+++ b/libc/kernel/uapi/rdma/mlx5_user_ioctl_cmds.h
@@ -178,6 +178,9 @@
   MLX5_IB_METHOD_FLOW_MATCHER_CREATE = (1U << UVERBS_ID_NS_SHIFT),
   MLX5_IB_METHOD_FLOW_MATCHER_DESTROY,
 };
+enum mlx5_ib_device_query_context_attrs {
+  MLX5_IB_ATTR_QUERY_CONTEXT_RESP_UCTX = (1U << UVERBS_ID_NS_SHIFT),
+};
 #define MLX5_IB_DW_MATCH_PARAM 0x80
 struct mlx5_ib_match_params {
   __u32 match_params[MLX5_IB_DW_MATCH_PARAM];
@@ -188,6 +191,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,8 +205,9 @@
   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 {
+enum mlx5_ib_destroy_flow_attrs {
   MLX5_IB_ATTR_DESTROY_FLOW_HANDLE = (1U << UVERBS_ID_NS_SHIFT),
 };
 enum mlx5_ib_flow_methods {
@@ -221,4 +229,11 @@
   MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_FT_TYPE,
   MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_DATA_BUF,
 };
+enum mlx5_ib_query_pd_attrs {
+  MLX5_IB_ATTR_QUERY_PD_HANDLE = (1U << UVERBS_ID_NS_SHIFT),
+  MLX5_IB_ATTR_QUERY_PD_RESP_PDN,
+};
+enum mlx5_ib_pd_methods {
+  MLX5_IB_METHOD_PD_QUERY = (1U << UVERBS_ID_NS_SHIFT),
+};
 #endif
diff --git a/libc/kernel/uapi/rdma/qedr-abi.h b/libc/kernel/uapi/rdma/qedr-abi.h
index 2e666f3..bf6dc76 100644
--- a/libc/kernel/uapi/rdma/qedr-abi.h
+++ b/libc/kernel/uapi/rdma/qedr-abi.h
@@ -21,8 +21,9 @@
 #include <linux/types.h>
 #define QEDR_ABI_VERSION (8)
 enum qedr_alloc_ucontext_flags {
-  QEDR_ALLOC_UCTX_RESERVED = 1 << 0,
-  QEDR_ALLOC_UCTX_DB_REC = 1 << 1
+  QEDR_ALLOC_UCTX_EDPM_MODE = 1 << 0,
+  QEDR_ALLOC_UCTX_DB_REC = 1 << 1,
+  QEDR_SUPPORT_DPM_SIZES = 1 << 2,
 };
 struct qedr_alloc_ucontext_req {
   __u32 context_flags;
@@ -30,12 +31,13 @@
 };
 #define QEDR_LDPM_MAX_SIZE (8192)
 #define QEDR_EDPM_TRANS_SIZE (64)
+#define QEDR_EDPM_MAX_SIZE (ROCE_REQ_MAX_INLINE_DATA_SIZE)
 enum qedr_rdma_dpm_type {
   QEDR_DPM_TYPE_NONE = 0,
   QEDR_DPM_TYPE_ROCE_ENHANCED = 1 << 0,
   QEDR_DPM_TYPE_ROCE_LEGACY = 1 << 1,
   QEDR_DPM_TYPE_IWARP_LEGACY = 1 << 2,
-  QEDR_DPM_TYPE_RESERVED = 1 << 3,
+  QEDR_DPM_TYPE_ROCE_EDPM_MODE = 1 << 3,
   QEDR_DPM_SIZES_SET = 1 << 4,
 };
 struct qedr_alloc_ucontext_resp {
@@ -54,6 +56,8 @@
   __u16 ldpm_limit_size;
   __u8 edpm_trans_size;
   __u8 reserved;
+  __u16 edpm_limit_size;
+  __u8 padding[6];
 };
 struct qedr_alloc_pd_ureq {
   __aligned_u64 rsvd1;
diff --git a/libc/kernel/uapi/rdma/rdma_netlink.h b/libc/kernel/uapi/rdma/rdma_netlink.h
index ed585cf..48444da 100644
--- a/libc/kernel/uapi/rdma/rdma_netlink.h
+++ b/libc/kernel/uapi/rdma/rdma_netlink.h
@@ -204,6 +204,9 @@
   RDMA_NLDEV_CMD_STAT_SET,
   RDMA_NLDEV_CMD_STAT_GET,
   RDMA_NLDEV_CMD_STAT_DEL,
+  RDMA_NLDEV_CMD_RES_QP_GET_RAW,
+  RDMA_NLDEV_CMD_RES_CQ_GET_RAW,
+  RDMA_NLDEV_CMD_RES_MR_GET_RAW,
   RDMA_NLDEV_NUM_OPS
 };
 enum rdma_nldev_print_type {
@@ -297,6 +300,7 @@
   RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_NAME,
   RDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_VALUE,
   RDMA_NLDEV_ATTR_DEV_DIM,
+  RDMA_NLDEV_ATTR_RES_RAW,
   RDMA_NLDEV_ATTR_MAX
 };
 enum rdma_nl_counter_mode {
@@ -307,5 +311,6 @@
 };
 enum rdma_nl_counter_mask {
   RDMA_COUNTER_MASK_QP_TYPE = 1,
+  RDMA_COUNTER_MASK_PID = 1 << 1,
 };
 #endif
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/scsi/fc/fc_els.h b/libc/kernel/uapi/scsi/fc/fc_els.h
index 843bc4e..9822579 100644
--- a/libc/kernel/uapi/scsi/fc/fc_els.h
+++ b/libc/kernel/uapi/scsi/fc/fc_els.h
@@ -42,6 +42,7 @@
   ELS_REC = 0x13,
   ELS_SRR = 0x14,
   ELS_FPIN = 0x16,
+  ELS_RDP = 0x18,
   ELS_RDF = 0x19,
   ELS_PRLI = 0x20,
   ELS_PRLO = 0x21,
@@ -84,7 +85,7 @@
   ELS_LKA = 0x80,
   ELS_AUTH_ELS = 0x90,
 };
-#define FC_ELS_CMDS_INIT {[ELS_LS_RJT] = "LS_RJT",[ELS_LS_ACC] = "LS_ACC",[ELS_PLOGI] = "PLOGI",[ELS_FLOGI] = "FLOGI",[ELS_LOGO] = "LOGO",[ELS_ABTX] = "ABTX",[ELS_RCS] = "RCS",[ELS_RES] = "RES",[ELS_RSS] = "RSS",[ELS_RSI] = "RSI",[ELS_ESTS] = "ESTS",[ELS_ESTC] = "ESTC",[ELS_ADVC] = "ADVC",[ELS_RTV] = "RTV",[ELS_RLS] = "RLS",[ELS_ECHO] = "ECHO",[ELS_TEST] = "TEST",[ELS_RRQ] = "RRQ",[ELS_REC] = "REC",[ELS_SRR] = "SRR",[ELS_FPIN] = "FPIN",[ELS_RDF] = "RDF",[ELS_PRLI] = "PRLI",[ELS_PRLO] = "PRLO",[ELS_SCN] = "SCN",[ELS_TPLS] = "TPLS",[ELS_TPRLO] = "TPRLO",[ELS_LCLM] = "LCLM",[ELS_GAID] = "GAID",[ELS_FACT] = "FACT",[ELS_FDACDT] = "FDACDT",[ELS_NACT] = "NACT",[ELS_NDACT] = "NDACT",[ELS_QOSR] = "QOSR",[ELS_RVCS] = "RVCS",[ELS_PDISC] = "PDISC",[ELS_FDISC] = "FDISC",[ELS_ADISC] = "ADISC",[ELS_RNC] = "RNC",[ELS_FARP_REQ] = "FARP_REQ",[ELS_FARP_REPL] = "FARP_REPL",[ELS_RPS] = "RPS",[ELS_RPL] = "RPL",[ELS_RPBC] = "RPBC",[ELS_FAN] = "FAN",[ELS_RSCN] = "RSCN",[ELS_SCR] = "SCR",[ELS_RNFT] = "RNFT",[ELS_CSR] = "CSR",[ELS_CSU] = "CSU",[ELS_LINIT] = "LINIT",[ELS_LSTS] = "LSTS",[ELS_RNID] = "RNID",[ELS_RLIR] = "RLIR",[ELS_LIRR] = "LIRR",[ELS_SRL] = "SRL",[ELS_SBRP] = "SBRP",[ELS_RPSC] = "RPSC",[ELS_QSA] = "QSA",[ELS_EVFP] = "EVFP",[ELS_LKA] = "LKA",[ELS_AUTH_ELS] = "AUTH_ELS", \
+#define FC_ELS_CMDS_INIT {[ELS_LS_RJT] = "LS_RJT",[ELS_LS_ACC] = "LS_ACC",[ELS_PLOGI] = "PLOGI",[ELS_FLOGI] = "FLOGI",[ELS_LOGO] = "LOGO",[ELS_ABTX] = "ABTX",[ELS_RCS] = "RCS",[ELS_RES] = "RES",[ELS_RSS] = "RSS",[ELS_RSI] = "RSI",[ELS_ESTS] = "ESTS",[ELS_ESTC] = "ESTC",[ELS_ADVC] = "ADVC",[ELS_RTV] = "RTV",[ELS_RLS] = "RLS",[ELS_ECHO] = "ECHO",[ELS_TEST] = "TEST",[ELS_RRQ] = "RRQ",[ELS_REC] = "REC",[ELS_SRR] = "SRR",[ELS_FPIN] = "FPIN",[ELS_RDP] = "RDP",[ELS_RDF] = "RDF",[ELS_PRLI] = "PRLI",[ELS_PRLO] = "PRLO",[ELS_SCN] = "SCN",[ELS_TPLS] = "TPLS",[ELS_TPRLO] = "TPRLO",[ELS_LCLM] = "LCLM",[ELS_GAID] = "GAID",[ELS_FACT] = "FACT",[ELS_FDACDT] = "FDACDT",[ELS_NACT] = "NACT",[ELS_NDACT] = "NDACT",[ELS_QOSR] = "QOSR",[ELS_RVCS] = "RVCS",[ELS_PDISC] = "PDISC",[ELS_FDISC] = "FDISC",[ELS_ADISC] = "ADISC",[ELS_RNC] = "RNC",[ELS_FARP_REQ] = "FARP_REQ",[ELS_FARP_REPL] = "FARP_REPL",[ELS_RPS] = "RPS",[ELS_RPL] = "RPL",[ELS_RPBC] = "RPBC",[ELS_FAN] = "FAN",[ELS_RSCN] = "RSCN",[ELS_SCR] = "SCR",[ELS_RNFT] = "RNFT",[ELS_CSR] = "CSR",[ELS_CSU] = "CSU",[ELS_LINIT] = "LINIT",[ELS_LSTS] = "LSTS",[ELS_RNID] = "RNID",[ELS_RLIR] = "RLIR",[ELS_LIRR] = "LIRR",[ELS_SRL] = "SRL",[ELS_SBRP] = "SBRP",[ELS_RPSC] = "RPSC",[ELS_QSA] = "QSA",[ELS_EVFP] = "EVFP",[ELS_LKA] = "LKA",[ELS_AUTH_ELS] = "AUTH_ELS", \
 }
 struct fc_els_ls_acc {
   __u8 la_cmd;
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..a17a33f 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -1476,8 +1476,8 @@
     # Used by libandroid_net
     android_getaddrinfofornet; # apex
 
-    # Used by libandroid_runtime, libmedia and libmediautils
-    android_mallopt; # apex
+    # Used by libandroid_runtime, libcutils, libmedia, and libmediautils
+    android_mallopt; # apex llndk
 } LIBC_P;
 
 LIBC_R { # introduced=R
@@ -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 {
@@ -1714,6 +1718,7 @@
     android_gethostbyaddrfornetcontext;
     android_gethostbynamefornet;
     android_gethostbynamefornetcontext;
+    android_run_on_all_threads;
     android_unsafe_frame_pointer_chase;
     arc4random_addrandom; # arm x86
     arc4random_stir; # arm x86
@@ -1766,4 +1771,5 @@
     android_net_res_stats_get_info_for_net;
     android_net_res_stats_aggregate;
     android_net_res_stats_get_usable_servers;
+    android_reset_stack_guards;
 } LIBC_Q;
diff --git a/libc/malloc_debug/MapData.cpp b/libc/malloc_debug/MapData.cpp
index e8fbc54..ded81a2 100644
--- a/libc/malloc_debug/MapData.cpp
+++ b/libc/malloc_debug/MapData.cpp
@@ -116,14 +116,17 @@
     if (!get_val<ElfW(Word)>(entry, addr + offsetof(ElfW(Phdr), p_type), &phdr.p_type)) {
       return;
     }
+    if (!get_val<ElfW(Word)>(entry, addr + offsetof(ElfW(Phdr), p_flags), &phdr.p_flags)) {
+      return;
+    }
     if (!get_val<ElfW(Off)>(entry, addr + offsetof(ElfW(Phdr), p_offset), &phdr.p_offset)) {
       return;
     }
-    if (phdr.p_type == PT_LOAD && phdr.p_offset == entry->offset) {
+    if ((phdr.p_type == PT_LOAD) && (phdr.p_flags & PF_X) ) {
       if (!get_val<ElfW(Addr)>(entry, addr + offsetof(ElfW(Phdr), p_vaddr), &phdr.p_vaddr)) {
         return;
       }
-      entry->load_bias = phdr.p_vaddr;
+      entry->load_bias = phdr.p_vaddr - phdr.p_offset;
       return;
     }
     addr += sizeof(phdr);
diff --git a/libc/malloc_hooks/Android.bp b/libc/malloc_hooks/Android.bp
index 77b523e..487f3fb 100644
--- a/libc/malloc_hooks/Android.bp
+++ b/libc/malloc_hooks/Android.bp
@@ -70,6 +70,7 @@
     cflags: [
         "-Wall",
         "-Werror",
+        "-O1",  // FIXME: http://b/169206016 - issues with aligned_alloc and -O2
     ],
     test_suites: ["general-tests"],
 }
diff --git a/libc/platform/bionic/malloc.h b/libc/platform/bionic/malloc.h
index f9eb03f..16ef3a0 100644
--- a/libc/platform/bionic/malloc.h
+++ b/libc/platform/bionic/malloc.h
@@ -105,6 +105,13 @@
   //   arg_size = sizeof(bool)
   M_INITIALIZE_GWP_ASAN = 10,
 #define M_INITIALIZE_GWP_ASAN M_INITIALIZE_GWP_ASAN
+  // Disable heap initialization across the whole process. If the hardware supports memory
+  // tagging, it also disables memory tagging. May be called at any time including
+  // when multiple threads are running. arg and arg_size are unused and must be set to 0.
+  // Note that the memory mitigations are only implemented in scudo and therefore this API call will
+  // have no effect when using another allocator.
+  M_DISABLE_MEMORY_MITIGATIONS = 11,
+#define M_DISABLE_MEMORY_MITIGATIONS M_DISABLE_MEMORY_MITIGATIONS
 };
 
 enum HeapTaggingLevel {
diff --git a/libc/platform/bionic/mte_kernel.h b/libc/platform/bionic/mte_kernel.h
index e8ef2a5..d81480a 100644
--- a/libc/platform/bionic/mte_kernel.h
+++ b/libc/platform/bionic/mte_kernel.h
@@ -54,4 +54,6 @@
 #define PTRACE_PEEKMTETAGS 33
 #define PTRACE_POKEMTETAGS 34
 
+#define NT_ARM_TAGGED_ADDR_CTRL 0x409
+
 #endif
diff --git a/libc/platform/bionic/reserved_signals.h b/libc/platform/bionic/reserved_signals.h
index e8e517e..dab58af 100644
--- a/libc/platform/bionic/reserved_signals.h
+++ b/libc/platform/bionic/reserved_signals.h
@@ -43,9 +43,7 @@
 //   37 (__SIGRTMIN + 5)        coverage (libprofile-extras)
 //   38 (__SIGRTMIN + 6)        heapprofd ART managed heap dumps
 //   39 (__SIGRTMIN + 7)        fdtrack
-//
-// If you change this, also change __ndk_legacy___libc_current_sigrtmin
-// in <android/legacy_signal_inlines.h> to match.
+//   40 (__SIGRTMIN + 8)        android_run_on_all_threads (bionic/pthread_internal.cpp)
 
 #define BIONIC_SIGNAL_POSIX_TIMERS (__SIGRTMIN + 0)
 #define BIONIC_SIGNAL_BACKTRACE (__SIGRTMIN + 1)
@@ -53,8 +51,9 @@
 #define BIONIC_SIGNAL_PROFILER (__SIGRTMIN + 4)
 #define BIONIC_SIGNAL_ART_PROFILER (__SIGRTMIN + 6)
 #define BIONIC_SIGNAL_FDTRACK (__SIGRTMIN + 7)
+#define BIONIC_SIGNAL_RUN_ON_ALL_THREADS (__SIGRTMIN + 8)
 
-#define __SIGRT_RESERVED 8
+#define __SIGRT_RESERVED 9
 static inline __always_inline sigset64_t filter_reserved_signals(sigset64_t sigset, int how) {
   int (*block)(sigset64_t*, int);
   int (*unblock)(sigset64_t*, int);
@@ -83,5 +82,6 @@
   unblock(&sigset, __SIGRTMIN + 5);
   unblock(&sigset, __SIGRTMIN + 6);
   unblock(&sigset, __SIGRTMIN + 7);
+  unblock(&sigset, __SIGRTMIN + 8);
   return sigset;
 }
diff --git a/libc/bionic/pututline.c b/libc/platform/scudo_platform_tls_slot.h
similarity index 63%
copy from libc/bionic/pututline.c
copy to libc/platform/scudo_platform_tls_slot.h
index 8cbf470..9d017c0 100644
--- a/libc/bionic/pututline.c
+++ b/libc/platform/scudo_platform_tls_slot.h
@@ -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,11 @@
  * 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 "bionic/tls.h"
 
-    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);
+inline uintptr_t *getPlatformAllocatorTlsSlot() {
+  return reinterpret_cast<uintptr_t*>(&__get_tls()[TLS_SLOT_SANITIZER]);
 }
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_asm.h b/libc/private/bionic_asm.h
index 6409563..6d4f7d5 100644
--- a/libc/private/bionic_asm.h
+++ b/libc/private/bionic_asm.h
@@ -35,6 +35,7 @@
 #define __bionic_asm_custom_entry(f)
 #define __bionic_asm_custom_end(f)
 #define __bionic_asm_function_type @function
+#define __bionic_asm_custom_note_gnu_section()
 
 #if defined(__aarch64__)
 #include <private/bionic_asm_arm64.h>
@@ -83,4 +84,7 @@
     .globl alias; \
     .equ alias, original
 
+#define NOTE_GNU_PROPERTY() \
+    __bionic_asm_custom_note_gnu_section()
+
 #endif
diff --git a/libc/private/bionic_asm_arm64.h b/libc/private/bionic_asm_arm64.h
index 463ca31..c11732a 100644
--- a/libc/private/bionic_asm_arm64.h
+++ b/libc/private/bionic_asm_arm64.h
@@ -41,3 +41,32 @@
 
 #undef __bionic_asm_function_type
 #define __bionic_asm_function_type %function
+
+#if defined(__ARM_FEATURE_BTI_DEFAULT)
+#define __bionic_asm_aarch64_feature_bti    (1 << 0)
+#undef __bionic_asm_custom_entry
+#define __bionic_asm_custom_entry(f)        hint #34  // BTI C
+#else
+#define __bionic_asm_aarch64_feature_bti    0
+#endif
+
+#if defined(__ARM_FEATURE_PAC_DEFAULT)
+#define __bionic_asm_aarch64_feature_pac    (1 << 1)
+#else
+#define __bionic_asm_aarch64_feature_pac    0
+#endif
+
+#undef __bionic_asm_custom_note_gnu_section
+#define __bionic_asm_custom_note_gnu_section() \
+    .pushsection .note.gnu.property, "a"; \
+    .balign 8; \
+    .long 4; \
+    .long 0x10; \
+    .long 0x5; /* NT_GNU_PROPERTY_TYPE_0 */ \
+    .asciz "GNU"; \
+    .long 0xc0000000; /* GNU_PROPERTY_AARCH64_FEATURE_1_AND */ \
+    .long 4; \
+    .long (__bionic_asm_aarch64_feature_pac | \
+           __bionic_asm_aarch64_feature_bti); \
+    .long 0; \
+    .popsection; \
diff --git a/libc/private/bionic_asm_dwarf_exprs.h b/libc/private/bionic_asm_dwarf_exprs.h
new file mode 100644
index 0000000..f988c6e
--- /dev/null
+++ b/libc/private/bionic_asm_dwarf_exprs.h
@@ -0,0 +1,101 @@
+/*
+ * 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.
+ */
+
+// Define assembler macros for generating DWARF CFI instructions that use DWARF expressions.
+// Assemblers don't natively support DWARF expressions, so use the C preprocessor and assembler
+// macros to lower them to .cfi_escape directives.
+//
+// Signal trampolines need to use DWARF expressions to record the locations of saved registers,
+// because the offsets from the restored SP to the saved registers is variable. e.g. A signal frame
+// can have optional FP/SIMD extensions, and there may be extra padding if the interrupted SP wasn't
+// aligned.
+
+// DWARF constants.
+#define DW_CFA_def_cfa_expression 0x0f
+#define DW_CFA_expression 0x10
+#define DW_OP_breg0 0x70
+#define DW_OP_deref 0x06
+
+// Return the size of a small uleb128 value: either 1 or 2 bytes
+#define ULEB128_14BIT_SIZE(val) \
+  (1 + (((val) > 0x7f) & 1))
+
+// Return the size of a small sleb128 value: either 1 or 2 bytes
+#define SLEB128_14BIT_SIZE(val)       \
+  (1 + (((val) < -0x40) & 1) +        \
+       (((val) > 0x3f) & 1)     )
+
+// Output a 1 or 2-byte CFI uleb128 absolute value.
+.macro m_cfi_uleb128 val
+  .if (\val) < 0 || (\val) > 0x3fff
+    .error "m_cfi_uleb128 value is out of range (\val)"
+  .elseif (\val) > 0x7f
+    .cfi_escape ((\val) & 0x7f) | 0x80
+    .cfi_escape (\val) >> 7
+  .else
+    .cfi_escape (\val)
+  .endif
+.endm
+
+// Output a 1 or 2-byte CFI sleb128 absolute value.
+.macro m_cfi_sleb128 val
+  .if (\val) < -0x2000 || (\val) > 0x1fff
+    .error "m_cfi_sleb128 value is out of range (\val)"
+  .elseif (\val) < -0x40 || (\val) > 0x3f
+    .cfi_escape ((\val) & 0x7f) | 0x80
+    .cfi_escape ((\val) >> 7) & 0x7f
+  .else
+    .cfi_escape (\val) & 0x7f
+  .endif
+.endm
+
+.macro check_base_reg reg_no
+  .if (\reg_no) < 0 || (\reg_no) > 31
+    .error "base register is out of range for DW_OP_breg0..DW_OP_breg31 (\reg_no)"
+  .endif
+.endm
+
+// Set CFA to the expression, *(base_reg + offset)
+.macro m_cfi_def_cfa_deref base_reg, offset
+  check_base_reg (\base_reg)
+  .cfi_escape DW_CFA_def_cfa_expression
+  m_cfi_uleb128 (1 + SLEB128_14BIT_SIZE(\offset) + 1)   // size of DWARF expression in bytes
+  .cfi_escape DW_OP_breg0 + (\base_reg)                 // expr: 1 byte
+  m_cfi_sleb128 (\offset)                               // expr: 1 or 2 bytes
+  .cfi_escape DW_OP_deref                               // expr: 1 byte
+.endm
+
+// Set the address of the register's previous value to the expression, (base_reg + offset)
+.macro m_cfi_breg_offset dest_reg, base_reg, offset
+  check_base_reg (\base_reg)
+  .cfi_escape DW_CFA_expression
+  m_cfi_uleb128 (\dest_reg)
+  m_cfi_uleb128 (1 + SLEB128_14BIT_SIZE(\offset)) // size of DWARF expression in bytes
+  .cfi_escape DW_OP_breg0 + (\base_reg)           // expr: 1 byte
+  m_cfi_sleb128 (\offset)                         // expr: 1 or 2 bytes
+.endm
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_defs.h b/libc/private/bionic_defs.h
index 1d4f86b..5a48f25 100644
--- a/libc/private/bionic_defs.h
+++ b/libc/private/bionic_defs.h
@@ -33,7 +33,15 @@
  * This label is used to mark libc/libdl symbols that may need to be replaced
  * by native bridge implementation.
  */
+#ifdef __ANDROID_NATIVE_BRIDGE__
 #define __BIONIC_WEAK_FOR_NATIVE_BRIDGE __attribute__((__weak__, __noinline__))
 #define __BIONIC_WEAK_VARIABLE_FOR_NATIVE_BRIDGE __attribute__((__weak__))
+#define __BIONIC_WEAK_FOR_NATIVE_BRIDGE_INLINE \
+  __BIONIC_WEAK_FOR_NATIVE_BRIDGE extern "C" __LIBC_HIDDEN__
+#else
+#define __BIONIC_WEAK_FOR_NATIVE_BRIDGE
+#define __BIONIC_WEAK_VARIABLE_FOR_NATIVE_BRIDGE
+#define __BIONIC_WEAK_FOR_NATIVE_BRIDGE_INLINE static inline
+#endif
 
 #endif /* __BIONIC_PRIVATE_BIONIC_DEFS_H_ */
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/private/bionic_ifuncs.h b/libc/private/bionic_ifuncs.h
index f175bec..e6b349a 100644
--- a/libc/private/bionic_ifuncs.h
+++ b/libc/private/bionic_ifuncs.h
@@ -40,9 +40,12 @@
 #define IFUNC_ARGS ()
 #endif
 
+// We can't have HWASAN enabled in resolvers because they may be called before HWASAN is
+// initialized.
 #define DEFINE_IFUNC_FOR(name) \
     name##_func name __attribute__((ifunc(#name "_resolver"))); \
     __attribute__((visibility("hidden"))) \
+    __attribute__((no_sanitize("hwaddress"))) \
     name##_func* name##_resolver IFUNC_ARGS
 
 #define DECLARE_FUNC(type, name) \
diff --git a/libc/private/bionic_systrace.h b/libc/private/bionic_systrace.h
index dbe1739..6b11812 100644
--- a/libc/private/bionic_systrace.h
+++ b/libc/private/bionic_systrace.h
@@ -16,8 +16,12 @@
 
 #pragma once
 
+#include <cutils/trace.h>  // For ATRACE_TAG_BIONIC.
+
 #include "platform/bionic/macros.h"
 
+static constexpr char kTraceTagsProp[] = "debug.atrace.tags.enableflags";
+
 // Tracing class for bionic. To begin a trace at a specified point:
 //   ScopedTrace("Trace message");
 // The trace will end when the contructor goes out of scope.
@@ -33,5 +37,9 @@
   BIONIC_DISALLOW_COPY_AND_ASSIGN(ScopedTrace);
 };
 
+int get_trace_marker_fd();
+bool should_trace(const uint64_t enable_tags = ATRACE_TAG_BIONIC);
+void output_trace(const char* message, const char event = 'B');
+
 void bionic_trace_begin(const char* message);
 void bionic_trace_end();
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/Android.bp b/libc/system_properties/Android.bp
index 8780dda..3846169 100644
--- a/libc/system_properties/Android.bp
+++ b/libc/system_properties/Android.bp
@@ -8,9 +8,11 @@
         "contexts_serialized.cpp",
         "prop_area.cpp",
         "prop_info.cpp",
+        "prop_trace.cpp",
         "system_properties.cpp",
     ],
     whole_static_libs: [
+        "libc_bionic_systrace",
         "libpropertyinfoparser",
     ],
     header_libs: [
@@ -23,3 +25,20 @@
     ],
     export_include_dirs: ["include"],
 }
+
+cc_benchmark {
+    name: "property_context_lookup_benchmark",
+    srcs: [
+        "context_lookup_benchmark.cpp",
+    ],
+    include_dirs: [
+        "bionic/libc",
+    ],
+
+    shared_libs: ["libbase"],
+    static_libs: [
+        "libpropertyinfoserializer",
+        "libsystemproperties",
+        "libasync_safe",
+    ],
+}
diff --git a/libc/system_properties/context_lookup_benchmark.cpp b/libc/system_properties/context_lookup_benchmark.cpp
new file mode 100644
index 0000000..1564250
--- /dev/null
+++ b/libc/system_properties/context_lookup_benchmark.cpp
@@ -0,0 +1,145 @@
+/*
+ * 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 <ctype.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <string>
+#include <vector>
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/strings.h>
+#include <benchmark/benchmark.h>
+#include <property_info_parser/property_info_parser.h>
+#include <property_info_serializer/property_info_serializer.h>
+#include <system_properties/contexts_split.h>
+
+#include "context_lookup_benchmark_data.h"
+
+using android::base::Split;
+using android::base::WriteStringToFd;
+using android::properties::BuildTrie;
+using android::properties::ParsePropertyInfoFile;
+using android::properties::PropertyInfoArea;
+using android::properties::PropertyInfoEntry;
+
+BENCHMARK_MAIN();
+
+class LegacyPropertyMapping : public ContextsSplit {
+ public:
+  LegacyPropertyMapping(const char* property_contexts) {
+    TemporaryFile file;
+    if (!WriteStringToFd(property_contexts, file.fd)) {
+      PLOG(FATAL) << "Could not write to temporary file";
+    }
+
+    if (!InitializePropertiesFromFile(file.path)) {
+      LOG(FATAL) << "Could not initialize properties";
+    }
+  }
+};
+
+static std::vector<std::string> PropertiesToLookup() {
+  std::vector<std::string> properties;
+  auto property_lines = Split(aosp_s_property_contexts, "\n");
+  for (const auto& line : property_lines) {
+    if (line.empty() || line[0] == '#') {
+      continue;
+    }
+
+    auto property = Split(line, " ")[0];
+    properties.push_back(property);
+    properties.push_back(property + "0");
+    properties.push_back(property + "A");
+  }
+  return properties;
+}
+
+static void LegacyLookupOreo(benchmark::State& state) {
+  LegacyPropertyMapping mapping(oreo_property_contexts);
+  auto properties = PropertiesToLookup();
+  for (auto _ : state) {
+    for (const auto& property : properties) {
+      benchmark::DoNotOptimize(mapping.GetPrefixNodeForName(property.c_str()));
+    }
+  }
+}
+BENCHMARK(LegacyLookupOreo);
+
+static void LegacyLookupS(benchmark::State& state) {
+  LegacyPropertyMapping mapping(aosp_s_property_contexts);
+  auto properties = PropertiesToLookup();
+  for (auto _ : state) {
+    for (const auto& property : properties) {
+      benchmark::DoNotOptimize(mapping.GetPrefixNodeForName(property.c_str()));
+    }
+  }
+}
+BENCHMARK(LegacyLookupS);
+
+static std::string CreateSerializedTrie(const char* input_file) {
+  std::vector<std::string> errors;
+  std::vector<PropertyInfoEntry> property_infos;
+  ParsePropertyInfoFile(input_file, false, &property_infos, &errors);
+
+  std::string serialized_trie;
+  std::string error;
+  if (!BuildTrie(property_infos, "u:object_r:default_prop:s0", "string", &serialized_trie,
+                 &error)) {
+    LOG(FATAL) << "Could not build trie: " << error;
+  }
+  return serialized_trie;
+}
+
+static void TrieLookupOreo(benchmark::State& state) {
+  std::string serialized_trie = CreateSerializedTrie(oreo_property_contexts);
+  PropertyInfoArea* trie = reinterpret_cast<PropertyInfoArea*>(serialized_trie.data());
+  auto properties = PropertiesToLookup();
+  for (auto _ : state) {
+    for (const auto& property : properties) {
+      trie->GetPropertyInfo(property.c_str(), nullptr, nullptr);
+    }
+  }
+}
+BENCHMARK(TrieLookupOreo);
+
+static void TrieLookupS(benchmark::State& state) {
+  std::string serialized_trie = CreateSerializedTrie(aosp_s_property_contexts);
+  PropertyInfoArea* trie = reinterpret_cast<PropertyInfoArea*>(serialized_trie.data());
+  auto properties = PropertiesToLookup();
+  for (auto _ : state) {
+    for (const auto& property : properties) {
+      trie->GetPropertyInfo(property.c_str(), nullptr, nullptr);
+    }
+  }
+}
+BENCHMARK(TrieLookupS);
diff --git a/libc/system_properties/context_lookup_benchmark_data.h b/libc/system_properties/context_lookup_benchmark_data.h
new file mode 100644
index 0000000..3cc3257
--- /dev/null
+++ b/libc/system_properties/context_lookup_benchmark_data.h
@@ -0,0 +1,1012 @@
+/*
+ * 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
+
+static char oreo_property_contexts[] = R"(
+net.rmnet               u:object_r:net_radio_prop:s0
+net.gprs                u:object_r:net_radio_prop:s0
+net.ppp                 u:object_r:net_radio_prop:s0
+net.qmi                 u:object_r:net_radio_prop:s0
+net.lte                 u:object_r:net_radio_prop:s0
+net.cdma                u:object_r:net_radio_prop:s0
+net.dns                 u:object_r:net_dns_prop:s0
+sys.usb.config          u:object_r:system_radio_prop:s0
+ril.                    u:object_r:radio_prop:s0
+ro.ril.                 u:object_r:radio_prop:s0
+gsm.                    u:object_r:radio_prop:s0
+persist.radio           u:object_r:radio_prop:s0
+net.                    u:object_r:system_prop:s0
+dev.                    u:object_r:system_prop:s0
+ro.runtime.             u:object_r:system_prop:s0
+ro.runtime.firstboot    u:object_r:firstboot_prop:s0
+hw.                     u:object_r:system_prop:s0
+ro.hw.                  u:object_r:system_prop:s0
+sys.                    u:object_r:system_prop:s0
+sys.cppreopt            u:object_r:cppreopt_prop:s0
+sys.powerctl            u:object_r:powerctl_prop:s0
+sys.usb.ffs.            u:object_r:ffs_prop:s0
+service.                u:object_r:system_prop:s0
+dhcp.                   u:object_r:dhcp_prop:s0
+dhcp.bt-pan.result      u:object_r:pan_result_prop:s0
+bluetooth.              u:object_r:bluetooth_prop:s0
+debug.                  u:object_r:debug_prop:s0
+debug.db.               u:object_r:debuggerd_prop:s0
+dumpstate.              u:object_r:dumpstate_prop:s0
+dumpstate.options       u:object_r:dumpstate_options_prop:s0
+log.                    u:object_r:log_prop:s0
+log.tag                 u:object_r:log_tag_prop:s0
+log.tag.WifiHAL         u:object_r:wifi_log_prop:s0
+security.perf_harden    u:object_r:shell_prop:s0
+service.adb.root        u:object_r:shell_prop:s0
+service.adb.tcp.port    u:object_r:shell_prop:s0
+persist.audio.          u:object_r:audio_prop:s0
+persist.bluetooth.      u:object_r:bluetooth_prop:s0
+persist.debug.          u:object_r:persist_debug_prop:s0
+persist.logd.           u:object_r:logd_prop:s0
+persist.logd.security   u:object_r:device_logging_prop:s0
+persist.logd.logpersistd        u:object_r:logpersistd_logging_prop:s0
+logd.logpersistd        u:object_r:logpersistd_logging_prop:s0
+persist.log.tag         u:object_r:log_tag_prop:s0
+persist.mmc.            u:object_r:mmc_prop:s0
+persist.sys.            u:object_r:system_prop:s0
+persist.sys.safemode    u:object_r:safemode_prop:s0
+ro.sys.safemode         u:object_r:safemode_prop:s0
+persist.sys.audit_safemode      u:object_r:safemode_prop:s0
+persist.service.        u:object_r:system_prop:s0
+persist.service.bdroid. u:object_r:bluetooth_prop:s0
+persist.security.       u:object_r:system_prop:s0
+persist.vendor.overlay.  u:object_r:overlay_prop:s0
+ro.boot.vendor.overlay.  u:object_r:overlay_prop:s0
+ro.boottime.             u:object_r:boottime_prop:s0
+ro.serialno             u:object_r:serialno_prop:s0
+ro.boot.btmacaddr       u:object_r:bluetooth_prop:s0
+ro.boot.serialno        u:object_r:serialno_prop:s0
+ro.bt.                  u:object_r:bluetooth_prop:s0
+# Boolean property set by system server upon boot indicating
+# if device owner is provisioned.
+ro.device_owner         u:object_r:device_logging_prop:s0
+# selinux non-persistent properties
+selinux.restorecon_recursive   u:object_r:restorecon_prop:s0
+# default property context
+*                       u:object_r:default_prop:s0
+# data partition encryption properties
+vold.                   u:object_r:vold_prop:s0
+ro.crypto.              u:object_r:vold_prop:s0
+# ro.build.fingerprint is either set in /system/build.prop, or is
+# set at runtime by system_server.
+ro.build.fingerprint    u:object_r:fingerprint_prop:s0
+ro.persistent_properties.ready  u:object_r:persistent_properties_ready_prop:s0
+# ctl properties
+ctl.bootanim            u:object_r:ctl_bootanim_prop:s0
+ctl.dumpstate           u:object_r:ctl_dumpstate_prop:s0
+ctl.fuse_               u:object_r:ctl_fuse_prop:s0
+ctl.mdnsd               u:object_r:ctl_mdnsd_prop:s0
+ctl.ril-daemon          u:object_r:ctl_rildaemon_prop:s0
+ctl.bugreport           u:object_r:ctl_bugreport_prop:s0
+ctl.console             u:object_r:ctl_console_prop:s0
+ctl.                    u:object_r:ctl_default_prop:s0
+# NFC properties
+nfc.                    u:object_r:nfc_prop:s0
+# These properties are not normally set by processes other than init.
+# They are only distinguished here for setting by qemu-props on the
+# emulator/goldfish.
+config.                 u:object_r:config_prop:s0
+ro.config.              u:object_r:config_prop:s0
+dalvik.                 u:object_r:dalvik_prop:s0
+ro.dalvik.              u:object_r:dalvik_prop:s0
+# Shared between system server and wificond
+wlan.                   u:object_r:wifi_prop:s0
+# hwservicemanager properties
+hwservicemanager.       u:object_r:hwservicemanager_prop:s0
+# ASAN install trigger
+asan.restore_reboot  u:object_r:asan_reboot_prop:s0)";
+
+static char aosp_s_property_contexts[] = R"(
+net.rmnet               u:object_r:net_radio_prop:s0
+net.gprs                u:object_r:net_radio_prop:s0
+net.ppp                 u:object_r:net_radio_prop:s0
+net.qmi                 u:object_r:net_radio_prop:s0
+net.lte                 u:object_r:net_radio_prop:s0
+net.cdma                u:object_r:net_radio_prop:s0
+net.dns                 u:object_r:net_dns_prop:s0
+ril.                    u:object_r:radio_prop:s0
+ro.ril.                 u:object_r:radio_prop:s0
+gsm.                    u:object_r:radio_prop:s0
+persist.radio           u:object_r:radio_prop:s0
+
+net.                    u:object_r:system_prop:s0
+dev.                    u:object_r:system_prop:s0
+ro.runtime.             u:object_r:system_prop:s0
+ro.runtime.firstboot    u:object_r:firstboot_prop:s0
+hw.                     u:object_r:system_prop:s0
+ro.hw.                  u:object_r:system_prop:s0
+sys.                    u:object_r:system_prop:s0
+sys.audio.              u:object_r:audio_prop:s0
+sys.init.perf_lsm_hooks u:object_r:init_perf_lsm_hooks_prop:s0
+sys.cppreopt            u:object_r:cppreopt_prop:s0
+sys.lpdumpd             u:object_r:lpdumpd_prop:s0
+sys.powerctl            u:object_r:powerctl_prop:s0
+service.                u:object_r:system_prop:s0
+dhcp.                   u:object_r:dhcp_prop:s0
+dhcp.bt-pan.result      u:object_r:pan_result_prop:s0
+bluetooth.              u:object_r:bluetooth_prop:s0
+
+debug.                  u:object_r:debug_prop:s0
+debug.db.               u:object_r:debuggerd_prop:s0
+dumpstate.              u:object_r:dumpstate_prop:s0
+dumpstate.options       u:object_r:dumpstate_options_prop:s0
+init.svc_debug_pid.     u:object_r:init_svc_debug_prop:s0
+llk.                    u:object_r:llkd_prop:s0
+khungtask.              u:object_r:llkd_prop:s0
+ro.llk.                 u:object_r:llkd_prop:s0
+ro.khungtask.           u:object_r:llkd_prop:s0
+log.                    u:object_r:log_prop:s0
+log.tag                 u:object_r:log_tag_prop:s0
+log.tag.WifiHAL         u:object_r:wifi_log_prop:s0
+security.perf_harden    u:object_r:shell_prop:s0
+service.adb.root        u:object_r:shell_prop:s0
+service.adb.tls.port    u:object_r:adbd_prop:s0
+persist.adb.wifi.       u:object_r:adbd_prop:s0
+persist.adb.tls_server.enable  u:object_r:system_adbd_prop:s0
+
+persist.audio.          u:object_r:audio_prop:s0
+persist.bluetooth.      u:object_r:bluetooth_prop:s0
+persist.nfc_cfg.        u:object_r:nfc_prop:s0
+persist.debug.          u:object_r:persist_debug_prop:s0
+logd.                   u:object_r:logd_prop:s0
+persist.logd.           u:object_r:logd_prop:s0
+ro.logd.                u:object_r:logd_prop:s0
+persist.logd.security   u:object_r:device_logging_prop:s0
+persist.logd.logpersistd        u:object_r:logpersistd_logging_prop:s0
+logd.logpersistd        u:object_r:logpersistd_logging_prop:s0
+persist.log.tag         u:object_r:log_tag_prop:s0
+persist.mmc.            u:object_r:mmc_prop:s0
+persist.netd.stable_secret      u:object_r:netd_stable_secret_prop:s0
+persist.pm.mock-upgrade u:object_r:mock_ota_prop:s0
+persist.sys.            u:object_r:system_prop:s0
+persist.sys.safemode    u:object_r:safemode_prop:s0
+persist.sys.theme       u:object_r:theme_prop:s0
+persist.sys.fflag.override.settings_dynamic_system    u:object_r:dynamic_system_prop:s0
+ro.sys.safemode         u:object_r:safemode_prop:s0
+persist.sys.audit_safemode      u:object_r:safemode_prop:s0
+persist.sys.dalvik.jvmtiagent   u:object_r:system_jvmti_agent_prop:s0
+persist.service.        u:object_r:system_prop:s0
+persist.service.bdroid. u:object_r:bluetooth_prop:s0
+persist.security.       u:object_r:system_prop:s0
+persist.traced.enable   u:object_r:traced_enabled_prop:s0
+traced.lazy.            u:object_r:traced_lazy_prop:s0
+persist.heapprofd.enable u:object_r:heapprofd_enabled_prop:s0
+persist.traced_perf.enable u:object_r:traced_perf_enabled_prop:s0
+persist.vendor.overlay.  u:object_r:overlay_prop:s0
+ro.boot.vendor.overlay.  u:object_r:overlay_prop:s0
+ro.boottime.             u:object_r:boottime_prop:s0
+ro.serialno             u:object_r:serialno_prop:s0
+ro.boot.btmacaddr       u:object_r:bluetooth_prop:s0
+ro.boot.serialno        u:object_r:serialno_prop:s0
+ro.bt.                  u:object_r:bluetooth_prop:s0
+ro.boot.bootreason      u:object_r:bootloader_boot_reason_prop:s0
+persist.sys.boot.reason u:object_r:last_boot_reason_prop:s0
+sys.boot.reason         u:object_r:system_boot_reason_prop:s0
+sys.boot.reason.last    u:object_r:last_boot_reason_prop:s0
+pm.                     u:object_r:pm_prop:s0
+test.sys.boot.reason    u:object_r:test_boot_reason_prop:s0
+test.userspace_reboot.requested u:object_r:userspace_reboot_test_prop:s0
+sys.lmk.                u:object_r:system_lmk_prop:s0
+sys.trace.              u:object_r:system_trace_prop:s0
+
+# Fastbootd protocol control property
+fastbootd.protocol    u:object_r:fastbootd_protocol_prop:s0 exact enum usb tcp
+
+# adbd protoctl configuration property
+service.adb.tcp.port    u:object_r:adbd_config_prop:s0 exact int
+
+# Boolean property set by system server upon boot indicating
+# if device is fully owned by organization instead of being
+# a personal device.
+ro.organization_owned   u:object_r:device_logging_prop:s0
+
+# selinux non-persistent properties
+selinux.restorecon_recursive   u:object_r:restorecon_prop:s0
+
+# default property context
+*                       u:object_r:default_prop:s0
+
+# data partition encryption properties
+vold.                   u:object_r:vold_prop:s0
+ro.crypto.              u:object_r:vold_prop:s0
+
+# ro.build.fingerprint is either set in /system/build.prop, or is
+# set at runtime by system_server.
+ro.build.fingerprint    u:object_r:fingerprint_prop:s0 exact string
+
+ro.persistent_properties.ready  u:object_r:persistent_properties_ready_prop:s0
+
+# ctl properties
+ctl.bootanim            u:object_r:ctl_bootanim_prop:s0
+ctl.dumpstate           u:object_r:ctl_dumpstate_prop:s0
+ctl.fuse_               u:object_r:ctl_fuse_prop:s0
+ctl.mdnsd               u:object_r:ctl_mdnsd_prop:s0
+ctl.ril-daemon          u:object_r:ctl_rildaemon_prop:s0
+ctl.bugreport           u:object_r:ctl_bugreport_prop:s0
+ctl.console             u:object_r:ctl_console_prop:s0
+ctl.                    u:object_r:ctl_default_prop:s0
+
+# Don't allow uncontrolled access to all services
+ctl.sigstop_on$         u:object_r:ctl_sigstop_prop:s0
+ctl.sigstop_off$        u:object_r:ctl_sigstop_prop:s0
+ctl.start$              u:object_r:ctl_start_prop:s0
+ctl.stop$               u:object_r:ctl_stop_prop:s0
+ctl.restart$            u:object_r:ctl_restart_prop:s0
+ctl.interface_start$    u:object_r:ctl_interface_start_prop:s0
+ctl.interface_stop$     u:object_r:ctl_interface_stop_prop:s0
+ctl.interface_restart$  u:object_r:ctl_interface_restart_prop:s0
+
+ # Restrict access to starting/stopping adbd
+ctl.start$adbd             u:object_r:ctl_adbd_prop:s0
+ctl.stop$adbd              u:object_r:ctl_adbd_prop:s0
+ctl.restart$adbd           u:object_r:ctl_adbd_prop:s0
+
+# Restrict access to starting/stopping gsid.
+ctl.start$gsid          u:object_r:ctl_gsid_prop:s0
+ctl.stop$gsid           u:object_r:ctl_gsid_prop:s0
+ctl.restart$gsid        u:object_r:ctl_gsid_prop:s0
+
+# Restrict access to stopping apexd.
+ctl.stop$apexd          u:object_r:ctl_apexd_prop:s0
+
+# Restrict access to restart dumpstate
+ctl.interface_restart$android.hardware.dumpstate u:object_r:ctl_dumpstate_prop:s0
+
+# NFC properties
+nfc.                    u:object_r:nfc_prop:s0
+
+# These properties are not normally set by processes other than init.
+# They are only distinguished here for setting by qemu-props on the
+# emulator/goldfish.
+config.                 u:object_r:config_prop:s0
+ro.config.              u:object_r:config_prop:s0
+dalvik.                 u:object_r:dalvik_prop:s0
+ro.dalvik.              u:object_r:dalvik_prop:s0
+
+# Shared between system server and wificond
+wifi.                   u:object_r:wifi_prop:s0
+wlan.                   u:object_r:wifi_prop:s0
+
+# Lowpan properties
+lowpan.                 u:object_r:lowpan_prop:s0
+ro.lowpan.              u:object_r:lowpan_prop:s0
+
+# heapprofd properties
+heapprofd.              u:object_r:heapprofd_prop:s0
+
+# hwservicemanager properties
+hwservicemanager.       u:object_r:hwservicemanager_prop:s0
+
+# Common default properties for vendor, odm, vendor_dlkm, and odm_dlkm.
+init.svc.odm.           u:object_r:vendor_default_prop:s0
+init.svc.vendor.        u:object_r:vendor_default_prop:s0
+ro.hardware.            u:object_r:vendor_default_prop:s0
+ro.odm.                 u:object_r:vendor_default_prop:s0
+ro.vendor.              u:object_r:vendor_default_prop:s0
+ro.vendor_dlkm.         u:object_r:vendor_default_prop:s0
+ro.odm_dlkm.            u:object_r:vendor_default_prop:s0
+odm.                    u:object_r:vendor_default_prop:s0
+persist.odm.            u:object_r:vendor_default_prop:s0
+persist.vendor.         u:object_r:vendor_default_prop:s0
+vendor.                 u:object_r:vendor_default_prop:s0
+
+# Properties that relate to time / time zone detection behavior.
+persist.time.           u:object_r:time_prop:s0
+
+# Properties that relate to server configurable flags
+device_config.reset_performed           u:object_r:device_config_reset_performed_prop:s0
+persist.device_config.activity_manager_native_boot. u:object_r:device_config_activity_manager_native_boot_prop:s0
+persist.device_config.attempted_boot_count        u:object_r:device_config_boot_count_prop:s0
+persist.device_config.input_native_boot. u:object_r:device_config_input_native_boot_prop:s0
+persist.device_config.netd_native.           u:object_r:device_config_netd_native_prop:s0
+persist.device_config.runtime_native.        u:object_r:device_config_runtime_native_prop:s0
+persist.device_config.runtime_native_boot.   u:object_r:device_config_runtime_native_boot_prop:s0
+persist.device_config.media_native.          u:object_r:device_config_media_native_prop:s0
+persist.device_config.storage_native_boot.   u:object_r:device_config_storage_native_boot_prop:s0
+persist.device_config.window_manager_native_boot. u:object_r:device_config_window_manager_native_boot_prop:s0
+persist.device_config.configuration. u:object_r:device_config_configuration_prop:s0
+
+# Properties that relate to legacy server configurable flags
+persist.device_config.global_settings.sys_traced u:object_r:device_config_sys_traced_prop:s0
+
+apexd.                  u:object_r:apexd_prop:s0
+persist.apexd.          u:object_r:apexd_prop:s0
+
+bpf.progs_loaded        u:object_r:bpf_progs_loaded_prop:s0
+
+gsid.                   u:object_r:gsid_prop:s0
+ro.gsid.                u:object_r:gsid_prop:s0
+
+# Property for disabling NNAPI vendor extensions on product image (used on GSI /product image,
+# which can't use NNAPI vendor extensions).
+ro.nnapi.extensions.deny_on_product                u:object_r:nnapi_ext_deny_product_prop:s0
+
+# Property that is set once ueventd finishes cold boot.
+ro.cold_boot_done       u:object_r:cold_boot_done_prop:s0
+
+# Charger properties
+ro.charger.                 u:object_r:charger_prop:s0
+sys.boot_from_charger_mode  u:object_r:charger_status_prop:s0 exact int
+ro.enable_boot_charger_mode u:object_r:charger_config_prop:s0 exact bool
+
+# Virtual A/B properties
+ro.virtual_ab.enabled   u:object_r:virtual_ab_prop:s0
+ro.virtual_ab.retrofit  u:object_r:virtual_ab_prop:s0
+
+ro.product.ab_ota_partitions u:object_r:ota_prop:s0 exact string
+# Property to set/clear the warm reset flag after an OTA update.
+ota.warm_reset  u:object_r:ota_prop:s0
+
+# Module properties
+com.android.sdkext.                  u:object_r:module_sdkextensions_prop:s0
+persist.com.android.sdkext.          u:object_r:module_sdkextensions_prop:s0
+
+# Userspace reboot properties
+sys.userspace_reboot.log.         u:object_r:userspace_reboot_log_prop:s0
+persist.sys.userspace_reboot.log. u:object_r:userspace_reboot_log_prop:s0
+
+# Integer property which is used in libgui to configure the number of frames
+# tracked by buffer queue's frame event timing history. The property is set
+# by devices with video decoding pipelines long enough to overflow the default
+# history size.
+ro.lib_gui.frame_event_history_size u:object_r:bq_config_prop:s0
+
+af.fast_track_multiplier     u:object_r:audio_config_prop:s0 exact int
+ro.af.client_heap_size_kbyte u:object_r:audio_config_prop:s0 exact int
+
+audio.camerasound.force         u:object_r:audio_config_prop:s0 exact bool
+audio.deep_buffer.media         u:object_r:audio_config_prop:s0 exact bool
+audio.offload.video             u:object_r:audio_config_prop:s0 exact bool
+audio.offload.min.duration.secs u:object_r:audio_config_prop:s0 exact int
+
+ro.audio.ignore_effects  u:object_r:audio_config_prop:s0 exact bool
+ro.audio.monitorRotation u:object_r:audio_config_prop:s0 exact bool
+
+persist.config.calibration_fac u:object_r:camera_calibration_prop:s0 exact string
+
+config.disable_cameraservice u:object_r:camera_config_prop:s0 exact bool
+
+camera.disable_zsl_mode u:object_r:camera_config_prop:s0 exact bool
+camera.fifo.disable     u:object_r:camera_config_prop:s0 exact bool
+ro.camera.notify_nfc    u:object_r:camera_config_prop:s0 exact bool
+ro.camera.enableLazyHal u:object_r:camera_config_prop:s0 exact bool
+
+# Should always_debuggable be bool? It's checked against the string "1".
+dalvik.vm.always_debuggable                   u:object_r:dalvik_config_prop:s0 exact int
+dalvik.vm.appimageformat                      u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.backgroundgctype                    u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.boot-dex2oat-cpu-set                u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.boot-dex2oat-threads                u:object_r:dalvik_config_prop:s0 exact int
+dalvik.vm.boot-image                          u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.checkjni                            u:object_r:dalvik_config_prop:s0 exact bool
+dalvik.vm.dex2oat-Xms                         u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.dex2oat-Xmx                         u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.dex2oat-cpu-set                     u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.dex2oat-filter                      u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.dex2oat-flags                       u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.dex2oat-max-image-block-size        u:object_r:dalvik_config_prop:s0 exact int
+dalvik.vm.dex2oat-minidebuginfo               u:object_r:dalvik_config_prop:s0 exact bool
+dalvik.vm.dex2oat-resolve-startup-strings     u:object_r:dalvik_config_prop:s0 exact bool
+dalvik.vm.dex2oat-threads                     u:object_r:dalvik_config_prop:s0 exact int
+dalvik.vm.dex2oat-updatable-bcp-packages-file u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.dex2oat-very-large                  u:object_r:dalvik_config_prop:s0 exact int
+dalvik.vm.dex2oat-swap                        u:object_r:dalvik_config_prop:s0 exact bool
+dalvik.vm.dex2oat64.enabled                   u:object_r:dalvik_config_prop:s0 exact bool
+dalvik.vm.dexopt.secondary                    u:object_r:dalvik_config_prop:s0 exact bool
+dalvik.vm.execution-mode                      u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.extra-opts                          u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.foreground-heap-growth-multiplier   u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.gctype                              u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.heapgrowthlimit                     u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.heapmaxfree                         u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.heapminfree                         u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.heapsize                            u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.heapstartsize                       u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.heaptargetutilization               u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.hot-startup-method-samples          u:object_r:dalvik_config_prop:s0 exact int
+dalvik.vm.image-dex2oat-Xms                   u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.image-dex2oat-Xmx                   u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.image-dex2oat-cpu-set               u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.image-dex2oat-filter                u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.image-dex2oat-flags                 u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.image-dex2oat-threads               u:object_r:dalvik_config_prop:s0 exact int
+dalvik.vm.isa.arm.features                    u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.isa.arm.variant                     u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.isa.arm64.features                  u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.isa.arm64.variant                   u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.isa.mips.features                   u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.isa.mips.variant                    u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.isa.mips64.features                 u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.isa.mips64.variant                  u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.isa.unknown.features                u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.isa.unknown.variant                 u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.isa.x86.features                    u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.isa.x86.variant                     u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.isa.x86_64.features                 u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.isa.x86_64.variant                  u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.jitinitialsize                      u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.jitmaxsize                          u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.jitprithreadweight                  u:object_r:dalvik_config_prop:s0 exact int
+dalvik.vm.jitthreshold                        u:object_r:dalvik_config_prop:s0 exact int
+dalvik.vm.jittransitionweight                 u:object_r:dalvik_config_prop:s0 exact int
+dalvik.vm.jniopts                             u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.lockprof.threshold                  u:object_r:dalvik_config_prop:s0 exact int
+dalvik.vm.method-trace                        u:object_r:dalvik_config_prop:s0 exact bool
+dalvik.vm.method-trace-file                   u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.method-trace-file-siz               u:object_r:dalvik_config_prop:s0 exact int
+dalvik.vm.method-trace-stream                 u:object_r:dalvik_config_prop:s0 exact bool
+dalvik.vm.profilesystemserver                 u:object_r:dalvik_config_prop:s0 exact bool
+dalvik.vm.profilebootclasspath                u:object_r:dalvik_config_prop:s0 exact bool
+dalvik.vm.restore-dex2oat-cpu-set             u:object_r:dalvik_config_prop:s0 exact string
+dalvik.vm.restore-dex2oat-threads             u:object_r:dalvik_config_prop:s0 exact int
+dalvik.vm.usejit                              u:object_r:dalvik_config_prop:s0 exact bool
+dalvik.vm.usejitprofiles                      u:object_r:dalvik_config_prop:s0 exact bool
+dalvik.vm.zygote.max-boot-retry               u:object_r:dalvik_config_prop:s0 exact int
+ro.zygote                                     u:object_r:dalvik_config_prop:s0 exact string
+
+persist.sys.dalvik.vm.lib.2 u:object_r:dalvik_runtime_prop:s0 exact string
+
+keyguard.no_require_sim u:object_r:keyguard_config_prop:s0 exact bool
+
+media.recorder.show_manufacturer_and_model   u:object_r:media_config_prop:s0 exact bool
+media.stagefright.cache-params               u:object_r:media_config_prop:s0 exact string
+media.stagefright.thumbnail.prefer_hw_codecs u:object_r:media_config_prop:s0 exact bool
+persist.sys.media.avsync                     u:object_r:media_config_prop:s0 exact bool
+
+persist.bluetooth.a2dp_offload.cap             u:object_r:bluetooth_a2dp_offload_prop:s0 exact string
+persist.bluetooth.a2dp_offload.disabled        u:object_r:bluetooth_a2dp_offload_prop:s0 exact bool
+persist.bluetooth.bluetooth_audio_hal.disabled u:object_r:bluetooth_audio_hal_prop:s0 exact bool
+persist.bluetooth.btsnoopenable                u:object_r:exported_bluetooth_prop:s0 exact bool
+
+persist.radio.multisim.config u:object_r:radio_control_prop:s0 exact string
+
+persist.sys.hdmi.keep_awake              u:object_r:hdmi_config_prop:s0 exact bool
+ro.hdmi.cec_device_types                 u:object_r:hdmi_config_prop:s0 exact string
+ro.hdmi.device_type                      u:object_r:hdmi_config_prop:s0 exact string
+ro.hdmi.wake_on_hotplug                  u:object_r:hdmi_config_prop:s0 exact bool
+ro.hdmi.cec.source.send_standby_on_sleep u:object_r:hdmi_config_prop:s0 exact enum to_tv broadcast none
+
+pm.dexopt.ab-ota                        u:object_r:exported_pm_prop:s0 exact string
+pm.dexopt.bg-dexopt                     u:object_r:exported_pm_prop:s0 exact string
+pm.dexopt.boot                          u:object_r:exported_pm_prop:s0 exact string
+pm.dexopt.disable_bg_dexopt             u:object_r:exported_pm_prop:s0 exact bool
+pm.dexopt.downgrade_after_inactive_days u:object_r:exported_pm_prop:s0 exact int
+pm.dexopt.first-boot                    u:object_r:exported_pm_prop:s0 exact string
+pm.dexopt.inactive                      u:object_r:exported_pm_prop:s0 exact string
+pm.dexopt.install                       u:object_r:exported_pm_prop:s0 exact string
+pm.dexopt.shared                        u:object_r:exported_pm_prop:s0 exact string
+
+ro.apk_verity.mode u:object_r:apk_verity_prop:s0 exact int
+
+ro.bluetooth.a2dp_offload.supported u:object_r:bluetooth_a2dp_offload_prop:s0 exact bool
+
+ro.boot.vendor.overlay.theme u:object_r:exported_overlay_prop:s0 exact string
+
+ro.bt.bdaddr_path u:object_r:exported_bluetooth_prop:s0 exact string
+
+ro.config.alarm_alert         u:object_r:systemsound_config_prop:s0 exact string
+ro.config.alarm_vol_default   u:object_r:systemsound_config_prop:s0 exact int
+ro.config.alarm_vol_steps     u:object_r:systemsound_config_prop:s0 exact int
+ro.config.media_vol_default   u:object_r:systemsound_config_prop:s0 exact int
+ro.config.media_vol_steps     u:object_r:systemsound_config_prop:s0 exact int
+ro.config.notification_sound  u:object_r:systemsound_config_prop:s0 exact string
+ro.config.ringtone            u:object_r:systemsound_config_prop:s0 exact string
+ro.config.system_vol_default  u:object_r:systemsound_config_prop:s0 exact int
+ro.config.system_vol_steps    u:object_r:systemsound_config_prop:s0 exact int
+ro.config.vc_call_vol_default u:object_r:systemsound_config_prop:s0 exact int
+
+ro.control_privapp_permissions u:object_r:packagemanager_config_prop:s0 exact enum disable enforce log
+ro.cp_system_other_odex        u:object_r:packagemanager_config_prop:s0 exact bool
+
+ro.crypto.allow_encrypt_override                u:object_r:vold_config_prop:s0 exact bool
+ro.crypto.dm_default_key.options_format.version u:object_r:vold_config_prop:s0 exact int
+ro.crypto.fde_algorithm                         u:object_r:vold_config_prop:s0 exact string
+ro.crypto.fde_sector_size                       u:object_r:vold_config_prop:s0 exact int
+ro.crypto.scrypt_params                         u:object_r:vold_config_prop:s0 exact string
+ro.crypto.set_dun                               u:object_r:vold_config_prop:s0 exact bool
+ro.crypto.volume.contents_mode                  u:object_r:vold_config_prop:s0 exact string
+ro.crypto.volume.filenames_mode                 u:object_r:vold_config_prop:s0 exact string
+ro.crypto.volume.metadata.encryption            u:object_r:vold_config_prop:s0 exact string
+ro.crypto.volume.metadata.method                u:object_r:vold_config_prop:s0 exact string
+ro.crypto.volume.options                        u:object_r:vold_config_prop:s0 exact string
+
+ro.dalvik.vm.native.bridge u:object_r:dalvik_config_prop:s0 exact string
+
+external_storage.projid.enabled   u:object_r:storage_config_prop:s0 exact bool
+external_storage.casefold.enabled u:object_r:storage_config_prop:s0 exact bool
+external_storage.sdcardfs.enabled u:object_r:storage_config_prop:s0 exact bool
+
+ro.config.per_app_memcg         u:object_r:lmkd_config_prop:s0 exact bool
+ro.lmk.critical                 u:object_r:lmkd_config_prop:s0 exact int
+ro.lmk.critical_upgrade         u:object_r:lmkd_config_prop:s0 exact bool
+ro.lmk.debug                    u:object_r:lmkd_config_prop:s0 exact bool
+ro.lmk.downgrade_pressure       u:object_r:lmkd_config_prop:s0 exact int
+ro.lmk.kill_heaviest_task       u:object_r:lmkd_config_prop:s0 exact bool
+ro.lmk.kill_timeout_ms          u:object_r:lmkd_config_prop:s0 exact int
+ro.lmk.low                      u:object_r:lmkd_config_prop:s0 exact int
+ro.lmk.medium                   u:object_r:lmkd_config_prop:s0 exact int
+ro.lmk.psi_partial_stall_ms     u:object_r:lmkd_config_prop:s0 exact int
+ro.lmk.psi_complete_stall_ms    u:object_r:lmkd_config_prop:s0 exact int
+ro.lmk.swap_free_low_percentage u:object_r:lmkd_config_prop:s0 exact int
+ro.lmk.swap_util_max            u:object_r:lmkd_config_prop:s0 exact int
+ro.lmk.thrashing_limit          u:object_r:lmkd_config_prop:s0 exact int
+ro.lmk.thrashing_limit_decay    u:object_r:lmkd_config_prop:s0 exact int
+ro.lmk.use_minfree_levels       u:object_r:lmkd_config_prop:s0 exact bool
+ro.lmk.upgrade_pressure         u:object_r:lmkd_config_prop:s0 exact int
+lmkd.reinit                     u:object_r:lmkd_prop:s0 exact int
+
+ro.media.xml_variant.codecs             u:object_r:media_variant_prop:s0 exact string
+ro.media.xml_variant.codecs_performance u:object_r:media_variant_prop:s0 exact string
+ro.media.xml_variant.profiles           u:object_r:media_variant_prop:s0 exact string
+
+ro.minui.default_rotation u:object_r:recovery_config_prop:s0 exact string
+ro.minui.overscan_percent u:object_r:recovery_config_prop:s0 exact int
+ro.minui.pixel_format     u:object_r:recovery_config_prop:s0 exact string
+
+ro.oem_unlock_supported u:object_r:oem_unlock_prop:s0 exact int
+
+ro.rebootescrow.device u:object_r:rebootescrow_hal_prop:s0 exact string
+
+ro.storage_manager.enabled u:object_r:storagemanager_config_prop:s0 exact bool
+
+ro.vehicle.hal u:object_r:vehicle_hal_prop:s0 exact string
+
+ro.vendor.build.security_patch u:object_r:vendor_security_patch_level_prop:s0 exact string
+
+ro.zram.mark_idle_delay_mins    u:object_r:zram_config_prop:s0 exact int
+ro.zram.first_wb_delay_mins     u:object_r:zram_config_prop:s0 exact int
+ro.zram.periodic_wb_delay_hours u:object_r:zram_config_prop:s0 exact int
+zram.force_writeback            u:object_r:zram_config_prop:s0 exact bool
+persist.sys.zram_enabled        u:object_r:zram_control_prop:s0 exact bool
+
+sendbug.preferred.domain u:object_r:sendbug_config_prop:s0 exact string
+
+persist.sys.usb.usbradio.config u:object_r:usb_control_prop:s0 exact string
+
+sys.usb.config     u:object_r:usb_control_prop:s0 exact string
+sys.usb.configfs   u:object_r:usb_control_prop:s0 exact int
+sys.usb.controller u:object_r:usb_control_prop:s0 exact string
+sys.usb.state      u:object_r:usb_control_prop:s0 exact string
+
+sys.usb.mtp.device_type u:object_r:usb_config_prop:s0 exact int
+
+sys.usb.config. u:object_r:usb_prop:s0
+
+sys.usb.ffs.aio_compat u:object_r:ffs_config_prop:s0 exact bool
+sys.usb.ffs.max_read   u:object_r:ffs_config_prop:s0 exact int
+sys.usb.ffs.max_write  u:object_r:ffs_config_prop:s0 exact int
+
+sys.usb.ffs.ready     u:object_r:ffs_control_prop:s0 exact bool
+sys.usb.ffs.mtp.ready u:object_r:ffs_control_prop:s0 exact bool
+
+tombstoned.max_tombstone_count u:object_r:tombstone_config_prop:s0 exact int
+
+vold.post_fs_data_done u:object_r:vold_config_prop:s0 exact int
+
+apexd.status u:object_r:apexd_prop:s0 exact enum starting activated ready
+
+dev.bootcomplete   u:object_r:boot_status_prop:s0 exact bool
+sys.boot_completed u:object_r:boot_status_prop:s0 exact bool
+
+persist.sys.device_provisioned u:object_r:provisioned_prop:s0 exact string
+
+persist.sys.theme               u:object_r:theme_prop:s0 exact string
+
+sys.retaildemo.enabled u:object_r:retaildemo_prop:s0 exact int
+
+sys.user.0.ce_available u:object_r:exported3_system_prop:s0 exact bool
+
+aac_drc_boost            u:object_r:aac_drc_prop:s0 exact int
+aac_drc_cut              u:object_r:aac_drc_prop:s0 exact int
+aac_drc_enc_target_level u:object_r:aac_drc_prop:s0 exact int
+aac_drc_heavy            u:object_r:aac_drc_prop:s0 exact int
+aac_drc_reference_level  u:object_r:aac_drc_prop:s0 exact int
+ro.aac_drc_effect_type   u:object_r:aac_drc_prop:s0 exact int
+
+build.version.extensions. u:object_r:module_sdkextensions_prop:s0 prefix int
+
+drm.64bit.enabled            u:object_r:mediadrm_config_prop:s0 exact bool
+media.mediadrmservice.enable u:object_r:mediadrm_config_prop:s0 exact bool
+
+drm.service.enabled u:object_r:drm_service_config_prop:s0 exact bool
+
+dumpstate.dry_run u:object_r:exported_dumpstate_prop:s0 exact bool
+dumpstate.unroot  u:object_r:exported_dumpstate_prop:s0 exact bool
+persist.dumpstate.verbose_logging.enabled u:object_r:hal_dumpstate_config_prop:s0 exact bool
+
+hal.instrumentation.enable u:object_r:hal_instrumentation_prop:s0 exact bool
+
+# default contexts only accessible by coredomain
+init.svc. u:object_r:init_service_status_private_prop:s0 prefix string
+
+# vendor-init-readable init service props
+init.svc.bugreport      u:object_r:init_service_status_prop:s0 exact string
+init.svc.bugreportd     u:object_r:init_service_status_prop:s0 exact string
+init.svc.console        u:object_r:init_service_status_prop:s0 exact string
+init.svc.dumpstatez     u:object_r:init_service_status_prop:s0 exact string
+init.svc.mediadrm       u:object_r:init_service_status_prop:s0 exact string
+init.svc.statsd         u:object_r:init_service_status_prop:s0 exact string
+init.svc.surfaceflinger u:object_r:init_service_status_prop:s0 exact string
+init.svc.tombstoned     u:object_r:init_service_status_prop:s0 exact string
+init.svc.zygote         u:object_r:init_service_status_prop:s0 exact string
+
+libc.debug.malloc.options u:object_r:libc_debug_prop:s0 exact string
+libc.debug.malloc.program u:object_r:libc_debug_prop:s0 exact string
+libc.debug.hooks.enable   u:object_r:libc_debug_prop:s0 exact string
+
+net.redirect_socket_calls.hooked u:object_r:socket_hook_prop:s0 exact bool
+
+persist.sys.locale       u:object_r:exported_system_prop:s0 exact string
+persist.sys.timezone     u:object_r:exported_system_prop:s0 exact string
+persist.sys.test_harness u:object_r:test_harness_prop:s0 exact bool
+
+ro.arch u:object_r:build_prop:s0 exact string
+
+# ro.boot. properties are set based on kernel commandline arguments, which are vendor owned.
+ro.boot.                   u:object_r:bootloader_prop:s0
+ro.boot.avb_version        u:object_r:bootloader_prop:s0 exact string
+ro.boot.baseband           u:object_r:bootloader_prop:s0 exact string
+ro.boot.bootdevice         u:object_r:bootloader_prop:s0 exact string
+ro.boot.bootloader         u:object_r:bootloader_prop:s0 exact string
+ro.boot.boottime           u:object_r:bootloader_prop:s0 exact string
+ro.boot.console            u:object_r:bootloader_prop:s0 exact string
+ro.boot.hardware           u:object_r:bootloader_prop:s0 exact string
+ro.boot.hardware.color     u:object_r:bootloader_prop:s0 exact string
+ro.boot.hardware.sku       u:object_r:bootloader_prop:s0 exact string
+ro.boot.keymaster          u:object_r:bootloader_prop:s0 exact string
+ro.boot.mode               u:object_r:bootloader_prop:s0 exact string
+ro.boot.revision           u:object_r:bootloader_prop:s0 exact string
+ro.boot.vbmeta.avb_version u:object_r:bootloader_prop:s0 exact string
+ro.boot.verifiedbootstate  u:object_r:bootloader_prop:s0 exact string
+ro.boot.veritymode         u:object_r:bootloader_prop:s0 exact string
+
+# These ro.X properties are set to values of ro.boot.X by property_service.
+ro.baseband   u:object_r:bootloader_prop:s0 exact string
+ro.bootloader u:object_r:bootloader_prop:s0 exact string
+ro.bootmode   u:object_r:bootloader_prop:s0 exact string
+ro.hardware   u:object_r:bootloader_prop:s0 exact string
+ro.revision   u:object_r:bootloader_prop:s0 exact string
+
+ro.boot.dynamic_partitions          u:object_r:exported_default_prop:s0 exact string
+ro.boot.dynamic_partitions_retrofit u:object_r:exported_default_prop:s0 exact string
+
+ro.build.date                        u:object_r:build_prop:s0 exact string
+ro.build.date.utc                    u:object_r:build_prop:s0 exact int
+ro.build.description                 u:object_r:build_prop:s0 exact string
+ro.build.display.id                  u:object_r:build_prop:s0 exact string
+ro.build.host                        u:object_r:build_prop:s0 exact string
+ro.build.id                          u:object_r:build_prop:s0 exact string
+ro.build.product                     u:object_r:build_prop:s0 exact string
+ro.build.system_root_image           u:object_r:build_prop:s0 exact bool
+ro.build.tags                        u:object_r:build_prop:s0 exact string
+ro.build.type                        u:object_r:build_prop:s0 exact string
+ro.build.user                        u:object_r:build_prop:s0 exact string
+ro.build.version.base_os             u:object_r:build_prop:s0 exact string
+ro.build.version.codename            u:object_r:build_prop:s0 exact string
+ro.build.version.incremental         u:object_r:build_prop:s0 exact string
+ro.build.version.preview_sdk         u:object_r:build_prop:s0 exact int
+ro.build.version.release             u:object_r:build_prop:s0 exact string
+ro.build.version.release_or_codename u:object_r:build_prop:s0 exact string
+ro.build.version.sdk                 u:object_r:build_prop:s0 exact int
+ro.build.version.security_patch      u:object_r:build_prop:s0 exact string
+
+ro.debuggable u:object_r:build_prop:s0 exact bool
+
+ro.product.cpu.abi       u:object_r:build_prop:s0 exact string
+ro.product.cpu.abilist   u:object_r:build_prop:s0 exact string
+ro.product.cpu.abilist32 u:object_r:build_prop:s0 exact string
+ro.product.cpu.abilist64 u:object_r:build_prop:s0 exact string
+
+ro.adb.secure u:object_r:build_prop:s0 exact bool
+ro.secure     u:object_r:build_prop:s0 exact int
+
+# These 5 properties are set by property_service
+ro.product.brand         u:object_r:build_prop:s0 exact string
+ro.product.device        u:object_r:build_prop:s0 exact string
+ro.product.manufacturer  u:object_r:build_prop:s0 exact string
+ro.product.model         u:object_r:build_prop:s0 exact string
+ro.product.name          u:object_r:build_prop:s0 exact string
+
+# Sanitizer properties
+ro.sanitize.address          u:object_r:build_prop:s0 exact bool
+ro.sanitize.cfi              u:object_r:build_prop:s0 exact bool
+ro.sanitize.default-ub       u:object_r:build_prop:s0 exact bool
+ro.sanitize.fuzzer           u:object_r:build_prop:s0 exact bool
+ro.sanitize.hwaddress        u:object_r:build_prop:s0 exact bool
+ro.sanitize.integer_overflow u:object_r:build_prop:s0 exact bool
+ro.sanitize.safe-stack       u:object_r:build_prop:s0 exact bool
+ro.sanitize.scudo            u:object_r:build_prop:s0 exact bool
+ro.sanitize.thread           u:object_r:build_prop:s0 exact bool
+ro.sanitize.undefined        u:object_r:build_prop:s0 exact bool
+
+# All odm build props are set by /odm/build.prop
+ro.odm.build.date                u:object_r:build_odm_prop:s0 exact string
+ro.odm.build.date.utc            u:object_r:build_odm_prop:s0 exact int
+ro.odm.build.fingerprint         u:object_r:build_odm_prop:s0 exact string
+ro.odm.build.version.incremental u:object_r:build_odm_prop:s0 exact string
+
+ro.product.odm.brand        u:object_r:build_odm_prop:s0 exact string
+ro.product.odm.device       u:object_r:build_odm_prop:s0 exact string
+ro.product.odm.manufacturer u:object_r:build_odm_prop:s0 exact string
+ro.product.odm.model        u:object_r:build_odm_prop:s0 exact string
+ro.product.odm.name         u:object_r:build_odm_prop:s0 exact string
+
+# All vendor_dlkm build props are set by /vendor_dlkm/etc/build.prop
+ro.vendor_dlkm.build.date                u:object_r:build_vendor_prop:s0 exact string
+ro.vendor_dlkm.build.date.utc            u:object_r:build_vendor_prop:s0 exact int
+ro.vendor_dlkm.build.fingerprint         u:object_r:build_vendor_prop:s0 exact string
+ro.vendor_dlkm.build.version.incremental u:object_r:build_vendor_prop:s0 exact string
+
+# All odm_dlkm build props are set by /odm_dlkm/etc/build.prop
+ro.odm_dlkm.build.date                u:object_r:build_vendor_prop:s0 exact string
+ro.odm_dlkm.build.date.utc            u:object_r:build_vendor_prop:s0 exact int
+ro.odm_dlkm.build.fingerprint         u:object_r:build_vendor_prop:s0 exact string
+ro.odm_dlkm.build.version.incremental u:object_r:build_vendor_prop:s0 exact string
+
+# All vendor build props are set by /vendor/build.prop
+ro.vendor.build.date                u:object_r:build_vendor_prop:s0 exact string
+ro.vendor.build.date.utc            u:object_r:build_vendor_prop:s0 exact int
+ro.vendor.build.fingerprint         u:object_r:build_vendor_prop:s0 exact string
+ro.vendor.build.version.incremental u:object_r:build_vendor_prop:s0 exact string
+ro.vendor.build.version.sdk         u:object_r:build_vendor_prop:s0 exact int
+
+ro.product.board               u:object_r:build_vendor_prop:s0 exact string
+ro.product.first_api_level     u:object_r:build_vendor_prop:s0 exact int
+ro.product.vendor.brand        u:object_r:build_vendor_prop:s0 exact string
+ro.product.vendor.device       u:object_r:build_vendor_prop:s0 exact string
+ro.product.vendor.manufacturer u:object_r:build_vendor_prop:s0 exact string
+ro.product.vendor.model        u:object_r:build_vendor_prop:s0 exact string
+ro.product.vendor.name         u:object_r:build_vendor_prop:s0 exact string
+
+ro.crypto.state u:object_r:vold_status_prop:s0 exact enum encrypted unencrypted unsupported
+ro.crypto.type  u:object_r:vold_status_prop:s0 exact enum block file none
+
+ro.property_service.version u:object_r:property_service_version_prop:s0 exact int
+
+ro.vendor.redirect_socket_calls u:object_r:vendor_socket_hook_prop:s0 exact bool
+
+service.bootanim.exit u:object_r:exported_system_prop:s0 exact int
+
+sys.init.userspace_reboot.in_progress u:object_r:userspace_reboot_exported_prop:s0 exact bool
+sys.use_memfd                         u:object_r:use_memfd_prop:s0 exact bool
+
+vold.decrypt u:object_r:vold_status_prop:s0 exact string
+
+aaudio.hw_burst_min_usec     u:object_r:aaudio_config_prop:s0 exact int
+aaudio.minimum_sleep_usec    u:object_r:aaudio_config_prop:s0 exact int
+aaudio.mixer_bursts          u:object_r:aaudio_config_prop:s0 exact int
+aaudio.mmap_exclusive_policy u:object_r:aaudio_config_prop:s0 exact int
+aaudio.mmap_policy           u:object_r:aaudio_config_prop:s0 exact int
+aaudio.wakeup_delay_usec     u:object_r:aaudio_config_prop:s0 exact int
+
+persist.rcs.supported u:object_r:exported_default_prop:s0 exact int
+
+ro.bionic.2nd_arch        u:object_r:cpu_variant_prop:s0 exact string
+ro.bionic.2nd_cpu_variant u:object_r:cpu_variant_prop:s0 exact string
+ro.bionic.arch            u:object_r:cpu_variant_prop:s0 exact string
+ro.bionic.cpu_variant     u:object_r:cpu_variant_prop:s0 exact string
+
+ro.board.platform u:object_r:exported_default_prop:s0 exact string
+
+ro.boot.fake_battery         u:object_r:exported_default_prop:s0 exact int
+ro.boot.fstab_suffix         u:object_r:exported_default_prop:s0 exact string
+ro.boot.hardware.revision    u:object_r:exported_default_prop:s0 exact string
+ro.boot.product.hardware.sku u:object_r:exported_default_prop:s0 exact string
+ro.boot.product.vendor.sku   u:object_r:exported_default_prop:s0 exact string
+ro.boot.slot_suffix          u:object_r:exported_default_prop:s0 exact string
+
+ro.boringcrypto.hwrand u:object_r:exported_default_prop:s0 exact bool
+
+ro.build.ab_update         u:object_r:exported_default_prop:s0 exact string
+ro.build.expect.baseband   u:object_r:exported_default_prop:s0 exact string
+ro.build.expect.bootloader u:object_r:exported_default_prop:s0 exact string
+
+ro.carrier u:object_r:exported_default_prop:s0 exact string
+
+ro.config.low_ram           u:object_r:exported_config_prop:s0 exact bool
+ro.config.vc_call_vol_steps u:object_r:exported_config_prop:s0 exact int
+
+ro.frp.pst u:object_r:exported_default_prop:s0 exact string
+
+ro.hardware.activity_recognition u:object_r:exported_default_prop:s0 exact string
+ro.hardware.audio                u:object_r:exported_default_prop:s0 exact string
+ro.hardware.audio.a2dp           u:object_r:exported_default_prop:s0 exact string
+ro.hardware.audio.hearing_aid    u:object_r:exported_default_prop:s0 exact string
+ro.hardware.audio.primary        u:object_r:exported_default_prop:s0 exact string
+ro.hardware.audio.usb            u:object_r:exported_default_prop:s0 exact string
+ro.hardware.audio_policy         u:object_r:exported_default_prop:s0 exact string
+ro.hardware.bootctrl             u:object_r:exported_default_prop:s0 exact string
+ro.hardware.camera               u:object_r:exported_default_prop:s0 exact string
+ro.hardware.consumerir           u:object_r:exported_default_prop:s0 exact string
+ro.hardware.context_hub          u:object_r:exported_default_prop:s0 exact string
+ro.hardware.egl                  u:object_r:exported_default_prop:s0 exact string
+ro.hardware.fingerprint          u:object_r:exported_default_prop:s0 exact string
+ro.hardware.flp                  u:object_r:exported_default_prop:s0 exact string
+ro.hardware.gatekeeper           u:object_r:exported_default_prop:s0 exact string
+ro.hardware.gps                  u:object_r:exported_default_prop:s0 exact string
+ro.hardware.gralloc              u:object_r:exported_default_prop:s0 exact string
+ro.hardware.hdmi_cec             u:object_r:exported_default_prop:s0 exact string
+ro.hardware.hwcomposer           u:object_r:exported_default_prop:s0 exact string
+ro.hardware.input                u:object_r:exported_default_prop:s0 exact string
+ro.hardware.keystore             u:object_r:exported_default_prop:s0 exact string
+ro.hardware.keystore_desede      u:object_r:exported_default_prop:s0 exact string
+ro.hardware.lights               u:object_r:exported_default_prop:s0 exact string
+ro.hardware.local_time           u:object_r:exported_default_prop:s0 exact string
+ro.hardware.memtrack             u:object_r:exported_default_prop:s0 exact string
+ro.hardware.nfc                  u:object_r:exported_default_prop:s0 exact string
+ro.hardware.nfc_nci              u:object_r:exported_default_prop:s0 exact string
+ro.hardware.nfc_tag              u:object_r:exported_default_prop:s0 exact string
+ro.hardware.nvram                u:object_r:exported_default_prop:s0 exact string
+ro.hardware.power                u:object_r:exported_default_prop:s0 exact string
+ro.hardware.radio                u:object_r:exported_default_prop:s0 exact string
+ro.hardware.sensors              u:object_r:exported_default_prop:s0 exact string
+ro.hardware.sound_trigger        u:object_r:exported_default_prop:s0 exact string
+ro.hardware.thermal              u:object_r:exported_default_prop:s0 exact string
+ro.hardware.tv_input             u:object_r:exported_default_prop:s0 exact string
+ro.hardware.type                 u:object_r:exported_default_prop:s0 exact string
+ro.hardware.vehicle              u:object_r:exported_default_prop:s0 exact string
+ro.hardware.vibrator             u:object_r:exported_default_prop:s0 exact string
+ro.hardware.virtual_device       u:object_r:exported_default_prop:s0 exact string
+ro.hardware.vulkan               u:object_r:exported_default_prop:s0 exact string
+
+ro.hwui.use_vulkan u:object_r:exported_default_prop:s0 exact bool
+
+ro.kernel.qemu             u:object_r:exported_default_prop:s0 exact bool
+ro.kernel.qemu.            u:object_r:exported_default_prop:s0
+ro.kernel.android.bootanim u:object_r:exported_default_prop:s0 exact int
+ro.kernel.ebpf.supported   u:object_r:exported_default_prop:s0 exact bool
+
+ro.oem.key1 u:object_r:exported_default_prop:s0 exact string
+
+ro.product.vndk.version u:object_r:vndk_prop:s0 exact string
+
+ro.vndk.lite    u:object_r:vndk_prop:s0 exact bool
+ro.vndk.version u:object_r:vndk_prop:s0 exact string
+
+ro.vts.coverage u:object_r:vts_config_prop:s0 exact int
+
+vts.native_server.on u:object_r:vts_status_prop:s0 exact bool
+
+wifi.active.interface     u:object_r:wifi_hal_prop:s0 exact string
+wifi.aware.interface      u:object_r:wifi_hal_prop:s0 exact string
+wifi.concurrent.interface u:object_r:wifi_hal_prop:s0 exact string
+wifi.direct.interface     u:object_r:wifi_hal_prop:s0 exact string
+wifi.interface            u:object_r:wifi_hal_prop:s0 exact string
+wlan.driver.status        u:object_r:wifi_hal_prop:s0 exact enum ok unloaded
+
+ro.boot.wificountrycode u:object_r:wifi_config_prop:s0 exact string
+
+ro.apex.updatable u:object_r:exported_default_prop:s0 exact bool
+
+# Property to enable incremental feature
+ro.incremental.enable      u:object_r:incremental_prop:s0
+
+# Properties to configure userspace reboot.
+init.userspace_reboot.is_supported u:object_r:userspace_reboot_config_prop:s0 exact bool
+init.userspace_reboot.sigkill.timeoutmillis u:object_r:userspace_reboot_config_prop:s0 exact int
+init.userspace_reboot.sigterm.timeoutmillis u:object_r:userspace_reboot_config_prop:s0 exact int
+init.userspace_reboot.started.timeoutmillis u:object_r:userspace_reboot_config_prop:s0 exact int
+init.userspace_reboot.userdata_remount.timeoutmillis u:object_r:userspace_reboot_config_prop:s0 exact int
+init.userspace_reboot.watchdog.timeoutmillis u:object_r:userspace_reboot_config_prop:s0 exact int
+
+sys.shutdown.requested u:object_r:exported_system_prop:s0 exact string
+
+# surfaceflinger properties
+ro.surface_flinger.default_composition_dataspace          u:object_r:surfaceflinger_prop:s0 exact int
+ro.surface_flinger.default_composition_pixel_format       u:object_r:surfaceflinger_prop:s0 exact int
+ro.surface_flinger.force_hwc_copy_for_virtual_displays    u:object_r:surfaceflinger_prop:s0 exact bool
+ro.surface_flinger.has_HDR_display                        u:object_r:surfaceflinger_prop:s0 exact bool
+ro.surface_flinger.has_wide_color_display                 u:object_r:surfaceflinger_prop:s0 exact bool
+ro.surface_flinger.max_frame_buffer_acquired_buffers      u:object_r:surfaceflinger_prop:s0 exact int
+ro.surface_flinger.max_graphics_height                    u:object_r:surfaceflinger_prop:s0 exact int
+ro.surface_flinger.max_graphics_width                     u:object_r:surfaceflinger_prop:s0 exact int
+ro.surface_flinger.max_virtual_display_dimension          u:object_r:surfaceflinger_prop:s0 exact int
+ro.surface_flinger.primary_display_orientation            u:object_r:surfaceflinger_prop:s0 exact enum ORIENTATION_0 ORIENTATION_180 ORIENTATION_270 ORIENTATION_90
+ro.surface_flinger.present_time_offset_from_vsync_ns      u:object_r:surfaceflinger_prop:s0 exact int
+ro.surface_flinger.running_without_sync_framework         u:object_r:surfaceflinger_prop:s0 exact bool
+ro.surface_flinger.start_graphics_allocator_service       u:object_r:surfaceflinger_prop:s0 exact bool
+ro.surface_flinger.use_color_management                   u:object_r:surfaceflinger_prop:s0 exact bool
+ro.surface_flinger.use_context_priority                   u:object_r:surfaceflinger_prop:s0 exact bool
+ro.surface_flinger.use_vr_flinger                         u:object_r:surfaceflinger_prop:s0 exact bool
+ro.surface_flinger.vsync_event_phase_offset_ns            u:object_r:surfaceflinger_prop:s0 exact int
+ro.surface_flinger.vsync_sf_event_phase_offset_ns         u:object_r:surfaceflinger_prop:s0 exact int
+ro.surface_flinger.wcg_composition_dataspace              u:object_r:surfaceflinger_prop:s0 exact int
+ro.surface_flinger.wcg_composition_pixel_format           u:object_r:surfaceflinger_prop:s0 exact int
+ro.surface_flinger.display_primary_red                    u:object_r:surfaceflinger_prop:s0 exact string
+ro.surface_flinger.display_primary_green                  u:object_r:surfaceflinger_prop:s0 exact string
+ro.surface_flinger.display_primary_blue                   u:object_r:surfaceflinger_prop:s0 exact string
+ro.surface_flinger.display_primary_white                  u:object_r:surfaceflinger_prop:s0 exact string
+ro.surface_flinger.protected_contents                     u:object_r:surfaceflinger_prop:s0 exact bool
+ro.surface_flinger.set_idle_timer_ms                      u:object_r:surfaceflinger_prop:s0 exact int
+ro.surface_flinger.set_touch_timer_ms                     u:object_r:surfaceflinger_prop:s0 exact int
+ro.surface_flinger.set_display_power_timer_ms             u:object_r:surfaceflinger_prop:s0 exact int
+ro.surface_flinger.support_kernel_idle_timer              u:object_r:surfaceflinger_prop:s0 exact bool
+ro.surface_flinger.use_smart_90_for_video                 u:object_r:surfaceflinger_prop:s0 exact bool
+ro.surface_flinger.use_content_detection_for_refresh_rate u:object_r:surfaceflinger_prop:s0 exact bool
+ro.surface_flinger.color_space_agnostic_dataspace         u:object_r:surfaceflinger_prop:s0 exact int
+ro.surface_flinger.refresh_rate_switching                 u:object_r:surfaceflinger_prop:s0 exact bool
+
+ro.sf.disable_triple_buffer u:object_r:surfaceflinger_prop:s0 exact bool
+ro.sf.lcd_density           u:object_r:surfaceflinger_prop:s0 exact int
+
+persist.sys.sf.color_mode       u:object_r:surfaceflinger_color_prop:s0 exact int
+persist.sys.sf.color_saturation u:object_r:surfaceflinger_color_prop:s0 exact string
+persist.sys.sf.native_mode      u:object_r:surfaceflinger_color_prop:s0 exact int
+
+# Binder cache properties.  These are world-readable
+cache_key.app_inactive                   u:object_r:binder_cache_system_server_prop:s0
+cache_key.is_compat_change_enabled       u:object_r:binder_cache_system_server_prop:s0
+cache_key.get_packages_for_uid           u:object_r:binder_cache_system_server_prop:s0
+cache_key.has_system_feature             u:object_r:binder_cache_system_server_prop:s0
+cache_key.is_interactive                 u:object_r:binder_cache_system_server_prop:s0
+cache_key.is_power_save_mode             u:object_r:binder_cache_system_server_prop:s0
+cache_key.is_user_unlocked               u:object_r:binder_cache_system_server_prop:s0
+cache_key.volume_list                    u:object_r:binder_cache_system_server_prop:s0
+cache_key.display_info                   u:object_r:binder_cache_system_server_prop:s0
+cache_key.location_enabled               u:object_r:binder_cache_system_server_prop:s0
+cache_key.package_info                   u:object_r:binder_cache_system_server_prop:s0
+
+cache_key.bluetooth.                     u:object_r:binder_cache_bluetooth_server_prop:s0 prefix string
+cache_key.system_server.                 u:object_r:binder_cache_system_server_prop:s0 prefix string
+cache_key.telephony.                     u:object_r:binder_cache_telephony_server_prop:s0 prefix string
+
+gsm.sim.operator.numeric       u:object_r:telephony_status_prop:s0 exact string
+persist.radio.airplane_mode_on u:object_r:telephony_status_prop:s0 exact bool
+
+ro.com.android.dataroaming        u:object_r:telephony_config_prop:s0 exact bool
+ro.com.android.prov_mobiledata    u:object_r:telephony_config_prop:s0 exact bool
+ro.radio.noril                    u:object_r:telephony_config_prop:s0 exact string
+ro.telephony.call_ring.multiple   u:object_r:telephony_config_prop:s0 exact bool
+ro.telephony.default_cdma_sub     u:object_r:telephony_config_prop:s0 exact int
+ro.telephony.default_network      u:object_r:telephony_config_prop:s0 exact string
+ro.telephony.iwlan_operation_mode u:object_r:telephony_config_prop:s0 exact enum default legacy AP-assisted
+telephony.active_modems.max_count u:object_r:telephony_config_prop:s0 exact int
+telephony.lteOnCdmaDevice         u:object_r:telephony_config_prop:s0 exact int
+persist.dbg.volte_avail_ovr       u:object_r:telephony_config_prop:s0 exact int
+persist.dbg.vt_avail_ovr          u:object_r:telephony_config_prop:s0 exact int
+persist.dbg.wfc_avail_ovr         u:object_r:telephony_config_prop:s0 exact int
+
+# System locale list filter configuration
+ro.localization.locale_filter u:object_r:localization_prop:s0 exact string
+
+# Graphics related properties
+ro.opengles.version u:object_r:graphics_config_prop:s0 exact int
+
+ro.gfx.driver.0        u:object_r:graphics_config_prop:s0 exact string
+ro.gfx.driver.1        u:object_r:graphics_config_prop:s0 exact string
+ro.gfx.angle.supported u:object_r:graphics_config_prop:s0 exact bool
+
+graphics.gpu.profiler.support          u:object_r:graphics_config_prop:s0 exact bool
+graphics.gpu.profiler.vulkan_layer_apk u:object_r:graphics_config_prop:s0 exact string
+    )";
diff --git a/libc/system_properties/contexts_split.cpp b/libc/system_properties/contexts_split.cpp
index 96b01a4..f71d70a 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) {
@@ -324,10 +324,16 @@
   return true;
 }
 
-prop_area* ContextsSplit::GetPropAreaForName(const char* name) {
+PrefixNode* ContextsSplit::GetPrefixNodeForName(const char* name) {
   auto entry = ListFind(prefixes_, [name](PrefixNode* l) {
     return l->prefix[0] == '*' || !strncmp(l->prefix, name, l->prefix_len);
   });
+
+  return entry;
+}
+
+prop_area* ContextsSplit::GetPropAreaForName(const char* name) {
+  auto entry = GetPrefixNodeForName(name);
   if (!entry) {
     return nullptr;
   }
diff --git a/libc/system_properties/include/system_properties/contexts_split.h b/libc/system_properties/include/system_properties/contexts_split.h
index acb18e3..1d954cc 100644
--- a/libc/system_properties/include/system_properties/contexts_split.h
+++ b/libc/system_properties/include/system_properties/contexts_split.h
@@ -47,7 +47,9 @@
   virtual void ResetAccess() override;
   virtual void FreeAndUnmap() override;
 
- private:
+  PrefixNode* GetPrefixNodeForName(const char* name);
+
+ protected:
   bool MapSerialPropertyArea(bool access_rw, bool* fsetxattr_failed);
   bool InitializePropertiesFromFile(const char* filename);
   bool InitializeProperties();
diff --git a/libc/system_properties/include/system_properties/prop_trace.h b/libc/system_properties/include/system_properties/prop_trace.h
new file mode 100644
index 0000000..7c65a6d
--- /dev/null
+++ b/libc/system_properties/include/system_properties/prop_trace.h
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "platform/bionic/macros.h"
+
+#include "prop_info.h"
+
+// Tracing class for sysprop. To begin a trace at a specified point:
+//   SyspropTrace trace ("prop_name", "prop_value");
+// The trace will end when the constructor goes out of scope.
+// For read-only properties (ro.*), also need to pass prop_info struct.
+
+enum class PropertyAction {
+  kPropertyFind = 0,
+  kPropertySet,
+  kPropertyGetReadOnly,
+  kPropertyGetReadWrite,
+};
+
+class __LIBC_HIDDEN__ SyspropTrace {
+ public:
+  explicit SyspropTrace(const char* prop_name, const char* prop_value, const prop_info* pi,
+                        PropertyAction action);
+  ~SyspropTrace();
+
+ private:
+  const char* prop_name_;
+  const char* prop_value_;
+  const prop_info* prop_info_;
+  PropertyAction prop_action_;
+  bool output_trace_;
+
+  BIONIC_DISALLOW_COPY_AND_ASSIGN(SyspropTrace);
+};
diff --git a/libc/system_properties/prop_trace.cpp b/libc/system_properties/prop_trace.cpp
new file mode 100644
index 0000000..ac7ff94
--- /dev/null
+++ b/libc/system_properties/prop_trace.cpp
@@ -0,0 +1,113 @@
+/*
+ * 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 "system_properties/prop_trace.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "private/CachedProperty.h"
+#include "private/bionic_lock.h"
+#include "private/bionic_systrace.h"
+
+#include <async_safe/log.h>
+#include <cutils/trace.h>  // For ATRACE_TAG_SYSPROP.
+
+#define PROP_TRACE_MSG_LENGTH 1024
+
+static bool should_trace_prop(const char* prop_name) {
+  // Should not trace kTraceTagsProp to avoid infinite recursion.
+  // Because the following g_trace_enable_flags.Get() will get the property value
+  // of kTraceTagsProp again, which in turn invokes should_trace_prop() here.
+  if (prop_name == nullptr || !strcmp(prop_name, kTraceTagsProp)) {
+    return false;
+  }
+
+  return should_trace(ATRACE_TAG_SYSPROP);
+}
+
+static void sysprop_trace_end() {
+  int trace_marker_fd = get_trace_marker_fd();
+  if (trace_marker_fd == -1) {
+    return;
+  }
+
+  TEMP_FAILURE_RETRY(write(trace_marker_fd, "E|", 2));
+}
+
+static void get_sysprop_trace_end(const prop_info* pi, const char* prop_value,
+                                  bool read_only = false) {
+  const char* output_value;
+  char message[PROP_TRACE_MSG_LENGTH];
+
+  if (read_only) {
+    if (pi->is_long()) {
+      output_value = pi->long_value();
+    } else {
+      output_value = pi->value;
+    }
+  } else {
+    output_value = prop_value;
+  }
+
+  snprintf(message, sizeof(message), "prop_get: %s, value: %s", pi->name,
+           output_value ? output_value : "null_value");
+  output_trace(message, 'E');  // 'E' for end.
+}
+
+SyspropTrace::SyspropTrace(const char* prop_name, const char* prop_value, const prop_info* pi,
+                           PropertyAction action)
+    : prop_name_(prop_name),
+      prop_value_(prop_value),
+      prop_info_(pi),
+      prop_action_(action),
+      output_trace_(false) {
+  if (!should_trace_prop(prop_name)) {
+    return;
+  }
+
+  char message[PROP_TRACE_MSG_LENGTH];
+  if (prop_action_ == PropertyAction::kPropertyFind) {
+    snprintf(message, sizeof(message), "prop_find: %s", prop_name_);
+  } else if (prop_action_ == PropertyAction::kPropertySet) {
+    snprintf(message, sizeof(message), "prop_set: %s, value: %s", prop_name_,
+             prop_value_ ? prop_value_ : "null_value");
+  } else {
+    // For property get, the prop_value_ will be resolved then printed in the destructor.
+    snprintf(message, sizeof(message), "prop_get: %s", prop_name_);
+  }
+
+  output_trace(message, 'B');  // 'B' for begin.
+  output_trace_ = true;
+}
+
+SyspropTrace::~SyspropTrace() {
+  if (!output_trace_) {
+    return;
+  }
+  if (prop_action_ == PropertyAction::kPropertyFind ||
+      prop_action_ == PropertyAction::kPropertySet) {
+    sysprop_trace_end();
+  } else if (prop_action_ == PropertyAction::kPropertyGetReadOnly) {
+    get_sysprop_trace_end(prop_info_, prop_value_, true /* read_only */);
+  } else if (prop_action_ == PropertyAction::kPropertyGetReadWrite) {
+    get_sysprop_trace_end(prop_info_, prop_value_, false /* read_only */);
+  }
+  output_trace_ = false;
+}
diff --git a/libc/system_properties/system_properties.cpp b/libc/system_properties/system_properties.cpp
index 8404778..3fd20b7 100644
--- a/libc/system_properties/system_properties.cpp
+++ b/libc/system_properties/system_properties.cpp
@@ -46,6 +46,7 @@
 #include "system_properties/context_node.h"
 #include "system_properties/prop_area.h"
 #include "system_properties/prop_info.h"
+#include "system_properties/prop_trace.h"
 
 #define SERIAL_DIRTY(serial) ((serial)&1)
 #define SERIAL_VALUE_LEN(serial) ((serial) >> 24)
@@ -127,6 +128,9 @@
     return nullptr;
   }
 
+  SyspropTrace trace(name, nullptr /* prop_value */, nullptr /* prop_info */,
+                     PropertyAction::kPropertyFind);
+
   prop_area* pa = contexts_->GetPropAreaForName(name);
   if (!pa) {
     async_safe_format_log(ANDROID_LOG_ERROR, "libc", "Access denied finding property \"%s\"", name);
@@ -201,6 +205,10 @@
   // Read only properties don't need to copy the value to a temporary buffer, since it can never
   // change.  We use relaxed memory order on the serial load for the same reason.
   if (is_read_only(pi->name)) {
+    // The 2nd argument is not required for read-only property tracing, as the
+    // value can be obtained via pi->value or pi->long_value().
+    SyspropTrace trace(pi->name, nullptr /* prop_value */, pi /* prop_info */,
+                       PropertyAction::kPropertyGetReadOnly);
     uint32_t serial = load_const_atomic(&pi->serial, memory_order_relaxed);
     if (pi->is_long()) {
       callback(cookie, pi->name, pi->long_value(), serial);
@@ -211,6 +219,8 @@
   }
 
   char value_buf[PROP_VALUE_MAX];
+  SyspropTrace trace(pi->name, value_buf, pi /* prop_info */,
+                     PropertyAction::kPropertyGetReadWrite);
   uint32_t serial = ReadMutablePropertyValue(pi, value_buf);
   callback(cookie, pi->name, value_buf, serial);
 }
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/gensyscalls.py b/libc/tools/gensyscalls.py
index 0271a04..0e0e25f 100755
--- a/libc/tools/gensyscalls.py
+++ b/libc/tools/gensyscalls.py
@@ -459,6 +459,8 @@
         if syscall.has_key("asm-%s" % arch):
             print(syscall["asm-%s" % arch])
 
+    if arch == 'arm64':
+        print('\nNOTE_GNU_PROPERTY()\n')
 
 if __name__ == "__main__":
     if len(sys.argv) < 2:
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/tzcode/strptime.c b/libc/tzcode/strptime.c
index 41eaa9b..7e8e234 100644
--- a/libc/tzcode/strptime.c
+++ b/libc/tzcode/strptime.c
@@ -95,9 +95,22 @@
     int century;
     int relyear;
 };
+
+static char gmt[] = { "GMT" };
+static char utc[] = { "UTC" };
+/* RFC-822/RFC-2822 */
+static const char * const nast[5] = {
+       "EST",    "CST",    "MST",    "PST",    "\0\0\0"
+};
+static const char * const nadt[5] = {
+       "EDT",    "CDT",    "MDT",    "PDT",    "\0\0\0"
+};
+
 static  int _conv_num(const unsigned char **, int *, int, int);
 static  unsigned char *_strptime(const unsigned char *, const char *, struct tm *,
         struct century_relyear *);
+static	const u_char *_find_string(const u_char *, int *, const char * const *,
+	    const char * const *, int);
 
 
 char *
@@ -113,9 +126,10 @@
 _strptime(const unsigned char *buf, const char *fmt, struct tm *tm, struct century_relyear *cr)
 {
     unsigned char c;
-    const unsigned char *bp;
+    const unsigned char *bp, *ep;
     size_t len = 0;
-    int alt_format, i;
+    int alt_format, i, offs;
+    int neg = 0;
 
     bp = (unsigned char *)buf;
     while ((c = *fmt) != '\0') {
@@ -432,6 +446,108 @@
                 return (NULL);
             break;
 
+		case 'Z':
+			tzset();
+			if (strncmp((const char *)bp, gmt, 3) == 0) {
+				tm->tm_isdst = 0;
+				tm->tm_gmtoff = 0;
+				tm->tm_zone = gmt;
+				bp += 3;
+			} else if (strncmp((const char *)bp, utc, 3) == 0) {
+				tm->tm_isdst = 0;
+				tm->tm_gmtoff = 0;
+				tm->tm_zone = utc;
+				bp += 3;
+			} else {
+				ep = _find_string(bp, &i,
+						 (const char * const *)tzname,
+						  NULL, 2);
+				if (ep == NULL)
+					return (NULL);
+
+				tm->tm_isdst = i;
+				tm->tm_gmtoff = -(timezone);
+				tm->tm_zone = tzname[i];
+				bp = ep;
+			}
+			continue;
+
+		case 'z':
+			/*
+			 * We recognize all ISO 8601 formats:
+			 * Z	= Zulu time/UTC
+			 * [+-]hhmm
+			 * [+-]hh:mm
+			 * [+-]hh
+			 * We recognize all RFC-822/RFC-2822 formats:
+			 * UT|GMT
+			 *          North American : UTC offsets
+			 * E[DS]T = Eastern : -4 | -5
+			 * C[DS]T = Central : -5 | -6
+			 * M[DS]T = Mountain: -6 | -7
+			 * P[DS]T = Pacific : -7 | -8
+			 */
+			while (isspace(*bp))
+				bp++;
+
+			switch (*bp++) {
+			case 'G':
+				if (*bp++ != 'M')
+					return NULL;
+				/*FALLTHROUGH*/
+			case 'U':
+				if (*bp++ != 'T')
+					return NULL;
+				/*FALLTHROUGH*/
+			case 'Z':
+				tm->tm_isdst = 0;
+				tm->tm_gmtoff = 0;
+				tm->tm_zone = utc;
+				continue;
+			case '+':
+				neg = 0;
+				break;
+			case '-':
+				neg = 1;
+				break;
+			default:
+				--bp;
+				ep = _find_string(bp, &i, nast, NULL, 4);
+				if (ep != NULL) {
+					tm->tm_gmtoff = (-5 - i) * SECSPERHOUR;
+					tm->tm_zone = (char *)nast[i];
+					bp = ep;
+					continue;
+				}
+				ep = _find_string(bp, &i, nadt, NULL, 4);
+				if (ep != NULL) {
+					tm->tm_isdst = 1;
+					tm->tm_gmtoff = (-4 - i) * SECSPERHOUR;
+					tm->tm_zone = (char *)nadt[i];
+					bp = ep;
+					continue;
+				}
+				return NULL;
+			}
+			if (!isdigit(bp[0]) || !isdigit(bp[1]))
+				return NULL;
+			offs = ((bp[0]-'0') * 10 + (bp[1]-'0')) * SECSPERHOUR;
+			bp += 2;
+			if (*bp == ':')
+				bp++;
+			if (isdigit(*bp)) {
+				offs += (*bp++ - '0') * 10 * SECSPERMIN;
+				if (!isdigit(*bp))
+					return NULL;
+				offs += (*bp++ - '0') * SECSPERMIN;
+			}
+			if (neg)
+				offs = -offs;
+			tm->tm_isdst = 0;	/* XXX */
+			tm->tm_gmtoff = offs;
+			tm->tm_zone = NULL;	/* XXX */
+			continue;
+
         /*
          * Miscellaneous conversions.
          */
@@ -468,28 +584,49 @@
     return (unsigned char*)bp;
 }
 
-
 static int
 _conv_num(const unsigned char **buf, int *dest, int llim, int ulim)
 {
-    int result = 0;
-    int rulim = ulim;
+	int result = 0;
+	int rulim = ulim;
 
-    if (**buf < '0' || **buf > '9')
-        return (0);
+	if (**buf < '0' || **buf > '9')
+		return (0);
 
-    /* we use rulim to break out of the loop when we run out of digits */
-    do {
-        result *= 10;
-        result += *(*buf)++ - '0';
-        rulim /= 10;
-    } while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
+	/* we use rulim to break out of the loop when we run out of digits */
+	do {
+		result *= 10;
+		result += *(*buf)++ - '0';
+		rulim /= 10;
+	} while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
 
-    if (result < llim || result > ulim)
-        return (0);
+	if (result < llim || result > ulim)
+		return (0);
 
-    *dest = result;
-    return (1);
+	*dest = result;
+	return (1);
+}
+
+static const u_char *
+_find_string(const u_char *bp, int *tgt, const char * const *n1,
+		const char * const *n2, int c)
+{
+	int i;
+	unsigned int len;
+
+	/* check full name - then abbreviated ones */
+	for (; n1 != NULL; n1 = n2, n2 = NULL) {
+		for (i = 0; i < c; i++, n1++) {
+			len = strlen(*n1);
+			if (strncasecmp(*n1, (const char *)bp, len) == 0) {
+				*tgt = i;
+				return bp + len;
+			}
+		}
+	}
+
+	/* Nothing matched */
+	return NULL;
 }
 
 char* strptime_l(const char* buf, const char* fmt, struct tm* tm, locale_t l) {
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/libdl/Android.bp b/libdl/Android.bp
index cee43a3..9a31d36 100644
--- a/libdl/Android.bp
+++ b/libdl/Android.bp
@@ -41,6 +41,7 @@
     recovery_available: true,
     native_bridge_supported: true,
     static_ndk_lib: true,
+    llndk_stubs: "libdl.llndk",
 
     defaults: ["linux_bionic_supported"],
 
@@ -118,7 +119,7 @@
         symbol_file: "libdl.map.txt",
         versions: [
             "29",
-            "10000",
+            "current",
         ],
     },
 
@@ -126,6 +127,10 @@
         "//apex_available:platform",
         "com.android.runtime",
     ],
+
+    lto: {
+        never: true,
+    },
 }
 
 cc_library {
@@ -196,13 +201,17 @@
 
     stubs: {
         symbol_file: "libdl_android.map.txt",
-        versions: ["10000"],
+        versions: ["current"],
     },
 
     apex_available: [
         "//apex_available:platform",
         "com.android.runtime",
     ],
+
+    lto: {
+        never: true,
+    },
 }
 
 ndk_library {
@@ -213,7 +222,7 @@
 }
 
 llndk_library {
-    name: "libdl",
+    name: "libdl.llndk",
     native_bridge_supported: true,
     symbol_file: "libdl.map.txt",
 }
diff --git a/libm/Android.bp b/libm/Android.bp
index 322d67a..6c8ad22 100644
--- a/libm/Android.bp
+++ b/libm/Android.bp
@@ -1,5 +1,3 @@
-bionic_coverage = false
-
 //
 // libm.so and libm.a for target.
 //
@@ -10,6 +8,7 @@
     vendor_ramdisk_available: true,
     recovery_available: true,
     static_ndk_lib: true,
+    llndk_stubs: "libm.llndk",
 
     whole_static_libs: ["libarm-optimized-routines-math"],
 
@@ -489,7 +488,6 @@
     include_dirs: ["bionic/libc"],
     system_shared_libs: ["libc"],
 
-    native_coverage: bionic_coverage,
     sanitize: {
         address: false,
         fuzzer: false,
@@ -502,7 +500,7 @@
         symbol_file: "libm.map.txt",
         versions: [
             "29",
-            "10000",
+            "current",
         ],
     },
 
@@ -510,6 +508,10 @@
         "//apex_available:platform",
         "com.android.runtime",
     ],
+
+    lto: {
+        never: true,
+    },
 }
 
 ndk_library {
@@ -520,7 +522,7 @@
 }
 
 llndk_library {
-    name: "libm",
+    name: "libm.llndk",
     native_bridge_supported: true,
     symbol_file: "libm.map.txt",
 }
diff --git a/libm/arm64/lrint.S b/libm/arm64/lrint.S
index 5f95ae8..e835d08 100644
--- a/libm/arm64/lrint.S
+++ b/libm/arm64/lrint.S
@@ -32,3 +32,5 @@
 ALIAS_SYMBOL(llrint, lrint);
 
 ALIAS_SYMBOL(llrintf, lrintf);
+
+NOTE_GNU_PROPERTY()
diff --git a/libm/arm64/sqrt.S b/libm/arm64/sqrt.S
index 3a58ef3..0659b13 100644
--- a/libm/arm64/sqrt.S
+++ b/libm/arm64/sqrt.S
@@ -25,3 +25,5 @@
   fsqrt s0, s0
   ret
 END(sqrtf)
+
+NOTE_GNU_PROPERTY()
diff --git a/libm/x86/e_acos.S b/libm/x86/e_acos.S
index fa61853..04b1787 100644
--- a/libm/x86/e_acos.S
+++ b/libm/x86/e_acos.S
@@ -1925,5 +1925,5 @@
 	.type	static_const_table,@object
 	.size	static_const_table,6112
 	.data
-	.section .note.GNU-stack, ""
+	.section .note.GNU-stack, "",@progbits
 # End
diff --git a/libm/x86/e_asin.S b/libm/x86/e_asin.S
index 5d7f331..6a3ff8e 100644
--- a/libm/x86/e_asin.S
+++ b/libm/x86/e_asin.S
@@ -1999,5 +1999,5 @@
 	.type	static_const_table,@object
 	.size	static_const_table,6096
 	.data
-	.section .note.GNU-stack, ""
+	.section .note.GNU-stack, "",@progbits
 # End
diff --git a/libm/x86/e_atan2.S b/libm/x86/e_atan2.S
index 1efdf65..e491396 100644
--- a/libm/x86/e_atan2.S
+++ b/libm/x86/e_atan2.S
@@ -1217,5 +1217,5 @@
 	.type	static_const_table,@object
 	.size	static_const_table,3024
 	.data
-	.section .note.GNU-stack, ""
+	.section .note.GNU-stack, "",@progbits
 # End
diff --git a/libm/x86/e_cosh.S b/libm/x86/e_cosh.S
index ecea8f4..567a9d0 100644
--- a/libm/x86/e_cosh.S
+++ b/libm/x86/e_cosh.S
@@ -1345,5 +1345,5 @@
 	.type	static_const_table,@object
 	.size	static_const_table,4256
 	.data
-	.section .note.GNU-stack, ""
+	.section .note.GNU-stack, "",@progbits
 # End
diff --git a/libm/x86/e_hypot.S b/libm/x86/e_hypot.S
index 6a143e5..8422024 100644
--- a/libm/x86/e_hypot.S
+++ b/libm/x86/e_hypot.S
@@ -216,5 +216,5 @@
 	.type	static_const_table,@object
 	.size	static_const_table,32
 	.data
-	.section .note.GNU-stack, ""
+	.section .note.GNU-stack, "",@progbits
 # End
diff --git a/libm/x86/e_log10.S b/libm/x86/e_log10.S
index 09b2952..473cea3 100644
--- a/libm/x86/e_log10.S
+++ b/libm/x86/e_log10.S
@@ -791,5 +791,5 @@
 	.type	static_const_table,@object
 	.size	static_const_table,2160
 	.data
-	.section .note.GNU-stack, ""
+	.section .note.GNU-stack, "",@progbits
 # End
diff --git a/libm/x86/e_sinh.S b/libm/x86/e_sinh.S
index d6b04b5..b9a2930 100644
--- a/libm/x86/e_sinh.S
+++ b/libm/x86/e_sinh.S
@@ -1403,5 +1403,5 @@
 	.type	static_const_table,@object
 	.size	static_const_table,4280
 	.data
-	.section .note.GNU-stack, ""
+	.section .note.GNU-stack, "",@progbits
 # End
diff --git a/libm/x86/libm_reduce_pi04l.S b/libm/x86/libm_reduce_pi04l.S
index af6a7d0..25976ea 100644
--- a/libm/x86/libm_reduce_pi04l.S
+++ b/libm/x86/libm_reduce_pi04l.S
@@ -3714,5 +3714,5 @@
 	.type	__4onpi_31l,@object
 	.size	__4onpi_31l,6444
 	.data
-	.section .note.GNU-stack, ""
+	.section .note.GNU-stack, "",@progbits
 # End
diff --git a/libm/x86/libm_sincos_huge.S b/libm/x86/libm_sincos_huge.S
index b43d193..4601b87 100644
--- a/libm/x86/libm_sincos_huge.S
+++ b/libm/x86/libm_sincos_huge.S
@@ -664,5 +664,5 @@
 	.size	_ones,16
 	.data
 	.hidden __libm_reduce_pi04l
-	.section .note.GNU-stack, ""
+	.section .note.GNU-stack, "",@progbits
 # End
diff --git a/libm/x86/libm_tancot_huge.S b/libm/x86/libm_tancot_huge.S
index 80f16d5..cdaa820 100644
--- a/libm/x86/libm_tancot_huge.S
+++ b/libm/x86/libm_tancot_huge.S
@@ -746,5 +746,5 @@
 	.size	_GP,144
 	.data
 	.hidden __libm_reduce_pi04l
-	.section .note.GNU-stack, ""
+	.section .note.GNU-stack, "",@progbits
 # End
diff --git a/libm/x86/s_atan.S b/libm/x86/s_atan.S
index c4413f1..71ca4db 100644
--- a/libm/x86/s_atan.S
+++ b/libm/x86/s_atan.S
@@ -930,5 +930,5 @@
 	.type	static_const_table,@object
 	.size	static_const_table,2704
 	.data
-	.section .note.GNU-stack, ""
+	.section .note.GNU-stack, "",@progbits
 # End
diff --git a/libm/x86/s_cbrt.S b/libm/x86/s_cbrt.S
index 0c98c99..53d3cc2 100644
--- a/libm/x86/s_cbrt.S
+++ b/libm/x86/s_cbrt.S
@@ -734,5 +734,5 @@
 	.type	static_const_table,@object
 	.size	static_const_table,2000
 	.data
-	.section .note.GNU-stack, ""
+	.section .note.GNU-stack, "",@progbits
 # End
diff --git a/libm/x86/s_cos.S b/libm/x86/s_cos.S
index fd5ef5d..e47c63e 100644
--- a/libm/x86/s_cos.S
+++ b/libm/x86/s_cos.S
@@ -888,5 +888,5 @@
 	.size	static_const_table,2256
 	.data
 	.hidden __libm_sincos_huge
-	.section .note.GNU-stack, ""
+	.section .note.GNU-stack, "",@progbits
 # End
diff --git a/libm/x86/s_expm1.S b/libm/x86/s_expm1.S
index 1f9e87b..1816f59 100644
--- a/libm/x86/s_expm1.S
+++ b/libm/x86/s_expm1.S
@@ -698,5 +698,5 @@
 	.type	static_const_table,@object
 	.size	static_const_table,1296
 	.data
-	.section .note.GNU-stack, ""
+	.section .note.GNU-stack, "",@progbits
 # End
diff --git a/libm/x86/s_log1p.S b/libm/x86/s_log1p.S
index 7a6d845..de7b87b 100644
--- a/libm/x86/s_log1p.S
+++ b/libm/x86/s_log1p.S
@@ -823,5 +823,5 @@
 	.type	static_const_table,@object
 	.size	static_const_table,2192
 	.data
-	.section .note.GNU-stack, ""
+	.section .note.GNU-stack, "",@progbits
 # End
diff --git a/libm/x86/s_sin.S b/libm/x86/s_sin.S
index 1e6cbd4..74d1b86 100644
--- a/libm/x86/s_sin.S
+++ b/libm/x86/s_sin.S
@@ -903,5 +903,5 @@
 	.size	static_const_table,2288
 	.data
 	.hidden __libm_sincos_huge
-	.section .note.GNU-stack, ""
+	.section .note.GNU-stack, "",@progbits
 # End
diff --git a/libm/x86/s_tan.S b/libm/x86/s_tan.S
index 3ee2107..7935efe 100644
--- a/libm/x86/s_tan.S
+++ b/libm/x86/s_tan.S
@@ -1762,5 +1762,5 @@
 	.size	static_const_table,5872
 	.data
 	.hidden __libm_tancot_huge
-	.section .note.GNU-stack, ""
+	.section .note.GNU-stack, "",@progbits
 # End
diff --git a/libm/x86/s_tanh.S b/libm/x86/s_tanh.S
index 737bcbb..777519f 100644
--- a/libm/x86/s_tanh.S
+++ b/libm/x86/s_tanh.S
@@ -1357,5 +1357,5 @@
 	.type	static_const_table,@object
 	.size	static_const_table,4280
 	.data
-	.section .note.GNU-stack, ""
+	.section .note.GNU-stack, "",@progbits
 # End
diff --git a/libm/x86_64/e_acos.S b/libm/x86_64/e_acos.S
index d83c66b..57c910e 100644
--- a/libm/x86_64/e_acos.S
+++ b/libm/x86_64/e_acos.S
@@ -1934,7 +1934,7 @@
 	.type	ONE_BY_2,@object
 	.size	ONE_BY_2,8
 	.data
-	.section .note.GNU-stack, ""
+	.section .note.GNU-stack, "",@progbits
 // -- Begin DWARF2 SEGMENT .eh_frame
 	.section .eh_frame,"a",@progbits
 .eh_frame_seg:
diff --git a/libm/x86_64/e_asin.S b/libm/x86_64/e_asin.S
index 9f41c7c..4242543 100644
--- a/libm/x86_64/e_asin.S
+++ b/libm/x86_64/e_asin.S
@@ -2013,7 +2013,7 @@
 	.type	cv,@object
 	.size	cv,24
 	.data
-	.section .note.GNU-stack, ""
+	.section .note.GNU-stack, "",@progbits
 // -- Begin DWARF2 SEGMENT .eh_frame
 	.section .eh_frame,"a",@progbits
 .eh_frame_seg:
diff --git a/libm/x86_64/e_atan2.S b/libm/x86_64/e_atan2.S
index f9baea9..f0ba43c 100644
--- a/libm/x86_64/e_atan2.S
+++ b/libm/x86_64/e_atan2.S
@@ -1219,7 +1219,7 @@
 	.type	EXPMASK,@object
 	.size	EXPMASK,8
 	.data
-	.section .note.GNU-stack, ""
+	.section .note.GNU-stack, "",@progbits
 // -- Begin DWARF2 SEGMENT .eh_frame
 	.section .eh_frame,"a",@progbits
 .eh_frame_seg:
diff --git a/libm/x86_64/e_cosh.S b/libm/x86_64/e_cosh.S
index 8cdbca6..97cb389 100644
--- a/libm/x86_64/e_cosh.S
+++ b/libm/x86_64/e_cosh.S
@@ -1349,7 +1349,7 @@
 	.type	ONEMASK,@object
 	.size	ONEMASK,8
 	.data
-	.section .note.GNU-stack, ""
+	.section .note.GNU-stack, "",@progbits
 // -- Begin DWARF2 SEGMENT .eh_frame
 	.section .eh_frame,"a",@progbits
 .eh_frame_seg:
diff --git a/libm/x86_64/e_hypot.S b/libm/x86_64/e_hypot.S
index 089b2b4..e46669f 100644
--- a/libm/x86_64/e_hypot.S
+++ b/libm/x86_64/e_hypot.S
@@ -191,7 +191,7 @@
 	.type	static_const_table,@object
 	.size	static_const_table,32
 	.data
-	.section .note.GNU-stack, ""
+	.section .note.GNU-stack, "",@progbits
 // -- Begin DWARF2 SEGMENT .eh_frame
 	.section .eh_frame,"a",@progbits
 .eh_frame_seg:
diff --git a/libm/x86_64/e_log10.S b/libm/x86_64/e_log10.S
index 4f43a36..86f86ce 100644
--- a/libm/x86_64/e_log10.S
+++ b/libm/x86_64/e_log10.S
@@ -784,7 +784,7 @@
 	.type	coeff,@object
 	.size	coeff,48
 	.data
-	.section .note.GNU-stack, ""
+	.section .note.GNU-stack, "",@progbits
 // -- Begin DWARF2 SEGMENT .eh_frame
 	.section .eh_frame,"a",@progbits
 .eh_frame_seg:
diff --git a/libm/x86_64/e_sinh.S b/libm/x86_64/e_sinh.S
index 4d8db63..d5f7b16 100644
--- a/libm/x86_64/e_sinh.S
+++ b/libm/x86_64/e_sinh.S
@@ -1407,7 +1407,7 @@
 	.type	HALFMASK,@object
 	.size	HALFMASK,8
 	.data
-	.section .note.GNU-stack, ""
+	.section .note.GNU-stack, "",@progbits
 // -- Begin DWARF2 SEGMENT .eh_frame
 	.section .eh_frame,"a",@progbits
 .eh_frame_seg:
diff --git a/libm/x86_64/s_atan.S b/libm/x86_64/s_atan.S
index 2453e10..d0e5d72 100644
--- a/libm/x86_64/s_atan.S
+++ b/libm/x86_64/s_atan.S
@@ -904,7 +904,7 @@
 	.type	SGNMASK,@object
 	.size	SGNMASK,8
 	.data
-	.section .note.GNU-stack, ""
+	.section .note.GNU-stack, "",@progbits
 // -- Begin DWARF2 SEGMENT .eh_frame
 	.section .eh_frame,"a",@progbits
 .eh_frame_seg:
diff --git a/libm/x86_64/s_cbrt.S b/libm/x86_64/s_cbrt.S
index 4aa4373..6b00f56 100644
--- a/libm/x86_64/s_cbrt.S
+++ b/libm/x86_64/s_cbrt.S
@@ -731,7 +731,7 @@
 	.type	NEG_INF,@object
 	.size	NEG_INF,8
 	.data
-	.section .note.GNU-stack, ""
+	.section .note.GNU-stack, "",@progbits
 // -- Begin DWARF2 SEGMENT .eh_frame
 	.section .eh_frame,"a",@progbits
 .eh_frame_seg:
diff --git a/libm/x86_64/s_cos.S b/libm/x86_64/s_cos.S
index ab5a0e1..3d9e402 100644
--- a/libm/x86_64/s_cos.S
+++ b/libm/x86_64/s_cos.S
@@ -1248,7 +1248,7 @@
 	.type	NEG_ZERO,@object
 	.size	NEG_ZERO,8
 	.data
-	.section .note.GNU-stack, ""
+	.section .note.GNU-stack, "",@progbits
 // -- Begin DWARF2 SEGMENT .eh_frame
 	.section .eh_frame,"a",@progbits
 .eh_frame_seg:
diff --git a/libm/x86_64/s_expm1.S b/libm/x86_64/s_expm1.S
index 9da1d9d..4b22f5a 100644
--- a/libm/x86_64/s_expm1.S
+++ b/libm/x86_64/s_expm1.S
@@ -704,7 +704,7 @@
 	.type	HIGHMASK,@object
 	.size	HIGHMASK,8
 	.data
-	.section .note.GNU-stack, ""
+	.section .note.GNU-stack, "",@progbits
 // -- Begin DWARF2 SEGMENT .eh_frame
 	.section .eh_frame,"a",@progbits
 .eh_frame_seg:
diff --git a/libm/x86_64/s_log1p.S b/libm/x86_64/s_log1p.S
index 1ff2d39..27fab74 100644
--- a/libm/x86_64/s_log1p.S
+++ b/libm/x86_64/s_log1p.S
@@ -806,7 +806,7 @@
 	.type	coeff2,@object
 	.size	coeff2,48
 	.data
-	.section .note.GNU-stack, ""
+	.section .note.GNU-stack, "",@progbits
 // -- Begin DWARF2 SEGMENT .eh_frame
 	.section .eh_frame,"a",@progbits
 .eh_frame_seg:
diff --git a/libm/x86_64/s_sin.S b/libm/x86_64/s_sin.S
index 2f93a34..fb54a2a 100644
--- a/libm/x86_64/s_sin.S
+++ b/libm/x86_64/s_sin.S
@@ -1273,7 +1273,7 @@
 	.type	NEG_ZERO,@object
 	.size	NEG_ZERO,8
 	.data
-	.section .note.GNU-stack, ""
+	.section .note.GNU-stack, "",@progbits
 // -- Begin DWARF2 SEGMENT .eh_frame
 	.section .eh_frame,"a",@progbits
 .eh_frame_seg:
diff --git a/libm/x86_64/s_tan.S b/libm/x86_64/s_tan.S
index 74cb044..4fa12e3 100644
--- a/libm/x86_64/s_tan.S
+++ b/libm/x86_64/s_tan.S
@@ -2212,7 +2212,7 @@
 	.type	NEG_ZERO,@object
 	.size	NEG_ZERO,8
 	.data
-	.section .note.GNU-stack, ""
+	.section .note.GNU-stack, "",@progbits
 // -- Begin DWARF2 SEGMENT .eh_frame
 	.section .eh_frame,"a",@progbits
 .eh_frame_seg:
diff --git a/libm/x86_64/s_tanh.S b/libm/x86_64/s_tanh.S
index 2c8f9bf..a76a5c2 100644
--- a/libm/x86_64/s_tanh.S
+++ b/libm/x86_64/s_tanh.S
@@ -1369,7 +1369,7 @@
 	.type	TWOMASK,@object
 	.size	TWOMASK,8
 	.data
-	.section .note.GNU-stack, ""
+	.section .note.GNU-stack, "",@progbits
 // -- Begin DWARF2 SEGMENT .eh_frame
 	.section .eh_frame,"a",@progbits
 .eh_frame_seg:
diff --git a/linker/Android.bp b/linker/Android.bp
index 0caa0ee..8a2809a 100644
--- a/linker/Android.bp
+++ b/linker/Android.bp
@@ -39,6 +39,9 @@
         "linker_wrapper.cpp",
     ],
     arch: {
+        arm64: {
+            srcs: ["arch/arm64/begin.S"],
+        },
         x86_64: {
             srcs: ["arch/x86_64/begin.S"],
         },
@@ -167,6 +170,7 @@
         "linker_namespaces.cpp",
         "linker_logger.cpp",
         "linker_mapped_file_fragment.cpp",
+        "linker_note_gnu_property.cpp",
         "linker_phdr.cpp",
         "linker_relocate.cpp",
         "linker_sdk_versions.cpp",
@@ -355,6 +359,10 @@
             ],
         }
     },
+
+    lto: {
+        never: true,
+    },
 }
 
 // ========================================================
@@ -426,6 +434,10 @@
         "//apex_available:platform",
         "com.android.runtime",
     ],
+
+    lto: {
+        never: true,
+    },
 }
 
 cc_test {
@@ -447,6 +459,7 @@
         "linker_block_allocator_test.cpp",
         "linker_config_test.cpp",
         "linked_list_test.cpp",
+        "linker_note_gnu_property_test.cpp",
         "linker_sleb128_test.cpp",
         "linker_utils_test.cpp",
         "linker_gnu_hash_test.cpp",
@@ -455,6 +468,7 @@
         "linker_block_allocator.cpp",
         "linker_config.cpp",
         "linker_debug.cpp",
+        "linker_note_gnu_property.cpp",
         "linker_test_globals.cpp",
         "linker_utils.cpp",
     ],
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..77f754c 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) {
@@ -3135,6 +3141,14 @@
         // resolves everything eagerly, so these can be ignored.
         break;
 
+#if defined(__aarch64__)
+      case DT_AARCH64_BTI_PLT:
+      case DT_AARCH64_PAC_PLT:
+      case DT_AARCH64_VARIANT_PCS:
+        // Ignored: AArch64 processor-specific dynamic array tags.
+        break;
+#endif
+
       default:
         if (!relocating_linker) {
           const char* tag_name;
@@ -3162,7 +3176,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 +3508,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..e1775fb 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
@@ -181,3 +181,9 @@
 int get_application_target_sdk_version();
 ElfW(Versym) find_verdef_version_index(const soinfo* si, const version_info* vi);
 bool validate_verdef_section(const soinfo* si);
+
+struct platform_properties {
+#if defined(__aarch64__)
+  bool bti_supported = false;
+#endif
+};
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_globals.cpp b/linker/linker_globals.cpp
index 31da02c..4a17d09 100644
--- a/linker/linker_globals.cpp
+++ b/linker/linker_globals.cpp
@@ -40,6 +40,8 @@
 
 std::unordered_map<uintptr_t, soinfo*> g_soinfo_handles_map;
 
+platform_properties g_platform_properties;
+
 static char __linker_dl_err_buf[768];
 
 char* linker_get_error_buffer() {
diff --git a/linker/linker_globals.h b/linker/linker_globals.h
index 83cedca..0998629 100644
--- a/linker/linker_globals.h
+++ b/linker/linker_globals.h
@@ -79,11 +79,14 @@
 
 struct soinfo;
 struct android_namespace_t;
+struct platform_properties;
 
 extern android_namespace_t g_default_namespace;
 
 extern std::unordered_map<uintptr_t, soinfo*> g_soinfo_handles_map;
 
+extern platform_properties g_platform_properties;
+
 // Error buffer "variable"
 char* linker_get_error_buffer();
 size_t linker_get_error_buffer_size();
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_main.cpp b/linker/linker_main.cpp
index 41bb4ba..aad8f6f 100644
--- a/linker/linker_main.cpp
+++ b/linker/linker_main.cpp
@@ -297,6 +297,13 @@
   return result;
 }
 
+static void platform_properties_init() {
+#if defined(__aarch64__)
+  const unsigned long hwcap2 = getauxval(AT_HWCAP2);
+  g_platform_properties.bti_supported = (hwcap2 & HWCAP2_BTI) != 0;
+#endif
+}
+
 static ElfW(Addr) linker_main(KernelArgumentBlock& args, const char* exe_to_load) {
   ProtectedDataGuard guard;
 
@@ -311,6 +318,9 @@
   // Initialize system properties
   __system_properties_init(); // may use 'environ'
 
+  // Initialize platform properties.
+  platform_properties_init();
+
   // Register the debuggerd signal handler.
   linker_debuggerd_init();
 
@@ -381,6 +391,20 @@
   solinker->set_realpath(interp);
   init_link_map_head(*solinker);
 
+#if defined(__aarch64__)
+  if (exe_to_load == nullptr) {
+    // Kernel does not add PROT_BTI to executable pages of the loaded ELF.
+    // Apply appropriate protections here if it is needed.
+    auto note_gnu_property = GnuPropertySection(somain);
+    if (note_gnu_property.IsBTICompatible() &&
+        (phdr_table_protect_segments(somain->phdr, somain->phnum, somain->load_bias,
+                                     &note_gnu_property) < 0)) {
+      __linker_error("error: can't protect segments for \"%s\": %s", exe_info.path.c_str(),
+                     strerror(errno));
+    }
+  }
+#endif
+
   // Register the main executable and the linker upfront to have
   // gdb aware of them before loading the rest of the dependency
   // tree.
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_note_gnu_property.cpp b/linker/linker_note_gnu_property.cpp
new file mode 100644
index 0000000..be1aebc
--- /dev/null
+++ b/linker/linker_note_gnu_property.cpp
@@ -0,0 +1,186 @@
+/*
+ * 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 "linker_note_gnu_property.h"
+
+#include <elf.h>
+#include <link.h>
+
+#include "linker.h"
+#include "linker_debug.h"
+#include "linker_globals.h"
+#include "linker_soinfo.h"
+
+GnuPropertySection::GnuPropertySection(const soinfo* si)
+    : GnuPropertySection(si->phdr, si->phnum, si->load_bias, si->get_realpath()) {}
+
+GnuPropertySection::GnuPropertySection(const ElfW(Phdr)* phdr, size_t phdr_count,
+                                       const ElfW(Addr) load_bias, const char* name) {
+  // Try to find PT_GNU_PROPERTY segment.
+  auto note_gnu_property = FindSegment(phdr, phdr_count, load_bias, name);
+  // Perform some validity checks.
+  if (note_gnu_property && SanityCheck(note_gnu_property, name)) {
+    // Parse section.
+    Parse(note_gnu_property, name);
+  }
+}
+
+const ElfW(NhdrGNUProperty)* GnuPropertySection::FindSegment(const ElfW(Phdr)* phdr,
+                                                             size_t phdr_count,
+                                                             const ElfW(Addr) load_bias,
+                                                             const char* name) const {
+  // According to Linux gABI extension this segment should contain
+  // .note.gnu.property section only.
+  if (phdr != nullptr) {
+    for (size_t i = 0; i < phdr_count; ++i) {
+      if (phdr[i].p_type != PT_GNU_PROPERTY) {
+        continue;
+      }
+
+      TRACE("\"%s\" PT_GNU_PROPERTY: found at segment index %zu", name, i);
+
+      // Check segment size.
+      if (phdr[i].p_memsz < sizeof(ElfW(NhdrGNUProperty))) {
+        DL_ERR_AND_LOG(
+            "\"%s\" PT_GNU_PROPERTY segment is too small. Segment "
+            "size is %zu, minimum is %zu.",
+            name, static_cast<size_t>(phdr[i].p_memsz), sizeof(ElfW(NhdrGNUProperty)));
+        return nullptr;
+      }
+
+      // PT_GNU_PROPERTY contains .note.gnu.property which has SHF_ALLOC
+      // attribute, therefore it is loaded.
+      auto note_nhdr = reinterpret_cast<ElfW(NhdrGNUProperty)*>(load_bias + phdr[i].p_vaddr);
+
+      // Check that the n_descsz <= p_memsz
+      if ((phdr[i].p_memsz - sizeof(ElfW(NhdrGNUProperty))) < note_nhdr->nhdr.n_descsz) {
+        DL_ERR_AND_LOG(
+            "\"%s\" PT_GNU_PROPERTY segment p_memsz (%zu) is too small for note n_descsz (%zu).",
+            name, static_cast<size_t>(phdr[i].p_memsz),
+            static_cast<size_t>(note_nhdr->nhdr.n_descsz));
+        return nullptr;
+      }
+
+      return note_nhdr;
+    }
+  }
+
+  TRACE("\"%s\" PT_GNU_PROPERTY: not found", name);
+  return nullptr;
+}
+
+bool GnuPropertySection::SanityCheck(const ElfW(NhdrGNUProperty)* note_nhdr,
+                                     const char* name) const {
+  // Check .note section type
+  if (note_nhdr->nhdr.n_type != NT_GNU_PROPERTY_TYPE_0) {
+    DL_ERR_AND_LOG("\"%s\" .note.gnu.property: unexpected note type. Expected %u, got %u.", name,
+                   NT_GNU_PROPERTY_TYPE_0, note_nhdr->nhdr.n_type);
+    return false;
+  }
+
+  if (note_nhdr->nhdr.n_namesz != 4) {
+    DL_ERR_AND_LOG("\"%s\" .note.gnu.property: unexpected name size. Expected 4, got %u.", name,
+                   note_nhdr->nhdr.n_namesz);
+    return false;
+  }
+
+  if (strncmp(note_nhdr->n_name, "GNU", 4) != 0) {
+    DL_ERR_AND_LOG("\"%s\" .note.gnu.property: unexpected name. Expected 'GNU', got '%s'.", name,
+                   note_nhdr->n_name);
+    return false;
+  }
+
+  return true;
+}
+
+bool GnuPropertySection::Parse(const ElfW(NhdrGNUProperty)* note_nhdr, const char* name) {
+  // The total length of the program property array is in _bytes_.
+  ElfW(Word) offset = 0;
+  while (offset < note_nhdr->nhdr.n_descsz) {
+    DEBUG("\"%s\" .note.gnu.property: processing at offset 0x%x", name, offset);
+
+    // At least the "header" part must fit.
+    // The ABI doesn't say that pr_datasz can't be 0.
+    if ((note_nhdr->nhdr.n_descsz - offset) < sizeof(ElfW(Prop))) {
+      DL_ERR_AND_LOG(
+          "\"%s\" .note.gnu.property: no more space left for a "
+          "Program Property Note header.",
+          name);
+      return false;
+    }
+
+    // Loop on program property array.
+    const ElfW(Prop)* property = reinterpret_cast<const ElfW(Prop)*>(&note_nhdr->n_desc[offset]);
+    const ElfW(Word) property_size =
+        align_up(sizeof(ElfW(Prop)) + property->pr_datasz, sizeof(ElfW(Addr)));
+    if ((note_nhdr->nhdr.n_descsz - offset) < property_size) {
+      DL_ERR_AND_LOG(
+          "\"%s\" .note.gnu.property: property descriptor size is "
+          "invalid. Expected at least %u bytes, got %u.",
+          name, property_size, note_nhdr->nhdr.n_descsz - offset);
+      return false;
+    }
+
+    // Cache found properties.
+    switch (property->pr_type) {
+#if defined(__aarch64__)
+      case GNU_PROPERTY_AARCH64_FEATURE_1_AND: {
+        if (property->pr_datasz != 4) {
+          DL_ERR_AND_LOG(
+              "\"%s\" .note.gnu.property: property descriptor size is "
+              "invalid. Expected %u bytes for GNU_PROPERTY_AARCH64_FEATURE_1_AND, got %u.",
+              name, 4, property->pr_datasz);
+          return false;
+        }
+
+        const ElfW(Word) flags = *reinterpret_cast<const ElfW(Word)*>(&property->pr_data[0]);
+        properties_.bti_compatible = (flags & GNU_PROPERTY_AARCH64_FEATURE_1_BTI) != 0;
+        if (properties_.bti_compatible) {
+          INFO("[ BTI compatible: \"%s\" ]", name);
+        }
+        break;
+      }
+#endif
+      default:
+        DEBUG("\"%s\" .note.gnu.property: found property pr_type %u pr_datasz 0x%x", name,
+              property->pr_type, property->pr_datasz);
+        break;
+    }
+
+    // Move offset, this should be safe to add because of previous checks.
+    offset += property_size;
+  }
+
+  return true;
+}
+
+#if defined(__aarch64__)
+bool GnuPropertySection::IsBTICompatible() const {
+  return (g_platform_properties.bti_supported && properties_.bti_compatible);
+}
+#endif
diff --git a/linker/linker_note_gnu_property.h b/linker/linker_note_gnu_property.h
new file mode 100644
index 0000000..b8b4ef7
--- /dev/null
+++ b/linker/linker_note_gnu_property.h
@@ -0,0 +1,93 @@
+/*
+ * 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
+
+#include <elf.h>
+#include <link.h>
+
+#include "linker_soinfo.h"
+
+// The Elf* structures below are derived from the document
+// Linux Extensions to gABI (https://github.com/hjl-tools/linux-abi/wiki).
+// Essentially, these types would be defined in <elf.h>, but this is not
+// the case at the moment.
+
+struct Elf32_Prop {
+  Elf32_Word pr_type;
+  Elf32_Word pr_datasz;
+  char pr_data[0];
+};
+
+// On 32-bit machines this should be 4-byte aligned.
+struct Elf32_NhdrGNUProperty {
+  Elf32_Nhdr nhdr;
+  char n_name[4];
+  char n_desc[0];
+};
+
+struct Elf64_Prop {
+  Elf64_Word pr_type;
+  Elf64_Word pr_datasz;
+  char pr_data[0];
+};
+
+// On 64-bit machines this should be 8-byte aligned.
+struct Elf64_NhdrGNUProperty {
+  Elf64_Nhdr nhdr;
+  char n_name[4];
+  char n_desc[0];
+};
+
+struct ElfProgramProperty {
+#if defined(__aarch64__)
+  bool bti_compatible = false;
+#endif
+};
+
+// Representation of the .note.gnu.property section found in the segment
+// with p_type = PT_GNU_PROPERTY.
+class GnuPropertySection {
+ public:
+  GnuPropertySection(){};
+  explicit GnuPropertySection(const soinfo* si);
+  GnuPropertySection(const ElfW(Phdr)* phdr, size_t phdr_count, const ElfW(Addr) load_bias,
+                     const char* name);
+
+#if defined(__aarch64__)
+  bool IsBTICompatible() const;
+#endif
+
+ private:
+  const ElfW(NhdrGNUProperty)* FindSegment(const ElfW(Phdr)* phdr, size_t phdr_count,
+                                           const ElfW(Addr) load_bias, const char* name) const;
+  bool SanityCheck(const ElfW(NhdrGNUProperty)* note_nhdr, const char* name) const;
+  bool Parse(const ElfW(NhdrGNUProperty)* note_nhdr, const char* name);
+
+  ElfProgramProperty properties_ __unused;
+};
diff --git a/linker/linker_note_gnu_property_test.cpp b/linker/linker_note_gnu_property_test.cpp
new file mode 100644
index 0000000..41fc47b
--- /dev/null
+++ b/linker/linker_note_gnu_property_test.cpp
@@ -0,0 +1,435 @@
+/*
+ * 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 <stdlib.h>
+#include <iostream>
+#include <sstream>
+#include <string>
+
+#include <gtest/gtest.h>
+
+#include "linker.h"
+#include "linker_globals.h"
+#include "linker_note_gnu_property.h"
+#include "platform/bionic/macros.h"
+
+#define SONAME "test_so"
+
+static char error_buffer[1024];
+
+char* linker_get_error_buffer() {
+  return error_buffer;
+}
+
+size_t linker_get_error_buffer_size() {
+  return std::size(error_buffer);
+}
+
+static void reset_error_buffer() {
+  error_buffer[0] = '\0';
+}
+
+platform_properties g_platform_properties {
+#if defined(__aarch64__)
+  // Assume "hardware" supports Armv8.5-A BTI.
+  .bti_supported = true
+#endif
+};
+
+// Helper macro to make the test cleaner.
+#define PHDR_WITH_NOTE_GNU_PROPERTY(__prop)                                   \
+  reset_error_buffer();                                                       \
+  ElfW(Phdr) phdrs[] = {                                                      \
+      {.p_type = PT_LOAD},                                                    \
+      {                                                                       \
+          .p_type = PT_GNU_PROPERTY,                                          \
+          .p_vaddr = reinterpret_cast<ElfW(Addr)>(__prop),                    \
+          .p_memsz = sizeof(ElfW(NhdrGNUProperty)) + (__prop)->nhdr.n_descsz, \
+      },                                                                      \
+      {.p_type = PT_NULL},                                                    \
+  };                                                                          \
+  auto note = GnuPropertySection(&phdrs[0], std::size(phdrs), 0, SONAME)
+
+// Helper to check for no error message.
+#define ASSERT_NO_ERROR_MSG() ASSERT_STREQ(error_buffer, "")
+
+// Helper to check expected error message.
+#define ASSERT_ERROR_MSG_EQ(__expected) ASSERT_STREQ(error_buffer, "\"" SONAME "\" " __expected)
+
+static void test_bti_not_supported(GnuPropertySection& note __unused) {
+#if defined(__aarch64__)
+  ASSERT_FALSE(note.IsBTICompatible());
+#endif
+}
+
+#if defined(__aarch64__)
+static void test_bti_supported(GnuPropertySection& note __unused) {
+  ASSERT_TRUE(note.IsBTICompatible());
+}
+#endif
+
+// Helper class to build a well-formed .note.gnu.property section.
+class GnuPropertySectionBuilder {
+ public:
+  GnuPropertySectionBuilder() {
+    note = reinterpret_cast<ElfW(NhdrGNUProperty)*>(&section[0]);
+    note->nhdr.n_namesz = 4;
+    note->nhdr.n_descsz = 0;
+    note->nhdr.n_type = NT_GNU_PROPERTY_TYPE_0;
+    memcpy(note->n_name, "GNU", 4);
+  }
+
+  template <typename T>
+  bool push(ElfW(Word) pr_type, ElfW(Word) pr_datasz, const T* pr_data) {
+    // Must be aligned.
+    const uintptr_t addition = align_up(pr_datasz, sizeof(ElfW(Addr)));
+    if ((offset() + addition) > kMaxSectionSize) {
+      return false;
+    }
+    ++entries;
+    ElfW(Prop)* prop = reinterpret_cast<ElfW(Prop)*>(&section[offset()]);
+    // Header
+    prop->pr_type = pr_type;
+    prop->pr_datasz = pr_datasz;
+    step(2 * sizeof(ElfW(Word)));
+    // Data
+    memcpy(&section[offset()], reinterpret_cast<const void*>(pr_data), pr_datasz);
+    step(pr_datasz);
+    // Padding
+    memset(&section[offset()], 0xAA, addition - pr_datasz);
+    step(addition - pr_datasz);
+    return true;
+  }
+
+  ElfW(NhdrGNUProperty)* data() const { return note; }
+
+  void dump() const {
+    std::cout << ".note.gnu.property\n";
+    dump_member("n_namesz", note->nhdr.n_namesz);
+    dump_member("n_descsz", note->nhdr.n_descsz);
+    dump_member("n_type  ", note->nhdr.n_type);
+    dump_member("n_name  ", note->n_name);
+    dump_member("entries ", entries);
+    if (entries > 0) {
+      std::cout << "    raw data:";
+      const uintptr_t offset = note->nhdr.n_descsz + 16;
+      for (uintptr_t offs = 16; offs < offset; ++offs) {
+        std::cout << std::hex;
+        if ((offs % 8) == 0) {
+          std::cout << "\n   ";
+        }
+        auto value = static_cast<unsigned>(section[offs]);
+        std::cout << " ";
+        if (value < 0x10) {
+          std::cout << "0";
+        }
+        std::cout << static_cast<unsigned>(section[offs]);
+      }
+      std::cout << std::dec << "\n";
+    }
+  }
+
+  void corrupt_n_descsz(ElfW(Word) n_descsz) { note->nhdr.n_descsz = n_descsz; }
+
+ private:
+  template <typename T>
+  void dump_member(const char* name, T value) const {
+    std::cout << "  " << name << " " << value << "\n";
+  }
+
+  ElfW(Word) offset() const { return note->nhdr.n_descsz + 16; }
+
+  template <typename T>
+  void step(T value) {
+    note->nhdr.n_descsz += static_cast<ElfW(Word)>(value);
+  }
+
+  static const size_t kMaxSectionSize = 1024;
+
+  alignas(8) uint8_t section[kMaxSectionSize];
+  ElfW(NhdrGNUProperty)* note;
+  size_t entries = 0;
+};
+
+// Tests that the default constructed instance does not report support
+// for Armv8.5-A BTI.
+TEST(note_gnu_property, default) {
+  GnuPropertySection note;
+  test_bti_not_supported(note);
+  ASSERT_NO_ERROR_MSG();
+}
+
+// Tests that an instance without valid phdr pointer does not report
+// support for Armv8.5-A BTI.
+TEST(note_gnu_property, phdr_null) {
+  auto note = GnuPropertySection(nullptr, 0, 0, SONAME);
+  test_bti_not_supported(note);
+  ASSERT_NO_ERROR_MSG();
+}
+
+// Tests that an instance without finding PT_GNU_PROPERTY does not
+// report support for Armv8.5-A BTI.
+TEST(note_gnu_property, no_pt_gnu_property) {
+  ElfW(Phdr) phdrs[] = {
+      {.p_type = PT_LOAD},
+      {.p_type = PT_NULL},
+  };
+
+  reset_error_buffer();
+  auto note = GnuPropertySection(&phdrs[0], std::size(phdrs), 0, SONAME);
+  test_bti_not_supported(note);
+  ASSERT_NO_ERROR_MSG();
+}
+
+// Tests the validity check for invalid PT_GNU_PROPERTY size.
+TEST(note_gnu_property, pt_gnu_property_bad_size) {
+  ElfW(Phdr) phdrs[] = {
+      {.p_type = PT_LOAD},
+      {
+          .p_type = PT_GNU_PROPERTY,
+          .p_vaddr = 0,
+          .p_memsz = sizeof(ElfW(NhdrGNUProperty)) - 1,  // Invalid
+      },
+      {.p_type = PT_NULL},
+  };
+
+  reset_error_buffer();
+  auto note = GnuPropertySection(&phdrs[0], std::size(phdrs), 0, SONAME);
+  test_bti_not_supported(note);
+  ASSERT_ERROR_MSG_EQ("PT_GNU_PROPERTY segment is too small. Segment size is 15, minimum is 16.");
+}
+
+// Tests that advertised n_descsz should still fit into p_memsz.
+TEST(note_gnu_property, pt_gnu_property_too_small) {
+  ElfW(NhdrGNUProperty) prop = {
+      .nhdr = {.n_namesz = PT_GNU_PROPERTY, .n_descsz = 1, .n_type = NT_GNU_PROPERTY_TYPE_0},
+      .n_name = "GNU",
+  };
+  ElfW(Phdr) phdrs[] = {
+      {
+          .p_type = PT_GNU_PROPERTY,
+          .p_vaddr = reinterpret_cast<ElfW(Addr)>(&prop),
+          .p_memsz = sizeof(ElfW(NhdrGNUProperty)),  // Off by one
+      },
+  };
+
+  reset_error_buffer();
+  auto note = GnuPropertySection(&phdrs[0], std::size(phdrs), 0, SONAME);
+  test_bti_not_supported(note);
+  ASSERT_ERROR_MSG_EQ("PT_GNU_PROPERTY segment p_memsz (16) is too small for note n_descsz (1).");
+}
+
+// Tests the validity check for invalid .note.gnu.property type.
+TEST(note_gnu_property, pt_gnu_property_bad_type) {
+  ElfW(NhdrGNUProperty) prop = {
+      .nhdr =
+          {
+              .n_namesz = 4,
+              .n_descsz = 0,
+              .n_type = NT_GNU_PROPERTY_TYPE_0 - 1  // Invalid
+          },
+      .n_name = "GNU",
+  };
+  PHDR_WITH_NOTE_GNU_PROPERTY(&prop);
+  test_bti_not_supported(note);
+  ASSERT_ERROR_MSG_EQ(".note.gnu.property: unexpected note type. Expected 5, got 4.");
+}
+
+// Tests the validity check for invalid .note.gnu.property name size.
+TEST(note_gnu_property, pt_gnu_property_bad_namesz) {
+  ElfW(NhdrGNUProperty) prop = {
+      .nhdr = {.n_namesz = 3,  // Invalid
+               .n_descsz = 0,
+               .n_type = NT_GNU_PROPERTY_TYPE_0},
+      .n_name = "GNU",
+  };
+  PHDR_WITH_NOTE_GNU_PROPERTY(&prop);
+  test_bti_not_supported(note);
+  ASSERT_ERROR_MSG_EQ(".note.gnu.property: unexpected name size. Expected 4, got 3.");
+}
+
+// Tests the validity check for invalid .note.gnu.property name.
+TEST(note_gnu_property, pt_gnu_property_bad_name) {
+  ElfW(NhdrGNUProperty) prop = {
+      .nhdr = {.n_namesz = 4, .n_descsz = 0, .n_type = NT_GNU_PROPERTY_TYPE_0},
+      .n_name = "ABC",  // Invalid
+  };
+  PHDR_WITH_NOTE_GNU_PROPERTY(&prop);
+  test_bti_not_supported(note);
+  ASSERT_ERROR_MSG_EQ(".note.gnu.property: unexpected name. Expected 'GNU', got 'ABC'.");
+}
+
+// Tests the validity check for not enough space for a Program Property header.
+TEST(note_gnu_property, pt_gnu_property_pphdr_no_space) {
+  ElfW(NhdrGNUProperty) prop = {
+      .nhdr = {.n_namesz = 4,
+               .n_descsz = 7,  // Invalid
+               .n_type = NT_GNU_PROPERTY_TYPE_0},
+      .n_name = "GNU",
+  };
+  PHDR_WITH_NOTE_GNU_PROPERTY(&prop);
+  test_bti_not_supported(note);
+  ASSERT_ERROR_MSG_EQ(".note.gnu.property: no more space left for a Program Property Note header.");
+}
+
+// Tests an empty .note.gnu.property.
+TEST(note_gnu_property, pt_gnu_property_no_data) {
+  GnuPropertySectionBuilder prop;
+  PHDR_WITH_NOTE_GNU_PROPERTY(prop.data());
+  test_bti_not_supported(note);
+  ASSERT_NO_ERROR_MSG();
+}
+
+// Tests a .note.gnu.property section with elements with pr_datasz = 0.
+TEST(note_gnu_property, pt_gnu_property_no_prop) {
+  GnuPropertySectionBuilder prop;
+  ASSERT_TRUE(prop.push(1, 0, (void*)nullptr));
+  ASSERT_TRUE(prop.push(2, 0, (void*)nullptr));
+  ASSERT_TRUE(prop.push(3, 0, (void*)nullptr));
+  PHDR_WITH_NOTE_GNU_PROPERTY(prop.data());
+  test_bti_not_supported(note);
+  ASSERT_NO_ERROR_MSG();
+}
+
+// Tests that GNU_PROPERTY_AARCH64_FEATURE_1_AND must have pr_datasz = 4.
+TEST(note_gnu_property, pt_gnu_property_bad_pr_datasz) {
+#if defined(__aarch64__)
+  GnuPropertySectionBuilder prop;
+  ElfW(Word) pr_data[] = {GNU_PROPERTY_AARCH64_FEATURE_1_BTI, 0, 0};
+  ASSERT_TRUE(prop.push(GNU_PROPERTY_AARCH64_FEATURE_1_AND, 12, &pr_data));
+  PHDR_WITH_NOTE_GNU_PROPERTY(prop.data());
+  test_bti_not_supported(note);
+  ASSERT_ERROR_MSG_EQ(
+      ".note.gnu.property: property descriptor size is invalid. Expected 4 bytes for "
+      "GNU_PROPERTY_AARCH64_FEATURE_1_AND, got 12.");
+#else
+  GTEST_SKIP() << "BTI is not supported on this architecture.";
+#endif
+}
+
+// Tests a .note.gnu.property section with only GNU_PROPERTY_AARCH64_FEATURE_1_BTI property array.
+TEST(note_gnu_property, pt_gnu_property_ok_1) {
+#if defined(__aarch64__)
+  GnuPropertySectionBuilder prop;
+  ElfW(Word) pr_data[] = {GNU_PROPERTY_AARCH64_FEATURE_1_BTI};
+  ASSERT_TRUE(prop.push(GNU_PROPERTY_AARCH64_FEATURE_1_AND, sizeof(pr_data), &pr_data));
+  PHDR_WITH_NOTE_GNU_PROPERTY(prop.data());
+  ASSERT_NO_ERROR_MSG();
+  test_bti_supported(note);
+#else
+  GTEST_SKIP() << "BTI is not supported on this architecture.";
+#endif
+}
+
+// Tests a .note.gnu.property section with only GNU_PROPERTY_AARCH64_FEATURE_1_BTI property array.
+TEST(note_gnu_property, pt_gnu_property_ok_2) {
+#if defined(__aarch64__)
+  GnuPropertySectionBuilder prop;
+  ElfW(Word) pr_data[] = {static_cast<ElfW(Word)>(~GNU_PROPERTY_AARCH64_FEATURE_1_BTI)};
+  ASSERT_TRUE(prop.push(GNU_PROPERTY_AARCH64_FEATURE_1_AND, sizeof(pr_data), &pr_data));
+  PHDR_WITH_NOTE_GNU_PROPERTY(prop.data());
+  ASSERT_NO_ERROR_MSG();
+  test_bti_not_supported(note);
+#else
+  GTEST_SKIP() << "BTI is not supported on this architecture.";
+#endif
+}
+
+// Tests a .note.gnu.property section with more property arrays.
+TEST(note_gnu_property, pt_gnu_property_ok_3) {
+#if defined(__aarch64__)
+  GnuPropertySectionBuilder prop;
+
+  ElfW(Word) pr_data_0[8] = {0xCD};
+  ASSERT_TRUE(prop.push(1, 4, &pr_data_0));
+  ASSERT_TRUE(prop.push(2, 3, &pr_data_0));
+  ASSERT_TRUE(prop.push(3, 8, &pr_data_0));
+
+  ElfW(Word) pr_data[] = {GNU_PROPERTY_AARCH64_FEATURE_1_BTI};
+  ASSERT_TRUE(prop.push(GNU_PROPERTY_AARCH64_FEATURE_1_AND, sizeof(pr_data), &pr_data));
+
+  ASSERT_TRUE(prop.push(4, 1, &pr_data_0));
+
+  PHDR_WITH_NOTE_GNU_PROPERTY(prop.data());
+  ASSERT_NO_ERROR_MSG();
+  test_bti_supported(note);
+#else
+  GTEST_SKIP() << "BTI is not supported on this architecture.";
+#endif
+}
+
+// Tests a .note.gnu.property but with bad property descriptor size.
+TEST(note_gnu_property, pt_gnu_property_bad_n_descsz) {
+#if defined(__aarch64__)
+  GnuPropertySectionBuilder prop;
+  ElfW(Word) pr_data[] = {GNU_PROPERTY_AARCH64_FEATURE_1_BTI};
+  ASSERT_TRUE(prop.push(GNU_PROPERTY_AARCH64_FEATURE_1_AND, sizeof(pr_data), &pr_data));
+
+  ElfW(Word) n_descsz;
+  if (sizeof(ElfW(Addr)) == 4) {
+    n_descsz = 11;
+  } else {
+    n_descsz = 15;
+  }
+
+  prop.corrupt_n_descsz(n_descsz);
+
+  PHDR_WITH_NOTE_GNU_PROPERTY(prop.data());
+  if (sizeof(ElfW(Addr)) == 4) {
+    ASSERT_ERROR_MSG_EQ(
+        ".note.gnu.property: property descriptor size is invalid. Expected at least 12 bytes, got "
+        "11.");
+  } else {
+    ASSERT_ERROR_MSG_EQ(
+        ".note.gnu.property: property descriptor size is invalid. Expected at least 16 bytes, got "
+        "15.");
+  }
+  test_bti_not_supported(note);
+#else
+  GTEST_SKIP() << "BTI is not supported on this architecture.";
+#endif
+}
+
+// Tests if platform support is missing.
+TEST(note_gnu_property, no_platform_support) {
+#if defined(__aarch64__)
+  auto bti_supported_orig = g_platform_properties.bti_supported;
+  g_platform_properties.bti_supported = false;
+
+  GnuPropertySectionBuilder prop;
+  ElfW(Word) pr_data[] = {GNU_PROPERTY_AARCH64_FEATURE_1_BTI};
+  ASSERT_TRUE(prop.push(GNU_PROPERTY_AARCH64_FEATURE_1_AND, sizeof(pr_data), &pr_data));
+  PHDR_WITH_NOTE_GNU_PROPERTY(prop.data());
+  ASSERT_NO_ERROR_MSG();
+  test_bti_not_supported(note);
+
+  g_platform_properties.bti_supported = bti_supported_orig;
+#else
+  GTEST_SKIP() << "BTI is not supported on this architecture.";
+#endif
+}
diff --git a/linker/linker_phdr.cpp b/linker/linker_phdr.cpp
index 9b7a461..9b1b99f 100644
--- a/linker/linker_phdr.cpp
+++ b/linker/linker_phdr.cpp
@@ -169,8 +169,16 @@
   if (did_load_) {
     return true;
   }
-  if (ReserveAddressSpace(address_space) && LoadSegments() && FindPhdr()) {
+  if (ReserveAddressSpace(address_space) && LoadSegments() && FindPhdr() &&
+      FindGnuPropertySection()) {
     did_load_ = true;
+#if defined(__aarch64__)
+    // For Armv8.5-A loaded executable segments may require PROT_BTI.
+    if (note_gnu_property_.IsBTICompatible()) {
+      did_load_ = (phdr_table_protect_segments(phdr_table_, phdr_num_, load_bias_,
+                                               &note_gnu_property_) == 0);
+    }
+#endif
   }
 
   return did_load_;
@@ -520,7 +528,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 +539,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 +556,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 +622,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.
@@ -703,15 +756,21 @@
     ElfW(Addr) seg_page_start = PAGE_START(phdr->p_vaddr) + load_bias;
     ElfW(Addr) seg_page_end   = PAGE_END(phdr->p_vaddr + phdr->p_memsz) + load_bias;
 
-    int prot = PFLAGS_TO_PROT(phdr->p_flags);
-    if ((extra_prot_flags & PROT_WRITE) != 0) {
+    int prot = PFLAGS_TO_PROT(phdr->p_flags) | extra_prot_flags;
+    if ((prot & PROT_WRITE) != 0) {
       // make sure we're never simultaneously writable / executable
       prot &= ~PROT_EXEC;
     }
+#if defined(__aarch64__)
+    if ((prot & PROT_EXEC) == 0) {
+      // Though it is not specified don't add PROT_BTI if segment is not
+      // executable.
+      prot &= ~PROT_BTI;
+    }
+#endif
 
-    int ret = mprotect(reinterpret_cast<void*>(seg_page_start),
-                       seg_page_end - seg_page_start,
-                       prot | extra_prot_flags);
+    int ret =
+        mprotect(reinterpret_cast<void*>(seg_page_start), seg_page_end - seg_page_start, prot);
     if (ret < 0) {
       return -1;
     }
@@ -723,16 +782,26 @@
  * You should only call this after phdr_table_unprotect_segments and
  * applying all relocations.
  *
+ * AArch64: also called from linker_main and ElfReader::Load to apply
+ *     PROT_BTI for loaded main so and other so-s.
+ *
  * Input:
  *   phdr_table  -> program header table
  *   phdr_count  -> number of entries in tables
  *   load_bias   -> load bias
+ *   prop        -> GnuPropertySection or nullptr
  * Return:
  *   0 on error, -1 on failure (error code in errno).
  */
-int phdr_table_protect_segments(const ElfW(Phdr)* phdr_table,
-                                size_t phdr_count, ElfW(Addr) load_bias) {
-  return _phdr_table_set_load_prot(phdr_table, phdr_count, load_bias, 0);
+int phdr_table_protect_segments(const ElfW(Phdr)* phdr_table, size_t phdr_count,
+                                ElfW(Addr) load_bias, const GnuPropertySection* prop __unused) {
+  int prot = 0;
+#if defined(__aarch64__)
+  if ((prop != nullptr) && prop->IsBTICompatible()) {
+    prot |= PROT_BTI;
+  }
+#endif
+  return _phdr_table_set_load_prot(phdr_table, phdr_count, load_bias, prot);
 }
 
 /* Change the protection of all loaded segments in memory to writable.
@@ -1036,7 +1105,7 @@
  * Return:
  *   pointer to the program interpreter string.
  */
-const char* phdr_table_get_interpreter_name(const ElfW(Phdr) * phdr_table, size_t phdr_count,
+const char* phdr_table_get_interpreter_name(const ElfW(Phdr)* phdr_table, size_t phdr_count,
                                             ElfW(Addr) load_bias) {
   for (size_t i = 0; i<phdr_count; ++i) {
     const ElfW(Phdr)& phdr = phdr_table[i];
@@ -1079,6 +1148,15 @@
   return false;
 }
 
+// Tries to find .note.gnu.property section.
+// It is not considered an error if such section is missing.
+bool ElfReader::FindGnuPropertySection() {
+#if defined(__aarch64__)
+  note_gnu_property_ = GnuPropertySection(phdr_table_, phdr_num_, load_start(), name_.c_str());
+#endif
+  return true;
+}
+
 // Ensures that our program header is actually within a loadable
 // segment. This should help catch badly-formed ELF files that
 // would cause the linker to crash later when trying to access it.
diff --git a/linker/linker_phdr.h b/linker/linker_phdr.h
index 5d1cfc2..548dc51 100644
--- a/linker/linker_phdr.h
+++ b/linker/linker_phdr.h
@@ -37,6 +37,7 @@
 
 #include "linker.h"
 #include "linker_mapped_file_fragment.h"
+#include "linker_note_gnu_property.h"
 
 class ElfReader {
  public:
@@ -49,6 +50,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_; }
@@ -65,6 +68,7 @@
   bool ReserveAddressSpace(address_space_params* address_space);
   bool LoadSegments();
   bool FindPhdr();
+  bool FindGnuPropertySection();
   bool CheckPhdr(ElfW(Addr));
   bool CheckFileRange(ElfW(Addr) offset, size_t size, size_t alignment);
 
@@ -96,6 +100,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_;
 
@@ -104,13 +112,16 @@
 
   // Is map owned by the caller
   bool mapped_by_caller_;
+
+  // Only used by AArch64 at the moment.
+  GnuPropertySection note_gnu_property_ __unused;
 };
 
 size_t phdr_table_get_load_size(const ElfW(Phdr)* phdr_table, size_t phdr_count,
                                 ElfW(Addr)* min_vaddr = nullptr, ElfW(Addr)* max_vaddr = nullptr);
 
-int phdr_table_protect_segments(const ElfW(Phdr)* phdr_table,
-                                size_t phdr_count, ElfW(Addr) load_bias);
+int phdr_table_protect_segments(const ElfW(Phdr)* phdr_table, size_t phdr_count,
+                                ElfW(Addr) load_bias, const GnuPropertySection* prop = nullptr);
 
 int phdr_table_unprotect_segments(const ElfW(Phdr)* phdr_table, size_t phdr_count,
                                   ElfW(Addr) load_bias);
@@ -133,5 +144,5 @@
                                     ElfW(Addr) load_bias, ElfW(Dyn)** dynamic,
                                     ElfW(Word)* dynamic_flags);
 
-const char* phdr_table_get_interpreter_name(const ElfW(Phdr) * phdr_table, size_t phdr_count,
+const char* phdr_table_get_interpreter_name(const ElfW(Phdr)* phdr_table, size_t phdr_count,
                                             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..9b95c61 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -41,9 +41,13 @@
         // We want to test deprecated API too.
         "-Wno-deprecated-declarations",
 
+        // Needed to test pthread_internal_t layout.
+        "-Wno-invalid-offsetof",
+
         // For glibc.
         "-D__STDC_LIMIT_MACROS",
     ],
+    header_libs: ["libcutils_headers"],
     // Ensure that the tests exercise shadow call stack support and
     // the hint space PAC/BTI instructions.
     arch: {
@@ -72,6 +76,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.
 // -----------------------------------------------------------------------------
 
@@ -180,6 +395,7 @@
         "string_posix_strerror_r_test.cpp",
         "strings_nofortify_test.cpp",
         "strings_test.cpp",
+        "struct_layout_test.cpp",
         "sstream_test.cpp",
         "sys_auxv_test.cpp",
         "sys_epoll_test.cpp",
@@ -211,6 +427,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 +953,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",
@@ -774,6 +991,8 @@
         "ld_config_test_helper_lib1",
         "ld_config_test_helper_lib2",
         "ld_config_test_helper_lib3",
+        "tls_properties_helper",
+        "thread_exit_cb_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/fenv_test.cpp b/tests/fenv_test.cpp
index e983a1c..89c7fd5 100644
--- a/tests/fenv_test.cpp
+++ b/tests/fenv_test.cpp
@@ -22,19 +22,20 @@
 #include <stdint.h>
 
 static void TestRounding(float expectation1, float expectation2) {
-  // volatile to prevent compiler optimizations.
+  // Volatile to prevent compile-time evaluation.
   volatile float f = 1.968750f;
   volatile float m = 0x1.0p23f;
-  volatile float x = f + m;
+  float x;
+  DoNotOptimize(x = f + m);
   ASSERT_FLOAT_EQ(expectation1, x);
-  x = x - m;
+  DoNotOptimize(x = x - m);
   ASSERT_EQ(expectation2, x);
 }
 
 static void DivideByZero() {
-  // volatile to prevent compiler optimizations.
+  // Volatile to prevent compile-time evaluation.
   volatile float zero = 0.0f;
-  volatile float result __attribute__((unused)) = 123.0f / zero;
+  DoNotOptimize(123.0f / zero);
 }
 
 TEST(fenv, fesetround_fegetround_FE_TONEAREST) {
diff --git a/tests/fortify_test.cpp b/tests/fortify_test.cpp
index 9a4b781..3ca0223 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"
 
@@ -212,8 +204,9 @@
   foo myfoo;
   volatile int asize = sizeof(myfoo.a) + 1;
   memcpy(myfoo.a, "0123456789", sizeof(myfoo.a));
-  ASSERT_FORTIFY(printf("%s", memchr(myfoo.a, 'a', asize)));
-  ASSERT_FORTIFY(printf("%s", memchr(static_cast<const void*>(myfoo.a), 'a', asize)));
+  ASSERT_FORTIFY(printf("%s", static_cast<const char*>(memchr(myfoo.a, 'a', asize))));
+  ASSERT_FORTIFY(printf(
+      "%s", static_cast<const char*>(memchr(static_cast<const void*>(myfoo.a), 'a', asize))));
 #else // __BIONIC__
   GTEST_SKIP() << "glibc is broken";
 #endif // __BIONIC__
@@ -224,8 +217,9 @@
   foo myfoo;
   volatile int asize = sizeof(myfoo.a) + 1;
   memcpy(myfoo.a, "0123456789", sizeof(myfoo.a));
-  ASSERT_FORTIFY(printf("%s", memrchr(myfoo.a, 'a', asize)));
-  ASSERT_FORTIFY(printf("%s", memrchr(static_cast<const void*>(myfoo.a), 'a', asize)));
+  ASSERT_FORTIFY(printf("%s", static_cast<const char*>(memrchr(myfoo.a, 'a', asize))));
+  ASSERT_FORTIFY(printf(
+      "%s", static_cast<const char*>(memrchr(static_cast<const void*>(myfoo.a), 'a', asize))));
 #else // __BIONIC__
   GTEST_SKIP() << "glibc is broken";
 #endif // __BIONIC__
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..4b86faf 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",
+   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..5982de4
--- /dev/null
+++ b/tests/libs/tls_properties_helper.cpp
@@ -0,0 +1,128 @@
+/*
+ * 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 <assert.h>
+#include <dlfcn.h>
+#include <elf.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sched.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/prctl.h>
+#include <sys/ptrace.h>
+#include <sys/uio.h>
+#include <sys/user.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+// Helper binary to use TLS-related functions in thread_properties
+
+// Tests __get_static_tls_bound.
+thread_local int local_var;
+void test_static_tls_bounds() {
+  local_var = 123;
+  void* start_addr = nullptr;
+  void* end_addr = nullptr;
+
+  __libc_get_static_tls_bounds(reinterpret_cast<void**>(&start_addr),
+                               reinterpret_cast<void**>(&end_addr));
+  assert(start_addr != nullptr);
+  assert(end_addr != nullptr);
+
+  assert(&local_var >= start_addr && &local_var < 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];
+// found_count  has to be Global variable so that the non-capturing lambda
+// can access it.
+int found_count = 0;
+void test_iter_tls() {
+  void* lib = dlopen("libtest_elftls_dynamic.so", RTLD_LOCAL | RTLD_NOW);
+  large_tls_var[1025] = 'a';
+  auto cb = +[](void* dtls_begin, void* dtls_end, size_t dso_id, void* arg) {
+    if (&large_tls_var >= dtls_begin && &large_tls_var < dtls_end) ++found_count;
+  };
+  __libc_iterate_dynamic_tls(gettid(), cb, nullptr);
+
+  // It should be found exactly once.
+  assert(found_count == 1);
+  printf("done_iterate_dynamic_tls\n");
+}
+
+void* parent_addr = nullptr;
+void test_iterate_another_thread_tls() {
+  large_tls_var[1025] = 'b';
+  parent_addr = &large_tls_var;
+  found_count = 0;
+
+  pid_t pid = fork();
+  assert(pid != -1);
+  int status;
+  if (pid) {
+    // Parent.
+    assert(pid == wait(&status));
+    assert(0 == status);
+  } else {
+    // Child.
+    pid_t parent_pid = getppid();
+    assert(0 == ptrace(PTRACE_ATTACH, parent_pid));
+    assert(parent_pid == waitpid(parent_pid, &status, 0));
+
+    auto cb = +[](void* dtls_begin, void* dtls_end, size_t dso_id, void* arg) {
+      if (parent_addr >= dtls_begin && parent_addr < dtls_end) ++found_count;
+    };
+    __libc_iterate_dynamic_tls(parent_pid, cb, nullptr);
+    // It should be found exactly once.
+    assert(found_count == 1);
+    printf("done_iterate_another_thread_tls\n");
+  }
+}
+int main() {
+  test_static_tls_bounds();
+  test_iter_tls();
+  test_iterate_another_thread_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..ddd3416 100644
--- a/tests/malloc_test.cpp
+++ b/tests/malloc_test.cpp
@@ -20,6 +20,7 @@
 #include <limits.h>
 #include <malloc.h>
 #include <pthread.h>
+#include <semaphore.h>
 #include <signal.h>
 #include <stdint.h>
 #include <stdio.h>
@@ -45,6 +46,7 @@
 #include "SignalUtils.h"
 
 #include "platform/bionic/malloc.h"
+#include "platform/bionic/mte.h"
 #include "platform/bionic/mte_kernel.h"
 #include "platform/bionic/reserved_signals.h"
 #include "private/bionic_config.h"
@@ -84,6 +86,24 @@
   free(ptr);
 }
 
+TEST(malloc, calloc_mem_init_disabled) {
+#if defined(__BIONIC__)
+  // calloc should still zero memory if mem-init is disabled.
+  // With jemalloc the mallopts will fail but that shouldn't affect the
+  // execution of the test.
+  mallopt(M_THREAD_DISABLE_MEM_INIT, 1);
+  size_t alloc_len = 100;
+  char *ptr = reinterpret_cast<char*>(calloc(1, alloc_len));
+  for (size_t i = 0; i < alloc_len; i++) {
+    ASSERT_EQ(0, ptr[i]);
+  }
+  free(ptr);
+  mallopt(M_THREAD_DISABLE_MEM_INIT, 0);
+#else
+  GTEST_SKIP() << "bionic-only test";
+#endif
+}
+
 TEST(malloc, calloc_illegal) {
   SKIP_WITH_HWASAN;
   errno = 0;
@@ -662,6 +682,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".
@@ -865,12 +925,8 @@
     std::thread* t = new std::thread([&stop] {
       while (!stop) {
         for (size_t size = kMinAllocationSize; size <= kMaxAllocationSize; size <<= 1) {
-          void* ptr = malloc(size);
-          if (ptr == nullptr) {
-            return;
-          }
-          // Make sure this value is not optimized away.
-          asm volatile("" : : "r,m"(ptr) : "memory");
+          void* ptr;
+          DoNotOptimize(ptr = malloc(size));
           free(ptr);
         }
       }
@@ -883,10 +939,9 @@
     pid_t pid;
     if ((pid = fork()) == 0) {
       for (size_t size = kMinAllocationSize; size <= kMaxAllocationSize; size <<= 1) {
-        void* ptr = malloc(size);
+        void* ptr;
+        DoNotOptimize(ptr = malloc(size));
         ASSERT_TRUE(ptr != nullptr);
-        // Make sure this value is not optimized away.
-        asm volatile("" : : "r,m"(ptr) : "memory");
         // Make sure we can touch all of the allocation.
         memset(ptr, 0x1, size);
         ASSERT_LE(size, malloc_usable_size(ptr));
@@ -1201,3 +1256,39 @@
   GTEST_SKIP() << "bionic extension";
 #endif
 }
+
+TEST(android_mallopt, disable_memory_mitigations) {
+#if defined(__BIONIC__)
+  if (!mte_supported()) {
+    GTEST_SKIP() << "This function can only be tested with MTE";
+  }
+
+#ifdef ANDROID_EXPERIMENTAL_MTE
+  sem_t sem;
+  ASSERT_EQ(0, sem_init(&sem, 0, 0));
+
+  pthread_t thread;
+  ASSERT_EQ(0, pthread_create(
+                   &thread, nullptr,
+                   [](void* ptr) -> void* {
+                     auto* sem = reinterpret_cast<sem_t*>(ptr);
+                     sem_wait(sem);
+                     return reinterpret_cast<void*>(prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0));
+                   },
+                   &sem));
+
+  ASSERT_TRUE(android_mallopt(M_DISABLE_MEMORY_MITIGATIONS, nullptr, 0));
+  ASSERT_EQ(0, sem_post(&sem));
+
+  int my_tagged_addr_ctrl = prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0);
+  ASSERT_EQ(PR_MTE_TCF_NONE, my_tagged_addr_ctrl & PR_MTE_TCF_MASK);
+
+  void* retval;
+  ASSERT_EQ(0, pthread_join(thread, &retval));
+  int thread_tagged_addr_ctrl = reinterpret_cast<uintptr_t>(retval);
+  ASSERT_EQ(my_tagged_addr_ctrl, thread_tagged_addr_ctrl);
+#endif
+#else
+  GTEST_SKIP() << "bionic extension";
+#endif
+}
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/pthread_test.cpp b/tests/pthread_test.cpp
index 851b86f..d9ad3cc 100644
--- a/tests/pthread_test.cpp
+++ b/tests/pthread_test.cpp
@@ -2975,3 +2975,48 @@
   spin_helper.UnSpin();
   ASSERT_EQ(0, pthread_join(t, nullptr));
 }
+
+extern "C" bool android_run_on_all_threads(bool (*func)(void*), void* arg);
+
+TEST(pthread, run_on_all_threads) {
+#if defined(__BIONIC__)
+  pthread_t t;
+  ASSERT_EQ(
+      0, pthread_create(
+             &t, nullptr,
+             [](void*) -> void* {
+               pthread_attr_t detached;
+               if (pthread_attr_init(&detached) != 0 ||
+                   pthread_attr_setdetachstate(&detached, PTHREAD_CREATE_DETACHED) != 0) {
+                 return reinterpret_cast<void*>(errno);
+               }
+
+               for (int i = 0; i != 1000; ++i) {
+                 pthread_t t1, t2;
+                 if (pthread_create(
+                         &t1, &detached, [](void*) -> void* { return nullptr; }, nullptr) != 0 ||
+                     pthread_create(
+                         &t2, nullptr, [](void*) -> void* { return nullptr; }, nullptr) != 0 ||
+                     pthread_join(t2, nullptr) != 0) {
+                   return reinterpret_cast<void*>(errno);
+                 }
+               }
+
+               if (pthread_attr_destroy(&detached) != 0) {
+                 return reinterpret_cast<void*>(errno);
+               }
+               return nullptr;
+             },
+             nullptr));
+
+  for (int i = 0; i != 1000; ++i) {
+    ASSERT_TRUE(android_run_on_all_threads([](void* arg) { return arg == nullptr; }, nullptr));
+  }
+
+  void *retval;
+  ASSERT_EQ(0, pthread_join(t, &retval));
+  ASSERT_EQ(nullptr, retval);
+#else
+  GTEST_SKIP() << "bionic-only test";
+#endif
+}
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 0ed0598..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/struct_layout_test.cpp b/tests/struct_layout_test.cpp
new file mode 100644
index 0000000..00fd4d5
--- /dev/null
+++ b/tests/struct_layout_test.cpp
@@ -0,0 +1,158 @@
+/*
+ * 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 <stdio.h>
+
+#if defined(__BIONIC__)
+#include "bionic/pthread_internal.h"
+
+// Ensure that the layout of these data structures is architecture independent and only depends on
+// the bitness of the architecture.
+template <typename CheckSize, typename CheckOffset>
+void tests(CheckSize check_size, CheckOffset check_offset) {
+#define CHECK_SIZE(name, size) \
+    check_size(#name, sizeof(name), size);
+#define CHECK_OFFSET(name, field, offset) \
+    check_offset(#name, #field, offsetof(name, field), offset);
+#ifdef __LP64__
+  CHECK_SIZE(pthread_internal_t, 776);
+  CHECK_OFFSET(pthread_internal_t, next, 0);
+  CHECK_OFFSET(pthread_internal_t, prev, 8);
+  CHECK_OFFSET(pthread_internal_t, tid, 16);
+  CHECK_OFFSET(pthread_internal_t, attr, 24);
+  CHECK_OFFSET(pthread_internal_t, join_state, 80);
+  CHECK_OFFSET(pthread_internal_t, cleanup_stack, 88);
+  CHECK_OFFSET(pthread_internal_t, start_routine, 96);
+  CHECK_OFFSET(pthread_internal_t, start_routine_arg, 104);
+  CHECK_OFFSET(pthread_internal_t, return_value, 112);
+  CHECK_OFFSET(pthread_internal_t, start_mask, 120);
+  CHECK_OFFSET(pthread_internal_t, alternate_signal_stack, 128);
+  CHECK_OFFSET(pthread_internal_t, shadow_call_stack_guard_region, 136);
+  CHECK_OFFSET(pthread_internal_t, stack_top, 144);
+  CHECK_OFFSET(pthread_internal_t, startup_handshake_lock, 156);
+  CHECK_OFFSET(pthread_internal_t, mmap_base, 168);
+  CHECK_OFFSET(pthread_internal_t, mmap_size, 176);
+  CHECK_OFFSET(pthread_internal_t, mmap_base_unguarded, 184);
+  CHECK_OFFSET(pthread_internal_t, mmap_size_unguarded, 192);
+  CHECK_OFFSET(pthread_internal_t, vma_name_buffer, 200);
+  CHECK_OFFSET(pthread_internal_t, thread_local_dtors, 232);
+  CHECK_OFFSET(pthread_internal_t, current_dlerror, 240);
+  CHECK_OFFSET(pthread_internal_t, dlerror_buffer, 248);
+  CHECK_OFFSET(pthread_internal_t, bionic_tls, 760);
+  CHECK_OFFSET(pthread_internal_t, errno_value, 768);
+  CHECK_SIZE(bionic_tls, 12200);
+  CHECK_OFFSET(bionic_tls, key_data, 0);
+  CHECK_OFFSET(bionic_tls, locale, 2080);
+  CHECK_OFFSET(bionic_tls, basename_buf, 2088);
+  CHECK_OFFSET(bionic_tls, dirname_buf, 6184);
+  CHECK_OFFSET(bionic_tls, mntent_buf, 10280);
+  CHECK_OFFSET(bionic_tls, mntent_strings, 10320);
+  CHECK_OFFSET(bionic_tls, ptsname_buf, 11344);
+  CHECK_OFFSET(bionic_tls, ttyname_buf, 11376);
+  CHECK_OFFSET(bionic_tls, strerror_buf, 11440);
+  CHECK_OFFSET(bionic_tls, strsignal_buf, 11695);
+  CHECK_OFFSET(bionic_tls, group, 11952);
+  CHECK_OFFSET(bionic_tls, passwd, 12040);
+  CHECK_OFFSET(bionic_tls, fdtrack_disabled, 12192);
+  CHECK_OFFSET(bionic_tls, padding, 12193);
+#else
+  CHECK_SIZE(pthread_internal_t, 668);
+  CHECK_OFFSET(pthread_internal_t, next, 0);
+  CHECK_OFFSET(pthread_internal_t, prev, 4);
+  CHECK_OFFSET(pthread_internal_t, tid, 8);
+  CHECK_OFFSET(pthread_internal_t, attr, 16);
+  CHECK_OFFSET(pthread_internal_t, join_state, 40);
+  CHECK_OFFSET(pthread_internal_t, cleanup_stack, 44);
+  CHECK_OFFSET(pthread_internal_t, start_routine, 48);
+  CHECK_OFFSET(pthread_internal_t, start_routine_arg, 52);
+  CHECK_OFFSET(pthread_internal_t, return_value, 56);
+  CHECK_OFFSET(pthread_internal_t, start_mask, 60);
+  CHECK_OFFSET(pthread_internal_t, alternate_signal_stack, 68);
+  CHECK_OFFSET(pthread_internal_t, shadow_call_stack_guard_region, 72);
+  CHECK_OFFSET(pthread_internal_t, stack_top, 76);
+  CHECK_OFFSET(pthread_internal_t, startup_handshake_lock, 84);
+  CHECK_OFFSET(pthread_internal_t, mmap_base, 92);
+  CHECK_OFFSET(pthread_internal_t, mmap_size, 96);
+  CHECK_OFFSET(pthread_internal_t, mmap_base_unguarded, 100);
+  CHECK_OFFSET(pthread_internal_t, mmap_size_unguarded, 104);
+  CHECK_OFFSET(pthread_internal_t, vma_name_buffer, 108);
+  CHECK_OFFSET(pthread_internal_t, thread_local_dtors, 140);
+  CHECK_OFFSET(pthread_internal_t, current_dlerror, 144);
+  CHECK_OFFSET(pthread_internal_t, dlerror_buffer, 148);
+  CHECK_OFFSET(pthread_internal_t, bionic_tls, 660);
+  CHECK_OFFSET(pthread_internal_t, errno_value, 664);
+  CHECK_SIZE(bionic_tls, 11080);
+  CHECK_OFFSET(bionic_tls, key_data, 0);
+  CHECK_OFFSET(bionic_tls, locale, 1040);
+  CHECK_OFFSET(bionic_tls, basename_buf, 1044);
+  CHECK_OFFSET(bionic_tls, dirname_buf, 5140);
+  CHECK_OFFSET(bionic_tls, mntent_buf, 9236);
+  CHECK_OFFSET(bionic_tls, mntent_strings, 9260);
+  CHECK_OFFSET(bionic_tls, ptsname_buf, 10284);
+  CHECK_OFFSET(bionic_tls, ttyname_buf, 10316);
+  CHECK_OFFSET(bionic_tls, strerror_buf, 10380);
+  CHECK_OFFSET(bionic_tls, strsignal_buf, 10635);
+  CHECK_OFFSET(bionic_tls, group, 10892);
+  CHECK_OFFSET(bionic_tls, passwd, 10952);
+  CHECK_OFFSET(bionic_tls, fdtrack_disabled, 11076);
+  CHECK_OFFSET(bionic_tls, padding, 11077);
+#endif  // __LP64__
+#undef CHECK_SIZE
+#undef CHECK_OFFSET
+}
+#endif  // defined(__BIONIC__)
+
+TEST(struct_layout, sizes_offsets) {
+#if defined(__BIONIC__)
+  bool failed = false;
+
+  auto check_size = [&](const char* name, size_t size, size_t expected_size) {
+    EXPECT_EQ(expected_size, size) << "sizeof(" << name << ")";
+    if (size != expected_size) {
+      failed = true;
+    }
+  };
+  auto check_offset = [&](const char* name, const char* field, size_t offset,
+                          size_t expected_offset) {
+    EXPECT_EQ(expected_offset, offset) << "offsetof(" << name << ", " << field << ")";
+    if (offset != expected_offset) {
+      failed = true;
+    }
+  };
+  tests(check_size, check_offset);
+
+  if (failed) {
+    printf(
+        "Please update the tests function in bionic/tests/struct_layout_test.cpp with the "
+        "following contents:\n");
+
+    auto print_size = [&](const char* name, size_t size, size_t expected_size) {
+      (void)expected_size;
+      printf("  CHECK_SIZE(%s, %zu);\n", name, size);
+    };
+    auto print_offset = [&](const char* name, const char* field, size_t offset,
+                            size_t expected_offset) {
+      (void)expected_offset;
+      printf("  CHECK_OFFSET(%s, %s, %zu);\n", name, field, offset);
+    };
+    tests(print_size, print_offset);
+  }
+#else
+  GTEST_SKIP() << "bionic-only test";
+#endif
+}
diff --git a/tests/sys_procfs_test.cpp b/tests/sys_procfs_test.cpp
index 8054869..5e0a0b0 100644
--- a/tests/sys_procfs_test.cpp
+++ b/tests/sys_procfs_test.cpp
@@ -18,7 +18,7 @@
 
 #include <sys/procfs.h>
 
-TEST(sys_procfs, smoke) {
+TEST(sys_procfs, types) {
   elf_greg_t reg;
   memset(&reg, 0, sizeof(reg));
 
@@ -37,3 +37,16 @@
   static_assert(sizeof(prgregset_t) == sizeof(elf_gregset_t), "");
   static_assert(sizeof(prfpregset_t) == sizeof(elf_fpregset_t), "");
 }
+
+TEST(sys_procfs, constants) {
+  // NGREG != ELF_NGREG (https://github.com/android/ndk/issues/1347)
+  static_assert(sizeof(gregset_t) / sizeof(greg_t) == NGREG);
+
+#if defined(__arm__)
+  static_assert(sizeof(user_regs) / sizeof(elf_greg_t) == ELF_NGREG);
+#elif defined(__aarch64__)
+  static_assert(sizeof(user_pt_regs) / sizeof(elf_greg_t) == ELF_NGREG);
+#else
+  static_assert(sizeof(user_regs_struct) / sizeof(elf_greg_t) == ELF_NGREG);
+#endif
+}
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..b1de0a4 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
@@ -363,6 +363,105 @@
   EXPECT_TRUE(memcmp(&tm, &zero, sizeof(tm)) == 0);
 }
 
+TEST(time, strptime_Z) {
+#if defined(__BIONIC__)
+  // glibc doesn't handle %Z at all.
+  // The BSDs only handle hard-coded "GMT" and "UTC", plus whatever two strings
+  // are in the global `tzname` (which correspond to the current $TZ).
+  struct tm tm;
+  setenv("TZ", "Europe/Berlin", 1);
+
+  // "GMT" always works.
+  tm = {};
+  ASSERT_EQ('\0', *strptime("GMT", "%Z", &tm));
+  EXPECT_STREQ("GMT", tm.tm_zone);
+  EXPECT_EQ(0, tm.tm_isdst);
+  EXPECT_EQ(0, tm.tm_gmtoff);
+
+  // As does "UTC".
+  tm = {};
+  ASSERT_EQ('\0', *strptime("UTC", "%Z", &tm));
+  EXPECT_STREQ("UTC", tm.tm_zone);
+  EXPECT_EQ(0, tm.tm_isdst);
+  EXPECT_EQ(0, tm.tm_gmtoff);
+
+  // Europe/Berlin is known as "CET" when there's no DST.
+  tm = {};
+  ASSERT_EQ('\0', *strptime("CET", "%Z", &tm));
+  EXPECT_STREQ("CET", tm.tm_zone);
+  EXPECT_EQ(0, tm.tm_isdst);
+  EXPECT_EQ(3600, tm.tm_gmtoff);
+
+  // Europe/Berlin is known as "CEST" when there's no DST.
+  tm = {};
+  ASSERT_EQ('\0', *strptime("CEST", "%Z", &tm));
+  EXPECT_STREQ("CEST", tm.tm_zone);
+  EXPECT_EQ(1, tm.tm_isdst);
+  EXPECT_EQ(3600, tm.tm_gmtoff);
+
+  // And as long as we're in Europe/Berlin, those are the only time zone
+  // abbreviations that are recognized.
+  tm = {};
+  ASSERT_TRUE(strptime("PDT", "%Z", &tm) == nullptr);
+#endif
+}
+
+TEST(time, strptime_z) {
+  struct tm tm;
+  setenv("TZ", "Europe/Berlin", 1);
+
+  // "UT" is what RFC822 called UTC.
+  tm = {};
+  ASSERT_EQ('\0', *strptime("UT", "%z", &tm));
+  EXPECT_STREQ("UTC", tm.tm_zone);
+  EXPECT_EQ(0, tm.tm_isdst);
+  EXPECT_EQ(0, tm.tm_gmtoff);
+  // "GMT" is RFC822's other name for UTC.
+  tm = {};
+  ASSERT_EQ('\0', *strptime("GMT", "%z", &tm));
+  EXPECT_STREQ("UTC", tm.tm_zone);
+  EXPECT_EQ(0, tm.tm_isdst);
+  EXPECT_EQ(0, tm.tm_gmtoff);
+
+  // "Z" ("Zulu") is a synonym for UTC.
+  tm = {};
+  ASSERT_EQ('\0', *strptime("Z", "%z", &tm));
+  EXPECT_STREQ("UTC", tm.tm_zone);
+  EXPECT_EQ(0, tm.tm_isdst);
+  EXPECT_EQ(0, tm.tm_gmtoff);
+
+  // "PST"/"PDT" and the other common US zone abbreviations are all supported.
+  tm = {};
+  ASSERT_EQ('\0', *strptime("PST", "%z", &tm));
+  EXPECT_STREQ("PST", tm.tm_zone);
+  EXPECT_EQ(0, tm.tm_isdst);
+  EXPECT_EQ(-28800, tm.tm_gmtoff);
+  tm = {};
+  ASSERT_EQ('\0', *strptime("PDT", "%z", &tm));
+  EXPECT_STREQ("PDT", tm.tm_zone);
+  EXPECT_EQ(1, tm.tm_isdst);
+  EXPECT_EQ(-25200, tm.tm_gmtoff);
+
+  // +-hh
+  tm = {};
+  ASSERT_EQ('\0', *strptime("+01", "%z", &tm));
+  EXPECT_EQ(3600, tm.tm_gmtoff);
+  EXPECT_TRUE(tm.tm_zone == nullptr);
+  EXPECT_EQ(0, tm.tm_isdst);
+  // +-hhmm
+  tm = {};
+  ASSERT_EQ('\0', *strptime("+0130", "%z", &tm));
+  EXPECT_EQ(5400, tm.tm_gmtoff);
+  EXPECT_TRUE(tm.tm_zone == nullptr);
+  EXPECT_EQ(0, tm.tm_isdst);
+  // +-hh:mm
+  tm = {};
+  ASSERT_EQ('\0', *strptime("+01:30", "%z", &tm));
+  EXPECT_EQ(5400, tm.tm_gmtoff);
+  EXPECT_TRUE(tm.tm_zone == nullptr);
+  EXPECT_EQ(0, tm.tm_isdst);
+}
+
 void SetTime(timer_t t, time_t value_s, time_t value_ns, time_t interval_s, time_t interval_ns) {
   itimerspec ts;
   ts.it_value.tv_sec = value_s;
@@ -1008,4 +1107,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..41ca8b4 100644
--- a/tests/unistd_test.cpp
+++ b/tests/unistd_test.cpp
@@ -676,14 +676,10 @@
   ASSERT_NE(static_cast<uint64_t>(parent_tid), reinterpret_cast<uint64_t>(result));
 }
 
-static void optimization_barrier(void* arg) {
-  asm volatile("" : : "r"(arg) : "memory");
-}
-
 __attribute__((noinline)) static void HwasanVforkTestChild() {
   // Allocate a tagged region on stack and leave it there.
   char x[10000];
-  optimization_barrier(x);
+  DoNotOptimize(x);
   _exit(0);
 }
 
@@ -700,7 +696,7 @@
   // Allocate a region on stack, but don't tag it (see the function attribute).
   // This depends on unallocated stack space at current function entry being untagged.
   char x[10000];
-  optimization_barrier(x);
+  DoNotOptimize(x);
   // Verify that contents of x[] are untagged.
   HwasanReadMemory(x, sizeof(x));
 }
@@ -1350,6 +1346,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 +1362,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 +1392,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 +1461,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 +1553,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/utils.h b/tests/utils.h
index c1b7f65..94ff050 100644
--- a/tests/utils.h
+++ b/tests/utils.h
@@ -78,13 +78,8 @@
 
 static inline bool running_with_native_bridge() {
 #if defined(__BIONIC__)
-#if defined(__arm__)
-  static const prop_info* pi = __system_property_find("ro.dalvik.vm.isa.arm");
+  static const prop_info* pi = __system_property_find("ro.dalvik.vm.isa." ABI_STRING);
   return pi != nullptr;
-#elif defined(__aarch64__)
-  static const prop_info* pi = __system_property_find("ro.dalvik.vm.isa.arm64");
-  return pi != nullptr;
-#endif
 #endif
   return false;
 }
@@ -295,3 +290,13 @@
 
   size_t start_count_ = CountOpenFds();
 };
+
+// From <benchmark/benchmark.h>.
+template <class Tp>
+static inline void DoNotOptimize(Tp const& value) {
+  asm volatile("" : : "r,m"(value) : "memory");
+}
+template <class Tp>
+static inline void DoNotOptimize(Tp& value) {
+  asm volatile("" : "+r,m"(value) : : "memory");
+}
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/Driver.cpp b/tools/versioner/src/Driver.cpp
index 184c3d4..adf93c3 100644
--- a/tools/versioner/src/Driver.cpp
+++ b/tools/versioner/src/Driver.cpp
@@ -42,6 +42,7 @@
 #include <llvm/ADT/SmallVector.h>
 #include <llvm/ADT/StringRef.h>
 #include <llvm/Option/Option.h>
+#include <llvm/Support/Host.h>
 #include <llvm/Support/VirtualFileSystem.h>
 
 #include "Arch.h"
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