Merge "[MTE] Allow remote mode override for process."
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 08fac4f..18e8bbc 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -38,6 +38,9 @@
     },
     {
       "name": "memunreachable_unit_test"
+    },
+    {
+      "name": "toybox-tests"
     }
   ],
   "hwasan-presubmit": [
@@ -76,6 +79,9 @@
     },
     {
       "name": "memunreachable_unit_test"
+    },
+    {
+      "name": "toybox-tests"
     }
   ]
 }
diff --git a/docs/clang_fortify_anatomy.md b/docs/clang_fortify_anatomy.md
new file mode 100644
index 0000000..4b95fdc
--- /dev/null
+++ b/docs/clang_fortify_anatomy.md
@@ -0,0 +1,841 @@
+*This document was originally written for a broad audience, and it was*
+*determined that it'd be good to hold in Bionic's docs, too. Due to the*
+*ever-changing nature of code, it tries to link to a stable tag of*
+*Bionic's libc, rather than the live code in Bionic. Same for Clang.*
+*Reader beware. :)*
+
+# The Anatomy of Clang FORTIFY
+
+## Objective
+
+The intent of this document is to run through the minutiae of how Clang FORTIFY
+actually works in Bionic at the time of writing. Other FORTIFY implementations
+that target Clang should use very similar mechanics. This document exists in part
+because many Clang-specific features serve multiple purposes simultaneously, so
+getting up-to-speed on how things function can be quite difficult.
+
+## Background
+
+FORTIFY is a broad suite of extensions to libc aimed at catching misuses of
+common library functions. Textually, these extensions exist purely in libc, but
+all implementations of FORTIFY rely heavily on C language extensions in order
+to function at all.
+
+Broadly, FORTIFY implementations try to guard against many misuses of C
+standard(-ish) libraries:
+- Buffer overruns in functions where pointers+sizes are passed (e.g., `memcpy`,
+  `poll`), or where sizes exist implicitly (e.g., `strcpy`).
+- Arguments with incorrect values passed to libc functions (e.g.,
+  out-of-bounds bits in `umask`).
+- Missing arguments to functions (e.g., `open()` with `O_CREAT`, but no mode
+  bits).
+
+FORTIFY is traditionally enabled by passing `-D_FORTIFY_SOURCE=N` to your
+compiler. `N==0` disables FORTIFY, whereas `N==1`, `N==2`, and `N==3` enable
+increasingly strict versions of it. In general, FORTIFY doesn't require user
+code changes; that said, some code patterns
+are [incompatible with stricter versions of FORTIFY checking]. This is largely
+because FORTIFY has significant flexibility in what it considers to be an
+"out-of-bounds" access.
+
+FORTIFY implementations use a mix of compiler diagnostics and runtime checks to
+flag and/or mitigate the impacts of the misuses mentioned above.
+
+Further, given FORTIFY's design, the effectiveness of FORTIFY is a function of
+-- among other things -- the optimization level you're compiling your code at.
+Many FORTIFY implementations are implicitly disabled when building with `-O0`,
+since FORTIFY's design for both Clang and GCC relies on optimizations in order
+to provide useful run-time checks. For the purpose of this document, all
+analysis of FORTIFY functions and commentary on builtins assume that code is
+being built with some optimization level > `-O0`.
+
+### A note on GCC
+
+This document talks specifically about Bionic's FORTIFY implementation targeted
+at Clang. While GCC also provides a set of language extensions necessary to
+implement FORTIFY, these tools are different from what Clang offers. This
+divergence is an artifact of Clang and GCC's differing architecture as
+compilers.
+
+Textually, quite a bit can be shared between a FORTIFY implementation for GCC
+and one for Clang (e.g., see [ChromeOS' Glibc patch]), but this kind of sharing
+requires things like macros that expand to unbalanced braces depending on your
+compiler:
+
+```c
+/*
+ * Highly simplified; if you're interested in FORTIFY's actual implementation,
+ * please see the patch linked above.
+ */
+#ifdef __clang__
+# define FORTIFY_PRECONDITIONS
+# define FORTIFY_FUNCTION_END
+#else
+# define FORTIFY_PRECONDITIONS {
+# define FORTIFY_FUNCTION_END }
+#endif
+
+/*
+ * FORTIFY_WARNING_ONLY_IF_SIZE_OF_BUF_LESS_THAN is not defined, due to its
+ * complexity and irrelevance. It turns into a compile-time warning if the
+ * compiler can determine `*buf` has fewer than `size` bytes available.
+ */
+
+char *getcwd(char *buf, size_t size)
+FORTIFY_PRECONDITIONS
+  FORTIFY_WARNING_ONLY_IF_SIZE_OF_BUF_LESS_THAN(buf, size, "`buf` is too smol.")
+{
+  // Actual shared function implementation goes here.
+}
+FORTIFY_FUNCTION_END
+```
+
+All talk of GCC-focused implementations and how to merge Clang and GCC
+implementations is out-of-scope for this doc, however.
+
+## The Life of a Clang FORTIFY Function
+
+As referenced in the Background section, FORTIFY performs many different checks
+for many functions. This section intends to go through real-world examples of
+FORTIFY functions in Bionic, breaking down how each part of these functions
+work, and how the pieces fit together to provide FORTIFY-like functionality.
+
+While FORTIFY implementations may differ between stdlibs, they broadly follow
+the same patterns when implementing their checks for Clang, and they try to
+make similar promises with respect to FORTIFY compiling to be zero-overhead in
+some cases, etc. Moreover, while this document specifically examines Bionic,
+many stdlibs will operate _very similarly_ to Bionic in their Clang FORTIFY
+implementations.
+
+**In general, when reading the below, be prepared for exceptions, subtlety, and
+corner cases. The individual function breakdowns below try to not offer
+redundant information. Each one focuses on different aspects of FORTIFY.**
+
+### Terminology
+
+Because FORTIFY should be mostly transparent to developers, there are inherent
+naming collisions here: `memcpy(x, y, z)` turns into fundamentally different
+generated code depending on the value of `_FORTIFY_SOURCE`. Further, said
+`memcpy` call with `_FORTIFY_SOURCE` enabled needs to be able to refer to the
+`memcpy` that would have been called, had `_FORTIFY_SOURCE` been disabled.
+Hence, the following convention is followed in the subsections below for all
+prose (namely, multiline code blocks are exempted from this):
+
+- Standard library function names preceded by `__builtin_` refer to the use of
+  the function with `_FORTIFY_SOURCE` disabled.
+- Standard library function names without a prefix refer to the use of the
+  function with `_FORTIFY_SOURCE` enabled.
+
+This convention also applies in `clang`. `__builtin_memcpy` will always call
+`memcpy` as though `_FORTIFY_SOURCE` were disabled.
+
+## Breakdown of `mempcpy`
+
+The [FORTIFY'ed version of `mempcpy`] is a full, featureful example of a
+FORTIFY'ed function from Bionic. From the user's perspective, it supports a few
+things:
+- Producing a compile-time error if the number of bytes to copy trivially
+  exceeds the number of bytes available at the destination pointer.
+- If the `mempcpy` has the potential to write to more bytes than what is
+  available at the destination, a run-time check is inserted to crash the
+  program if more bytes are written than what is allowed.
+- Compiling away to be zero overhead when none of the buffer sizes can be
+  determined at compile-time[^1].
+
+The declaration in Bionic's headers for `__builtin_mempcpy` is:
+```c
+void* mempcpy(void* __dst, const void* __src, size_t __n) __INTRODUCED_IN(23);
+```
+
+Which is annotated with nothing special, except for Bionic's versioner, which
+is Android-specific (and orthogonal to FORTIFY anyway), so it will be ignored.
+
+The [source for `mempcpy`] in Bionic's headers for is:
+```c
+__BIONIC_FORTIFY_INLINE
+void* mempcpy(void* const dst __pass_object_size0, const void* src, size_t copy_amount)
+        __overloadable
+        __clang_error_if(__bos_unevaluated_lt(__bos0(dst), copy_amount),
+                         "'mempcpy' called with size bigger than buffer") {
+#if __BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED
+    size_t bos_dst = __bos0(dst);
+    if (!__bos_trivially_ge(bos_dst, copy_amount)) {
+        return __builtin___mempcpy_chk(dst, src, copy_amount, bos_dst);
+    }
+#endif
+    return __builtin_mempcpy(dst, src, copy_amount);
+}
+```
+
+Expanding some of the important macros here, this function expands to roughly:
+```c
+static
+__inline__
+__attribute__((no_stack_protector))
+__attribute__((always_inline))
+void* mempcpy(
+        void* const dst __attribute__((pass_object_size(0))),
+        const void* src,
+        size_t copy_amount)
+        __attribute__((overloadable))
+        __attribute__((diagnose_if(
+            __builtin_object_size(dst, 0) != -1 && __builtin_object_size(dst, 0) <= copy_amount),
+            "'mempcpy' called with size bigger than buffer"))) {
+#if __BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED
+    size_t bos_dst = __builtin_object_size(dst, 0);
+    if (!(__bos_trivially_ge(bos_dst, copy_amount))) {
+        return __builtin___mempcpy_chk(dst, src, copy_amount, bos_dst);
+    }
+#endif
+    return __builtin_mempcpy(dst, src, copy_amount);
+}
+```
+
+So let's walk through this step by step, to see how FORTIFY does what it says on
+the tin here.
+
+[^1]: "Zero overhead" in a way [similar to C++11's `std::unique_ptr`]: this will
+turn into a direct call `__builtin_mempcpy` (or an optimized form thereof) with
+no other surrounding checks at runtime. However, the additional complexity may
+hinder optimizations that are performed before the optimizer can prove that the
+`if (...) { ... }` can be optimized out. Depending on how late this happens,
+the additional complexity may skew inlining costs, hide opportunities for e.g.,
+`memcpy` coalescing, etc etc.
+
+### How does Clang select `mempcpy`?
+
+First, it's critical to notice that `mempcpy` is marked `overloadable`. This
+function is a `static inline __attribute__((always_inline))` overload of
+`__builtin_mempcpy`:
+- `__attribute__((overloadable))` allows us to perform overloading in C.
+- `__attribute__((overloadable))` mangles all calls to functions marked with
+  `__attribute__((overloadable))`.
+- `__attribute__((overloadable))` allows exactly one function signature with a
+  given name to not be marked with `__attribute__((overloadable))`. Calls to
+  this overload will not be mangled.
+
+Second, one might note that this `mempcpy` implementation has the same C-level
+signature as `__builtin_mempcpy`. `pass_object_size` is a Clang attribute that
+is generally needed by FORTIFY, but it carries the side-effect that functions
+may be overloaded simply on the presence (or lack of presence) of
+`pass_object_size` attributes. Given two overloads of a function that only
+differ on the presence of `pass_object_size` attributes, the candidate with
+`pass_object_size` attributes is preferred.
+
+Finally, the prior paragraph gets thrown out if one tries to take the address of
+`mempcpy`. It is impossible to take the address of a function with one or more
+parameters that are annotated with `pass_object_size`. Hence,
+`&__builtin_mempcpy == &mempcpy`. Further, because this is an issue of overload
+resolution, `(&mempcpy)(x, y, z);` is functionally identical to
+`__builtin_mempcpy(x, y, z);`.
+
+All of this accomplishes the following:
+- Direct calls to `mempcpy` should call the FORTIFY-protected `mempcpy`.
+- Indirect calls to `&mempcpy` should call `__builtin_mempcpy`.
+
+### How does Clang offer compile-time diagnostics?
+
+Once one is convinced that the FORTIFY-enabled overload of `mempcpy` will be
+selected for direct calls, Clang's `diagnose_if` and `__builtin_object_size` do
+all of the work from there.
+
+Subtleties here primarily fall out of the discussion in the above section about
+`&__builtin_mempcpy == &mempcpy`:
+```c
+#define _FORTIFY_SOURCE 2
+#include <string.h>
+void example_code() {
+  char buf[4]; // ...Assume sizeof(char) == 1.
+  const char input_buf[] = "Hello, World";
+  mempcpy(buf, input_buf, 4); // Valid, no diagnostic issued.
+
+  mempcpy(buf, input_buf, 5); // Emits a compile-time error since sizeof(buf) < 5.
+  __builtin_mempcpy(buf, input_buf, 5); // No compile-time error.
+  (&mempcpy)(buf, input_buf, 5); // No compile-time error, since __builtin_mempcpy is selected.
+}
+```
+
+Otherwise, the rest of this subsection is dedicated to preliminary discussion
+about `__builtin_object_size`.
+
+Clang's frontend can do one of two things with `__builtin_object_size(p, n)`:
+- Evaluate it as a constant.
+  - This can either mean declaring that the number of bytes at `p` is definitely
+    impossible to know, so the default value is used, or the number of bytes at
+    `p` can be known without optimizations.
+- Declare that the expression cannot form a constant, and lower it to
+  `@llvm.objectsize`, which is discussed in depth later.
+
+In the examples above, since `diagnose_if` is evaluated with context from the
+caller, Clang should be able to trivially determine that `buf` refers to a
+`char` array with 4 elements.
+
+The primary consequence of the above is that diagnostics can only be emitted if
+no optimizations are required to detect a broken code pattern. To be specific,
+clang's constexpr evaluator must be able to determine the logical object that
+any given pointer points to in order to fold `__builtin_object_size` to a
+constant, non-default answer:
+
+```c
+#define _FORTIFY_SOURCE 2
+#include <string.h>
+void example_code() {
+  char buf[4]; // ...Assume sizeof(char) == 1.
+  const char input_buf[] = "Hello, World";
+  mempcpy(buf, input_buf, 4); // Valid, no diagnostic issued.
+  mempcpy(buf, input_buf, 5); // Emits a compile-time error since sizeof(buf) < 5.
+  char *buf_ptr = buf;
+  mempcpy(buf_ptr, input_buf, 5); // No compile-time error; `buf_ptr`'s target can't be determined.
+}
+```
+
+### How does Clang insert run-time checks?
+
+This section expands on the following statement: FORTIFY has zero runtime cost
+in instances where there is no chance of catching a bug at run-time. Otherwise,
+it introduces a tiny additional run-time cost to ensure that functions aren't
+misused.
+
+In prior sections, the following was established:
+- `overloadable` and `pass_object_size` prompt Clang to always select this
+  overload of `mempcpy` over `__builtin_mempcpy` for direct calls.
+- If a call to `mempcpy` was trivially broken, Clang would produce a
+  compile-time error, rather than producing a binary.
+
+Hence, the case we're interested in here is one where Clang's frontend selected
+a FORTIFY'ed function's implementation for a function call, but was unable to
+find anything seriously wrong with said function call. Since the frontend is
+powerless to detect bugs at this point, our focus shifts to the mechanisms that
+LLVM uses to support FORTIFY.
+
+Going back to Bionic's `mempcpy` implementation, we have the following (ignoring
+diagnose_if and assuming run-time checks are enabled):
+```c
+static
+__inline__
+__attribute__((no_stack_protector))
+__attribute__((always_inline))
+void* mempcpy(
+        void* const dst __attribute__((pass_object_size(0))),
+        const void* src,
+        size_t copy_amount)
+        __attribute__((overloadable)) {
+    size_t bos_dst = __builtin_object_size(dst, 0);
+    if (bos_dst != -1 &&
+        !(__builtin_constant_p(copy_amount) && bos_dst >= copy_amount)) {
+        return __builtin___mempcpy_chk(dst, src, copy_amount, bos_dst);
+    }
+    return __builtin_mempcpy(dst, src, copy_amount);
+}
+```
+
+In other words, we have a `static`, `always_inline` function which:
+- If `__builtin_object_size(dst, 0)` cannot be determined (in which case, it
+  returns -1), calls `__builtin_mempcpy`.
+- Otherwise, if `copy_amount` can be folded to a constant, and if
+  `__builtin_object_size(dst, 0) >= copy_amount`, calls `__builtin_mempcpy`.
+- Otherwise, calls `__builtin___mempcpy_chk`.
+
+
+How can this be "zero overhead"? Let's focus on the following part of the
+function:
+
+```c
+    size_t bos_dst = __builtin_object_size(dst, 0);
+    if (bos_dst != -1 &&
+        !(__builtin_constant_p(copy_amount) && bos_dst >= copy_amount)) {
+```
+
+If Clang's frontend cannot determine a value for `__builtin_object_size`, Clang
+lowers it to LLVM's `@llvm.objectsize` intrinsic. The `@llvm.objectsize`
+invocation corresponding to `__builtin_object_size(p, 0)` is guaranteed to
+always fold to a constant value by the time LLVM emits machine code.
+
+Hence, `bos_dst` is guaranteed to be a constant; if it's -1, the above branch
+can be eliminated entirely, since it folds to `if (false && ...)`. Further, the
+RHS of the `&&` in this branch has us call `__builtin_mempcpy` if `copy_amount`
+is a known value less than `bos_dst` (yet another constant value). Therefore,
+the entire condition is always knowable when LLVM is done with LLVM IR-level
+optimizations, so no condition is ever emitted to machine code in practice.
+
+#### Why is "zero overhead" in quotes? Why is `unique_ptr` relevant?
+
+`__builtin_object_size` and `__builtin_constant_p` are forced to be constants
+after most optimizations take place. Until LLVM replaces both of these with
+constants and optimizes them out, we have additional branches and function calls
+in our IR. This can have negative effects, such as distorting inlining costs and
+inhibiting optimizations that are conservative around branches in control-flow.
+
+So FORTIFY is free in these cases _in isolation of any of the code around it_.
+Due to its implementation, it may impact the optimizations that occur on code
+around the literal call to the FORTIFY-hardened libc function.
+
+`unique_ptr` was just the first thing that came to the author's mind for "the
+type should be zero cost with any level of optimization enabled, but edge-cases
+might make it only-mostly-free to use."
+
+### How is checking actually performed?
+
+In cases where checking can be performed (e.g., where we call
+`__builtin___mempcpy_chk(dst, src, copy_amount, bos_dst);`), Bionic provides [an
+implementation for `__mempcpy_chk`]. This is:
+
+```c
+extern "C" void* __mempcpy_chk(void* dst, const void* src, size_t count, size_t dst_len) {
+  __check_count("mempcpy", "count", count);
+  __check_buffer_access("mempcpy", "write into", count, dst_len);
+  return mempcpy(dst, src, count);
+}
+```
+This function itself boils down to a few small branches which abort the program
+if they fail, and a direct call to `__builtin_mempcpy`.
+
+### Wrapping up
+
+In the above breakdown, it was shown how Clang and Bionic work together to:
+- represent FORTIFY-hardened overloads of functions,
+- report misuses of stdlib functions at compile-time, and
+- insert run-time checks for uses of functions that might be incorrect, but only
+  if we have the potential of proving the incorrectness of these.
+
+## Breakdown of open
+
+In Bionic, the [FORTIFY'ed implementation of `open`] is quite large. Much like
+`mempcpy`, the `__builtin_open` declaration is simple:
+
+```c
+int open(const char* __path, int __flags, ...);
+```
+
+With some macros expanded, the FORTIFY-hardened header implementation is:
+```c
+int __open_2(const char*, int);
+int __open_real(const char*, int, ...) __asm__(open);
+
+#define __open_modes_useful(flags) (((flags) & O_CREAT) || ((flags) & O_TMPFILE) == O_TMPFILE)
+
+static
+int open(const char* pathname, int flags, mode_t modes, ...) __overloadable
+        __attribute__((diagnose_if(1, "error", "too many arguments")));
+
+static
+__inline__
+__attribute__((no_stack_protector))
+__attribute__((always_inline))
+int open(const char* const __attribute__((pass_object_size(1))) pathname, int flags)
+        __attribute__((overloadable))
+        __attribute__((diagnose_if(
+            __open_modes_useful(flags),
+            "error",
+            "'open' called with O_CREAT or O_TMPFILE, but missing mode"))) {
+#if __ANDROID_API__ >= 17 && __BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED
+    return __open_2(pathname, flags);
+#else
+    return __open_real(pathname, flags);
+#endif
+}
+static
+__inline__
+__attribute__((no_stack_protector))
+__attribute__((always_inline))
+int open(const char* const __attribute__((pass_object_size(1))) pathname, int flags, mode_t modes)
+        __attribute__((overloadable))
+        __clang_warning_if(!__open_modes_useful(flags) && modes,
+                           "'open' has superfluous mode bits; missing O_CREAT?") {
+    return __open_real(pathname, flags, modes);
+}
+```
+
+Which may be a lot to take in.
+
+Before diving too deeply, please note that the remainder of these subsections
+assume that the programmer didn't make any egregious typos. Moreover, there's no
+real way that Bionic tries to prevent calls to `open` like
+`open("foo", 0, "how do you convert a const char[N] to mode_t?");`. The only
+real C-compatible solution the author can think of is "stamp out many overloads
+to catch sort-of-common instances of this very uncommon typo." This isn't great.
+
+More directly, no effort is made below to recognize calls that, due to
+incompatible argument types, cannot go to any `open` implementation other than
+`__builtin_open`, since it's recognized right here. :)
+
+### Implementation breakdown
+
+This `open` implementation does a few things:
+- Turns calls to `open` with too many arguments into a compile-time error.
+- Diagnoses calls to `open` with missing modes at compile-time and run-time
+  (both cases turn into errors).
+- Emits warnings on calls to `open` with useless mode bits, unless the mode bits
+  are all 0.
+
+One common bit of code not explained below is the `__open_real` declaration above:
+```c
+int __open_real(const char*, int, ...) __asm__(open);
+```
+
+This exists as a way for us to call `__builtin_open` without needing clang to
+have a pre-defined `__builtin_open` function.
+
+#### Compile-time error on too many arguments
+
+```c
+static
+int open(const char* pathname, int flags, mode_t modes, ...) __overloadable
+        __attribute__((diagnose_if(1, "error", "too many arguments")));
+```
+
+Which matches most calls to open that supply too many arguments, since
+`int(const char *, int, ...)` matches less strongly than
+`int(const char *, int, mode_t, ...)` for calls where the 3rd arg can be
+converted to `mode_t` without too much effort. Because of the `diagnose_if`
+attribute, all of these calls turn into compile-time errors.
+
+#### Compile-time or run-time error on missing arguments
+The following overload handles all two-argument calls to `open`.
+```c
+static
+__inline__
+__attribute__((no_stack_protector))
+__attribute__((always_inline))
+int open(const char* const __attribute__((pass_object_size(1))) pathname, int flags)
+        __attribute__((overloadable))
+        __attribute__((diagnose_if(
+            __open_modes_useful(flags),
+            "error",
+            "'open' called with O_CREAT or O_TMPFILE, but missing mode"))) {
+#if __ANDROID_API__ >= 17 && __BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED
+    return __open_2(pathname, flags);
+#else
+    return __open_real(pathname, flags);
+#endif
+}
+```
+
+Like `mempcpy`, `diagnose_if` handles emitting a compile-time error if the call
+to `open` is broken in a way that's visible to Clang's frontend. This
+essentially boils down to "`open` is being called with a `flags` value that
+requires mode bits to be set."
+
+If that fails to catch a bug, we [unconditionally call `__open_2`], which
+performs a run-time check:
+```c
+int __open_2(const char* pathname, int flags) {
+  if (needs_mode(flags)) __fortify_fatal("open: called with O_CREAT/O_TMPFILE but no mode");
+  return FDTRACK_CREATE_NAME("open", __openat(AT_FDCWD, pathname, force_O_LARGEFILE(flags), 0));
+}
+```
+
+#### Compile-time warning if modes are pointless
+
+Finally, we have the following `open` call:
+```c
+static
+__inline__
+__attribute__((no_stack_protector))
+__attribute__((always_inline))
+int open(const char* const __attribute__((pass_object_size(1))) pathname, int flags, mode_t modes)
+        __attribute__((overloadable))
+        __clang_warning_if(!__open_modes_useful(flags) && modes,
+                           "'open' has superfluous mode bits; missing O_CREAT?") {
+    return __open_real(pathname, flags, modes);
+}
+```
+
+This simply issues a warning if Clang's frontend can determine that `flags`
+isn't necessary. Due to conventions in existing code, a `modes` value of `0` is
+not diagnosed.
+
+#### What about `&open`?
+One yet-unaddressed aspect of the above is how `&open` works. This is thankfully
+a short answer:
+- It happens that `open` takes a parameter of type `const char*`.
+- It happens that `pass_object_size` -- an attribute only applicable to
+  parameters of type `T*` --  makes it impossible to take the address of a
+  function.
+
+Since clang doesn't support a "this function should never have its address
+taken," attribute, Bionic uses the next best thing: `pass_object_size`. :)
+
+## Breakdown of poll
+
+(Preemptively: at the time of writing, Clang has no literal `__builtin_poll`
+builtin. `__builtin_poll` is referenced below to remain consistent with the
+convention established in the Terminology section.)
+
+Bionic's `poll` implementation is closest to `mempcpy` above, though it has a
+few interesting aspects worth examining.
+
+The [full header implementation of `poll`] is, with some macros expanded:
+```c
+#define __bos_fd_count_trivially_safe(bos_val, fds, fd_count) \
+  ((bos_val) == -1) || \
+    (__builtin_constant_p(fd_count) && \
+    (bos_val) >= sizeof(*fds) * (fd_count)))
+
+static
+__inline__
+__attribute__((no_stack_protector))
+__attribute__((always_inline))
+int poll(struct pollfd* const fds __attribute__((pass_object_size(1))), nfds_t fd_count, int timeout)
+    __attribute__((overloadable))
+    __attriubte__((diagnose_if(
+       __builtin_object_size(fds, 1) != -1 && __builtin_object_size(fds, 1) < sizeof(*fds) * fd_count,
+        "error",
+        "in call to 'poll', fd_count is larger than the given buffer"))) {
+  size_t bos_fds = __builtin_object_size(fds, 1);
+  if (!__bos_fd_count_trivially_safe(bos_fds, fds, fd_count)) {
+    return __poll_chk(fds, fd_count, timeout, bos_fds);
+  }
+  return (&poll)(fds, fd_count, timeout);
+}
+```
+
+To get the commonality with `mempcpy` and `open` out of the way:
+- This function is an overload with `__builtin_poll`.
+- The signature is the same, modulo the presence of a `pass_object_size`
+  attribute. Hence, for direct calls, overload resolution will always prefer it
+  over `__builtin_poll`. Taking the address of `poll` is forbidden, so all
+  references to `&poll` actually reference `__builtin_poll`.
+- When `fds` is too small to hold `fd_count` `pollfd`s, Clang will emit a
+  compile-time error if possible using `diagnose_if`.
+- If this can't be observed until run-time, `__poll_chk` verifies this.
+- When `fds` is a constant according to `__builtin_constant_p`, this always
+  compiles into `__poll_chk` for always-broken calls to `poll`, or
+  `__builtin_poll` for always-safe calls to `poll`.
+
+The critical bits to highlight here are on this line:
+```c
+int poll(struct pollfd* const fds __attribute__((pass_object_size(1))), nfds_t fd_count, int timeout)
+```
+
+And this line:
+```c
+  return (&poll)(fds, fd_count, timeout);
+```
+
+Starting with the simplest, we call `__builtin_poll` with `(&poll)(...);`. As
+referenced above, taking the address of an overloaded function where all but one
+overload has a `pass_object_size` attribute on one or more parameters always
+resolves to the function without any `pass_object_size` attributes.
+
+The other line deserves a section. The subtlety of it is almost entirely in the
+use of `pass_object_size(1)` instead of `pass_object_size(0)`. on the `fds`
+parameter, and the corresponding use of `__builtin_object_size(fds, 1);` in the
+body of `poll`.
+
+### Subtleties of __builtin_object_size(p, N)
+
+Earlier in this document, it was said that a full description of each
+attribute/builtin necessary to power FORTIFY was out of scope. This is... only
+somewhat the case when we talk about `__builtin_object_size` and
+`pass_object_size`, especially when their second argument is `1`.
+
+#### tl;dr
+`__builtin_object_size(p, N)` and `pass_object_size(N)`, where `(N & 1) == 1`,
+can only be accurately determined by Clang. LLVM's `@llvm.objectsize` intrinsic
+ignores the value of `N & 1`, since handling `(N & 1) == 1` accurately requires
+data that's currently entirely inaccessible to LLVM, and that is difficult to
+preserve through LLVM's optimization passes.
+
+`pass_object_size`'s "lifting" of the evaluation of
+`__builtin_object_size(p, N)` to the caller is critical, since it allows Clang
+full visibility into the expression passed to e.g., `poll(&foo->bar, baz, qux)`.
+It's not a perfect solution, but it allows `N == 1` to be fully accurate in at
+least some cases.
+
+#### Background
+Clang's implementation of `__builtin_object_size` aims to be compatible with
+GCC's, which has [a decent bit of documentation]. Put simply,
+`__builtin_object_size(p, N)` is intended to evaluate at compile-time how many
+bytes can be accessed after `p` in a well-defined way. Straightforward examples
+of this are:
+```c
+char buf[8];
+assert(__builtin_object_size(buf, N) == 8);
+assert(__builtin_object_size(buf + 1, N) == 7);
+```
+
+This should hold for all values of N that are valid to pass to
+`__builtin_object_size`. The `N` value of `__builtin_object_size` is a mask of
+settings.
+
+##### (N & 2) == ?
+
+This is mostly for completeness sake; in Bionic's FORTIFY implementation, N is
+always either 0 or 1.
+
+If there are multiple possible values of `p` in a call to
+`__builtin_object_size(p, N)`, the second bit in `N` determines the behavior of
+the compiler. If `(N & 2) == 0`, `__builtin_object_size` should return the
+greatest possible size for each possible value of `p`. Otherwise, it should
+return the least possible value. For example:
+
+```c
+char smol_buf[7];
+char buf[8];
+char *p = rand() ? smol_buf : buf;
+assert(__builtin_object_size(p, 0) == 8);
+assert(__builtin_object_size(p, 2) == 7);
+```
+
+##### (N & 1) == 0
+
+`__builtin_object_size(p, 0)` is more or less as simple as the example in the
+Background section directly above. When Clang attempts to evaluate
+`__builtin_object_size(p, 0);` and when LLVM tries to determine the result of a
+corresponding `@llvm.objectsize` call to, they search for the storage underlying
+the pointer in question. If that can be determined, Clang or LLVM can provide an
+answer; otherwise, they cannot.
+
+##### (N & 1) == 1, and the true magic of pass_object_size
+
+`__builtin_object_size(p, 1)` has a less uniform implementation between LLVM and
+Clang. According to GCC's documentation, "If the least significant bit [of
+__builtin_object_size's second argument] is clear, objects are whole variables,
+if it is set, a closest surrounding subobject is considered the object a pointer
+points to."
+
+The "closest surrounding subobject," means that `(N & 1) == 1` depends on type
+information in order to operate in many cases. Consider the following examples:
+```c
+struct Foo {
+  int a;
+  int b;
+};
+
+struct Foo foo;
+assert(__builtin_object_size(&foo, 0) == sizeof(foo));
+assert(__builtin_object_size(&foo, 1) == sizeof(foo));
+assert(__builtin_object_size(&foo->a, 0) == sizeof(foo));
+assert(__builtin_object_size(&foo->a, 1) == sizeof(int));
+
+struct Foo foos[2];
+assert(__builtin_object_size(&foos[0], 0) == 2 * sizeof(foo));
+assert(__builtin_object_size(&foos[0], 1) == sizeof(foo));
+assert(__builtin_object_size(&foos[0]->a, 0) == 2 * sizeof(foo));
+assert(__builtin_object_size(&foos[0]->a, 1) == sizeof(int));
+```
+
+...And perhaps somewhat surprisingly:
+```c
+void example(struct Foo *foo) {
+  // (As a reminder, `-1` is "I don't know" when `(N & 2) == 0`.)
+  assert(__builtin_object_size(foo, 0) == -1);
+  assert(__builtin_object_size(foo, 1) == -1);
+  assert(__builtin_object_size(foo->a, 0) == -1);
+  assert(__builtin_object_size(foo->a, 1) == sizeof(int));
+}
+```
+
+In Clang, [this type-aware requirement poses problems for us]: Clang's frontend
+knows everything we could possibly want about the types of variables, but
+optimizations are only performed by LLVM. LLVM has no reliable source for C or
+C++ data types, so calls to `__builtin_object_size(p, N)` that cannot be
+resolved by clang are lowered to the equivalent of
+`__builtin_object_size(p, N & ~1)` in LLVM IR.
+
+Moreover, Clang's frontend is the best-equipped part of the compiler to
+accurately determine the answer for `__builtin_object_size(p, N)`, given we know
+what `p` is. LLVM is the best-equipped part of the compiler to determine the
+value of `p`. This ordering issue is unfortunate.
+
+This is where `pass_object_size(N)` comes in. To summarize [the docs for
+`pass_object_size`], it evaluates `__builtin_object_size(p, N)` within the
+context of the caller of the function annotated with `pass_object_size`, and
+passes the value of that into the callee as an invisible parameter. All calls to
+`__builtin_object_size(parameter, N)` are substituted with references to this
+invisible parameter.
+
+Putting this plainly, Clang's frontend struggles to evaluate the following:
+```c
+int foo(void *p) {
+  return __builtin_object_size(p, 1);
+}
+
+void bar() {
+  struct { int i, j } k;
+  // The frontend can't figure this interprocedural objectsize out, so it gets lowered to
+  // LLVM, which determines that the answer here is sizeof(k).
+  int baz = foo(&k.i);
+}
+```
+
+However, with the magic of `pass_object_size`, we get one level of inlining to
+look through:
+```c
+int foo(void *const __attribute__((pass_object_size(1))) p) {
+  return __builtin_object_size(p, 1);
+}
+
+void bar() {
+  struct { int i, j } k;
+  // Due to pass_object_size, this is equivalent to:
+  // int baz = foo(&k.i, __builtin_object_size(&k.i, 1));
+  // ...and `int foo(void *)` is actually equivalent to:
+  // int foo(void *const, size_t size) {
+  //   return size;
+  // }
+  int baz = foo(&k.i);
+}
+```
+
+So we can obtain an accurate result in this case.
+
+##### What about pass_object_size(0)?
+It's sort of tangential, but if you find yourself wondering about the utility of
+`pass_object_size(0)` ... it's somewhat split. `pass_object_size(0)` in Bionic's
+FORTIFY exists mostly for visual consistency, simplicity, and as a useful way to
+have e.g., `&mempcpy` == `&__builtin_mempcpy`.
+
+Outside of these fringe benefits, all of the functions with
+`pass_object_size(0)` on parameters are marked with `always_inline`, so
+"lifting" the `__builtin_object_size` call isn't ultimately very helpful. In
+theory, users can always have something like:
+
+```c
+// In some_header.h
+// This function does cool and interesting things with the `__builtin_object_size` of its parameter,
+// and is able to work with that as though the function were defined inline.
+void out_of_line_function(void *__attribute__((pass_object_size(0))));
+```
+
+Though the author isn't aware of uses like this in practice, beyond a few folks
+on LLVM's mailing list seeming interested in trying it someday.
+
+#### Wrapping up
+In the (long) section above, two things were covered:
+- The use of `(&poll)(...);` is a convenient shorthand for calling
+  `__builtin_poll`.
+- `__builtin_object_size(p, N)` with `(N & 1) == 1` is not easy for Clang to
+  answer accurately, since it relies on type info only available in the
+  frontend, and it sometimes relies on optimizations only available in the
+  middle-end. `pass_object_size` helps mitigate this.
+
+## Miscellaneous Notes
+The above should be a roughly comprehensive view of how FORTIFY works in the
+real world. The main thing it fails to mention is the use of [the `diagnose_as_builtin` attribute] in Clang.
+
+As time has moved on, Clang has increasingly gained support for emitting
+warnings that were previously emitted by FORTIFY machinery.
+`diagnose_as_builtin` allows us to remove the `diagnose_if`s from some of the
+`static inline` overloads of stdlib functions above, so Clang may diagnose them
+instead.
+
+Clang's built-in diagnostics are often better than `diagnose_if` diagnostics,
+since Clang can format its diagnostics to include e.g., information about the
+sizes of buffers in a suspect call to a function. `diagnose_if` can only have
+the compiler output constant strings.
+
+[ChromeOS' Glibc patch]: https://chromium.googlesource.com/chromiumos/overlays/chromiumos-overlay/+/90fa9b27731db10a6010c7f7c25b24028145b091/sys-libs/glibc/files/local/glibc-2.33/0007-glibc-add-clang-style-FORTIFY.patch
+[FORTIFY'ed implementation of `open`]: https://android.googlesource.com/platform/bionic/+/refs/heads/android12-release/libc/include/bits/fortify/fcntl.h#41
+[FORTIFY'ed version of `mempcpy`]: https://android.googlesource.com/platform/bionic/+/refs/heads/android12-release/libc/include/bits/fortify/string.h#45
+[a decent bit of documentation]: https://gcc.gnu.org/onlinedocs/gcc/Object-Size-Checking.html
+[an implementation for `__mempcpy_chk`]: https://android.googlesource.com/platform/bionic/+/refs/heads/android12-release/libc/bionic/fortify.cpp#501
+[full header implementation of `poll`]: https://android.googlesource.com/platform/bionic/+/refs/heads/android12-release/libc/include/bits/fortify/poll.h#43
+[incompatible with stricter versions of FORTIFY checking]: https://godbolt.org/z/fGfEYxfnf
+[similar to C++11's `std::unique_ptr`]: https://stackoverflow.com/questions/58339165/why-can-a-t-be-passed-in-register-but-a-unique-ptrt-cannot
+[source for `mempcpy`]: https://android.googlesource.com/platform/bionic/+/refs/heads/android12-release/libc/include/string.h#55
+[the `diagnose_as_builtin` attribute]: https://releases.llvm.org/14.0.0/tools/clang/docs/AttributeReference.html#diagnose-as-builtin
+[the docs for `pass_object_size`]: https://releases.llvm.org/14.0.0/tools/clang/docs/AttributeReference.html#pass-object-size-pass-dynamic-object-size
+[this type-aware requirement poses problems for us]: https://github.com/llvm/llvm-project/issues/55742
+[unconditionally call `__open_2`]: https://android.googlesource.com/platform/bionic/+/refs/heads/android12-release/libc/bionic/open.cpp#70
diff --git a/docs/status.md b/docs/status.md
index bf246a6..de1eed1 100644
--- a/docs/status.md
+++ b/docs/status.md
@@ -29,6 +29,7 @@
   * `gethostid`
   * `shm_open`/`shm_unlink`
   * `sockatmark`
+  * `ualarm`
 
 Missing functionality:
   * `<aio.h>`
diff --git a/libc/Android.bp b/libc/Android.bp
index 97146aa..b7cb59d 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -259,18 +259,22 @@
         // Include tzsetwall, timelocal, timegm, time2posix, and posix2time.
         "-DSTD_INSPIRED",
         // Obviously, we want to be thread-safe.
-        "-DTHREAD_SAFE",
+        "-DTHREAD_SAFE=1",
         // The name of the tm_gmtoff field in our struct tm.
         "-DTM_GMTOFF=tm_gmtoff",
+        // TZDEFAULT is not applicable to Android as there is no one file per time zone mapping
+        "-DTZDEFAULT=NULL",
         // Where we store our tzdata.
         "-DTZDIR=\"/system/usr/share/zoneinfo\"",
         // Include `tzname`, `timezone`, and `daylight` globals.
         "-DHAVE_POSIX_DECLS=0",
-        "-DUSG_COMPAT=1",
+        "-DUSG_COMPAT=2",
+        "-DHAVE_TZNAME=2",
+        // stdbool.h is available
+        "-DHAVE_STDBOOL_H",
         // Use the empty string (instead of "   ") as the timezone abbreviation
         // fallback.
         "-DWILDABBR=\"\"",
-        "-DNO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU",
         "-Dlint",
     ],
 
@@ -372,7 +376,6 @@
                 "upstream-freebsd/lib/libc/string/wcscat.c",
                 "upstream-freebsd/lib/libc/string/wcscpy.c",
                 "upstream-freebsd/lib/libc/string/wmemcmp.c",
-                "upstream-freebsd/lib/libc/string/wmemset.c",
             ],
         },
     },
@@ -923,24 +926,42 @@
                 "arch-x86/generic/string/wcscat.c",
                 "arch-x86/generic/string/wcscpy.c",
                 "arch-x86/generic/string/wmemcmp.c",
-                "arch-x86/generic/string/wmemset.c",
 
-                "arch-x86/atom/string/sse2-memchr-atom.S",
-                "arch-x86/atom/string/sse2-memrchr-atom.S",
-                "arch-x86/atom/string/sse2-strchr-atom.S",
-                "arch-x86/atom/string/sse2-strnlen-atom.S",
-                "arch-x86/atom/string/sse2-strrchr-atom.S",
-                "arch-x86/atom/string/sse2-wcschr-atom.S",
-                "arch-x86/atom/string/sse2-wcsrchr-atom.S",
-                "arch-x86/atom/string/sse2-wcslen-atom.S",
-                "arch-x86/atom/string/sse2-wcscmp-atom.S",
-                "arch-x86/silvermont/string/sse2-memmove-slm.S",
-                "arch-x86/silvermont/string/sse2-memset-slm.S",
-                "arch-x86/silvermont/string/sse2-stpcpy-slm.S",
-                "arch-x86/silvermont/string/sse2-stpncpy-slm.S",
-                "arch-x86/silvermont/string/sse2-strcpy-slm.S",
-                "arch-x86/silvermont/string/sse2-strlen-slm.S",
-                "arch-x86/silvermont/string/sse2-strncpy-slm.S",
+                "arch-x86/string/sse2-memchr-atom.S",
+                "arch-x86/string/sse2-memmove-slm.S",
+                "arch-x86/string/sse2-memrchr-atom.S",
+                "arch-x86/string/sse2-memset-atom.S",
+                "arch-x86/string/sse2-memset-slm.S",
+                "arch-x86/string/sse2-stpcpy-slm.S",
+                "arch-x86/string/sse2-stpncpy-slm.S",
+                "arch-x86/string/sse2-strchr-atom.S",
+                "arch-x86/string/sse2-strcpy-slm.S",
+                "arch-x86/string/sse2-strlen-slm.S",
+                "arch-x86/string/sse2-strncpy-slm.S",
+                "arch-x86/string/sse2-strnlen-atom.S",
+                "arch-x86/string/sse2-strrchr-atom.S",
+                "arch-x86/string/sse2-wcschr-atom.S",
+                "arch-x86/string/sse2-wcsrchr-atom.S",
+                "arch-x86/string/sse2-wcslen-atom.S",
+                "arch-x86/string/sse2-wcscmp-atom.S",
+                "arch-x86/string/sse2-strlen-atom.S",
+
+                "arch-x86/string/ssse3-memcmp-atom.S",
+                "arch-x86/string/ssse3-memmove-atom.S",
+                "arch-x86/string/ssse3-strcat-atom.S",
+                "arch-x86/string/ssse3-strcmp-atom.S",
+                "arch-x86/string/ssse3-strcpy-atom.S",
+                "arch-x86/string/ssse3-strlcat-atom.S",
+                "arch-x86/string/ssse3-strlcpy-atom.S",
+                "arch-x86/string/ssse3-strncat-atom.S",
+                "arch-x86/string/ssse3-strncmp-atom.S",
+                "arch-x86/string/ssse3-strncpy-atom.S",
+                "arch-x86/string/ssse3-wcscat-atom.S",
+                "arch-x86/string/ssse3-wcscpy-atom.S",
+                "arch-x86/string/ssse3-wmemcmp-atom.S",
+
+                "arch-x86/string/sse4-memcmp-slm.S",
+                "arch-x86/string/sse4-wmemcmp-slm.S",
 
                 "arch-x86/bionic/__bionic_clone.S",
                 "arch-x86/bionic/_exit_with_stack_teardown.S",
@@ -950,32 +971,6 @@
                 "arch-x86/bionic/syscall.S",
                 "arch-x86/bionic/vfork.S",
                 "arch-x86/bionic/__x86.get_pc_thunk.S",
-
-                // ssse3 functions
-                "arch-x86/atom/string/ssse3-strcat-atom.S",
-                "arch-x86/atom/string/ssse3-strcmp-atom.S",
-                "arch-x86/atom/string/ssse3-strlcat-atom.S",
-                "arch-x86/atom/string/ssse3-strlcpy-atom.S",
-                "arch-x86/atom/string/ssse3-strncat-atom.S",
-                "arch-x86/atom/string/ssse3-strncmp-atom.S",
-                "arch-x86/atom/string/ssse3-wcscat-atom.S",
-                "arch-x86/atom/string/ssse3-wcscpy-atom.S",
-
-                // sse4 functions
-                "arch-x86/silvermont/string/sse4-memcmp-slm.S",
-                "arch-x86/silvermont/string/sse4-wmemcmp-slm.S",
-
-                // atom functions
-                "arch-x86/atom/string/sse2-memset-atom.S",
-                "arch-x86/atom/string/sse2-strlen-atom.S",
-                "arch-x86/atom/string/ssse3-memcmp-atom.S",
-                "arch-x86/atom/string/ssse3-memmove-atom.S",
-                "arch-x86/atom/string/ssse3-strcpy-atom.S",
-                "arch-x86/atom/string/ssse3-strncpy-atom.S",
-                "arch-x86/atom/string/ssse3-wmemcmp-atom.S",
-
-                // avx2 functions
-                "arch-x86/kabylake/string/avx2-wmemset-kbl.S",
             ],
 
             exclude_srcs: [
@@ -986,6 +981,7 @@
         },
         x86_64: {
             srcs: [
+                "arch-x86_64/string/avx2-memset-kbl.S",
                 "arch-x86_64/string/sse2-memmove-slm.S",
                 "arch-x86_64/string/sse2-memset-slm.S",
                 "arch-x86_64/string/sse2-stpcpy-slm.S",
@@ -998,7 +994,6 @@
                 "arch-x86_64/string/sse4-memcmp-slm.S",
                 "arch-x86_64/string/ssse3-strcmp-slm.S",
                 "arch-x86_64/string/ssse3-strncmp-slm.S",
-                "arch-x86_64/string/avx2-wmemset-kbl.S",
 
                 "arch-x86_64/bionic/__bionic_clone.S",
                 "arch-x86_64/bionic/_exit_with_stack_teardown.S",
@@ -1303,8 +1298,8 @@
     name: "syscalls-arm.S",
     out: ["syscalls-arm.S"],
     srcs: ["SYSCALLS.TXT"],
-    tool_files: [":bionic-gensyscalls"],
-    cmd: "$(location :bionic-gensyscalls) arm $(in) > $(out)",
+    tools: ["gensyscalls"],
+    cmd: "$(location gensyscalls) arm $(in) > $(out)",
     bazel_module: {
         bp2build_available: true,
     }
@@ -1314,8 +1309,8 @@
     name: "syscalls-arm64.S",
     out: ["syscalls-arm64.S"],
     srcs: ["SYSCALLS.TXT"],
-    tool_files: [":bionic-gensyscalls"],
-    cmd: "$(location :bionic-gensyscalls) arm64 $(in) > $(out)",
+    tools: ["gensyscalls"],
+    cmd: "$(location gensyscalls) arm64 $(in) > $(out)",
     bazel_module: {
         bp2build_available: true,
     },
@@ -1325,8 +1320,8 @@
     name: "syscalls-x86.S",
     out: ["syscalls-x86.S"],
     srcs: ["SYSCALLS.TXT"],
-    tool_files: [":bionic-gensyscalls"],
-    cmd: "$(location :bionic-gensyscalls) x86 $(in) > $(out)",
+    tools: ["gensyscalls"],
+    cmd: "$(location gensyscalls) x86 $(in) > $(out)",
     bazel_module: {
         bp2build_available: true,
     },
@@ -1336,8 +1331,8 @@
     name: "syscalls-x86_64.S",
     out: ["syscalls-x86_64.S"],
     srcs: ["SYSCALLS.TXT"],
-    tool_files: [":bionic-gensyscalls"],
-    cmd: "$(location :bionic-gensyscalls) x86_64 $(in) > $(out)",
+    tools: ["gensyscalls"],
+    cmd: "$(location gensyscalls) x86_64 $(in) > $(out)",
     bazel_module: {
         bp2build_available: true,
     },
@@ -1511,6 +1506,9 @@
     name: "libc_static_dispatch",
 
     arch: {
+        x86_64: {
+            srcs: ["arch-x86_64/static_function_dispatch.S"],
+        },
         x86: {
             srcs: ["arch-x86/static_function_dispatch.S"],
         },
@@ -1536,6 +1534,9 @@
         "-fno-jump-tables",
     ],
     arch: {
+        x86_64: {
+            srcs: ["arch-x86_64/dynamic_function_dispatch.cpp"],
+        },
         x86: {
             srcs: ["arch-x86/dynamic_function_dispatch.cpp"],
         },
@@ -1686,8 +1687,8 @@
     },
 
     required: [
-        "tzdata",
-        "tz_version", // Version metadata for tzdata to help debugging.
+        "tzdata_prebuilt",
+        "tz_version_prebuilt", // Version metadata for tzdata to help debugging.
     ],
 
     // Do not pack libc.so relocations; see http://b/20645321 for details.
@@ -1807,8 +1808,8 @@
     name: "libc.arm.map",
     out: ["libc.arm.map"],
     srcs: ["libc.map.txt"],
-    tool_files: [":bionic-generate-version-script"],
-    cmd: "$(location :bionic-generate-version-script) arm $(in) $(out)",
+    tools: ["generate-version-script"],
+    cmd: "$(location generate-version-script) arm $(in) $(out)",
     bazel_module: { bp2build_available: true },
 }
 
@@ -1816,8 +1817,8 @@
     name: "libc.arm64.map",
     out: ["libc.arm64.map"],
     srcs: ["libc.map.txt"],
-    tool_files: [":bionic-generate-version-script"],
-    cmd: "$(location :bionic-generate-version-script) arm64 $(in) $(out)",
+    tools: ["generate-version-script"],
+    cmd: "$(location generate-version-script) arm64 $(in) $(out)",
     bazel_module: { bp2build_available: true },
 }
 
@@ -1825,8 +1826,8 @@
     name: "libc.x86.map",
     out: ["libc.x86.map"],
     srcs: ["libc.map.txt"],
-    tool_files: [":bionic-generate-version-script"],
-    cmd: "$(location :bionic-generate-version-script) x86 $(in) $(out)",
+    tools: ["generate-version-script"],
+    cmd: "$(location generate-version-script) x86 $(in) $(out)",
     bazel_module: { bp2build_available: true },
 }
 
@@ -1834,8 +1835,8 @@
     name: "libc.x86_64.map",
     out: ["libc.x86_64.map"],
     srcs: ["libc.map.txt"],
-    tool_files: [":bionic-generate-version-script"],
-    cmd: "$(location :bionic-generate-version-script) x86_64 $(in) $(out)",
+    tools: ["generate-version-script"],
+    cmd: "$(location generate-version-script) x86_64 $(in) $(out)",
     bazel_module: { bp2build_available: true },
 }
 
@@ -2036,32 +2037,32 @@
     name: "libstdc++.arm.map",
     out: ["libstdc++.arm.map"],
     srcs: ["libstdc++.map.txt"],
-    tool_files: [":bionic-generate-version-script"],
-    cmd: "$(location :bionic-generate-version-script) arm $(in) $(out)",
+    tools: ["generate-version-script"],
+    cmd: "$(location generate-version-script) arm $(in) $(out)",
 }
 
 genrule {
     name: "libstdc++.arm64.map",
     out: ["libstdc++.arm64.map"],
     srcs: ["libstdc++.map.txt"],
-    tool_files: [":bionic-generate-version-script"],
-    cmd: "$(location :bionic-generate-version-script) arm64 $(in) $(out)",
+    tools: ["generate-version-script"],
+    cmd: "$(location generate-version-script) arm64 $(in) $(out)",
 }
 
 genrule {
     name: "libstdc++.x86.map",
     out: ["libstdc++.x86.map"],
     srcs: ["libstdc++.map.txt"],
-    tool_files: [":bionic-generate-version-script"],
-    cmd: "$(location :bionic-generate-version-script) x86 $(in) $(out)",
+    tools: ["generate-version-script"],
+    cmd: "$(location generate-version-script) x86 $(in) $(out)",
 }
 
 genrule {
     name: "libstdc++.x86_64.map",
     out: ["libstdc++.x86_64.map"],
     srcs: ["libstdc++.map.txt"],
-    tool_files: [":bionic-generate-version-script"],
-    cmd: "$(location :bionic-generate-version-script) x86_64 $(in) $(out)",
+    tools: ["generate-version-script"],
+    cmd: "$(location generate-version-script) x86_64 $(in) $(out)",
 }
 
 // ========================================================
diff --git a/libc/BUILD b/libc/BUILD
new file mode 100644
index 0000000..e26c026
--- /dev/null
+++ b/libc/BUILD
@@ -0,0 +1,42 @@
+# Copyright (C) 2022 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.
+
+load("//build/bazel/rules/apis:cc_api_contribution.bzl", "cc_api_contribution")
+
+cc_api_contribution(
+  name="libc_contributions",
+  library_name="libc",
+  api=":libc.map.txt",
+  hdrs=[
+    "//bionic/libc/kernel/android:libc_kernel_android_uapi_headers",
+    "//bionic/libc/kernel/android:libc_kernel_android_scsi_headers",
+    "//bionic/libc/kernel/uapi:libc_kernel_uapi_headers",
+    "//bionic/libc/kernel/uapi:libc_kernal_uapi_asm_arm_headers", #arm
+    "//bionic/libc/kernel/uapi:libc_kernal_uapi_asm_arm64_headers", #arm64
+    "//bionic/libc/kernel/uapi:libc_kernal_uapi_asm_x86_headers", #x86
+    "//bionic/libc/kernel/uapi:libc_kernal_uapi_asm_x86_64_headers", #x86_64
+  ],
+)
diff --git a/libc/NOTICE b/libc/NOTICE
index 9cbbde2..fa3dd2c 100644
--- a/libc/NOTICE
+++ b/libc/NOTICE
@@ -783,22 +783,6 @@
 -------------------------------------------------------------------
 
 Copyright (C) 2019 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) 2019 The Android Open Source Project
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -826,34 +810,6 @@
 
 -------------------------------------------------------------------
 
-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.
-
--------------------------------------------------------------------
-
 Copyright (C) 2020 The Android Open Source Project
 All rights reserved.
 
diff --git a/libc/arch-x86/atom/string/cache.h b/libc/arch-x86/atom/string/cache.h
deleted file mode 100644
index 823bb1e..0000000
--- a/libc/arch-x86/atom/string/cache.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
-Copyright (c) 2010, Intel Corporation
-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.
-
-    * Neither the name of Intel Corporation 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 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.
-*/
-
-/* Values are optimized for Atom */
-#define SHARED_CACHE_SIZE	(512*1024)			/* Atom L2 Cache */
-#define DATA_CACHE_SIZE		(24*1024)			/* Atom L1 Data Cache */
-
-#define SHARED_CACHE_SIZE_HALF	(SHARED_CACHE_SIZE / 2)
-#define DATA_CACHE_SIZE_HALF	(DATA_CACHE_SIZE / 2)
diff --git a/libc/arch-x86/dynamic_function_dispatch.cpp b/libc/arch-x86/dynamic_function_dispatch.cpp
index e94fa1f..38d8a0a 100644
--- a/libc/arch-x86/dynamic_function_dispatch.cpp
+++ b/libc/arch-x86/dynamic_function_dispatch.cpp
@@ -95,13 +95,6 @@
     RETURN_FUNC(wmemcmp_func, wmemcmp_freebsd);
 }
 
-typedef int wmemset_func(const wchar_t* __lhs, const wchar_t* __rhs, size_t __n);
-DEFINE_IFUNC_FOR(wmemset) {
-    __builtin_cpu_init();
-    if (__builtin_cpu_supports("avx2")) RETURN_FUNC(wmemset_func, wmemset_avx2);
-    RETURN_FUNC(wmemset_func, wmemset_freebsd);
-}
-
 typedef int strcmp_func(const char* __lhs, const char* __rhs);
 DEFINE_IFUNC_FOR(strcmp) {
     __builtin_cpu_init();
diff --git a/libc/arch-x86/generic/string/wmemset.c b/libc/arch-x86/generic/string/wmemset.c
deleted file mode 100644
index 35d489f..0000000
--- a/libc/arch-x86/generic/string/wmemset.c
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2019 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.
-*/
-
-#define wmemset wmemset_freebsd
-
-#include <upstream-freebsd/lib/libc/string/wmemset.c>
diff --git a/libc/arch-x86/kabylake/string/avx2-wmemset-kbl.S b/libc/arch-x86/kabylake/string/avx2-wmemset-kbl.S
deleted file mode 100644
index 69b66c7..0000000
--- a/libc/arch-x86/kabylake/string/avx2-wmemset-kbl.S
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
-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.
-*/
-
-#include <private/bionic_asm.h>
-
-#ifndef WMEMSET
- #define WMEMSET wmemset_avx2
-#endif
-
-ENTRY(WMEMSET)
-# BB#0:
-	pushl	%ebp
-	pushl	%ebx
-	pushl	%edi
-	pushl	%esi
-	pushl	%eax
-	movl	32(%esp), %ecx
-	movl	24(%esp), %eax
-	testl	%ecx, %ecx
-	je	.LBB0_12
-# BB#1:
-	movl	28(%esp), %edx
-	xorl	%edi, %edi
-	movl	%eax, %esi
-	cmpl	$32, %ecx
-	jb	.LBB0_10
-# BB#2:
-	movl	%ecx, %eax
-	andl	$-32, %eax
-	vmovd	%edx, %xmm0
-	vpbroadcastd	%xmm0, %ymm0
-	movl	%eax, (%esp)            # 4-byte Spill
-	leal	-32(%eax), %esi
-	movl	%esi, %eax
-	shrl	$5, %eax
-	leal	1(%eax), %edi
-	andl	$7, %edi
-	xorl	%ebx, %ebx
-	cmpl	$224, %esi
-	jb	.LBB0_5
-# BB#3:
-	movl	24(%esp), %esi
-	leal	992(%esi), %ebp
-	leal	-1(%edi), %esi
-	subl	%eax, %esi
-	xorl	%ebx, %ebx
-	.p2align	4, 0x90
-.LBB0_4:                                # =>This Inner Loop Header: Depth=1
-	vmovdqu	%ymm0, -992(%ebp,%ebx,4)
-	vmovdqu	%ymm0, -960(%ebp,%ebx,4)
-	vmovdqu	%ymm0, -928(%ebp,%ebx,4)
-	vmovdqu	%ymm0, -896(%ebp,%ebx,4)
-	vmovdqu	%ymm0, -864(%ebp,%ebx,4)
-	vmovdqu	%ymm0, -832(%ebp,%ebx,4)
-	vmovdqu	%ymm0, -800(%ebp,%ebx,4)
-	vmovdqu	%ymm0, -768(%ebp,%ebx,4)
-	vmovdqu	%ymm0, -736(%ebp,%ebx,4)
-	vmovdqu	%ymm0, -704(%ebp,%ebx,4)
-	vmovdqu	%ymm0, -672(%ebp,%ebx,4)
-	vmovdqu	%ymm0, -640(%ebp,%ebx,4)
-	vmovdqu	%ymm0, -608(%ebp,%ebx,4)
-	vmovdqu	%ymm0, -576(%ebp,%ebx,4)
-	vmovdqu	%ymm0, -544(%ebp,%ebx,4)
-	vmovdqu	%ymm0, -512(%ebp,%ebx,4)
-	vmovdqu	%ymm0, -480(%ebp,%ebx,4)
-	vmovdqu	%ymm0, -448(%ebp,%ebx,4)
-	vmovdqu	%ymm0, -416(%ebp,%ebx,4)
-	vmovdqu	%ymm0, -384(%ebp,%ebx,4)
-	vmovdqu	%ymm0, -352(%ebp,%ebx,4)
-	vmovdqu	%ymm0, -320(%ebp,%ebx,4)
-	vmovdqu	%ymm0, -288(%ebp,%ebx,4)
-	vmovdqu	%ymm0, -256(%ebp,%ebx,4)
-	vmovdqu	%ymm0, -224(%ebp,%ebx,4)
-	vmovdqu	%ymm0, -192(%ebp,%ebx,4)
-	vmovdqu	%ymm0, -160(%ebp,%ebx,4)
-	vmovdqu	%ymm0, -128(%ebp,%ebx,4)
-	vmovdqu	%ymm0, -96(%ebp,%ebx,4)
-	vmovdqu	%ymm0, -64(%ebp,%ebx,4)
-	vmovdqu	%ymm0, -32(%ebp,%ebx,4)
-	vmovdqu	%ymm0, (%ebp,%ebx,4)
-	addl	$256, %ebx              # imm = 0x100
-	addl	$8, %esi
-	jne	.LBB0_4
-.LBB0_5:
-	testl	%edi, %edi
-	movl	24(%esp), %eax
-	je	.LBB0_8
-# BB#6:
-	leal	(%eax,%ebx,4), %esi
-	addl	$96, %esi
-	negl	%edi
-	.p2align	4, 0x90
-.LBB0_7:                                # =>This Inner Loop Header: Depth=1
-	vmovdqu	%ymm0, -96(%esi)
-	vmovdqu	%ymm0, -64(%esi)
-	vmovdqu	%ymm0, -32(%esi)
-	vmovdqu	%ymm0, (%esi)
-	subl	$-128, %esi
-	addl	$1, %edi
-	jne	.LBB0_7
-.LBB0_8:
-	movl	(%esp), %edi            # 4-byte Reload
-	cmpl	%ecx, %edi
-	je	.LBB0_12
-# BB#9:
-	leal	(%eax,%edi,4), %esi
-.LBB0_10:
-	subl	%edi, %ecx
-	.p2align	4, 0x90
-.LBB0_11:                               # =>This Inner Loop Header: Depth=1
-	movl	%edx, (%esi)
-	addl	$4, %esi
-	addl	$-1, %ecx
-	jne	.LBB0_11
-.LBB0_12:
-	addl	$4, %esp
-	popl	%esi
-	popl	%edi
-	popl	%ebx
-	popl	%ebp
-	vzeroupper
-	retl
-END(WMEMSET)
diff --git a/libc/arch-x86/static_function_dispatch.S b/libc/arch-x86/static_function_dispatch.S
index 1560c04..7e8e63d 100644
--- a/libc/arch-x86/static_function_dispatch.S
+++ b/libc/arch-x86/static_function_dispatch.S
@@ -45,7 +45,6 @@
 FUNCTION_DELEGATE(strncmp, strncmp_generic)
 FUNCTION_DELEGATE(strcat, strcat_generic)
 FUNCTION_DELEGATE(wmemcmp, wmemcmp_freebsd)
-FUNCTION_DELEGATE(wmemset, wmemset_freebsd)
 FUNCTION_DELEGATE(wcscat, wcscat_freebsd)
 FUNCTION_DELEGATE(strncat, strncat_openbsd)
 FUNCTION_DELEGATE(strlcat, strlcat_openbsd)
diff --git a/libc/arch-x86/silvermont/string/cache.h b/libc/arch-x86/string/cache.h
similarity index 80%
rename from libc/arch-x86/silvermont/string/cache.h
rename to libc/arch-x86/string/cache.h
index c342b1c..33719a0 100644
--- a/libc/arch-x86/silvermont/string/cache.h
+++ b/libc/arch-x86/string/cache.h
@@ -28,9 +28,14 @@
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-/* Values are optimized for Silvermont */
-#define SHARED_CACHE_SIZE	(1024*1024)			/* Silvermont L2 Cache */
-#define DATA_CACHE_SIZE		(24*1024)			/* Silvermont L1 Data Cache */
+#ifdef FOR_ATOM
+#define SHARED_CACHE_SIZE (512 * 1024) /* Atom L2 Cache */
+#endif
+#ifdef FOR_SILVERMONT
+#define SHARED_CACHE_SIZE (1024 * 1024) /* Silvermont L2 Cache */
+#endif
 
-#define SHARED_CACHE_SIZE_HALF	(SHARED_CACHE_SIZE / 2)
-#define DATA_CACHE_SIZE_HALF	(DATA_CACHE_SIZE / 2)
+#define DATA_CACHE_SIZE (24 * 1024) /* Atom and Silvermont L1 Data Cache */
+
+#define SHARED_CACHE_SIZE_HALF (SHARED_CACHE_SIZE / 2)
+#define DATA_CACHE_SIZE_HALF (DATA_CACHE_SIZE / 2)
diff --git a/libc/arch-x86/atom/string/sse2-memchr-atom.S b/libc/arch-x86/string/sse2-memchr-atom.S
similarity index 100%
rename from libc/arch-x86/atom/string/sse2-memchr-atom.S
rename to libc/arch-x86/string/sse2-memchr-atom.S
diff --git a/libc/arch-x86/silvermont/string/sse2-memmove-slm.S b/libc/arch-x86/string/sse2-memmove-slm.S
similarity index 99%
rename from libc/arch-x86/silvermont/string/sse2-memmove-slm.S
rename to libc/arch-x86/string/sse2-memmove-slm.S
index da6456c..79b5d1b 100644
--- a/libc/arch-x86/silvermont/string/sse2-memmove-slm.S
+++ b/libc/arch-x86/string/sse2-memmove-slm.S
@@ -28,6 +28,7 @@
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
+#define FOR_SILVERMONT
 #include "cache.h"
 
 #ifndef MEMMOVE
diff --git a/libc/arch-x86/atom/string/sse2-memrchr-atom.S b/libc/arch-x86/string/sse2-memrchr-atom.S
similarity index 100%
rename from libc/arch-x86/atom/string/sse2-memrchr-atom.S
rename to libc/arch-x86/string/sse2-memrchr-atom.S
diff --git a/libc/arch-x86/atom/string/sse2-memset-atom.S b/libc/arch-x86/string/sse2-memset-atom.S
similarity index 99%
rename from libc/arch-x86/atom/string/sse2-memset-atom.S
rename to libc/arch-x86/string/sse2-memset-atom.S
index e4cd038..320afec 100644
--- a/libc/arch-x86/atom/string/sse2-memset-atom.S
+++ b/libc/arch-x86/string/sse2-memset-atom.S
@@ -30,6 +30,7 @@
 
 #include <private/bionic_asm.h>
 
+#define FOR_ATOM
 #include "cache.h"
 
 #ifndef L
diff --git a/libc/arch-x86/silvermont/string/sse2-memset-slm.S b/libc/arch-x86/string/sse2-memset-slm.S
similarity index 99%
rename from libc/arch-x86/silvermont/string/sse2-memset-slm.S
rename to libc/arch-x86/string/sse2-memset-slm.S
index b7633f5..5cff141 100644
--- a/libc/arch-x86/silvermont/string/sse2-memset-slm.S
+++ b/libc/arch-x86/string/sse2-memset-slm.S
@@ -30,6 +30,7 @@
 
 #include <private/bionic_asm.h>
 
+#define FOR_SILVERMONT
 #include "cache.h"
 
 #ifndef L
diff --git a/libc/arch-x86/silvermont/string/sse2-stpcpy-slm.S b/libc/arch-x86/string/sse2-stpcpy-slm.S
similarity index 100%
rename from libc/arch-x86/silvermont/string/sse2-stpcpy-slm.S
rename to libc/arch-x86/string/sse2-stpcpy-slm.S
diff --git a/libc/arch-x86/silvermont/string/sse2-stpncpy-slm.S b/libc/arch-x86/string/sse2-stpncpy-slm.S
similarity index 100%
rename from libc/arch-x86/silvermont/string/sse2-stpncpy-slm.S
rename to libc/arch-x86/string/sse2-stpncpy-slm.S
diff --git a/libc/arch-x86/atom/string/sse2-strchr-atom.S b/libc/arch-x86/string/sse2-strchr-atom.S
similarity index 100%
rename from libc/arch-x86/atom/string/sse2-strchr-atom.S
rename to libc/arch-x86/string/sse2-strchr-atom.S
diff --git a/libc/arch-x86/silvermont/string/sse2-strcpy-slm.S b/libc/arch-x86/string/sse2-strcpy-slm.S
similarity index 100%
rename from libc/arch-x86/silvermont/string/sse2-strcpy-slm.S
rename to libc/arch-x86/string/sse2-strcpy-slm.S
diff --git a/libc/arch-x86/atom/string/sse2-strlen-atom.S b/libc/arch-x86/string/sse2-strlen-atom.S
similarity index 100%
rename from libc/arch-x86/atom/string/sse2-strlen-atom.S
rename to libc/arch-x86/string/sse2-strlen-atom.S
diff --git a/libc/arch-x86/silvermont/string/sse2-strlen-slm.S b/libc/arch-x86/string/sse2-strlen-slm.S
similarity index 100%
rename from libc/arch-x86/silvermont/string/sse2-strlen-slm.S
rename to libc/arch-x86/string/sse2-strlen-slm.S
diff --git a/libc/arch-x86/silvermont/string/sse2-strncpy-slm.S b/libc/arch-x86/string/sse2-strncpy-slm.S
similarity index 100%
rename from libc/arch-x86/silvermont/string/sse2-strncpy-slm.S
rename to libc/arch-x86/string/sse2-strncpy-slm.S
diff --git a/libc/arch-x86/atom/string/sse2-strnlen-atom.S b/libc/arch-x86/string/sse2-strnlen-atom.S
similarity index 100%
rename from libc/arch-x86/atom/string/sse2-strnlen-atom.S
rename to libc/arch-x86/string/sse2-strnlen-atom.S
diff --git a/libc/arch-x86/atom/string/sse2-strrchr-atom.S b/libc/arch-x86/string/sse2-strrchr-atom.S
similarity index 100%
rename from libc/arch-x86/atom/string/sse2-strrchr-atom.S
rename to libc/arch-x86/string/sse2-strrchr-atom.S
diff --git a/libc/arch-x86/atom/string/sse2-wcschr-atom.S b/libc/arch-x86/string/sse2-wcschr-atom.S
similarity index 100%
rename from libc/arch-x86/atom/string/sse2-wcschr-atom.S
rename to libc/arch-x86/string/sse2-wcschr-atom.S
diff --git a/libc/arch-x86/atom/string/sse2-wcscmp-atom.S b/libc/arch-x86/string/sse2-wcscmp-atom.S
similarity index 100%
rename from libc/arch-x86/atom/string/sse2-wcscmp-atom.S
rename to libc/arch-x86/string/sse2-wcscmp-atom.S
diff --git a/libc/arch-x86/atom/string/sse2-wcslen-atom.S b/libc/arch-x86/string/sse2-wcslen-atom.S
similarity index 100%
rename from libc/arch-x86/atom/string/sse2-wcslen-atom.S
rename to libc/arch-x86/string/sse2-wcslen-atom.S
diff --git a/libc/arch-x86/atom/string/sse2-wcsrchr-atom.S b/libc/arch-x86/string/sse2-wcsrchr-atom.S
similarity index 100%
rename from libc/arch-x86/atom/string/sse2-wcsrchr-atom.S
rename to libc/arch-x86/string/sse2-wcsrchr-atom.S
diff --git a/libc/arch-x86/silvermont/string/sse4-memcmp-slm.S b/libc/arch-x86/string/sse4-memcmp-slm.S
similarity index 100%
rename from libc/arch-x86/silvermont/string/sse4-memcmp-slm.S
rename to libc/arch-x86/string/sse4-memcmp-slm.S
diff --git a/libc/arch-x86/silvermont/string/sse4-wmemcmp-slm.S b/libc/arch-x86/string/sse4-wmemcmp-slm.S
similarity index 100%
rename from libc/arch-x86/silvermont/string/sse4-wmemcmp-slm.S
rename to libc/arch-x86/string/sse4-wmemcmp-slm.S
diff --git a/libc/arch-x86/atom/string/ssse3-memcmp-atom.S b/libc/arch-x86/string/ssse3-memcmp-atom.S
similarity index 100%
rename from libc/arch-x86/atom/string/ssse3-memcmp-atom.S
rename to libc/arch-x86/string/ssse3-memcmp-atom.S
diff --git a/libc/arch-x86/atom/string/ssse3-memcpy-atom.S b/libc/arch-x86/string/ssse3-memcpy-atom.S
similarity index 99%
rename from libc/arch-x86/atom/string/ssse3-memcpy-atom.S
rename to libc/arch-x86/string/ssse3-memcpy-atom.S
index 5532e2e..fe3082e 100644
--- a/libc/arch-x86/atom/string/ssse3-memcpy-atom.S
+++ b/libc/arch-x86/string/ssse3-memcpy-atom.S
@@ -28,6 +28,7 @@
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
+#define FOR_ATOM
 #include "cache.h"
 
 #ifndef MEMCPY
diff --git a/libc/arch-x86/atom/string/ssse3-memmove-atom.S b/libc/arch-x86/string/ssse3-memmove-atom.S
similarity index 100%
rename from libc/arch-x86/atom/string/ssse3-memmove-atom.S
rename to libc/arch-x86/string/ssse3-memmove-atom.S
diff --git a/libc/arch-x86/atom/string/ssse3-strcat-atom.S b/libc/arch-x86/string/ssse3-strcat-atom.S
similarity index 100%
rename from libc/arch-x86/atom/string/ssse3-strcat-atom.S
rename to libc/arch-x86/string/ssse3-strcat-atom.S
diff --git a/libc/arch-x86/atom/string/ssse3-strcmp-atom.S b/libc/arch-x86/string/ssse3-strcmp-atom.S
similarity index 100%
rename from libc/arch-x86/atom/string/ssse3-strcmp-atom.S
rename to libc/arch-x86/string/ssse3-strcmp-atom.S
diff --git a/libc/arch-x86/atom/string/ssse3-strcpy-atom.S b/libc/arch-x86/string/ssse3-strcpy-atom.S
similarity index 100%
rename from libc/arch-x86/atom/string/ssse3-strcpy-atom.S
rename to libc/arch-x86/string/ssse3-strcpy-atom.S
diff --git a/libc/arch-x86/atom/string/ssse3-strlcat-atom.S b/libc/arch-x86/string/ssse3-strlcat-atom.S
similarity index 100%
rename from libc/arch-x86/atom/string/ssse3-strlcat-atom.S
rename to libc/arch-x86/string/ssse3-strlcat-atom.S
diff --git a/libc/arch-x86/atom/string/ssse3-strlcpy-atom.S b/libc/arch-x86/string/ssse3-strlcpy-atom.S
similarity index 100%
rename from libc/arch-x86/atom/string/ssse3-strlcpy-atom.S
rename to libc/arch-x86/string/ssse3-strlcpy-atom.S
diff --git a/libc/arch-x86/atom/string/ssse3-strncat-atom.S b/libc/arch-x86/string/ssse3-strncat-atom.S
similarity index 100%
rename from libc/arch-x86/atom/string/ssse3-strncat-atom.S
rename to libc/arch-x86/string/ssse3-strncat-atom.S
diff --git a/libc/arch-x86/atom/string/ssse3-strncmp-atom.S b/libc/arch-x86/string/ssse3-strncmp-atom.S
similarity index 100%
rename from libc/arch-x86/atom/string/ssse3-strncmp-atom.S
rename to libc/arch-x86/string/ssse3-strncmp-atom.S
diff --git a/libc/arch-x86/atom/string/ssse3-strncpy-atom.S b/libc/arch-x86/string/ssse3-strncpy-atom.S
similarity index 100%
rename from libc/arch-x86/atom/string/ssse3-strncpy-atom.S
rename to libc/arch-x86/string/ssse3-strncpy-atom.S
diff --git a/libc/arch-x86/atom/string/ssse3-wcscat-atom.S b/libc/arch-x86/string/ssse3-wcscat-atom.S
similarity index 100%
rename from libc/arch-x86/atom/string/ssse3-wcscat-atom.S
rename to libc/arch-x86/string/ssse3-wcscat-atom.S
diff --git a/libc/arch-x86/atom/string/ssse3-wcscpy-atom.S b/libc/arch-x86/string/ssse3-wcscpy-atom.S
similarity index 100%
rename from libc/arch-x86/atom/string/ssse3-wcscpy-atom.S
rename to libc/arch-x86/string/ssse3-wcscpy-atom.S
diff --git a/libc/arch-x86/atom/string/ssse3-wmemcmp-atom.S b/libc/arch-x86/string/ssse3-wmemcmp-atom.S
similarity index 100%
rename from libc/arch-x86/atom/string/ssse3-wmemcmp-atom.S
rename to libc/arch-x86/string/ssse3-wmemcmp-atom.S
diff --git a/libc/arch-x86_64/dynamic_function_dispatch.cpp b/libc/arch-x86_64/dynamic_function_dispatch.cpp
new file mode 100644
index 0000000..c846ded
--- /dev/null
+++ b/libc/arch-x86_64/dynamic_function_dispatch.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2022 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 <stddef.h>
+
+#include <private/bionic_ifuncs.h>
+
+extern "C" {
+
+typedef int memset_func(void* __dst, int __ch, size_t __n);
+DEFINE_IFUNC_FOR(memset) {
+  __builtin_cpu_init();
+  if (__builtin_cpu_supports("avx2")) RETURN_FUNC(memset_func, memset_avx2);
+  RETURN_FUNC(memset_func, memset_generic);
+}
+
+typedef void* __memset_chk_func(void* s, int c, size_t n, size_t n2);
+DEFINE_IFUNC_FOR(__memset_chk) {
+  __builtin_cpu_init();
+  if (__builtin_cpu_supports("avx2")) RETURN_FUNC(__memset_chk_func, __memset_chk_avx2);
+  RETURN_FUNC(__memset_chk_func, __memset_chk_generic);
+}
+
+}  // extern "C"
diff --git a/libc/arch-x86_64/static_function_dispatch.S b/libc/arch-x86_64/static_function_dispatch.S
new file mode 100644
index 0000000..93ff5f2
--- /dev/null
+++ b/libc/arch-x86_64/static_function_dispatch.S
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2022 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 <private/bionic_asm.h>
+
+#define FUNCTION_DELEGATE(name, impl) \
+ENTRY(name); \
+    jmp impl; \
+END(name)
+
+FUNCTION_DELEGATE(memset, memset_generic)
+FUNCTION_DELEGATE(__memset_chk, __memset_chk_generic)
diff --git a/libc/arch-x86_64/string/avx2-memset-kbl.S b/libc/arch-x86_64/string/avx2-memset-kbl.S
new file mode 100644
index 0000000..09dd07d
--- /dev/null
+++ b/libc/arch-x86_64/string/avx2-memset-kbl.S
@@ -0,0 +1,160 @@
+/*
+Copyright (c) 2014, Intel Corporation
+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.
+
+    * Neither the name of Intel Corporation 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 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 <private/bionic_asm.h>
+
+#include "cache.h"
+
+#ifndef L
+# define L(label)	.L##label
+#endif
+
+#ifndef ALIGN
+# define ALIGN(n)	.p2align n
+#endif
+
+	.section .text.avx2,"ax",@progbits
+
+ENTRY(__memset_chk_avx2)
+	# %rdi = dst, %rsi = byte, %rdx = n, %rcx = dst_len
+	cmp %rcx, %rdx
+	ja __memset_chk_fail
+	// Fall through to memset...
+END(__memset_chk_avx2)
+
+ENTRY(memset_avx2)
+	movq	%rdi, %rax
+	and	$0xff, %rsi
+	mov	$0x0101010101010101, %rcx
+	imul	%rsi, %rcx
+	cmpq	$16, %rdx
+	jae	L(16bytesormore)
+	testb	$8, %dl
+	jnz	L(8_15bytes)
+	testb	$4, %dl
+	jnz	L(4_7bytes)
+	testb	$2, %dl
+	jnz	L(2_3bytes)
+	testb	$1, %dl
+	jz	L(return)
+	movb	%cl, (%rdi)
+L(return):
+	ret
+
+L(8_15bytes):
+	movq	%rcx, (%rdi)
+	movq	%rcx, -8(%rdi, %rdx)
+	ret
+
+L(4_7bytes):
+	movl	%ecx, (%rdi)
+	movl	%ecx, -4(%rdi, %rdx)
+	ret
+
+L(2_3bytes):
+	movw	%cx, (%rdi)
+	movw	%cx, -2(%rdi, %rdx)
+	ret
+
+	ALIGN (4)
+L(16bytesormore):
+	movd	%rcx, %xmm0
+	pshufd	$0, %xmm0, %xmm0
+	movdqu	%xmm0, (%rdi)
+	movdqu	%xmm0, -16(%rdi, %rdx)
+	cmpq	$32, %rdx
+	jbe	L(32bytesless)
+	movdqu	%xmm0, 16(%rdi)
+	movdqu	%xmm0, -32(%rdi, %rdx)
+	cmpq	$64, %rdx
+	jbe	L(64bytesless)
+	movdqu	%xmm0, 32(%rdi)
+	movdqu	%xmm0, 48(%rdi)
+	movdqu	%xmm0, -64(%rdi, %rdx)
+	movdqu	%xmm0, -48(%rdi, %rdx)
+	cmpq	$128, %rdx
+	jbe	L(128bytesless)
+        vpbroadcastb %xmm0, %ymm0
+	vmovdqu	%ymm0, 64(%rdi)
+	vmovdqu	%ymm0, 96(%rdi)
+	vmovdqu	%ymm0, -128(%rdi, %rdx)
+	vmovdqu	%ymm0, -96(%rdi, %rdx)
+	cmpq	$256, %rdx
+        ja      L(256bytesmore)
+L(32bytesless):
+L(64bytesless):
+L(128bytesless):
+	ret
+
+	ALIGN (4)
+L(256bytesmore):
+	leaq	128(%rdi), %rcx
+	andq	$-128, %rcx
+	movq	%rdx, %r8
+	addq	%rdi, %rdx
+	andq	$-128, %rdx
+	cmpq	%rcx, %rdx
+	je	L(return)
+
+#ifdef SHARED_CACHE_SIZE
+	cmp	$SHARED_CACHE_SIZE, %r8
+#else
+	cmp	__x86_64_shared_cache_size(%rip), %r8
+#endif
+	ja	L(256bytesmore_nt)
+
+	ALIGN (4)
+L(256bytesmore_normal):
+	vmovdqa	%ymm0, (%rcx)
+	vmovdqa	%ymm0, 32(%rcx)
+	vmovdqa	%ymm0, 64(%rcx)
+	vmovdqa	%ymm0, 96(%rcx)
+	addq	$128, %rcx
+	cmpq	%rcx, %rdx
+	jne	L(256bytesmore_normal)
+	ret
+
+	ALIGN (4)
+L(256bytesmore_nt):
+	movntdq	 %xmm0, (%rcx)
+	movntdq	 %xmm0, 16(%rcx)
+	movntdq	 %xmm0, 32(%rcx)
+	movntdq	 %xmm0, 48(%rcx)
+	movntdq	 %xmm0, 64(%rcx)
+	movntdq	 %xmm0, 80(%rcx)
+	movntdq	 %xmm0, 96(%rcx)
+	movntdq	 %xmm0, 112(%rcx)
+	leaq	128(%rcx), %rcx
+	cmpq	%rcx, %rdx
+	jne	L(256bytesmore_nt)
+	sfence
+	ret
+
+END(memset_avx2)
diff --git a/libc/arch-x86_64/string/avx2-wmemset-kbl.S b/libc/arch-x86_64/string/avx2-wmemset-kbl.S
deleted file mode 100644
index 7c485cf..0000000
--- a/libc/arch-x86_64/string/avx2-wmemset-kbl.S
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
-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.
-*/
-
-#include <private/bionic_asm.h>
-
-#ifndef WMEMSET
- #define WMEMSET wmemset_avx2
-#endif
-
-        .section .text.avx2,"ax",@progbits
-
-ENTRY (WMEMSET)
-# BB#0:
-	testq	%rdx, %rdx
-	je	.LBB0_14
-# BB#1:
-	cmpq	$32, %rdx
-	jae	.LBB0_3
-# BB#2:
-	xorl	%r8d, %r8d
-	movq	%rdi, %rax
-	jmp	.LBB0_12
-.LBB0_3:
-	movq	%rdx, %r8
-	andq	$-32, %r8
-	vmovd	%esi, %xmm0
-	vpbroadcastd	%xmm0, %ymm0
-	leaq	-32(%r8), %rcx
-	movq	%rcx, %rax
-	shrq	$5, %rax
-	leal	1(%rax), %r9d
-	andl	$7, %r9d
-	cmpq	$224, %rcx
-	jae	.LBB0_5
-# BB#4:
-	xorl	%eax, %eax
-	testq	%r9, %r9
-	jne	.LBB0_8
-	jmp	.LBB0_10
-.LBB0_5:
-	leaq	992(%rdi), %rcx
-	leaq	-1(%r9), %r10
-	subq	%rax, %r10
-	xorl	%eax, %eax
-	.p2align	4, 0x90
-.LBB0_6:                                # =>This Inner Loop Header: Depth=1
-	vmovdqu	%ymm0, -992(%rcx,%rax,4)
-	vmovdqu	%ymm0, -960(%rcx,%rax,4)
-	vmovdqu	%ymm0, -928(%rcx,%rax,4)
-	vmovdqu	%ymm0, -896(%rcx,%rax,4)
-	vmovdqu	%ymm0, -864(%rcx,%rax,4)
-	vmovdqu	%ymm0, -832(%rcx,%rax,4)
-	vmovdqu	%ymm0, -800(%rcx,%rax,4)
-	vmovdqu	%ymm0, -768(%rcx,%rax,4)
-	vmovdqu	%ymm0, -736(%rcx,%rax,4)
-	vmovdqu	%ymm0, -704(%rcx,%rax,4)
-	vmovdqu	%ymm0, -672(%rcx,%rax,4)
-	vmovdqu	%ymm0, -640(%rcx,%rax,4)
-	vmovdqu	%ymm0, -608(%rcx,%rax,4)
-	vmovdqu	%ymm0, -576(%rcx,%rax,4)
-	vmovdqu	%ymm0, -544(%rcx,%rax,4)
-	vmovdqu	%ymm0, -512(%rcx,%rax,4)
-	vmovdqu	%ymm0, -480(%rcx,%rax,4)
-	vmovdqu	%ymm0, -448(%rcx,%rax,4)
-	vmovdqu	%ymm0, -416(%rcx,%rax,4)
-	vmovdqu	%ymm0, -384(%rcx,%rax,4)
-	vmovdqu	%ymm0, -352(%rcx,%rax,4)
-	vmovdqu	%ymm0, -320(%rcx,%rax,4)
-	vmovdqu	%ymm0, -288(%rcx,%rax,4)
-	vmovdqu	%ymm0, -256(%rcx,%rax,4)
-	vmovdqu	%ymm0, -224(%rcx,%rax,4)
-	vmovdqu	%ymm0, -192(%rcx,%rax,4)
-	vmovdqu	%ymm0, -160(%rcx,%rax,4)
-	vmovdqu	%ymm0, -128(%rcx,%rax,4)
-	vmovdqu	%ymm0, -96(%rcx,%rax,4)
-	vmovdqu	%ymm0, -64(%rcx,%rax,4)
-	vmovdqu	%ymm0, -32(%rcx,%rax,4)
-	vmovdqu	%ymm0, (%rcx,%rax,4)
-	addq	$256, %rax              # imm = 0x100
-	addq	$8, %r10
-	jne	.LBB0_6
-# BB#7:
-	testq	%r9, %r9
-	je	.LBB0_10
-.LBB0_8:
-	leaq	(%rdi,%rax,4), %rax
-	addq	$96, %rax
-	negq	%r9
-	.p2align	4, 0x90
-.LBB0_9:                                # =>This Inner Loop Header: Depth=1
-	vmovdqu	%ymm0, -96(%rax)
-	vmovdqu	%ymm0, -64(%rax)
-	vmovdqu	%ymm0, -32(%rax)
-	vmovdqu	%ymm0, (%rax)
-	subq	$-128, %rax
-	addq	$1, %r9
-	jne	.LBB0_9
-.LBB0_10:
-	cmpq	%rdx, %r8
-	je	.LBB0_14
-# BB#11:
-	leaq	(%rdi,%r8,4), %rax
-.LBB0_12:
-	subq	%r8, %rdx
-	.p2align	4, 0x90
-.LBB0_13:                               # =>This Inner Loop Header: Depth=1
-	movl	%esi, (%rax)
-	addq	$4, %rax
-	addq	$-1, %rdx
-	jne	.LBB0_13
-.LBB0_14:
-	movq	%rdi, %rax
-	vzeroupper
-	retq
-END(WMEMSET)
diff --git a/libc/arch-x86_64/string/sse2-memset-slm.S b/libc/arch-x86_64/string/sse2-memset-slm.S
index fc502c0..cceadd2 100644
--- a/libc/arch-x86_64/string/sse2-memset-slm.S
+++ b/libc/arch-x86_64/string/sse2-memset-slm.S
@@ -41,16 +41,16 @@
 #endif
 
 
-ENTRY(__memset_chk)
+ENTRY(__memset_chk_generic)
   # %rdi = dst, %rsi = byte, %rdx = n, %rcx = dst_len
   cmp %rcx, %rdx
   ja __memset_chk_fail
   // Fall through to memset...
-END(__memset_chk)
+END(__memset_chk_generic)
 
 
 	.section .text.sse2,"ax",@progbits
-ENTRY(memset)
+ENTRY(memset_generic)
 	movq	%rdi, %rax
 	and	$0xff, %rsi
 	mov	$0x0101010101010101, %rcx
@@ -146,4 +146,4 @@
 	sfence
 	ret
 
-END(memset)
+END(memset_generic)
diff --git a/libc/bionic/gwp_asan_wrappers.cpp b/libc/bionic/gwp_asan_wrappers.cpp
index 7e19b31..fc59c88 100644
--- a/libc/bionic/gwp_asan_wrappers.cpp
+++ b/libc/bionic/gwp_asan_wrappers.cpp
@@ -41,6 +41,7 @@
 #include "gwp_asan_wrappers.h"
 #include "malloc_common.h"
 #include "platform/bionic/android_unsafe_frame_pointer_chase.h"
+#include "platform/bionic/macros.h"
 #include "platform/bionic/malloc.h"
 #include "private/bionic_arc4random.h"
 #include "private/bionic_globals.h"
@@ -221,6 +222,8 @@
 static const char* kMaxAllocsTargetedSyspropPrefix = "libc.debug.gwp_asan.max_allocs.";
 static const char* kMaxAllocsEnvVar = "GWP_ASAN_MAX_ALLOCS";
 
+static const char kPersistPrefix[] = "persist.";
+
 void SetDefaultGwpAsanOptions(Options* options, unsigned* process_sample_rate,
                               const android_mallopt_gwp_asan_options_t& mallopt_options) {
   options->Enabled = true;
@@ -244,26 +247,40 @@
   const char* basename = "";
   if (mallopt_options.program_name) basename = __gnu_basename(mallopt_options.program_name);
 
-  size_t program_specific_sysprop_size = strlen(targeted_sysprop_prefix) + strlen(basename) + 1;
-  char* program_specific_sysprop_name = static_cast<char*>(alloca(program_specific_sysprop_size));
-  async_safe_format_buffer(program_specific_sysprop_name, program_specific_sysprop_size, "%s%s",
-                           targeted_sysprop_prefix, basename);
-
-  const char* sysprop_names[2] = {nullptr, nullptr};
+  constexpr size_t kSyspropMaxLen = 512;
+  char program_specific_sysprop[kSyspropMaxLen] = {};
+  char persist_program_specific_sysprop[kSyspropMaxLen] = {};
+  char persist_default_sysprop[kSyspropMaxLen] = {};
+  const char* sysprop_names[4] = {};
   // Tests use a blank program name to specify that system properties should not
   // be used. Tests still continue to use the environment variable though.
   if (*basename != '\0') {
-    sysprop_names[0] = program_specific_sysprop_name;
+    const char* default_sysprop = system_sysprop;
     if (mallopt_options.desire == Action::TURN_ON_FOR_APP) {
-      sysprop_names[1] = app_sysprop;
-    } else {
-      sysprop_names[1] = system_sysprop;
+      default_sysprop = app_sysprop;
     }
+    async_safe_format_buffer(&program_specific_sysprop[0], kSyspropMaxLen, "%s%s",
+                             targeted_sysprop_prefix, basename);
+    async_safe_format_buffer(&persist_program_specific_sysprop[0], kSyspropMaxLen, "%s%s",
+                             kPersistPrefix, program_specific_sysprop);
+    async_safe_format_buffer(&persist_default_sysprop[0], kSyspropMaxLen, "%s%s", kPersistPrefix,
+                             default_sysprop);
+
+    // In order of precedence, always take the program-specific sysprop (e.g.
+    // '[persist.]libc.debug.gwp_asan.sample_rate.cameraserver') over the
+    // generic sysprop (e.g.
+    // '[persist.]libc.debug.gwp_asan.(system_default|app_default)'). In
+    // addition, always take the non-persistent option over the persistent
+    // option.
+    sysprop_names[0] = program_specific_sysprop;
+    sysprop_names[1] = persist_program_specific_sysprop;
+    sysprop_names[2] = default_sysprop;
+    sysprop_names[3] = persist_default_sysprop;
   }
 
   char settings_buf[PROP_VALUE_MAX];
-  if (!get_config_from_env_or_sysprops(env_var, sysprop_names,
-                                       /* sys_prop_names_size */ 2, settings_buf, PROP_VALUE_MAX)) {
+  if (!get_config_from_env_or_sysprops(env_var, sysprop_names, arraysize(sysprop_names),
+                                       settings_buf, PROP_VALUE_MAX)) {
     return false;
   }
 
diff --git a/libc/bionic/locale.cpp b/libc/bionic/locale.cpp
index 0b7037a..2f4d206 100644
--- a/libc/bionic/locale.cpp
+++ b/libc/bionic/locale.cpp
@@ -54,23 +54,23 @@
 
 struct __locale_t {
   size_t mb_cur_max;
-
-  explicit __locale_t(size_t mb_cur_max) : mb_cur_max(mb_cur_max) {
-  }
-
-  explicit __locale_t(const __locale_t* other) {
-    if (other == LC_GLOBAL_LOCALE) {
-      mb_cur_max = __bionic_current_locale_is_utf8 ? 4 : 1;
-    } else {
-      mb_cur_max = other->mb_cur_max;
-    }
-  }
-
-  BIONIC_DISALLOW_IMPLICIT_CONSTRUCTORS(__locale_t);
 };
 
-size_t __ctype_get_mb_cur_max() {
-  locale_t l = uselocale(nullptr);
+// Avoid using new/delete in this file, because a user may have overridden
+// new/delete, and we want to avoid making extraneous calls to them. This isn't
+// an issue for libc.so in the platform, but this file is also compiled into the
+// NDK's libandroid_support.a, and there are libc++ tests that count the number
+// of calls to new/delete.
+#pragma clang poison new delete
+
+static inline locale_t __alloc_locale(size_t mb_cur_max) {
+  auto result = static_cast<__locale_t*>(malloc(sizeof(__locale_t)));
+  if (result == nullptr) return nullptr;
+  result->mb_cur_max = mb_cur_max;
+  return result;
+}
+
+static inline size_t get_locale_mb_cur_max(locale_t l) {
   if (l == LC_GLOBAL_LOCALE) {
     return __bionic_current_locale_is_utf8 ? 4 : 1;
   } else {
@@ -78,6 +78,10 @@
   }
 }
 
+size_t __ctype_get_mb_cur_max() {
+  return get_locale_mb_cur_max(uselocale(nullptr));
+}
+
 #if !USE_TLS_SLOT
 static thread_local locale_t g_current_locale;
 #endif
@@ -133,11 +137,11 @@
 }
 
 locale_t duplocale(locale_t l) {
-  return new __locale_t(l);
+  return __alloc_locale(get_locale_mb_cur_max(l));
 }
 
 void freelocale(locale_t l) {
-  delete l;
+  free(l);
 }
 
 locale_t newlocale(int category_mask, const char* locale_name, locale_t /*base*/) {
@@ -152,7 +156,7 @@
     return nullptr;
   }
 
-  return new __locale_t(__is_utf8_locale(locale_name) ? 4 : 1);
+  return __alloc_locale(__is_utf8_locale(locale_name) ? 4 : 1);
 }
 
 char* setlocale(int category, const char* locale_name) {
diff --git a/libc/bionic/sysinfo.cpp b/libc/bionic/sysinfo.cpp
index 7ab8e9e..1e4a0e8 100644
--- a/libc/bionic/sysinfo.cpp
+++ b/libc/bionic/sysinfo.cpp
@@ -36,47 +36,31 @@
 #include "private/get_cpu_count_from_string.h"
 #include "private/ScopedReaddir.h"
 
-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 unused;
-  return (sscanf(s, "cpu%u%c", &cpu, &unused) == 1);
-}
-
-int get_nprocs_conf() {
-  // On x86 kernels you can use /proc/cpuinfo for this, but on ARM kernels offline CPUs disappear
-  // from there. This method works on both.
-  ScopedReaddir reader("/sys/devices/system/cpu");
-  if (reader.IsBad()) {
-    return 1;
-  }
-
-  int result = 0;
-  dirent* entry;
-  while ((entry = reader.ReadEntry()) != nullptr) {
-    if (entry->d_type == DT_DIR && __matches_cpuN(entry->d_name)) {
-      ++result;
-    }
-  }
-  return result;
-}
-
-int get_nprocs() {
+int __get_cpu_count(const char* sys_file) {
   int cpu_count = 1;
-  FILE* fp = fopen("/sys/devices/system/cpu/online", "re");
+  FILE* fp = fopen(sys_file, "re");
   if (fp != nullptr) {
     char* line = nullptr;
-    size_t len = 0;
-    if (getline(&line, &len, fp) != -1) {
+    size_t allocated_size = 0;
+    if (getline(&line, &allocated_size, fp) != -1) {
       cpu_count = GetCpuCountFromString(line);
-      free(line);
     }
+    free(line);
     fclose(fp);
   }
   return cpu_count;
 }
 
+int get_nprocs_conf() {
+  // It's unclear to me whether this is intended to be "possible" or "present",
+  // but on mobile they're unlikely to differ.
+  return __get_cpu_count("/sys/devices/system/cpu/possible");
+}
+
+int get_nprocs() {
+  return __get_cpu_count("/sys/devices/system/cpu/online");
+}
+
 long get_phys_pages() {
   struct sysinfo si;
   sysinfo(&si);
diff --git a/libc/bionic/sysprop_helpers.cpp b/libc/bionic/sysprop_helpers.cpp
index edae6cc..5627034 100644
--- a/libc/bionic/sysprop_helpers.cpp
+++ b/libc/bionic/sysprop_helpers.cpp
@@ -53,9 +53,7 @@
         strncpy(cb_cookie->dest, value, cb_cookie->size);
       },
       &cb_cookie);
-  if (*dest != '\0' && *dest != '0') return true;
-
-  return false;
+  return *dest != '\0';
 }
 
 bool get_config_from_env_or_sysprops(const char* env_var_name, const char* const* sys_prop_names,
diff --git a/libc/bionic/time64.c b/libc/bionic/time64.c
index da38bf3..73f24ab 100644
--- a/libc/bionic/time64.c
+++ b/libc/bionic/time64.c
@@ -483,6 +483,11 @@
 }
 
 
+/* This implementation violates mktime specification, according to which
+   tm_yday, tm_wday, and tm_isdst fields should be updated. This function
+   leaves input_date unmodified. Given that there were no bug reports, fixing
+   it might cause more troubles than just leaving it as it is.
+ */
 Time64_T mktime64(const struct TM *input_date) {
     struct tm safe_date;
     struct TM date;
diff --git a/libc/dns/resolv/res_send.c b/libc/dns/resolv/res_send.c
index fa81e6d..a95997d 100644
--- a/libc/dns/resolv/res_send.c
+++ b/libc/dns/resolv/res_send.c
@@ -680,8 +680,7 @@
 /* Private */
 
 static int
-get_salen(sa)
-	const struct sockaddr *sa;
+get_salen(const struct sockaddr *sa)
 {
 
 #ifdef HAVE_SA_LEN
@@ -702,9 +701,7 @@
  * pick appropriate nsaddr_list for use.  see res_init() for initialization.
  */
 static struct sockaddr *
-get_nsaddr(statp, n)
-	res_state statp;
-	size_t n;
+get_nsaddr(res_state statp, size_t n)
 {
 
 	if (!statp->nsaddr_list[n].sin_family && EXT(statp).ext) {
diff --git a/libc/include/android/api-level.h b/libc/include/android/api-level.h
index ecf318d..79085d1 100644
--- a/libc/include/android/api-level.h
+++ b/libc/include/android/api-level.h
@@ -139,21 +139,32 @@
 #define __ANDROID_API_P__ 28
 
 /**
- * Names the "Q" API level (29), for comparison against `__ANDROID_API__`.
- * This release was called Android 10 publicly, not to be (but sure to be)
- * confused with API level 10.
+ * Names the Android 10 (aka "Q" or "Quince Tart") API level (29), for
+ * comparison against `__ANDROID_API__`.
  */
 #define __ANDROID_API_Q__ 29
 
-/** Names the "R" API level (30), for comparison against `__ANDROID_API__`. */
+/**
+ * Names the Android 11 (aka "R" or "Red Velvet Cake") API level (30), for
+ * comparison against `__ANDROID_API__`.
+ */
 #define __ANDROID_API_R__ 30
 
-/** Names the "S" API level (31), for comparison against `__ANDROID_API__`. */
+/**
+ * Names the Android 12 (aka "S" or "Snowcone") API level (31), for
+ * comparison against `__ANDROID_API__`.
+ */
 #define __ANDROID_API_S__ 31
 
-/** Names the "T" API level (33), for comparison against `__ANDROID_API__`. */
+/**
+ * Names the Android 13 (aka "T" or "Tiramisu") API level (33), for
+ * comparison against `__ANDROID_API__`.
+ */
 #define __ANDROID_API_T__ 33
 
+/** Names the "U" API level (34), for comparison against `__ANDROID_API__`. */
+#define __ANDROID_API_U__ 34
+
 /* This file is included in <features.h>, and might be used from .S files. */
 #if !defined(__ASSEMBLY__)
 
diff --git a/libc/include/bits/fortify/fcntl.h b/libc/include/bits/fortify/fcntl.h
index 7063541..7fe60f4 100644
--- a/libc/include/bits/fortify/fcntl.h
+++ b/libc/include/bits/fortify/fcntl.h
@@ -41,7 +41,7 @@
 #if defined(__BIONIC_FORTIFY)
 #define __open_too_many_args_error "too many arguments"
 #define __open_too_few_args_error "called with O_CREAT or O_TMPFILE, but missing mode"
-#define __open_useless_modes_warning "has superfluous mode bits; missing O_CREAT?"
+#define __open_useless_modes_warning "has superfluous mode bits; missing O_CREAT or O_TMPFILE?"
 /* O_TMPFILE shares bits with O_DIRECTORY. */
 #define __open_modes_useful(flags) (((flags) & O_CREAT) || ((flags) & O_TMPFILE) == O_TMPFILE)
 
diff --git a/libc/include/elf.h b/libc/include/elf.h
index 4739bbd..536b8c3 100644
--- a/libc/include/elf.h
+++ b/libc/include/elf.h
@@ -460,8 +460,6 @@
 #define PF_MASKOS   0x0ff00000
 #define PF_MASKPROC 0xf0000000
 
-#define PT_GNU_RELRO 0x6474e552
-
 #define STB_LOOS 10
 #define STB_HIOS 12
 #define STB_LOPROC 13
diff --git a/libc/kernel/android/BUILD b/libc/kernel/android/BUILD
new file mode 100644
index 0000000..b862a6d
--- /dev/null
+++ b/libc/kernel/android/BUILD
@@ -0,0 +1,43 @@
+# Copyright (C) 2022 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.
+
+load("//build/bazel/rules/apis:cc_api_contribution.bzl", "cc_api_headers")
+
+package(default_visibility = ["//bionic/libc:__pkg__"])
+
+cc_api_headers(
+  name="libc_kernel_android_uapi_headers",
+  include_dir="uapi",
+  hdrs=glob(["uapi/**/*.h"]),
+  system=True,
+)
+
+cc_api_headers(
+  name="libc_kernel_android_scsi_headers",
+  include_dir="scsi",
+  hdrs=glob(["scsi/**/*.h"]),
+  system=True,
+)
diff --git a/libc/kernel/uapi/BUILD b/libc/kernel/uapi/BUILD
new file mode 100644
index 0000000..2f92464
--- /dev/null
+++ b/libc/kernel/uapi/BUILD
@@ -0,0 +1,67 @@
+# Copyright (C) 2022 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.
+
+load("//build/bazel/rules/apis:cc_api_contribution.bzl", "cc_api_headers")
+
+package(default_visibility = ["//bionic/libc:__pkg__"])
+
+cc_api_headers(
+  name="libc_kernel_uapi_headers",
+  hdrs=glob(["**/*.h"]),
+  system=True,
+)
+
+cc_api_headers(
+  name="libc_kernal_uapi_asm_arm_headers",
+  include_dir="asm-arm",
+  hdrs=glob(["asm-arm/**/*.h"]),
+  system=True,
+  arch="arm",
+)
+
+cc_api_headers(
+  name="libc_kernal_uapi_asm_arm64_headers",
+  include_dir="asm-arm64",
+  hdrs=glob(["asm-arm64/**/*.h"]),
+  system=True,
+  arch="arm64",
+)
+
+cc_api_headers(
+  name="libc_kernal_uapi_asm_x86_headers",
+  include_dir="asm-x86",
+  hdrs=glob(["asm-x86/**/*.h"]),
+  system=True,
+  arch="x86",
+)
+
+cc_api_headers(
+  name="libc_kernal_uapi_asm_x86_64_headers",
+  include_dir="asm-x86_64",
+  hdrs=glob(["asm-x86_64/**/*.h"]),
+  system=True,
+  arch="x86_64",
+)
diff --git a/libc/kernel/uapi/asm-arm/asm/signal.h b/libc/kernel/uapi/asm-arm/asm/signal.h
index 5f7e0c5..0424380 100644
--- a/libc/kernel/uapi/asm-arm/asm/signal.h
+++ b/libc/kernel/uapi/asm-arm/asm/signal.h
@@ -78,6 +78,6 @@
 typedef struct sigaltstack {
   void __user * ss_sp;
   int ss_flags;
-  size_t ss_size;
+  __kernel_size_t ss_size;
 } stack_t;
 #endif
diff --git a/libc/kernel/uapi/asm-arm64/asm/hwcap.h b/libc/kernel/uapi/asm-arm64/asm/hwcap.h
index 4316724..e0dbb13 100644
--- a/libc/kernel/uapi/asm-arm64/asm/hwcap.h
+++ b/libc/kernel/uapi/asm-arm64/asm/hwcap.h
@@ -72,4 +72,5 @@
 #define HWCAP2_ECV (1 << 19)
 #define HWCAP2_AFP (1 << 20)
 #define HWCAP2_RPRES (1 << 21)
+#define HWCAP2_MTE3 (1 << 22)
 #endif
diff --git a/libc/kernel/uapi/asm-arm64/asm/kvm.h b/libc/kernel/uapi/asm-arm64/asm/kvm.h
index c53ee87..eee066b 100644
--- a/libc/kernel/uapi/asm-arm64/asm/kvm.h
+++ b/libc/kernel/uapi/asm-arm64/asm/kvm.h
@@ -214,6 +214,7 @@
 #define KVM_ARM_VCPU_PMU_V3_IRQ 0
 #define KVM_ARM_VCPU_PMU_V3_INIT 1
 #define KVM_ARM_VCPU_PMU_V3_FILTER 2
+#define KVM_ARM_VCPU_PMU_V3_SET_PMU 3
 #define KVM_ARM_VCPU_TIMER_CTRL 1
 #define KVM_ARM_VCPU_TIMER_IRQ_VTIMER 0
 #define KVM_ARM_VCPU_TIMER_IRQ_PTIMER 1
@@ -244,5 +245,7 @@
 #define KVM_PSCI_RET_NI PSCI_RET_NOT_SUPPORTED
 #define KVM_PSCI_RET_INVAL PSCI_RET_INVALID_PARAMS
 #define KVM_PSCI_RET_DENIED PSCI_RET_DENIED
+#define KVM_SYSTEM_EVENT_RESET_FLAG_PSCI_RESET2 (1ULL << 0)
+#define KVM_EXIT_FAIL_ENTRY_CPU_UNSUPPORTED (1ULL << 0)
 #endif
 #endif
diff --git a/libc/kernel/uapi/asm-generic/mman-common.h b/libc/kernel/uapi/asm-generic/mman-common.h
index 9440576..e96f4cc 100644
--- a/libc/kernel/uapi/asm-generic/mman-common.h
+++ b/libc/kernel/uapi/asm-generic/mman-common.h
@@ -62,6 +62,7 @@
 #define MADV_PAGEOUT 21
 #define MADV_POPULATE_READ 22
 #define MADV_POPULATE_WRITE 23
+#define MADV_DONTNEED_LOCKED 24
 #define MAP_FILE 0
 #define PKEY_DISABLE_ACCESS 0x1
 #define PKEY_DISABLE_WRITE 0x2
diff --git a/libc/kernel/uapi/asm-generic/shmbuf.h b/libc/kernel/uapi/asm-generic/shmbuf.h
index 067ffbc..11487f4 100644
--- a/libc/kernel/uapi/asm-generic/shmbuf.h
+++ b/libc/kernel/uapi/asm-generic/shmbuf.h
@@ -19,9 +19,11 @@
 #ifndef __ASM_GENERIC_SHMBUF_H
 #define __ASM_GENERIC_SHMBUF_H
 #include <asm/bitsperlong.h>
+#include <asm/ipcbuf.h>
+#include <asm/posix_types.h>
 struct shmid64_ds {
   struct ipc64_perm shm_perm;
-  size_t shm_segsz;
+  __kernel_size_t shm_segsz;
 #if __BITS_PER_LONG == 64
   long shm_atime;
   long shm_dtime;
diff --git a/libc/kernel/uapi/asm-generic/signal.h b/libc/kernel/uapi/asm-generic/signal.h
index 874fece..5cb1dce 100644
--- a/libc/kernel/uapi/asm-generic/signal.h
+++ b/libc/kernel/uapi/asm-generic/signal.h
@@ -84,7 +84,7 @@
 typedef struct sigaltstack {
   void __user * ss_sp;
   int ss_flags;
-  size_t ss_size;
+  __kernel_size_t ss_size;
 } stack_t;
 #endif
 #endif
diff --git a/libc/kernel/uapi/asm-generic/socket.h b/libc/kernel/uapi/asm-generic/socket.h
index 6767993..6926187 100644
--- a/libc/kernel/uapi/asm-generic/socket.h
+++ b/libc/kernel/uapi/asm-generic/socket.h
@@ -100,6 +100,7 @@
 #define SO_NETNS_COOKIE 71
 #define SO_BUF_LOCK 72
 #define SO_RESERVE_MEM 73
+#define SO_TXREHASH 74
 #if __BITS_PER_LONG == 64 || defined(__x86_64__) && defined(__ILP32__)
 #define SO_TIMESTAMP SO_TIMESTAMP_OLD
 #define SO_TIMESTAMPNS SO_TIMESTAMPNS_OLD
diff --git a/libc/kernel/uapi/asm-x86/asm/amd_hsmp.h b/libc/kernel/uapi/asm-x86/asm/amd_hsmp.h
new file mode 100644
index 0000000..ed59bb8
--- /dev/null
+++ b/libc/kernel/uapi/asm-x86/asm/amd_hsmp.h
@@ -0,0 +1,136 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   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_ASM_X86_AMD_HSMP_H_
+#define _UAPI_ASM_X86_AMD_HSMP_H_
+#include <linux/types.h>
+#pragma pack(4)
+#define HSMP_MAX_MSG_LEN 8
+enum hsmp_message_ids {
+  HSMP_TEST = 1,
+  HSMP_GET_SMU_VER,
+  HSMP_GET_PROTO_VER,
+  HSMP_GET_SOCKET_POWER,
+  HSMP_SET_SOCKET_POWER_LIMIT,
+  HSMP_GET_SOCKET_POWER_LIMIT,
+  HSMP_GET_SOCKET_POWER_LIMIT_MAX,
+  HSMP_SET_BOOST_LIMIT,
+  HSMP_SET_BOOST_LIMIT_SOCKET,
+  HSMP_GET_BOOST_LIMIT,
+  HSMP_GET_PROC_HOT,
+  HSMP_SET_XGMI_LINK_WIDTH,
+  HSMP_SET_DF_PSTATE,
+  HSMP_SET_AUTO_DF_PSTATE,
+  HSMP_GET_FCLK_MCLK,
+  HSMP_GET_CCLK_THROTTLE_LIMIT,
+  HSMP_GET_C0_PERCENT,
+  HSMP_SET_NBIO_DPM_LEVEL,
+  HSMP_GET_DDR_BANDWIDTH = 0x14,
+  HSMP_GET_TEMP_MONITOR,
+  HSMP_MSG_ID_MAX,
+};
+struct hsmp_message {
+  __u32 msg_id;
+  __u16 num_args;
+  __u16 response_sz;
+  __u32 args[HSMP_MAX_MSG_LEN];
+  __u16 sock_ind;
+};
+enum hsmp_msg_type {
+  HSMP_RSVD = - 1,
+  HSMP_SET = 0,
+  HSMP_GET = 1,
+};
+struct hsmp_msg_desc {
+  int num_args;
+  int response_sz;
+  enum hsmp_msg_type type;
+};
+static const struct hsmp_msg_desc hsmp_msg_desc_table[] = {
+ {
+    0, 0, HSMP_RSVD
+  }
+ , {
+    1, 1, HSMP_GET
+  }
+ , {
+    0, 1, HSMP_GET
+  }
+ , {
+    0, 1, HSMP_GET
+  }
+ , {
+    0, 1, HSMP_GET
+  }
+ , {
+    1, 0, HSMP_SET
+  }
+ , {
+    0, 1, HSMP_GET
+  }
+ , {
+    0, 1, HSMP_GET
+  }
+ , {
+    1, 0, HSMP_SET
+  }
+ , {
+    1, 0, HSMP_SET
+  }
+ , {
+    1, 1, HSMP_GET
+  }
+ , {
+    0, 1, HSMP_GET
+  }
+ , {
+    1, 0, HSMP_SET
+  }
+ , {
+    1, 0, HSMP_SET
+  }
+ , {
+    0, 0, HSMP_SET
+  }
+ , {
+    0, 2, HSMP_GET
+  }
+ , {
+    0, 1, HSMP_GET
+  }
+ , {
+    0, 1, HSMP_GET
+  }
+ , {
+    1, 0, HSMP_SET
+  }
+ , {
+    0, 0, HSMP_RSVD
+  }
+ , {
+    0, 1, HSMP_GET
+  }
+ , {
+    0, 1, HSMP_GET
+  }
+ ,
+};
+#pragma pack()
+#define HSMP_BASE_IOCTL_NR 0xF8
+#define HSMP_IOCTL_CMD _IOWR(HSMP_BASE_IOCTL_NR, 0, struct hsmp_message)
+#endif
diff --git a/libc/kernel/uapi/asm-x86/asm/processor-flags.h b/libc/kernel/uapi/asm-x86/asm/processor-flags.h
index 85f9d7e..0a95afd 100644
--- a/libc/kernel/uapi/asm-x86/asm/processor-flags.h
+++ b/libc/kernel/uapi/asm-x86/asm/processor-flags.h
@@ -127,6 +127,8 @@
 #define X86_CR4_SMAP _BITUL(X86_CR4_SMAP_BIT)
 #define X86_CR4_PKE_BIT 22
 #define X86_CR4_PKE _BITUL(X86_CR4_PKE_BIT)
+#define X86_CR4_CET_BIT 23
+#define X86_CR4_CET _BITUL(X86_CR4_CET_BIT)
 #define X86_CR8_TPR _AC(0x0000000f, UL)
 #define CX86_PCR0 0x20
 #define CX86_GCR 0xb8
diff --git a/libc/kernel/uapi/asm-x86/asm/shmbuf.h b/libc/kernel/uapi/asm-x86/asm/shmbuf.h
index 03e195e..2a0dcb5 100644
--- a/libc/kernel/uapi/asm-x86/asm/shmbuf.h
+++ b/libc/kernel/uapi/asm-x86/asm/shmbuf.h
@@ -21,9 +21,11 @@
 #if !defined(__x86_64__) || !defined(__ILP32__)
 #include <asm-generic/shmbuf.h>
 #else
+#include <asm/ipcbuf.h>
+#include <asm/posix_types.h>
 struct shmid64_ds {
   struct ipc64_perm shm_perm;
-  size_t shm_segsz;
+  __kernel_size_t shm_segsz;
   __kernel_long_t shm_atime;
   __kernel_long_t shm_dtime;
   __kernel_long_t shm_ctime;
diff --git a/libc/kernel/uapi/asm-x86/asm/signal.h b/libc/kernel/uapi/asm-x86/asm/signal.h
index 8226da8..cbeeac4 100644
--- a/libc/kernel/uapi/asm-x86/asm/signal.h
+++ b/libc/kernel/uapi/asm-x86/asm/signal.h
@@ -90,7 +90,7 @@
 typedef struct sigaltstack {
   void __user * ss_sp;
   int ss_flags;
-  size_t ss_size;
+  __kernel_size_t ss_size;
 } stack_t;
 #endif
 #endif
diff --git a/libc/kernel/uapi/drm/amdgpu_drm.h b/libc/kernel/uapi/drm/amdgpu_drm.h
index 3764d51..f38b612 100644
--- a/libc/kernel/uapi/drm/amdgpu_drm.h
+++ b/libc/kernel/uapi/drm/amdgpu_drm.h
@@ -112,6 +112,8 @@
 #define AMDGPU_CTX_OP_FREE_CTX 2
 #define AMDGPU_CTX_OP_QUERY_STATE 3
 #define AMDGPU_CTX_OP_QUERY_STATE2 4
+#define AMDGPU_CTX_OP_GET_STABLE_PSTATE 5
+#define AMDGPU_CTX_OP_SET_STABLE_PSTATE 6
 #define AMDGPU_CTX_NO_RESET 0
 #define AMDGPU_CTX_GUILTY_RESET 1
 #define AMDGPU_CTX_INNOCENT_RESET 2
@@ -127,6 +129,12 @@
 #define AMDGPU_CTX_PRIORITY_NORMAL 0
 #define AMDGPU_CTX_PRIORITY_HIGH 512
 #define AMDGPU_CTX_PRIORITY_VERY_HIGH 1023
+#define AMDGPU_CTX_STABLE_PSTATE_FLAGS_MASK 0xf
+#define AMDGPU_CTX_STABLE_PSTATE_NONE 0
+#define AMDGPU_CTX_STABLE_PSTATE_STANDARD 1
+#define AMDGPU_CTX_STABLE_PSTATE_MIN_SCLK 2
+#define AMDGPU_CTX_STABLE_PSTATE_MIN_MCLK 3
+#define AMDGPU_CTX_STABLE_PSTATE_PEAK 4
 struct drm_amdgpu_ctx_in {
   __u32 op;
   __u32 flags;
@@ -143,6 +151,10 @@
     __u32 hangs;
     __u32 reset_status;
   } state;
+  struct {
+    __u32 flags;
+    __u32 _pad;
+  } pstate;
 };
 union drm_amdgpu_ctx {
   struct drm_amdgpu_ctx_in in;
@@ -438,6 +450,7 @@
 #define AMDGPU_INFO_FW_TA 0x13
 #define AMDGPU_INFO_FW_DMCUB 0x14
 #define AMDGPU_INFO_FW_TOC 0x15
+#define AMDGPU_INFO_FW_CAP 0x16
 #define AMDGPU_INFO_NUM_BYTES_MOVED 0x0f
 #define AMDGPU_INFO_VRAM_USAGE 0x10
 #define AMDGPU_INFO_GTT_USAGE 0x11
@@ -682,6 +695,8 @@
 #define AMDGPU_FAMILY_NV 143
 #define AMDGPU_FAMILY_VGH 144
 #define AMDGPU_FAMILY_YC 146
+#define AMDGPU_FAMILY_GC_10_3_6 149
+#define AMDGPU_FAMILY_GC_10_3_7 151
 #ifdef __cplusplus
 }
 #endif
diff --git a/libc/kernel/uapi/drm/msm_drm.h b/libc/kernel/uapi/drm/msm_drm.h
index b4ba1d0..376f909 100644
--- a/libc/kernel/uapi/drm/msm_drm.h
+++ b/libc/kernel/uapi/drm/msm_drm.h
@@ -43,6 +43,7 @@
 #define MSM_PARAM_PP_PGTABLE 0x08
 #define MSM_PARAM_FAULTS 0x09
 #define MSM_PARAM_SUSPENDS 0x0a
+#define MSM_PARAM_SYSPROF 0x0b
 #define MSM_PARAM_NR_RINGS MSM_PARAM_PRIORITIES
 struct drm_msm_param {
   __u32 pipe;
@@ -119,7 +120,8 @@
 #define MSM_SUBMIT_SUDO 0x10000000
 #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_FENCE_SN_IN 0x02000000
+#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 | MSM_SUBMIT_FENCE_SN_IN | 0)
 #define MSM_SUBMIT_SYNCOBJ_RESET 0x00000001
 #define MSM_SUBMIT_SYNCOBJ_FLAGS (MSM_SUBMIT_SYNCOBJ_RESET | 0)
 struct drm_msm_gem_submit_syncobj {
@@ -172,6 +174,7 @@
   __u32 pad;
 };
 #define DRM_MSM_GET_PARAM 0x00
+#define DRM_MSM_SET_PARAM 0x01
 #define DRM_MSM_GEM_NEW 0x02
 #define DRM_MSM_GEM_INFO 0x03
 #define DRM_MSM_GEM_CPU_PREP 0x04
@@ -183,6 +186,7 @@
 #define DRM_MSM_SUBMITQUEUE_CLOSE 0x0B
 #define DRM_MSM_SUBMITQUEUE_QUERY 0x0C
 #define DRM_IOCTL_MSM_GET_PARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_MSM_GET_PARAM, struct drm_msm_param)
+#define DRM_IOCTL_MSM_SET_PARAM DRM_IOW(DRM_COMMAND_BASE + DRM_MSM_SET_PARAM, struct drm_msm_param)
 #define DRM_IOCTL_MSM_GEM_NEW DRM_IOWR(DRM_COMMAND_BASE + DRM_MSM_GEM_NEW, struct drm_msm_gem_new)
 #define DRM_IOCTL_MSM_GEM_INFO DRM_IOWR(DRM_COMMAND_BASE + DRM_MSM_GEM_INFO, struct drm_msm_gem_info)
 #define DRM_IOCTL_MSM_GEM_CPU_PREP DRM_IOW(DRM_COMMAND_BASE + DRM_MSM_GEM_CPU_PREP, struct drm_msm_gem_cpu_prep)
diff --git a/libc/kernel/uapi/linux/android/binder.h b/libc/kernel/uapi/linux/android/binder.h
index ded1756..34ccf44 100644
--- a/libc/kernel/uapi/linux/android/binder.h
+++ b/libc/kernel/uapi/linux/android/binder.h
@@ -155,7 +155,11 @@
   binder_uintptr_t cookie;
   __u32 code;
   __u32 flags;
-  pid_t sender_pid;
+  __kernel_pid_t sender_pid;
+  /* Modified to __kernel_uid_t in the headers but this is not the same size
+   * as uid_t on 32 bit systems. This is fixed in upstream, but wait until
+   * 5.19 to get the fix. See b/234125620.
+   */
   uid_t sender_euid;
   binder_size_t data_size;
   binder_size_t offsets_size;
diff --git a/libc/kernel/uapi/linux/bpf.h b/libc/kernel/uapi/linux/bpf.h
index d363e81..8de48a1 100644
--- a/libc/kernel/uapi/linux/bpf.h
+++ b/libc/kernel/uapi/linux/bpf.h
@@ -228,6 +228,7 @@
   BPF_SK_REUSEPORT_SELECT,
   BPF_SK_REUSEPORT_SELECT_OR_MIGRATE,
   BPF_PERF_EVENT,
+  BPF_TRACE_KPROBE_MULTI,
   __MAX_BPF_ATTACH_TYPE
 };
 #define MAX_BPF_ATTACH_TYPE __MAX_BPF_ATTACH_TYPE
@@ -240,6 +241,7 @@
   BPF_LINK_TYPE_NETNS = 5,
   BPF_LINK_TYPE_XDP = 6,
   BPF_LINK_TYPE_PERF_EVENT = 7,
+  BPF_LINK_TYPE_KPROBE_MULTI = 8,
   MAX_BPF_LINK_TYPE,
 };
 #define BPF_F_ALLOW_OVERRIDE (1U << 0)
@@ -250,6 +252,8 @@
 #define BPF_F_TEST_RND_HI32 (1U << 2)
 #define BPF_F_TEST_STATE_FREQ (1U << 3)
 #define BPF_F_SLEEPABLE (1U << 4)
+#define BPF_F_XDP_HAS_FRAGS (1U << 5)
+#define BPF_F_KPROBE_MULTI_RETURN (1U << 0)
 #define BPF_PSEUDO_MAP_FD 1
 #define BPF_PSEUDO_MAP_IDX 5
 #define BPF_PSEUDO_MAP_VALUE 2
@@ -281,6 +285,7 @@
 };
 #define BPF_F_QUERY_EFFECTIVE (1U << 0)
 #define BPF_F_TEST_RUN_ON_CPU (1U << 0)
+#define BPF_F_TEST_XDP_LIVE_FRAMES (1U << 1)
 enum bpf_stats_type {
   BPF_STATS_RUN_TIME = 0,
 };
@@ -392,6 +397,7 @@
     __aligned_u64 ctx_out;
     __u32 flags;
     __u32 cpu;
+    __u32 batch_size;
   } test;
   struct {
     union {
@@ -456,6 +462,13 @@
       struct {
         __u64 bpf_cookie;
       } perf_event;
+      struct {
+        __u32 flags;
+        __u32 cnt;
+        __aligned_u64 syms;
+        __aligned_u64 addrs;
+        __aligned_u64 cookies;
+      } kprobe_multi;
     };
   } link_create;
   struct {
@@ -480,7 +493,7 @@
     __u32 flags;
   } prog_bind_map;
 } __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), 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), FN(load_hdr_opt), FN(store_hdr_opt), FN(reserve_hdr_opt), FN(inode_storage_get), FN(inode_storage_delete), FN(d_path), FN(copy_from_user), FN(snprintf_btf), FN(seq_printf_btf), FN(skb_cgroup_classid), FN(redirect_neigh), FN(per_cpu_ptr), FN(this_cpu_ptr), FN(redirect_peer), FN(task_storage_get), FN(task_storage_delete), FN(get_current_task_btf), FN(bprm_opts_set), FN(ktime_get_coarse_ns), FN(ima_inode_hash), FN(sock_from_file), FN(check_mtu), FN(for_each_map_elem), FN(snprintf), FN(sys_bpf), FN(btf_find_by_name_kind), FN(sys_close), FN(timer_init), FN(timer_set_callback), FN(timer_start), FN(timer_cancel), FN(get_func_ip), FN(get_attach_cookie), FN(task_pt_regs), FN(get_branch_snapshot), FN(trace_vprintk), FN(skc_to_unix_sock), FN(kallsyms_lookup_name), FN(find_vma), FN(loop), FN(strncmp), FN(get_func_arg), FN(get_func_ret), FN(get_func_arg_cnt),
+#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), FN(load_hdr_opt), FN(store_hdr_opt), FN(reserve_hdr_opt), FN(inode_storage_get), FN(inode_storage_delete), FN(d_path), FN(copy_from_user), FN(snprintf_btf), FN(seq_printf_btf), FN(skb_cgroup_classid), FN(redirect_neigh), FN(per_cpu_ptr), FN(this_cpu_ptr), FN(redirect_peer), FN(task_storage_get), FN(task_storage_delete), FN(get_current_task_btf), FN(bprm_opts_set), FN(ktime_get_coarse_ns), FN(ima_inode_hash), FN(sock_from_file), FN(check_mtu), FN(for_each_map_elem), FN(snprintf), FN(sys_bpf), FN(btf_find_by_name_kind), FN(sys_close), FN(timer_init), FN(timer_set_callback), FN(timer_start), FN(timer_cancel), FN(get_func_ip), FN(get_attach_cookie), FN(task_pt_regs), FN(get_branch_snapshot), FN(trace_vprintk), FN(skc_to_unix_sock), FN(kallsyms_lookup_name), FN(find_vma), FN(loop), FN(strncmp), FN(get_func_arg), FN(get_func_ret), FN(get_func_arg_cnt), FN(get_retval), FN(set_retval), FN(xdp_get_buff_len), FN(xdp_load_bytes), FN(xdp_store_bytes), FN(copy_from_user_task), FN(skb_set_tstamp), FN(ima_file_hash),
 #define __BPF_ENUM_FN(x) BPF_FUNC_ ##x
 enum bpf_func_id {
   __BPF_FUNC_MAPPER(__BPF_ENUM_FN) __BPF_FUNC_MAX_ID,
@@ -595,6 +608,10 @@
 };
 #define __bpf_md_ptr(type,name) union { type name; __u64 : 64; \
 } __attribute__((aligned(8)))
+enum {
+  BPF_SKB_TSTAMP_UNSPEC,
+  BPF_SKB_TSTAMP_DELIVERY_MONO,
+};
 struct __sk_buff {
   __u32 len;
   __u32 pkt_type;
@@ -628,7 +645,8 @@
   __u32 gso_segs;
   __bpf_md_ptr(struct bpf_sock *, sk);
   __u32 gso_size;
-  __u32 : 32;
+  __u8 tstamp_type;
+  __u32 : 24;
   __u64 hwtstamp;
 };
 struct bpf_tunnel_key {
@@ -668,7 +686,8 @@
   __u32 src_ip4;
   __u32 src_ip6[4];
   __u32 src_port;
-  __u32 dst_port;
+  __be16 dst_port;
+  __u16 : 16;
   __u32 dst_ip4;
   __u32 dst_ip6[4];
   __u32 state;
@@ -1160,7 +1179,8 @@
   __u32 protocol;
   __u32 remote_ip4;
   __u32 remote_ip6[4];
-  __u32 remote_port;
+  __be16 remote_port;
+  __u16 : 16;
   __u32 local_ip4;
   __u32 local_ip6[4];
   __u32 local_port;
diff --git a/libc/kernel/uapi/linux/btrfs.h b/libc/kernel/uapi/linux/btrfs.h
index 08b96a3..9f76d52 100644
--- a/libc/kernel/uapi/linux/btrfs.h
+++ b/libc/kernel/uapi/linux/btrfs.h
@@ -189,6 +189,7 @@
 #define BTRFS_FEATURE_INCOMPAT_METADATA_UUID (1ULL << 10)
 #define BTRFS_FEATURE_INCOMPAT_RAID1C34 (1ULL << 11)
 #define BTRFS_FEATURE_INCOMPAT_ZONED (1ULL << 12)
+#define BTRFS_FEATURE_INCOMPAT_EXTENT_TREE_V2 (1ULL << 13)
 struct btrfs_ioctl_feature_flags {
   __u64 compat_flags;
   __u64 compat_ro_flags;
@@ -461,6 +462,29 @@
   __u8 num_items;
   __u8 align[7];
 };
+struct btrfs_ioctl_encoded_io_args {
+  const struct iovec __user * iov;
+  unsigned long iovcnt;
+  __s64 offset;
+  __u64 flags;
+  __u64 len;
+  __u64 unencoded_len;
+  __u64 unencoded_offset;
+  __u32 compression;
+  __u32 encryption;
+  __u8 reserved[64];
+};
+#define BTRFS_ENCODED_IO_COMPRESSION_NONE 0
+#define BTRFS_ENCODED_IO_COMPRESSION_ZLIB 1
+#define BTRFS_ENCODED_IO_COMPRESSION_ZSTD 2
+#define BTRFS_ENCODED_IO_COMPRESSION_LZO_4K 3
+#define BTRFS_ENCODED_IO_COMPRESSION_LZO_8K 4
+#define BTRFS_ENCODED_IO_COMPRESSION_LZO_16K 5
+#define BTRFS_ENCODED_IO_COMPRESSION_LZO_32K 6
+#define BTRFS_ENCODED_IO_COMPRESSION_LZO_64K 7
+#define BTRFS_ENCODED_IO_COMPRESSION_TYPES 8
+#define BTRFS_ENCODED_IO_ENCRYPTION_NONE 0
+#define BTRFS_ENCODED_IO_ENCRYPTION_TYPES 1
 enum btrfs_err_code {
   BTRFS_ERROR_DEV_RAID1_MIN_NOT_MET = 1,
   BTRFS_ERROR_DEV_RAID10_MIN_NOT_MET,
@@ -534,4 +558,6 @@
 #define BTRFS_IOC_GET_SUBVOL_ROOTREF _IOWR(BTRFS_IOCTL_MAGIC, 61, struct btrfs_ioctl_get_subvol_rootref_args)
 #define BTRFS_IOC_INO_LOOKUP_USER _IOWR(BTRFS_IOCTL_MAGIC, 62, struct btrfs_ioctl_ino_lookup_user_args)
 #define BTRFS_IOC_SNAP_DESTROY_V2 _IOW(BTRFS_IOCTL_MAGIC, 63, struct btrfs_ioctl_vol_args_v2)
+#define BTRFS_IOC_ENCODED_READ _IOR(BTRFS_IOCTL_MAGIC, 64, struct btrfs_ioctl_encoded_io_args)
+#define BTRFS_IOC_ENCODED_WRITE _IOW(BTRFS_IOCTL_MAGIC, 64, struct btrfs_ioctl_encoded_io_args)
 #endif
diff --git a/libc/kernel/uapi/linux/btrfs_tree.h b/libc/kernel/uapi/linux/btrfs_tree.h
index 0476733..8e3c6fe 100644
--- a/libc/kernel/uapi/linux/btrfs_tree.h
+++ b/libc/kernel/uapi/linux/btrfs_tree.h
@@ -31,6 +31,7 @@
 #define BTRFS_QUOTA_TREE_OBJECTID 8ULL
 #define BTRFS_UUID_TREE_OBJECTID 9ULL
 #define BTRFS_FREE_SPACE_TREE_OBJECTID 10ULL
+#define BTRFS_BLOCK_GROUP_TREE_OBJECTID 11ULL
 #define BTRFS_DEV_STATS_OBJECTID 0ULL
 #define BTRFS_BALANCE_OBJECTID - 4ULL
 #define BTRFS_ORPHAN_OBJECTID - 5ULL
diff --git a/libc/kernel/uapi/linux/can/isotp.h b/libc/kernel/uapi/linux/can/isotp.h
index dd5e4f5..57d3001 100644
--- a/libc/kernel/uapi/linux/can/isotp.h
+++ b/libc/kernel/uapi/linux/can/isotp.h
@@ -59,11 +59,12 @@
 #define CAN_ISOTP_DEFAULT_FLAGS 0
 #define CAN_ISOTP_DEFAULT_EXT_ADDRESS 0x00
 #define CAN_ISOTP_DEFAULT_PAD_CONTENT 0xCC
-#define CAN_ISOTP_DEFAULT_FRAME_TXTIME 0
+#define CAN_ISOTP_DEFAULT_FRAME_TXTIME 50000
 #define CAN_ISOTP_DEFAULT_RECV_BS 0
 #define CAN_ISOTP_DEFAULT_RECV_STMIN 0x00
 #define CAN_ISOTP_DEFAULT_RECV_WFTMAX 0
 #define CAN_ISOTP_DEFAULT_LL_MTU CAN_MTU
 #define CAN_ISOTP_DEFAULT_LL_TX_DL CAN_MAX_DLEN
 #define CAN_ISOTP_DEFAULT_LL_TX_FLAGS 0
+#define CAN_ISOTP_FRAME_TXTIME_ZERO 0xFFFFFFFF
 #endif
diff --git a/libc/kernel/uapi/linux/counter.h b/libc/kernel/uapi/linux/counter.h
index 091e33d..4b86b28 100644
--- a/libc/kernel/uapi/linux/counter.h
+++ b/libc/kernel/uapi/linux/counter.h
@@ -45,6 +45,7 @@
   COUNTER_EVENT_OVERFLOW_UNDERFLOW,
   COUNTER_EVENT_THRESHOLD,
   COUNTER_EVENT_INDEX,
+  COUNTER_EVENT_CHANGE_OF_STATE,
 };
 struct counter_watch {
   struct counter_component component;
diff --git a/libc/kernel/uapi/linux/dm-ioctl.h b/libc/kernel/uapi/linux/dm-ioctl.h
index 09f8a98..98cbc1f 100644
--- a/libc/kernel/uapi/linux/dm-ioctl.h
+++ b/libc/kernel/uapi/linux/dm-ioctl.h
@@ -106,9 +106,9 @@
 #define DM_TARGET_MSG _IOWR(DM_IOCTL, DM_TARGET_MSG_CMD, struct dm_ioctl)
 #define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl)
 #define DM_VERSION_MAJOR 4
-#define DM_VERSION_MINOR 45
+#define DM_VERSION_MINOR 46
 #define DM_VERSION_PATCHLEVEL 0
-#define DM_VERSION_EXTRA "-ioctl(2021-03-22)"
+#define DM_VERSION_EXTRA "-ioctl(2022-02-22)"
 #define DM_READONLY_FLAG (1 << 0)
 #define DM_SUSPEND_FLAG (1 << 1)
 #define DM_PERSISTENT_DEV_FLAG (1 << 3)
diff --git a/libc/kernel/uapi/linux/dma-buf.h b/libc/kernel/uapi/linux/dma-buf.h
index 221c20f..4e31379 100644
--- a/libc/kernel/uapi/linux/dma-buf.h
+++ b/libc/kernel/uapi/linux/dma-buf.h
@@ -32,6 +32,6 @@
 #define DMA_BUF_BASE 'b'
 #define DMA_BUF_IOCTL_SYNC _IOW(DMA_BUF_BASE, 0, struct dma_buf_sync)
 #define DMA_BUF_SET_NAME _IOW(DMA_BUF_BASE, 1, const char *)
-#define DMA_BUF_SET_NAME_A _IOW(DMA_BUF_BASE, 1, u32)
-#define DMA_BUF_SET_NAME_B _IOW(DMA_BUF_BASE, 1, u64)
+#define DMA_BUF_SET_NAME_A _IOW(DMA_BUF_BASE, 1, __u32)
+#define DMA_BUF_SET_NAME_B _IOW(DMA_BUF_BASE, 1, __u64)
 #endif
diff --git a/libc/kernel/uapi/linux/elf.h b/libc/kernel/uapi/linux/elf.h
index 7655f12..65ab245 100644
--- a/libc/kernel/uapi/linux/elf.h
+++ b/libc/kernel/uapi/linux/elf.h
@@ -45,9 +45,11 @@
 #define PT_HIOS 0x6fffffff
 #define PT_LOPROC 0x70000000
 #define PT_HIPROC 0x7fffffff
-#define PT_GNU_EH_FRAME 0x6474e550
-#define PT_GNU_PROPERTY 0x6474e553
+#define PT_GNU_EH_FRAME (PT_LOOS + 0x474e550)
 #define PT_GNU_STACK (PT_LOOS + 0x474e551)
+#define PT_GNU_RELRO (PT_LOOS + 0x474e552)
+#define PT_GNU_PROPERTY (PT_LOOS + 0x474e553)
+#define PT_AARCH64_MEMTAG_MTE (PT_LOPROC + 0x2)
 #define PN_XNUM 0xffff
 #define ET_NONE 0
 #define ET_REL 1
diff --git a/libc/kernel/uapi/linux/ethtool_netlink.h b/libc/kernel/uapi/linux/ethtool_netlink.h
index 7dcae22..8e1f38f 100644
--- a/libc/kernel/uapi/linux/ethtool_netlink.h
+++ b/libc/kernel/uapi/linux/ethtool_netlink.h
@@ -240,6 +240,11 @@
   ETHTOOL_A_PRIVFLAGS_MAX = __ETHTOOL_A_PRIVFLAGS_CNT - 1
 };
 enum {
+  ETHTOOL_TCP_DATA_SPLIT_UNKNOWN = 0,
+  ETHTOOL_TCP_DATA_SPLIT_DISABLED,
+  ETHTOOL_TCP_DATA_SPLIT_ENABLED,
+};
+enum {
   ETHTOOL_A_RINGS_UNSPEC,
   ETHTOOL_A_RINGS_HEADER,
   ETHTOOL_A_RINGS_RX_MAX,
@@ -251,6 +256,8 @@
   ETHTOOL_A_RINGS_RX_JUMBO,
   ETHTOOL_A_RINGS_TX,
   ETHTOOL_A_RINGS_RX_BUF_LEN,
+  ETHTOOL_A_RINGS_TCP_DATA_SPLIT,
+  ETHTOOL_A_RINGS_CQE_SIZE,
   __ETHTOOL_A_RINGS_CNT,
   ETHTOOL_A_RINGS_MAX = (__ETHTOOL_A_RINGS_CNT - 1)
 };
diff --git a/libc/kernel/uapi/linux/fsi.h b/libc/kernel/uapi/linux/fsi.h
index fc88464..b080c21 100644
--- a/libc/kernel/uapi/linux/fsi.h
+++ b/libc/kernel/uapi/linux/fsi.h
@@ -48,4 +48,5 @@
 #define FSI_SCOM_READ _IOWR('s', 0x01, struct scom_access)
 #define FSI_SCOM_WRITE _IOWR('s', 0x02, struct scom_access)
 #define FSI_SCOM_RESET _IOW('s', 0x03, __u32)
+#define FSI_SBEFIFO_READ_TIMEOUT_SECONDS _IOW('s', 0x00, __u32)
 #endif
diff --git a/libc/kernel/uapi/linux/gtp.h b/libc/kernel/uapi/linux/gtp.h
index 3b9416e..20bc3d6 100644
--- a/libc/kernel/uapi/linux/gtp.h
+++ b/libc/kernel/uapi/linux/gtp.h
@@ -23,6 +23,7 @@
   GTP_CMD_NEWPDP,
   GTP_CMD_DELPDP,
   GTP_CMD_GETPDP,
+  GTP_CMD_ECHOREQ,
   GTP_CMD_MAX,
 };
 enum gtp_version {
diff --git a/libc/kernel/uapi/linux/if_addr.h b/libc/kernel/uapi/linux/if_addr.h
index 6a6b640..a225e69 100644
--- a/libc/kernel/uapi/linux/if_addr.h
+++ b/libc/kernel/uapi/linux/if_addr.h
@@ -39,6 +39,7 @@
   IFA_FLAGS,
   IFA_RT_PRIORITY,
   IFA_TARGET_NETNSID,
+  IFA_PROTO,
   __IFA_MAX,
 };
 #define IFA_MAX (__IFA_MAX - 1)
@@ -63,4 +64,8 @@
 };
 #define IFA_RTA(r) ((struct rtattr *) (((char *) (r)) + NLMSG_ALIGN(sizeof(struct ifaddrmsg))))
 #define IFA_PAYLOAD(n) NLMSG_PAYLOAD(n, sizeof(struct ifaddrmsg))
+#define IFAPROT_UNSPEC 0
+#define IFAPROT_KERNEL_LO 1
+#define IFAPROT_KERNEL_RA 2
+#define IFAPROT_KERNEL_LL 3
 #endif
diff --git a/libc/kernel/uapi/linux/if_bridge.h b/libc/kernel/uapi/linux/if_bridge.h
index 2054fb3..0f08866 100644
--- a/libc/kernel/uapi/linux/if_bridge.h
+++ b/libc/kernel/uapi/linux/if_bridge.h
@@ -108,6 +108,7 @@
   IFLA_BRIDGE_VLAN_TUNNEL_INFO,
   IFLA_BRIDGE_MRP,
   IFLA_BRIDGE_CFM,
+  IFLA_BRIDGE_MST,
   __IFLA_BRIDGE_MAX,
 };
 #define IFLA_BRIDGE_MAX (__IFLA_BRIDGE_MAX - 1)
@@ -384,6 +385,19 @@
   __IFLA_BRIDGE_CFM_CC_PEER_STATUS_MAX,
 };
 #define IFLA_BRIDGE_CFM_CC_PEER_STATUS_MAX (__IFLA_BRIDGE_CFM_CC_PEER_STATUS_MAX - 1)
+enum {
+  IFLA_BRIDGE_MST_UNSPEC,
+  IFLA_BRIDGE_MST_ENTRY,
+  __IFLA_BRIDGE_MST_MAX,
+};
+#define IFLA_BRIDGE_MST_MAX (__IFLA_BRIDGE_MST_MAX - 1)
+enum {
+  IFLA_BRIDGE_MST_ENTRY_UNSPEC,
+  IFLA_BRIDGE_MST_ENTRY_MSTI,
+  IFLA_BRIDGE_MST_ENTRY_STATE,
+  __IFLA_BRIDGE_MST_ENTRY_MAX,
+};
+#define IFLA_BRIDGE_MST_ENTRY_MAX (__IFLA_BRIDGE_MST_ENTRY_MAX - 1)
 struct bridge_stp_xstats {
   __u64 transition_blk;
   __u64 transition_fwd;
@@ -460,6 +474,7 @@
   BRIDGE_VLANDB_GOPTS_MCAST_QUERIER,
   BRIDGE_VLANDB_GOPTS_MCAST_ROUTER_PORTS,
   BRIDGE_VLANDB_GOPTS_MCAST_QUERIER_STATE,
+  BRIDGE_VLANDB_GOPTS_MSTI,
   __BRIDGE_VLANDB_GOPTS_MAX
 };
 #define BRIDGE_VLANDB_GOPTS_MAX (__BRIDGE_VLANDB_GOPTS_MAX - 1)
@@ -599,6 +614,7 @@
 enum br_boolopt_id {
   BR_BOOLOPT_NO_LL_LEARN,
   BR_BOOLOPT_MCAST_VLAN_SNOOPING,
+  BR_BOOLOPT_MST_ENABLE,
   BR_BOOLOPT_MAX
 };
 struct br_boolopt_multi {
diff --git a/libc/kernel/uapi/linux/if_ether.h b/libc/kernel/uapi/linux/if_ether.h
index 1f7f8f2..bd8e045 100644
--- a/libc/kernel/uapi/linux/if_ether.h
+++ b/libc/kernel/uapi/linux/if_ether.h
@@ -67,8 +67,10 @@
 #define ETH_P_LINK_CTL 0x886c
 #define ETH_P_ATMFATE 0x8884
 #define ETH_P_PAE 0x888E
+#define ETH_P_PROFINET 0x8892
 #define ETH_P_REALTEK 0x8899
 #define ETH_P_AOE 0x88A2
+#define ETH_P_ETHERCAT 0x88A4
 #define ETH_P_8021AD 0x88A8
 #define ETH_P_802_EX1 0x88B5
 #define ETH_P_PREAUTH 0x88C7
diff --git a/libc/kernel/uapi/linux/if_link.h b/libc/kernel/uapi/linux/if_link.h
index 7e413ae..640fa50 100644
--- a/libc/kernel/uapi/linux/if_link.h
+++ b/libc/kernel/uapi/linux/if_link.h
@@ -72,6 +72,17 @@
   __u64 tx_compressed;
   __u64 rx_nohandler;
 };
+struct rtnl_hw_stats64 {
+  __u64 rx_packets;
+  __u64 tx_packets;
+  __u64 rx_bytes;
+  __u64 tx_bytes;
+  __u64 rx_errors;
+  __u64 tx_errors;
+  __u64 rx_dropped;
+  __u64 tx_dropped;
+  __u64 multicast;
+};
 struct rtnl_link_ifmap {
   __u64 mem_start;
   __u64 mem_end;
@@ -289,6 +300,7 @@
   IFLA_BRPORT_MRP_IN_OPEN,
   IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT,
   IFLA_BRPORT_MCAST_EHT_HOSTS_CNT,
+  IFLA_BRPORT_LOCKED,
   __IFLA_BRPORT_MAX
 };
 #define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1)
@@ -428,6 +440,44 @@
 };
 #define IPVLAN_F_PRIVATE 0x01
 #define IPVLAN_F_VEPA 0x02
+struct tunnel_msg {
+  __u8 family;
+  __u8 flags;
+  __u16 reserved2;
+  __u32 ifindex;
+};
+#define TUNNEL_MSG_FLAG_STATS 0x01
+#define TUNNEL_MSG_VALID_USER_FLAGS TUNNEL_MSG_FLAG_STATS
+enum {
+  VNIFILTER_ENTRY_STATS_UNSPEC,
+  VNIFILTER_ENTRY_STATS_RX_BYTES,
+  VNIFILTER_ENTRY_STATS_RX_PKTS,
+  VNIFILTER_ENTRY_STATS_RX_DROPS,
+  VNIFILTER_ENTRY_STATS_RX_ERRORS,
+  VNIFILTER_ENTRY_STATS_TX_BYTES,
+  VNIFILTER_ENTRY_STATS_TX_PKTS,
+  VNIFILTER_ENTRY_STATS_TX_DROPS,
+  VNIFILTER_ENTRY_STATS_TX_ERRORS,
+  VNIFILTER_ENTRY_STATS_PAD,
+  __VNIFILTER_ENTRY_STATS_MAX
+};
+#define VNIFILTER_ENTRY_STATS_MAX (__VNIFILTER_ENTRY_STATS_MAX - 1)
+enum {
+  VXLAN_VNIFILTER_ENTRY_UNSPEC,
+  VXLAN_VNIFILTER_ENTRY_START,
+  VXLAN_VNIFILTER_ENTRY_END,
+  VXLAN_VNIFILTER_ENTRY_GROUP,
+  VXLAN_VNIFILTER_ENTRY_GROUP6,
+  VXLAN_VNIFILTER_ENTRY_STATS,
+  __VXLAN_VNIFILTER_ENTRY_MAX
+};
+#define VXLAN_VNIFILTER_ENTRY_MAX (__VXLAN_VNIFILTER_ENTRY_MAX - 1)
+enum {
+  VXLAN_VNIFILTER_UNSPEC,
+  VXLAN_VNIFILTER_ENTRY,
+  __VXLAN_VNIFILTER_MAX
+};
+#define VXLAN_VNIFILTER_MAX (__VXLAN_VNIFILTER_MAX - 1)
 enum {
   IFLA_VXLAN_UNSPEC,
   IFLA_VXLAN_ID,
@@ -459,6 +509,7 @@
   IFLA_VXLAN_GPE,
   IFLA_VXLAN_TTL_INHERIT,
   IFLA_VXLAN_DF,
+  IFLA_VXLAN_VNIFILTER,
   __IFLA_VXLAN_MAX
 };
 #define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1)
@@ -488,6 +539,7 @@
   IFLA_GENEVE_LABEL,
   IFLA_GENEVE_TTL_INHERIT,
   IFLA_GENEVE_DF,
+  IFLA_GENEVE_INNER_PROTO_INHERIT,
   __IFLA_GENEVE_MAX
 };
 #define IFLA_GENEVE_MAX (__IFLA_GENEVE_MAX - 1)
@@ -523,6 +575,8 @@
   IFLA_GTP_FD1,
   IFLA_GTP_PDP_HASHSIZE,
   IFLA_GTP_ROLE,
+  IFLA_GTP_CREATE_SOCKETS,
+  IFLA_GTP_RESTART_COUNT,
   __IFLA_GTP_MAX,
 };
 #define IFLA_GTP_MAX (__IFLA_GTP_MAX - 1)
@@ -558,6 +612,7 @@
   IFLA_BOND_PEER_NOTIF_DELAY,
   IFLA_BOND_AD_LACP_ACTIVE,
   IFLA_BOND_MISSED_MAX,
+  IFLA_BOND_NS_IP6_TARGET,
   __IFLA_BOND_MAX,
 };
 #define IFLA_BOND_MAX (__IFLA_BOND_MAX - 1)
@@ -777,6 +832,13 @@
 #define IFLA_STATS_MAX (__IFLA_STATS_MAX - 1)
 #define IFLA_STATS_FILTER_BIT(ATTR) (1 << (ATTR - 1))
 enum {
+  IFLA_STATS_GETSET_UNSPEC,
+  IFLA_STATS_GET_FILTERS,
+  IFLA_STATS_SET_OFFLOAD_XSTATS_L3_STATS,
+  __IFLA_STATS_GETSET_MAX,
+};
+#define IFLA_STATS_GETSET_MAX (__IFLA_STATS_GETSET_MAX - 1)
+enum {
   LINK_XSTATS_TYPE_UNSPEC,
   LINK_XSTATS_TYPE_BRIDGE,
   LINK_XSTATS_TYPE_BOND,
@@ -786,9 +848,18 @@
 enum {
   IFLA_OFFLOAD_XSTATS_UNSPEC,
   IFLA_OFFLOAD_XSTATS_CPU_HIT,
+  IFLA_OFFLOAD_XSTATS_HW_S_INFO,
+  IFLA_OFFLOAD_XSTATS_L3_STATS,
   __IFLA_OFFLOAD_XSTATS_MAX
 };
 #define IFLA_OFFLOAD_XSTATS_MAX (__IFLA_OFFLOAD_XSTATS_MAX - 1)
+enum {
+  IFLA_OFFLOAD_XSTATS_HW_S_INFO_UNSPEC,
+  IFLA_OFFLOAD_XSTATS_HW_S_INFO_REQUEST,
+  IFLA_OFFLOAD_XSTATS_HW_S_INFO_USED,
+  __IFLA_OFFLOAD_XSTATS_HW_S_INFO_MAX,
+};
+#define IFLA_OFFLOAD_XSTATS_HW_S_INFO_MAX (__IFLA_OFFLOAD_XSTATS_HW_S_INFO_MAX - 1)
 #define XDP_FLAGS_UPDATE_IF_NOEXIST (1U << 0)
 #define XDP_FLAGS_SKB_MODE (1U << 1)
 #define XDP_FLAGS_DRV_MODE (1U << 2)
diff --git a/libc/kernel/uapi/linux/if_tunnel.h b/libc/kernel/uapi/linux/if_tunnel.h
index 8e1847f..01c2dc9 100644
--- a/libc/kernel/uapi/linux/if_tunnel.h
+++ b/libc/kernel/uapi/linux/if_tunnel.h
@@ -169,5 +169,6 @@
 #define TUNNEL_VXLAN_OPT __cpu_to_be16(0x1000)
 #define TUNNEL_NOCACHE __cpu_to_be16(0x2000)
 #define TUNNEL_ERSPAN_OPT __cpu_to_be16(0x4000)
-#define TUNNEL_OPTIONS_PRESENT (TUNNEL_GENEVE_OPT | TUNNEL_VXLAN_OPT | TUNNEL_ERSPAN_OPT)
+#define TUNNEL_GTP_OPT __cpu_to_be16(0x8000)
+#define TUNNEL_OPTIONS_PRESENT (TUNNEL_GENEVE_OPT | TUNNEL_VXLAN_OPT | TUNNEL_ERSPAN_OPT | TUNNEL_GTP_OPT)
 #endif
diff --git a/libc/kernel/uapi/linux/iio/types.h b/libc/kernel/uapi/linux/iio/types.h
index 22409a7..aa66d50 100644
--- a/libc/kernel/uapi/linux/iio/types.h
+++ b/libc/kernel/uapi/linux/iio/types.h
@@ -109,6 +109,7 @@
   IIO_EV_TYPE_THRESH_ADAPTIVE,
   IIO_EV_TYPE_MAG_ADAPTIVE,
   IIO_EV_TYPE_CHANGE,
+  IIO_EV_TYPE_MAG_REFERENCED,
 };
 enum iio_event_direction {
   IIO_EV_DIR_EITHER,
diff --git a/libc/kernel/uapi/linux/input-event-codes.h b/libc/kernel/uapi/linux/input-event-codes.h
index 34cd23c..4b251df 100644
--- a/libc/kernel/uapi/linux/input-event-codes.h
+++ b/libc/kernel/uapi/linux/input-event-codes.h
@@ -580,6 +580,21 @@
 #define KEY_ONSCREEN_KEYBOARD 0x278
 #define KEY_PRIVACY_SCREEN_TOGGLE 0x279
 #define KEY_SELECTIVE_SCREENSHOT 0x27a
+#define KEY_NEXT_ELEMENT 0x27b
+#define KEY_PREVIOUS_ELEMENT 0x27c
+#define KEY_AUTOPILOT_ENGAGE_TOGGLE 0x27d
+#define KEY_MARK_WAYPOINT 0x27e
+#define KEY_SOS 0x27f
+#define KEY_NAV_CHART 0x280
+#define KEY_FISHING_CHART 0x281
+#define KEY_SINGLE_RANGE_RADAR 0x282
+#define KEY_DUAL_RANGE_RADAR 0x283
+#define KEY_RADAR_OVERLAY 0x284
+#define KEY_TRADITIONAL_SONAR 0x285
+#define KEY_CLEARVU_SONAR 0x286
+#define KEY_SIDEVU_SONAR 0x287
+#define KEY_NAV_INFO 0x288
+#define KEY_BRIGHTNESS_MENU 0x289
 #define KEY_MACRO1 0x290
 #define KEY_MACRO2 0x291
 #define KEY_MACRO3 0x292
diff --git a/libc/kernel/uapi/linux/io_uring.h b/libc/kernel/uapi/linux/io_uring.h
index 96944f8..2f599aa 100644
--- a/libc/kernel/uapi/linux/io_uring.h
+++ b/libc/kernel/uapi/linux/io_uring.h
@@ -87,6 +87,7 @@
 #define IORING_SETUP_CLAMP (1U << 4)
 #define IORING_SETUP_ATTACH_WQ (1U << 5)
 #define IORING_SETUP_R_DISABLED (1U << 6)
+#define IORING_SETUP_SUBMIT_ALL (1U << 7)
 enum {
   IORING_OP_NOP,
   IORING_OP_READV,
@@ -128,6 +129,7 @@
   IORING_OP_MKDIRAT,
   IORING_OP_SYMLINKAT,
   IORING_OP_LINKAT,
+  IORING_OP_MSG_RING,
   IORING_OP_LAST,
 };
 #define IORING_FSYNC_DATASYNC (1U << 0)
@@ -185,6 +187,7 @@
 #define IORING_ENTER_SQ_WAKEUP (1U << 1)
 #define IORING_ENTER_SQ_WAIT (1U << 2)
 #define IORING_ENTER_EXT_ARG (1U << 3)
+#define IORING_ENTER_REGISTERED_RING (1U << 4)
 struct io_uring_params {
   __u32 sq_entries;
   __u32 cq_entries;
@@ -209,6 +212,7 @@
 #define IORING_FEAT_NATIVE_WORKERS (1U << 9)
 #define IORING_FEAT_RSRC_TAGS (1U << 10)
 #define IORING_FEAT_CQE_SKIP (1U << 11)
+#define IORING_FEAT_LINKED_FILE (1U << 12)
 enum {
   IORING_REGISTER_BUFFERS = 0,
   IORING_UNREGISTER_BUFFERS = 1,
@@ -230,6 +234,8 @@
   IORING_REGISTER_IOWQ_AFF = 17,
   IORING_UNREGISTER_IOWQ_AFF = 18,
   IORING_REGISTER_IOWQ_MAX_WORKERS = 19,
+  IORING_REGISTER_RING_FDS = 20,
+  IORING_UNREGISTER_RING_FDS = 21,
   IORING_REGISTER_LAST
 };
 enum {
diff --git a/libc/kernel/uapi/linux/ioam6_iptunnel.h b/libc/kernel/uapi/linux/ioam6_iptunnel.h
index 7426225..ec1a6a8 100644
--- a/libc/kernel/uapi/linux/ioam6_iptunnel.h
+++ b/libc/kernel/uapi/linux/ioam6_iptunnel.h
@@ -32,6 +32,10 @@
   IOAM6_IPTUNNEL_MODE,
   IOAM6_IPTUNNEL_DST,
   IOAM6_IPTUNNEL_TRACE,
+#define IOAM6_IPTUNNEL_FREQ_MIN 1
+#define IOAM6_IPTUNNEL_FREQ_MAX 1000000
+  IOAM6_IPTUNNEL_FREQ_K,
+  IOAM6_IPTUNNEL_FREQ_N,
   __IOAM6_IPTUNNEL_MAX,
 };
 #define IOAM6_IPTUNNEL_MAX (__IOAM6_IPTUNNEL_MAX - 1)
diff --git a/libc/kernel/uapi/linux/iommu.h b/libc/kernel/uapi/linux/iommu.h
index 0a0af92..0304a32 100644
--- a/libc/kernel/uapi/linux/iommu.h
+++ b/libc/kernel/uapi/linux/iommu.h
@@ -85,76 +85,4 @@
   __u32 grpid;
   __u32 code;
 };
-enum iommu_inv_granularity {
-  IOMMU_INV_GRANU_DOMAIN,
-  IOMMU_INV_GRANU_PASID,
-  IOMMU_INV_GRANU_ADDR,
-  IOMMU_INV_GRANU_NR,
-};
-struct iommu_inv_addr_info {
-#define IOMMU_INV_ADDR_FLAGS_PASID (1 << 0)
-#define IOMMU_INV_ADDR_FLAGS_ARCHID (1 << 1)
-#define IOMMU_INV_ADDR_FLAGS_LEAF (1 << 2)
-  __u32 flags;
-  __u32 archid;
-  __u64 pasid;
-  __u64 addr;
-  __u64 granule_size;
-  __u64 nb_granules;
-};
-struct iommu_inv_pasid_info {
-#define IOMMU_INV_PASID_FLAGS_PASID (1 << 0)
-#define IOMMU_INV_PASID_FLAGS_ARCHID (1 << 1)
-  __u32 flags;
-  __u32 archid;
-  __u64 pasid;
-};
-struct iommu_cache_invalidate_info {
-  __u32 argsz;
-#define IOMMU_CACHE_INVALIDATE_INFO_VERSION_1 1
-  __u32 version;
-#define IOMMU_CACHE_INV_TYPE_IOTLB (1 << 0)
-#define IOMMU_CACHE_INV_TYPE_DEV_IOTLB (1 << 1)
-#define IOMMU_CACHE_INV_TYPE_PASID (1 << 2)
-#define IOMMU_CACHE_INV_TYPE_NR (3)
-  __u8 cache;
-  __u8 granularity;
-  __u8 padding[6];
-  union {
-    struct iommu_inv_pasid_info pasid_info;
-    struct iommu_inv_addr_info addr_info;
-  } granu;
-};
-struct iommu_gpasid_bind_data_vtd {
-#define IOMMU_SVA_VTD_GPASID_SRE (1 << 0)
-#define IOMMU_SVA_VTD_GPASID_EAFE (1 << 1)
-#define IOMMU_SVA_VTD_GPASID_PCD (1 << 2)
-#define IOMMU_SVA_VTD_GPASID_PWT (1 << 3)
-#define IOMMU_SVA_VTD_GPASID_EMTE (1 << 4)
-#define IOMMU_SVA_VTD_GPASID_CD (1 << 5)
-#define IOMMU_SVA_VTD_GPASID_WPE (1 << 6)
-#define IOMMU_SVA_VTD_GPASID_LAST (1 << 7)
-  __u64 flags;
-  __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 {
-  __u32 argsz;
-#define IOMMU_GPASID_BIND_VERSION_1 1
-  __u32 version;
-#define IOMMU_PASID_FORMAT_INTEL_VTD 1
-#define IOMMU_PASID_FORMAT_LAST 2
-  __u32 format;
-  __u32 addr_width;
-#define IOMMU_SVA_GPASID_VAL (1 << 0)
-  __u64 flags;
-  __u64 gpgd;
-  __u64 hpasid;
-  __u64 gpasid;
-  __u8 padding[8];
-  union {
-    struct iommu_gpasid_bind_data_vtd vtd;
-  } vendor;
-};
 #endif
diff --git a/libc/kernel/uapi/linux/kexec.h b/libc/kernel/uapi/linux/kexec.h
index 2e3bd0c..7dbc87e 100644
--- a/libc/kernel/uapi/linux/kexec.h
+++ b/libc/kernel/uapi/linux/kexec.h
@@ -43,8 +43,8 @@
 #define KEXEC_SEGMENT_MAX 16
 struct kexec_segment {
   const void * buf;
-  size_t bufsz;
+  __kernel_size_t bufsz;
   const void * mem;
-  size_t memsz;
+  __kernel_size_t memsz;
 };
 #endif
diff --git a/libc/kernel/uapi/linux/kfd_ioctl.h b/libc/kernel/uapi/linux/kfd_ioctl.h
index c52ac64..8ec47f4 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 6
+#define KFD_IOCTL_MINOR_VERSION 8
 struct kfd_ioctl_get_version_args {
   __u32 major_version;
   __u32 minor_version;
@@ -132,6 +132,7 @@
   __u32 gpu_id;
   __u32 buf_size_in_bytes;
 };
+#define KFD_INVALID_FD 0xffffffff
 #define KFD_IOC_EVENT_SIGNAL 0
 #define KFD_IOC_EVENT_NODECHANGE 1
 #define KFD_IOC_EVENT_DEVICESTATECHANGE 2
@@ -296,10 +297,45 @@
   KFD_SMI_EVENT_GPU_POST_RESET = 4,
 };
 #define KFD_SMI_EVENT_MASK_FROM_INDEX(i) (1ULL << ((i) - 1))
+#define KFD_SMI_EVENT_MSG_SIZE 96
 struct kfd_ioctl_smi_events_args {
   __u32 gpuid;
   __u32 anon_fd;
 };
+enum kfd_criu_op {
+  KFD_CRIU_OP_PROCESS_INFO,
+  KFD_CRIU_OP_CHECKPOINT,
+  KFD_CRIU_OP_UNPAUSE,
+  KFD_CRIU_OP_RESTORE,
+  KFD_CRIU_OP_RESUME,
+};
+struct kfd_ioctl_criu_args {
+  __u64 devices;
+  __u64 bos;
+  __u64 priv_data;
+  __u64 priv_data_size;
+  __u32 num_devices;
+  __u32 num_bos;
+  __u32 num_objects;
+  __u32 pid;
+  __u32 op;
+};
+struct kfd_criu_device_bucket {
+  __u32 user_gpu_id;
+  __u32 actual_gpu_id;
+  __u32 drm_fd;
+  __u32 pad;
+};
+struct kfd_criu_bo_bucket {
+  __u64 addr;
+  __u64 size;
+  __u64 offset;
+  __u64 restored_offset;
+  __u32 gpu_id;
+  __u32 alloc_flags;
+  __u32 dmabuf_fd;
+  __u32 pad;
+};
 enum kfd_mmio_remap {
   KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL = 0,
   KFD_MMIO_REMAP_HDP_REG_FLUSH_CNTL = 4,
@@ -337,7 +373,7 @@
   __u64 size;
   __u32 op;
   __u32 nattr;
-  struct kfd_ioctl_svm_attribute attrs[0];
+  struct kfd_ioctl_svm_attribute attrs[];
 };
 struct kfd_ioctl_set_xnack_mode_args {
   __s32 xnack_enabled;
@@ -359,10 +395,10 @@
 #define AMDKFD_IOC_SET_EVENT AMDKFD_IOW(0x0A, struct kfd_ioctl_set_event_args)
 #define AMDKFD_IOC_RESET_EVENT AMDKFD_IOW(0x0B, struct kfd_ioctl_reset_event_args)
 #define AMDKFD_IOC_WAIT_EVENTS AMDKFD_IOWR(0x0C, struct kfd_ioctl_wait_events_args)
-#define AMDKFD_IOC_DBG_REGISTER AMDKFD_IOW(0x0D, struct kfd_ioctl_dbg_register_args)
-#define AMDKFD_IOC_DBG_UNREGISTER AMDKFD_IOW(0x0E, struct kfd_ioctl_dbg_unregister_args)
-#define AMDKFD_IOC_DBG_ADDRESS_WATCH AMDKFD_IOW(0x0F, struct kfd_ioctl_dbg_address_watch_args)
-#define AMDKFD_IOC_DBG_WAVE_CONTROL AMDKFD_IOW(0x10, struct kfd_ioctl_dbg_wave_control_args)
+#define AMDKFD_IOC_DBG_REGISTER_DEPRECATED AMDKFD_IOW(0x0D, struct kfd_ioctl_dbg_register_args)
+#define AMDKFD_IOC_DBG_UNREGISTER_DEPRECATED AMDKFD_IOW(0x0E, struct kfd_ioctl_dbg_unregister_args)
+#define AMDKFD_IOC_DBG_ADDRESS_WATCH_DEPRECATED AMDKFD_IOW(0x0F, struct kfd_ioctl_dbg_address_watch_args)
+#define AMDKFD_IOC_DBG_WAVE_CONTROL_DEPRECATED AMDKFD_IOW(0x10, struct kfd_ioctl_dbg_wave_control_args)
 #define AMDKFD_IOC_SET_SCRATCH_BACKING_VA AMDKFD_IOWR(0x11, struct kfd_ioctl_set_scratch_backing_va_args)
 #define AMDKFD_IOC_GET_TILE_CONFIG AMDKFD_IOWR(0x12, struct kfd_ioctl_get_tile_config_args)
 #define AMDKFD_IOC_SET_TRAP_HANDLER AMDKFD_IOW(0x13, struct kfd_ioctl_set_trap_handler_args)
@@ -380,6 +416,7 @@
 #define AMDKFD_IOC_SMI_EVENTS AMDKFD_IOWR(0x1F, struct kfd_ioctl_smi_events_args)
 #define AMDKFD_IOC_SVM AMDKFD_IOWR(0x20, struct kfd_ioctl_svm_args)
 #define AMDKFD_IOC_SET_XNACK_MODE AMDKFD_IOWR(0x21, struct kfd_ioctl_set_xnack_mode_args)
+#define AMDKFD_IOC_CRIU_OP AMDKFD_IOWR(0x22, struct kfd_ioctl_criu_args)
 #define AMDKFD_COMMAND_START 0x01
-#define AMDKFD_COMMAND_END 0x22
+#define AMDKFD_COMMAND_END 0x23
 #endif
diff --git a/libc/kernel/uapi/linux/kvm.h b/libc/kernel/uapi/linux/kvm.h
index 1cf7182..5cc9905 100644
--- a/libc/kernel/uapi/linux/kvm.h
+++ b/libc/kernel/uapi/linux/kvm.h
@@ -337,7 +337,11 @@
 #define KVM_SYSTEM_EVENT_RESET 2
 #define KVM_SYSTEM_EVENT_CRASH 3
       __u32 type;
-      __u64 flags;
+      __u32 ndata;
+      union {
+        __u64 flags;
+        __u64 data[16];
+      };
     } system_event;
     struct {
       __u64 addr;
@@ -419,7 +423,10 @@
   __u32 op;
   __u64 buf;
   union {
-    __u8 ar;
+    struct {
+      __u8 ar;
+      __u8 key;
+    };
     __u32 sida_offset;
     __u8 reserved[32];
   };
@@ -428,8 +435,11 @@
 #define KVM_S390_MEMOP_LOGICAL_WRITE 1
 #define KVM_S390_MEMOP_SIDA_READ 2
 #define KVM_S390_MEMOP_SIDA_WRITE 3
+#define KVM_S390_MEMOP_ABSOLUTE_READ 4
+#define KVM_S390_MEMOP_ABSOLUTE_WRITE 5
 #define KVM_S390_MEMOP_F_CHECK_ONLY (1ULL << 0)
 #define KVM_S390_MEMOP_F_INJECT_EXCEPTION (1ULL << 1)
+#define KVM_S390_MEMOP_F_SKEY_PROTECTION (1ULL << 2)
 struct kvm_interrupt {
   __u32 irq;
 };
@@ -890,6 +900,10 @@
 #define KVM_CAP_XSAVE2 208
 #define KVM_CAP_SYS_ATTRIBUTES 209
 #define KVM_CAP_PPC_AIL_MODE_3 210
+#define KVM_CAP_S390_MEM_OP_EXTENSION 211
+#define KVM_CAP_PMU_CAPABILITY 212
+#define KVM_CAP_DISABLE_QUIRKS2 213
+#define KVM_CAP_SYSTEM_EVENT_DATA 215
 #ifdef KVM_CAP_IRQ_ROUTING
 struct kvm_irq_routing_irqchip {
   __u32 irqchip;
@@ -1480,6 +1494,7 @@
 };
 #define KVM_BUS_LOCK_DETECTION_OFF (1 << 0)
 #define KVM_BUS_LOCK_DETECTION_EXIT (1 << 1)
+#define KVM_PMU_CAP_DISABLE (1 << 0)
 struct kvm_stats_header {
   __u32 flags;
   __u32 name_size;
diff --git a/libc/kernel/uapi/linux/lirc.h b/libc/kernel/uapi/linux/lirc.h
index a0ac24a..ea45506 100644
--- a/libc/kernel/uapi/linux/lirc.h
+++ b/libc/kernel/uapi/linux/lirc.h
@@ -26,18 +26,21 @@
 #define LIRC_MODE2_PULSE 0x01000000
 #define LIRC_MODE2_FREQUENCY 0x02000000
 #define LIRC_MODE2_TIMEOUT 0x03000000
+#define LIRC_MODE2_OVERFLOW 0x04000000
 #define LIRC_VALUE_MASK 0x00FFFFFF
 #define LIRC_MODE2_MASK 0xFF000000
 #define LIRC_SPACE(val) (((val) & LIRC_VALUE_MASK) | LIRC_MODE2_SPACE)
 #define LIRC_PULSE(val) (((val) & LIRC_VALUE_MASK) | LIRC_MODE2_PULSE)
 #define LIRC_FREQUENCY(val) (((val) & LIRC_VALUE_MASK) | LIRC_MODE2_FREQUENCY)
 #define LIRC_TIMEOUT(val) (((val) & LIRC_VALUE_MASK) | LIRC_MODE2_TIMEOUT)
+#define LIRC_OVERFLOW(val) (((val) & LIRC_VALUE_MASK) | LIRC_MODE2_OVERFLOW)
 #define LIRC_VALUE(val) ((val) & LIRC_VALUE_MASK)
 #define LIRC_MODE2(val) ((val) & LIRC_MODE2_MASK)
 #define LIRC_IS_SPACE(val) (LIRC_MODE2(val) == LIRC_MODE2_SPACE)
 #define LIRC_IS_PULSE(val) (LIRC_MODE2(val) == LIRC_MODE2_PULSE)
 #define LIRC_IS_FREQUENCY(val) (LIRC_MODE2(val) == LIRC_MODE2_FREQUENCY)
 #define LIRC_IS_TIMEOUT(val) (LIRC_MODE2(val) == LIRC_MODE2_TIMEOUT)
+#define LIRC_IS_OVERFLOW(val) (LIRC_MODE2(val) == LIRC_MODE2_OVERFLOW)
 #define lirc_t int
 #define LIRC_MODE2SEND(x) (x)
 #define LIRC_SEND2MODE(x) (x)
@@ -63,17 +66,13 @@
 #define LIRC_CAN_REC_LIRCCODE LIRC_MODE2REC(LIRC_MODE_LIRCCODE)
 #define LIRC_CAN_REC_MASK LIRC_MODE2REC(LIRC_CAN_SEND_MASK)
 #define LIRC_CAN_SET_REC_CARRIER (LIRC_CAN_SET_SEND_CARRIER << 16)
-#define LIRC_CAN_SET_REC_DUTY_CYCLE (LIRC_CAN_SET_SEND_DUTY_CYCLE << 16)
-#define LIRC_CAN_SET_REC_DUTY_CYCLE_RANGE 0x40000000
 #define LIRC_CAN_SET_REC_CARRIER_RANGE 0x80000000
 #define LIRC_CAN_GET_REC_RESOLUTION 0x20000000
 #define LIRC_CAN_SET_REC_TIMEOUT 0x10000000
-#define LIRC_CAN_SET_REC_FILTER 0x08000000
 #define LIRC_CAN_MEASURE_CARRIER 0x02000000
 #define LIRC_CAN_USE_WIDEBAND_RECEIVER 0x04000000
 #define LIRC_CAN_SEND(x) ((x) & LIRC_CAN_SEND_MASK)
 #define LIRC_CAN_REC(x) ((x) & LIRC_CAN_REC_MASK)
-#define LIRC_CAN_NOTIFY_DECODE 0x01000000
 #define LIRC_GET_FEATURES _IOR('i', 0x00000000, __u32)
 #define LIRC_GET_SEND_MODE _IOR('i', 0x00000001, __u32)
 #define LIRC_GET_REC_MODE _IOR('i', 0x00000002, __u32)
diff --git a/libc/kernel/uapi/linux/mctp.h b/libc/kernel/uapi/linux/mctp.h
index 21a9a14..f02c12f 100644
--- a/libc/kernel/uapi/linux/mctp.h
+++ b/libc/kernel/uapi/linux/mctp.h
@@ -46,5 +46,13 @@
 #define MCTP_ADDR_ANY 0xff
 #define MCTP_TAG_MASK 0x07
 #define MCTP_TAG_OWNER 0x08
+#define MCTP_TAG_PREALLOC 0x10
 #define MCTP_OPT_ADDR_EXT 1
+#define SIOCMCTPALLOCTAG (SIOCPROTOPRIVATE + 0)
+#define SIOCMCTPDROPTAG (SIOCPROTOPRIVATE + 1)
+struct mctp_ioc_tag_ctl {
+  mctp_eid_t peer_addr;
+  __u8 tag;
+  __u16 flags;
+};
 #endif
diff --git a/libc/kernel/uapi/linux/mptcp.h b/libc/kernel/uapi/linux/mptcp.h
index 67b0ce3..7b3acd5 100644
--- a/libc/kernel/uapi/linux/mptcp.h
+++ b/libc/kernel/uapi/linux/mptcp.h
@@ -77,6 +77,7 @@
 #define MPTCP_PM_ADDR_FLAG_SUBFLOW (1 << 1)
 #define MPTCP_PM_ADDR_FLAG_BACKUP (1 << 2)
 #define MPTCP_PM_ADDR_FLAG_FULLMESH (1 << 3)
+#define MPTCP_PM_ADDR_FLAG_IMPLICIT (1 << 4)
 enum {
   MPTCP_PM_CMD_UNSPEC,
   MPTCP_PM_CMD_ADD_ADDR,
diff --git a/libc/kernel/uapi/linux/mroute6.h b/libc/kernel/uapi/linux/mroute6.h
index c73765c..68480de 100644
--- a/libc/kernel/uapi/linux/mroute6.h
+++ b/libc/kernel/uapi/linux/mroute6.h
@@ -93,6 +93,7 @@
 #define MRT6MSG_NOCACHE 1
 #define MRT6MSG_WRONGMIF 2
 #define MRT6MSG_WHOLEPKT 3
+#define MRT6MSG_WRMIFWHOLE 4
   __u8 im6_mbz;
   __u8 im6_msgtype;
   __u16 im6_mif;
diff --git a/libc/kernel/uapi/linux/ndctl.h b/libc/kernel/uapi/linux/ndctl.h
index 53f8ba4..0fd3ac4 100644
--- a/libc/kernel/uapi/linux/ndctl.h
+++ b/libc/kernel/uapi/linux/ndctl.h
@@ -129,7 +129,6 @@
 #define ND_DEVICE_REGION_BLK 3
 #define ND_DEVICE_NAMESPACE_IO 4
 #define ND_DEVICE_NAMESPACE_PMEM 5
-#define ND_DEVICE_NAMESPACE_BLK 6
 #define ND_DEVICE_DAX_PMEM 7
 enum nd_driver_flags {
   ND_DRIVER_DIMM = 1 << ND_DEVICE_DIMM,
@@ -137,7 +136,6 @@
   ND_DRIVER_REGION_BLK = 1 << ND_DEVICE_REGION_BLK,
   ND_DRIVER_NAMESPACE_IO = 1 << ND_DEVICE_NAMESPACE_IO,
   ND_DRIVER_NAMESPACE_PMEM = 1 << ND_DEVICE_NAMESPACE_PMEM,
-  ND_DRIVER_NAMESPACE_BLK = 1 << ND_DEVICE_NAMESPACE_BLK,
   ND_DRIVER_DAX_PMEM = 1 << ND_DEVICE_DAX_PMEM,
 };
 enum ars_masks {
diff --git a/libc/kernel/uapi/linux/net_dropmon.h b/libc/kernel/uapi/linux/net_dropmon.h
index 01b76cb..35f70a5 100644
--- a/libc/kernel/uapi/linux/net_dropmon.h
+++ b/libc/kernel/uapi/linux/net_dropmon.h
@@ -87,6 +87,7 @@
   NET_DM_ATTR_SW_DROPS,
   NET_DM_ATTR_HW_DROPS,
   NET_DM_ATTR_FLOW_ACTION_COOKIE,
+  NET_DM_ATTR_REASON,
   __NET_DM_ATTR_MAX,
   NET_DM_ATTR_MAX = __NET_DM_ATTR_MAX - 1
 };
diff --git a/libc/kernel/uapi/linux/netfilter/nfnetlink_queue.h b/libc/kernel/uapi/linux/netfilter/nfnetlink_queue.h
index 75fa359..d100dec 100644
--- a/libc/kernel/uapi/linux/netfilter/nfnetlink_queue.h
+++ b/libc/kernel/uapi/linux/netfilter/nfnetlink_queue.h
@@ -70,6 +70,7 @@
   NFQA_SECCTX,
   NFQA_VLAN,
   NFQA_L2HDR,
+  NFQA_PRIORITY,
   __NFQA_MAX
 };
 #define NFQA_MAX (__NFQA_MAX - 1)
diff --git a/libc/kernel/uapi/linux/nfs4.h b/libc/kernel/uapi/linux/nfs4.h
index 9d614ce..ef860e2 100644
--- a/libc/kernel/uapi/linux/nfs4.h
+++ b/libc/kernel/uapi/linux/nfs4.h
@@ -45,6 +45,7 @@
 #define NFS4_FH_VOL_RENAME 0x0008
 #define NFS4_OPEN_RESULT_CONFIRM 0x0002
 #define NFS4_OPEN_RESULT_LOCKTYPE_POSIX 0x0004
+#define NFS4_OPEN_RESULT_PRESERVE_UNLINKED 0x0008
 #define NFS4_OPEN_RESULT_MAY_NOTIFY_LOCK 0x0020
 #define NFS4_SHARE_ACCESS_MASK 0x000F
 #define NFS4_SHARE_ACCESS_READ 0x0001
diff --git a/libc/kernel/uapi/linux/nl80211.h b/libc/kernel/uapi/linux/nl80211.h
index e902178..61de391 100644
--- a/libc/kernel/uapi/linux/nl80211.h
+++ b/libc/kernel/uapi/linux/nl80211.h
@@ -511,6 +511,7 @@
   NL80211_ATTR_MBSSID_ELEMS,
   NL80211_ATTR_RADAR_BACKGROUND,
   NL80211_ATTR_AP_SETTINGS_FLAGS,
+  NL80211_ATTR_EHT_CAPABILITY,
   __NL80211_ATTR_AFTER_LAST,
   NUM_NL80211_ATTR = __NL80211_ATTR_AFTER_LAST,
   NL80211_ATTR_MAX = __NL80211_ATTR_AFTER_LAST - 1
@@ -555,6 +556,8 @@
 #define NL80211_HE_MAX_CAPABILITY_LEN 54
 #define NL80211_MAX_NR_CIPHER_SUITES 5
 #define NL80211_MAX_NR_AKM_SUITES 2
+#define NL80211_EHT_MIN_CAPABILITY_LEN 13
+#define NL80211_EHT_MAX_CAPABILITY_LEN 51
 #define NL80211_MIN_REMAIN_ON_CHANNEL_TIME 10
 #define NL80211_SCAN_RSSI_THOLD_OFF - 300
 #define NL80211_CQM_TXE_MAX_INTVL 1800
@@ -616,6 +619,29 @@
   NL80211_RATE_INFO_HE_RU_ALLOC_996,
   NL80211_RATE_INFO_HE_RU_ALLOC_2x996,
 };
+enum nl80211_eht_gi {
+  NL80211_RATE_INFO_EHT_GI_0_8,
+  NL80211_RATE_INFO_EHT_GI_1_6,
+  NL80211_RATE_INFO_EHT_GI_3_2,
+};
+enum nl80211_eht_ru_alloc {
+  NL80211_RATE_INFO_EHT_RU_ALLOC_26,
+  NL80211_RATE_INFO_EHT_RU_ALLOC_52,
+  NL80211_RATE_INFO_EHT_RU_ALLOC_52P26,
+  NL80211_RATE_INFO_EHT_RU_ALLOC_106,
+  NL80211_RATE_INFO_EHT_RU_ALLOC_106P26,
+  NL80211_RATE_INFO_EHT_RU_ALLOC_242,
+  NL80211_RATE_INFO_EHT_RU_ALLOC_484,
+  NL80211_RATE_INFO_EHT_RU_ALLOC_484P242,
+  NL80211_RATE_INFO_EHT_RU_ALLOC_996,
+  NL80211_RATE_INFO_EHT_RU_ALLOC_996P484,
+  NL80211_RATE_INFO_EHT_RU_ALLOC_996P484P242,
+  NL80211_RATE_INFO_EHT_RU_ALLOC_2x996,
+  NL80211_RATE_INFO_EHT_RU_ALLOC_2x996P484,
+  NL80211_RATE_INFO_EHT_RU_ALLOC_3x996,
+  NL80211_RATE_INFO_EHT_RU_ALLOC_3x996P484,
+  NL80211_RATE_INFO_EHT_RU_ALLOC_4x996,
+};
 enum nl80211_rate_info {
   __NL80211_RATE_INFO_INVALID,
   NL80211_RATE_INFO_BITRATE,
@@ -635,6 +661,11 @@
   NL80211_RATE_INFO_HE_GI,
   NL80211_RATE_INFO_HE_DCM,
   NL80211_RATE_INFO_HE_RU_ALLOC,
+  NL80211_RATE_INFO_320_MHZ_WIDTH,
+  NL80211_RATE_INFO_EHT_MCS,
+  NL80211_RATE_INFO_EHT_NSS,
+  NL80211_RATE_INFO_EHT_GI,
+  NL80211_RATE_INFO_EHT_RU_ALLOC,
   __NL80211_RATE_INFO_AFTER_LAST,
   NL80211_RATE_INFO_MAX = __NL80211_RATE_INFO_AFTER_LAST - 1
 };
@@ -754,6 +785,10 @@
   NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE,
   NL80211_BAND_IFTYPE_ATTR_HE_6GHZ_CAPA,
   NL80211_BAND_IFTYPE_ATTR_VENDOR_ELEMS,
+  NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MAC,
+  NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY,
+  NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MCS_SET,
+  NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PPE,
   __NL80211_BAND_IFTYPE_ATTR_AFTER_LAST,
   NL80211_BAND_IFTYPE_ATTR_MAX = __NL80211_BAND_IFTYPE_ATTR_AFTER_LAST - 1
 };
@@ -810,6 +845,8 @@
   NL80211_FREQUENCY_ATTR_4MHZ,
   NL80211_FREQUENCY_ATTR_8MHZ,
   NL80211_FREQUENCY_ATTR_16MHZ,
+  NL80211_FREQUENCY_ATTR_NO_320MHZ,
+  NL80211_FREQUENCY_ATTR_NO_EHT,
   __NL80211_FREQUENCY_ATTR_AFTER_LAST,
   NL80211_FREQUENCY_ATTR_MAX = __NL80211_FREQUENCY_ATTR_AFTER_LAST - 1
 };
@@ -878,6 +915,7 @@
   NL80211_RRF_NO_80MHZ = 1 << 15,
   NL80211_RRF_NO_160MHZ = 1 << 16,
   NL80211_RRF_NO_HE = 1 << 17,
+  NL80211_RRF_NO_320MHZ = 1 << 18,
 };
 #define NL80211_RRF_PASSIVE_SCAN NL80211_RRF_NO_IR
 #define NL80211_RRF_NO_IBSS NL80211_RRF_NO_IR
@@ -1033,6 +1071,7 @@
   NL80211_CHAN_WIDTH_4,
   NL80211_CHAN_WIDTH_8,
   NL80211_CHAN_WIDTH_16,
+  NL80211_CHAN_WIDTH_320,
 };
 enum nl80211_bss_scan_width {
   NL80211_BSS_CHAN_WIDTH_20,
diff --git a/libc/kernel/uapi/linux/nvme_ioctl.h b/libc/kernel/uapi/linux/nvme_ioctl.h
index f2a328e..a2f9914 100644
--- a/libc/kernel/uapi/linux/nvme_ioctl.h
+++ b/libc/kernel/uapi/linux/nvme_ioctl.h
@@ -63,7 +63,10 @@
   __u64 metadata;
   __u64 addr;
   __u32 metadata_len;
-  __u32 data_len;
+  union {
+    __u32 data_len;
+    __u32 vec_cnt;
+  };
   __u32 cdw10;
   __u32 cdw11;
   __u32 cdw12;
@@ -84,4 +87,5 @@
 #define NVME_IOCTL_RESCAN _IO('N', 0x46)
 #define NVME_IOCTL_ADMIN64_CMD _IOWR('N', 0x47, struct nvme_passthru_cmd64)
 #define NVME_IOCTL_IO64_CMD _IOWR('N', 0x48, struct nvme_passthru_cmd64)
+#define NVME_IOCTL_IO64_CMD_VEC _IOWR('N', 0x49, struct nvme_passthru_cmd64)
 #endif
diff --git a/libc/kernel/uapi/linux/omap3isp.h b/libc/kernel/uapi/linux/omap3isp.h
index d2eceb7..53345e3 100644
--- a/libc/kernel/uapi/linux/omap3isp.h
+++ b/libc/kernel/uapi/linux/omap3isp.h
@@ -89,10 +89,11 @@
 struct omap3isp_stat_data {
   struct timeval ts;
   void __user * buf;
-  __u32 buf_size;
+  __struct_group(, frame,, __u32 buf_size;
   __u16 frame_number;
   __u16 cur_frame;
   __u16 config_counter;
+ );
 };
 #define OMAP3ISP_HIST_BINS_32 0
 #define OMAP3ISP_HIST_BINS_64 1
diff --git a/libc/kernel/uapi/linux/openvswitch.h b/libc/kernel/uapi/linux/openvswitch.h
index 1f8ae17..c7d719c 100644
--- a/libc/kernel/uapi/linux/openvswitch.h
+++ b/libc/kernel/uapi/linux/openvswitch.h
@@ -190,6 +190,10 @@
   OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4,
   OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6,
   OVS_KEY_ATTR_NSH,
+  OVS_KEY_ATTR_PACKET_TYPE,
+  OVS_KEY_ATTR_ND_EXTENSIONS,
+  OVS_KEY_ATTR_TUNNEL_INFO,
+  OVS_KEY_ATTR_IPV6_EXTHDRS,
   __OVS_KEY_ATTR_MAX
 };
 #define OVS_KEY_ATTR_MAX (__OVS_KEY_ATTR_MAX - 1)
@@ -245,6 +249,9 @@
   __u8 ipv6_hlimit;
   __u8 ipv6_frag;
 };
+struct ovs_key_ipv6_exthdrs {
+  __u16 hdrs;
+};
 struct ovs_key_tcp {
   __be16 tcp_src;
   __be16 tcp_dst;
diff --git a/libc/kernel/uapi/linux/perf_event.h b/libc/kernel/uapi/linux/perf_event.h
index b022586..bcc4e97 100644
--- a/libc/kernel/uapi/linux/perf_event.h
+++ b/libc/kernel/uapi/linux/perf_event.h
@@ -165,6 +165,8 @@
   PERF_BR_SYSRET = 8,
   PERF_BR_COND_CALL = 9,
   PERF_BR_COND_RET = 10,
+  PERF_BR_ERET = 11,
+  PERF_BR_IRQ = 12,
   PERF_BR_MAX,
 };
 #define PERF_SAMPLE_BRANCH_PLM_ALL (PERF_SAMPLE_BRANCH_USER | PERF_SAMPLE_BRANCH_KERNEL | PERF_SAMPLE_BRANCH_HV)
diff --git a/libc/kernel/uapi/linux/pkt_cls.h b/libc/kernel/uapi/linux/pkt_cls.h
index 9fd89e0..58d8205 100644
--- a/libc/kernel/uapi/linux/pkt_cls.h
+++ b/libc/kernel/uapi/linux/pkt_cls.h
@@ -476,6 +476,7 @@
   TCA_FLOWER_KEY_ENC_OPTS_GENEVE,
   TCA_FLOWER_KEY_ENC_OPTS_VXLAN,
   TCA_FLOWER_KEY_ENC_OPTS_ERSPAN,
+  TCA_FLOWER_KEY_ENC_OPTS_GTP,
   __TCA_FLOWER_KEY_ENC_OPTS_MAX,
 };
 #define TCA_FLOWER_KEY_ENC_OPTS_MAX (__TCA_FLOWER_KEY_ENC_OPTS_MAX - 1)
@@ -503,6 +504,13 @@
 };
 #define TCA_FLOWER_KEY_ENC_OPT_ERSPAN_MAX (__TCA_FLOWER_KEY_ENC_OPT_ERSPAN_MAX - 1)
 enum {
+  TCA_FLOWER_KEY_ENC_OPT_GTP_UNSPEC,
+  TCA_FLOWER_KEY_ENC_OPT_GTP_PDU_TYPE,
+  TCA_FLOWER_KEY_ENC_OPT_GTP_QFI,
+  __TCA_FLOWER_KEY_ENC_OPT_GTP_MAX,
+};
+#define TCA_FLOWER_KEY_ENC_OPT_GTP_MAX (__TCA_FLOWER_KEY_ENC_OPT_GTP_MAX - 1)
+enum {
   TCA_FLOWER_KEY_MPLS_OPTS_UNSPEC,
   TCA_FLOWER_KEY_MPLS_OPTS_LSE,
   __TCA_FLOWER_KEY_MPLS_OPTS_MAX,
diff --git a/libc/kernel/uapi/linux/psci.h b/libc/kernel/uapi/linux/psci.h
index bc522e7..31e7465 100644
--- a/libc/kernel/uapi/linux/psci.h
+++ b/libc/kernel/uapi/linux/psci.h
@@ -60,6 +60,8 @@
 #define PSCI_0_2_TOS_UP_MIGRATE 0
 #define PSCI_0_2_TOS_UP_NO_MIGRATE 1
 #define PSCI_0_2_TOS_MP 2
+#define PSCI_1_1_RESET_TYPE_SYSTEM_WARM_RESET 0
+#define PSCI_1_1_RESET_TYPE_VENDOR_START 0x80000000U
 #define PSCI_VERSION_MAJOR_SHIFT 16
 #define PSCI_VERSION_MINOR_MASK ((1U << PSCI_VERSION_MAJOR_SHIFT) - 1)
 #define PSCI_VERSION_MAJOR_MASK ~PSCI_VERSION_MINOR_MASK
diff --git a/libc/kernel/uapi/linux/reiserfs_xattr.h b/libc/kernel/uapi/linux/reiserfs_xattr.h
index 36d31f6..16a7a08 100644
--- a/libc/kernel/uapi/linux/reiserfs_xattr.h
+++ b/libc/kernel/uapi/linux/reiserfs_xattr.h
@@ -27,6 +27,6 @@
 struct reiserfs_security_handle {
   const char * name;
   void * value;
-  size_t length;
+  __kernel_size_t length;
 };
 #endif
diff --git a/libc/kernel/uapi/linux/rfkill.h b/libc/kernel/uapi/linux/rfkill.h
index 6020baf..b90e67c 100644
--- a/libc/kernel/uapi/linux/rfkill.h
+++ b/libc/kernel/uapi/linux/rfkill.h
@@ -63,4 +63,6 @@
 #define RFKILL_IOC_MAGIC 'R'
 #define RFKILL_IOC_NOINPUT 1
 #define RFKILL_IOCTL_NOINPUT _IO(RFKILL_IOC_MAGIC, RFKILL_IOC_NOINPUT)
+#define RFKILL_IOC_MAX_SIZE 2
+#define RFKILL_IOCTL_MAX_SIZE _IOW(RFKILL_IOC_MAGIC, RFKILL_IOC_MAX_SIZE, __u32)
 #endif
diff --git a/libc/kernel/uapi/linux/rpmsg.h b/libc/kernel/uapi/linux/rpmsg.h
index c5b5a76..9ceccdd 100644
--- a/libc/kernel/uapi/linux/rpmsg.h
+++ b/libc/kernel/uapi/linux/rpmsg.h
@@ -28,4 +28,6 @@
 };
 #define RPMSG_CREATE_EPT_IOCTL _IOW(0xb5, 0x1, struct rpmsg_endpoint_info)
 #define RPMSG_DESTROY_EPT_IOCTL _IO(0xb5, 0x2)
+#define RPMSG_CREATE_DEV_IOCTL _IOW(0xb5, 0x3, struct rpmsg_endpoint_info)
+#define RPMSG_RELEASE_DEV_IOCTL _IOW(0xb5, 0x4, struct rpmsg_endpoint_info)
 #endif
diff --git a/libc/kernel/uapi/linux/rseq.h b/libc/kernel/uapi/linux/rseq.h
index ba0ceb1..29a9457 100644
--- a/libc/kernel/uapi/linux/rseq.h
+++ b/libc/kernel/uapi/linux/rseq.h
@@ -47,22 +47,7 @@
 struct rseq {
   __u32 cpu_id_start;
   __u32 cpu_id;
-  union {
-    __u64 ptr64;
-#ifdef __LP64__
-    __u64 ptr;
-#else
-    struct {
-#if defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN || defined(__BIG_ENDIAN)
-      __u32 padding;
-      __u32 ptr32;
-#else
-      __u32 ptr32;
-      __u32 padding;
-#endif
-    } ptr;
-#endif
-  } rseq_cs;
+  __u64 rseq_cs;
   __u32 flags;
 } __attribute__((aligned(4 * sizeof(__u64))));
 #endif
diff --git a/libc/kernel/uapi/linux/rtc.h b/libc/kernel/uapi/linux/rtc.h
index cf5f22a..d75bc45 100644
--- a/libc/kernel/uapi/linux/rtc.h
+++ b/libc/kernel/uapi/linux/rtc.h
@@ -96,7 +96,8 @@
 #define RTC_FEATURE_UPDATE_INTERRUPT 4
 #define RTC_FEATURE_CORRECTION 5
 #define RTC_FEATURE_BACKUP_SWITCH_MODE 6
-#define RTC_FEATURE_CNT 7
+#define RTC_FEATURE_ALARM_WAKEUP_ONLY 7
+#define RTC_FEATURE_CNT 8
 #define RTC_PARAM_FEATURES 0
 #define RTC_PARAM_CORRECTION 1
 #define RTC_PARAM_BACKUP_SWITCH_MODE 2
diff --git a/libc/kernel/uapi/linux/rtnetlink.h b/libc/kernel/uapi/linux/rtnetlink.h
index 91c3ee4..321e487 100644
--- a/libc/kernel/uapi/linux/rtnetlink.h
+++ b/libc/kernel/uapi/linux/rtnetlink.h
@@ -131,6 +131,8 @@
 #define RTM_NEWSTATS RTM_NEWSTATS
   RTM_GETSTATS = 94,
 #define RTM_GETSTATS RTM_GETSTATS
+  RTM_SETSTATS,
+#define RTM_SETSTATS RTM_SETSTATS
   RTM_NEWCACHEREPORT = 96,
 #define RTM_NEWCACHEREPORT RTM_NEWCACHEREPORT
   RTM_NEWCHAIN = 100,
@@ -163,6 +165,12 @@
 #define RTM_DELNEXTHOPBUCKET RTM_DELNEXTHOPBUCKET
   RTM_GETNEXTHOPBUCKET,
 #define RTM_GETNEXTHOPBUCKET RTM_GETNEXTHOPBUCKET
+  RTM_NEWTUNNEL = 120,
+#define RTM_NEWTUNNEL RTM_NEWTUNNEL
+  RTM_DELTUNNEL,
+#define RTM_DELTUNNEL RTM_DELTUNNEL
+  RTM_GETTUNNEL,
+#define RTM_GETTUNNEL RTM_GETTUNNEL
   __RTM_MAX,
 #define RTM_MAX (((__RTM_MAX + 3) & ~3) - 1)
 };
@@ -561,6 +569,10 @@
 #define RTNLGRP_BRVLAN RTNLGRP_BRVLAN
   RTNLGRP_MCTP_IFADDR,
 #define RTNLGRP_MCTP_IFADDR RTNLGRP_MCTP_IFADDR
+  RTNLGRP_TUNNEL,
+#define RTNLGRP_TUNNEL RTNLGRP_TUNNEL
+  RTNLGRP_STATS,
+#define RTNLGRP_STATS RTNLGRP_STATS
   __RTNLGRP_MAX
 };
 #define RTNLGRP_MAX (__RTNLGRP_MAX - 1)
@@ -592,4 +604,5 @@
 #define RTEXT_FILTER_MRP (1 << 4)
 #define RTEXT_FILTER_CFM_CONFIG (1 << 5)
 #define RTEXT_FILTER_CFM_STATUS (1 << 6)
+#define RTEXT_FILTER_MST (1 << 7)
 #endif
diff --git a/libc/kernel/uapi/linux/serial_core.h b/libc/kernel/uapi/linux/serial_core.h
index 0caf698..b99c7d4 100644
--- a/libc/kernel/uapi/linux/serial_core.h
+++ b/libc/kernel/uapi/linux/serial_core.h
@@ -47,6 +47,7 @@
 #define PORT_SUNSAB 39
 #define PORT_NPCM 40
 #define PORT_TEGRA_TCU 41
+#define PORT_ASPEED_VUART 42
 #define PORT_PCH_8LINE 44
 #define PORT_PCH_2LINE 45
 #define PORT_DZ 46
@@ -122,4 +123,5 @@
 #define PORT_SIFIVE_V0 120
 #define PORT_SUNIX 121
 #define PORT_LINFLEXUART 122
+#define PORT_SUNPLUS 123
 #endif
diff --git a/libc/kernel/uapi/linux/smc.h b/libc/kernel/uapi/linux/smc.h
index 01494da..be6b71f 100644
--- a/libc/kernel/uapi/linux/smc.h
+++ b/libc/kernel/uapi/linux/smc.h
@@ -57,6 +57,9 @@
   SMC_NETLINK_DUMP_SEID,
   SMC_NETLINK_ENABLE_SEID,
   SMC_NETLINK_DISABLE_SEID,
+  SMC_NETLINK_DUMP_HS_LIMITATION,
+  SMC_NETLINK_ENABLE_HS_LIMITATION,
+  SMC_NETLINK_DISABLE_HS_LIMITATION,
 };
 enum {
   SMC_GEN_UNSPEC,
@@ -249,4 +252,11 @@
   __SMC_NLA_SEID_TABLE_MAX,
   SMC_NLA_SEID_TABLE_MAX = __SMC_NLA_SEID_TABLE_MAX - 1
 };
+enum {
+  SMC_NLA_HS_LIMITATION_UNSPEC,
+  SMC_NLA_HS_LIMITATION_ENABLED,
+  __SMC_NLA_HS_LIMITATION_MAX,
+  SMC_NLA_HS_LIMITATION_MAX = __SMC_NLA_HS_LIMITATION_MAX - 1
+};
+#define SMC_LIMIT_HS 1
 #endif
diff --git a/libc/kernel/uapi/linux/socket.h b/libc/kernel/uapi/linux/socket.h
index be16548..49dce45 100644
--- a/libc/kernel/uapi/linux/socket.h
+++ b/libc/kernel/uapi/linux/socket.h
@@ -32,4 +32,7 @@
 #define SOCK_SNDBUF_LOCK 1
 #define SOCK_RCVBUF_LOCK 2
 #define SOCK_BUF_LOCK_MASK (SOCK_SNDBUF_LOCK | SOCK_RCVBUF_LOCK)
+#define SOCK_TXREHASH_DEFAULT ((u8) - 1)
+#define SOCK_TXREHASH_DISABLED 0
+#define SOCK_TXREHASH_ENABLED 1
 #endif
diff --git a/libc/kernel/uapi/linux/stddef.h b/libc/kernel/uapi/linux/stddef.h
index d5cdf80..6bc6925 100644
--- a/libc/kernel/uapi/linux/stddef.h
+++ b/libc/kernel/uapi/linux/stddef.h
@@ -16,9 +16,12 @@
  ***
  ****************************************************************************
  ****************************************************************************/
+#ifndef _UAPI_LINUX_STDDEF_H
+#define _UAPI_LINUX_STDDEF_H
 #include <linux/compiler_types.h>
 #ifndef __always_inline
 #define __always_inline inline
 #endif
 #define __struct_group(TAG,NAME,ATTRS,MEMBERS...) union { struct { MEMBERS } ATTRS; struct TAG { MEMBERS } ATTRS NAME; }
 #define __DECLARE_FLEX_ARRAY(TYPE,NAME) struct { struct { } __empty_ ##NAME; TYPE NAME[]; }
+#endif
diff --git a/libc/kernel/uapi/linux/thermal.h b/libc/kernel/uapi/linux/thermal.h
index 72ea378..2f9dccb 100644
--- a/libc/kernel/uapi/linux/thermal.h
+++ b/libc/kernel/uapi/linux/thermal.h
@@ -54,6 +54,10 @@
   THERMAL_GENL_ATTR_CDEV_MAX_STATE,
   THERMAL_GENL_ATTR_CDEV_NAME,
   THERMAL_GENL_ATTR_GOV_NAME,
+  THERMAL_GENL_ATTR_CPU_CAPABILITY,
+  THERMAL_GENL_ATTR_CPU_CAPABILITY_ID,
+  THERMAL_GENL_ATTR_CPU_CAPABILITY_PERFORMANCE,
+  THERMAL_GENL_ATTR_CPU_CAPABILITY_EFFICIENCY,
   __THERMAL_GENL_ATTR_MAX,
 };
 #define THERMAL_GENL_ATTR_MAX (__THERMAL_GENL_ATTR_MAX - 1)
@@ -77,6 +81,7 @@
   THERMAL_GENL_EVENT_CDEV_DELETE,
   THERMAL_GENL_EVENT_CDEV_STATE_UPDATE,
   THERMAL_GENL_EVENT_TZ_GOV_CHANGE,
+  THERMAL_GENL_EVENT_CPU_CAPABILITY_CHANGE,
   __THERMAL_GENL_EVENT_MAX,
 };
 #define THERMAL_GENL_EVENT_MAX (__THERMAL_GENL_EVENT_MAX - 1)
diff --git a/libc/kernel/uapi/linux/tipc_config.h b/libc/kernel/uapi/linux/tipc_config.h
index a371e37..c6ee1d1 100644
--- a/libc/kernel/uapi/linux/tipc_config.h
+++ b/libc/kernel/uapi/linux/tipc_config.h
@@ -22,7 +22,6 @@
 #include <linux/string.h>
 #include <linux/tipc.h>
 #include <asm/byteorder.h>
-#include <arpa/inet.h>
 #define TIPC_CMD_NOOP 0x0000
 #define TIPC_CMD_GET_NODES 0x0001
 #define TIPC_CMD_GET_MEDIA_NAMES 0x0002
diff --git a/libc/kernel/uapi/linux/tty.h b/libc/kernel/uapi/linux/tty.h
index dcce572..fb2379e 100644
--- a/libc/kernel/uapi/linux/tty.h
+++ b/libc/kernel/uapi/linux/tty.h
@@ -18,7 +18,6 @@
  ****************************************************************************/
 #ifndef _UAPI_LINUX_TTY_H
 #define _UAPI_LINUX_TTY_H
-#define NR_LDISCS 30
 #define N_TTY 0
 #define N_SLIP 1
 #define N_MOUSE 2
@@ -48,4 +47,6 @@
 #define N_SPEAKUP 26
 #define N_NULL 27
 #define N_MCTP 28
+#define N_DEVELOPMENT 29
+#define NR_LDISCS 30
 #endif
diff --git a/libc/kernel/uapi/linux/types.h b/libc/kernel/uapi/linux/types.h
index 9145e66..ce82a24 100644
--- a/libc/kernel/uapi/linux/types.h
+++ b/libc/kernel/uapi/linux/types.h
@@ -21,8 +21,7 @@
 #include <asm/types.h>
 #ifndef __ASSEMBLY__
 #include <linux/posix_types.h>
-#define __bitwise__
-#define __bitwise __bitwise__
+#define __bitwise
 typedef __u16 __bitwise __le16;
 typedef __u16 __bitwise __be16;
 typedef __u32 __bitwise __le32;
diff --git a/libc/kernel/uapi/linux/userfaultfd.h b/libc/kernel/uapi/linux/userfaultfd.h
index ca7b7a5..3727d0a 100644
--- a/libc/kernel/uapi/linux/userfaultfd.h
+++ b/libc/kernel/uapi/linux/userfaultfd.h
@@ -21,7 +21,7 @@
 #include <linux/types.h>
 #define UFFD_API ((__u64) 0xAA)
 #define UFFD_API_REGISTER_MODES (UFFDIO_REGISTER_MODE_MISSING | UFFDIO_REGISTER_MODE_WP | UFFDIO_REGISTER_MODE_MINOR)
-#define UFFD_API_FEATURES (UFFD_FEATURE_PAGEFAULT_FLAG_WP | UFFD_FEATURE_EVENT_FORK | UFFD_FEATURE_EVENT_REMAP | UFFD_FEATURE_EVENT_REMOVE | UFFD_FEATURE_EVENT_UNMAP | UFFD_FEATURE_MISSING_HUGETLBFS | UFFD_FEATURE_MISSING_SHMEM | UFFD_FEATURE_SIGBUS | UFFD_FEATURE_THREAD_ID | UFFD_FEATURE_MINOR_HUGETLBFS | UFFD_FEATURE_MINOR_SHMEM)
+#define UFFD_API_FEATURES (UFFD_FEATURE_PAGEFAULT_FLAG_WP | UFFD_FEATURE_EVENT_FORK | UFFD_FEATURE_EVENT_REMAP | UFFD_FEATURE_EVENT_REMOVE | UFFD_FEATURE_EVENT_UNMAP | UFFD_FEATURE_MISSING_HUGETLBFS | UFFD_FEATURE_MISSING_SHMEM | UFFD_FEATURE_SIGBUS | UFFD_FEATURE_THREAD_ID | UFFD_FEATURE_MINOR_HUGETLBFS | UFFD_FEATURE_MINOR_SHMEM | UFFD_FEATURE_EXACT_ADDRESS)
 #define UFFD_API_IOCTLS ((__u64) 1 << _UFFDIO_REGISTER | (__u64) 1 << _UFFDIO_UNREGISTER | (__u64) 1 << _UFFDIO_API)
 #define UFFD_API_RANGE_IOCTLS ((__u64) 1 << _UFFDIO_WAKE | (__u64) 1 << _UFFDIO_COPY | (__u64) 1 << _UFFDIO_ZEROPAGE | (__u64) 1 << _UFFDIO_WRITEPROTECT | (__u64) 1 << _UFFDIO_CONTINUE)
 #define UFFD_API_RANGE_IOCTLS_BASIC ((__u64) 1 << _UFFDIO_WAKE | (__u64) 1 << _UFFDIO_COPY | (__u64) 1 << _UFFDIO_CONTINUE)
@@ -95,6 +95,7 @@
 #define UFFD_FEATURE_THREAD_ID (1 << 8)
 #define UFFD_FEATURE_MINOR_HUGETLBFS (1 << 9)
 #define UFFD_FEATURE_MINOR_SHMEM (1 << 10)
+#define UFFD_FEATURE_EXACT_ADDRESS (1 << 11)
   __u64 features;
   __u64 ioctls;
 };
diff --git a/libc/kernel/uapi/linux/v4l2-controls.h b/libc/kernel/uapi/linux/v4l2-controls.h
index 1a11355..43014ef 100644
--- a/libc/kernel/uapi/linux/v4l2-controls.h
+++ b/libc/kernel/uapi/linux/v4l2-controls.h
@@ -119,6 +119,7 @@
 #define V4L2_CID_USER_CODA_BASE (V4L2_CID_USER_BASE + 0x10e0)
 #define V4L2_CID_USER_CCS_BASE (V4L2_CID_USER_BASE + 0x10f0)
 #define V4L2_CID_USER_ALLEGRO_BASE (V4L2_CID_USER_BASE + 0x1170)
+#define V4L2_CID_USER_ISL7998X_BASE (V4L2_CID_USER_BASE + 0x1180)
 #define V4L2_CID_CODEC_BASE (V4L2_CTRL_CLASS_CODEC | 0x900)
 #define V4L2_CID_CODEC_CLASS (V4L2_CTRL_CLASS_CODEC | 1)
 #define V4L2_CID_MPEG_STREAM_TYPE (V4L2_CID_CODEC_BASE + 0)
@@ -1153,6 +1154,8 @@
 #define V4L2_H264_DECODE_PARAM_FLAG_IDR_PIC 0x01
 #define V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC 0x02
 #define V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD 0x04
+#define V4L2_H264_DECODE_PARAM_FLAG_PFRAME 0x08
+#define V4L2_H264_DECODE_PARAM_FLAG_BFRAME 0x10
 #define V4L2_CID_STATELESS_H264_DECODE_PARAMS (V4L2_CID_CODEC_STATELESS_BASE + 7)
 struct v4l2_ctrl_h264_decode_params {
   struct v4l2_h264_dpb_entry dpb[V4L2_H264_NUM_DPB_ENTRIES];
diff --git a/libc/kernel/uapi/linux/version.h b/libc/kernel/uapi/linux/version.h
index 2dfd696..2677406 100644
--- a/libc/kernel/uapi/linux/version.h
+++ b/libc/kernel/uapi/linux/version.h
@@ -16,8 +16,8 @@
  ***
  ****************************************************************************
  ****************************************************************************/
-#define LINUX_VERSION_CODE 332032
+#define LINUX_VERSION_CODE 332288
 #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + ((c) > 255 ? 255 : (c)))
 #define LINUX_VERSION_MAJOR 5
-#define LINUX_VERSION_PATCHLEVEL 17
+#define LINUX_VERSION_PATCHLEVEL 18
 #define LINUX_VERSION_SUBLEVEL 0
diff --git a/libc/kernel/uapi/linux/vfio.h b/libc/kernel/uapi/linux/vfio.h
index e0f322b..8075408 100644
--- a/libc/kernel/uapi/linux/vfio.h
+++ b/libc/kernel/uapi/linux/vfio.h
@@ -110,7 +110,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_TYPE_MIGRATION_DEPRECATED (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)
@@ -130,17 +130,17 @@
 #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)
+#define VFIO_REGION_SUBTYPE_MIGRATION_DEPRECATED (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)
+#define VFIO_DEVICE_STATE_V1_STOP (0)
+#define VFIO_DEVICE_STATE_V1_RUNNING (1 << 0)
+#define VFIO_DEVICE_STATE_V1_SAVING (1 << 1)
+#define VFIO_DEVICE_STATE_V1_RESUMING (1 << 2)
+#define VFIO_DEVICE_STATE_MASK (VFIO_DEVICE_STATE_V1_RUNNING | VFIO_DEVICE_STATE_V1_SAVING | VFIO_DEVICE_STATE_V1_RESUMING)
+#define VFIO_DEVICE_STATE_VALID(state) (state & VFIO_DEVICE_STATE_V1_RESUMING ? (state & VFIO_DEVICE_STATE_MASK) == VFIO_DEVICE_STATE_V1_RESUMING : 1)
+#define VFIO_DEVICE_STATE_IS_ERROR(state) ((state & VFIO_DEVICE_STATE_MASK) == (VFIO_DEVICE_STATE_V1_SAVING | VFIO_DEVICE_STATE_V1_RESUMING))
+#define VFIO_DEVICE_STATE_SET_ERROR(state) ((state & ~VFIO_DEVICE_STATE_MASK) | VFIO_DEVICE_STATE_V1_SAVING | VFIO_DEVICE_STATE_V1_RESUMING)
   __u32 reserved;
   __u64 pending_bytes;
   __u64 data_offset;
@@ -285,6 +285,25 @@
 };
 #define VFIO_DEVICE_FEATURE _IO(VFIO_TYPE, VFIO_BASE + 17)
 #define VFIO_DEVICE_FEATURE_PCI_VF_TOKEN (0)
+struct vfio_device_feature_migration {
+  __aligned_u64 flags;
+#define VFIO_MIGRATION_STOP_COPY (1 << 0)
+#define VFIO_MIGRATION_P2P (1 << 1)
+};
+#define VFIO_DEVICE_FEATURE_MIGRATION 1
+struct vfio_device_feature_mig_state {
+  __u32 device_state;
+  __s32 data_fd;
+};
+#define VFIO_DEVICE_FEATURE_MIG_DEVICE_STATE 2
+enum vfio_device_mig_state {
+  VFIO_DEVICE_STATE_ERROR = 0,
+  VFIO_DEVICE_STATE_STOP = 1,
+  VFIO_DEVICE_STATE_RUNNING = 2,
+  VFIO_DEVICE_STATE_STOP_COPY = 3,
+  VFIO_DEVICE_STATE_RESUMING = 4,
+  VFIO_DEVICE_STATE_RUNNING_P2P = 5,
+};
 struct vfio_iommu_type1_info {
   __u32 argsz;
   __u32 flags;
diff --git a/libc/kernel/uapi/linux/vhost.h b/libc/kernel/uapi/linux/vhost.h
index 53b01c4..7769beb 100644
--- a/libc/kernel/uapi/linux/vhost.h
+++ b/libc/kernel/uapi/linux/vhost.h
@@ -64,4 +64,6 @@
 #define VHOST_VDPA_GET_VRING_NUM _IOR(VHOST_VIRTIO, 0x76, __u16)
 #define VHOST_VDPA_SET_CONFIG_CALL _IOW(VHOST_VIRTIO, 0x77, int)
 #define VHOST_VDPA_GET_IOVA_RANGE _IOR(VHOST_VIRTIO, 0x78, struct vhost_vdpa_iova_range)
+#define VHOST_VDPA_GET_CONFIG_SIZE _IOR(VHOST_VIRTIO, 0x79, __u32)
+#define VHOST_VDPA_GET_VQS_COUNT _IOR(VHOST_VIRTIO, 0x80, __u32)
 #endif
diff --git a/libc/kernel/uapi/linux/videodev2.h b/libc/kernel/uapi/linux/videodev2.h
index 74bd328..55c1a95 100644
--- a/libc/kernel/uapi/linux/videodev2.h
+++ b/libc/kernel/uapi/linux/videodev2.h
@@ -24,12 +24,7 @@
 #include <linux/types.h>
 #include <linux/v4l2-common.h>
 #include <linux/v4l2-controls.h>
-/* ---------------------------------------------------
- * This value manually changed due to b/228783882.
- * Next kernel update should keep this value as is.
- */
 #define VIDEO_MAX_FRAME 64
-/* --------------------------------------------------- */
 #define VIDEO_MAX_PLANES 8
 #define v4l2_fourcc(a,b,c,d) ((__u32) (a) | ((__u32) (b) << 8) | ((__u32) (c) << 16) | ((__u32) (d) << 24))
 #define v4l2_fourcc_be(a,b,c,d) (v4l2_fourcc(a, b, c, d) | (1U << 31))
@@ -305,6 +300,8 @@
 #define V4L2_PIX_FMT_NV12_32L32 v4l2_fourcc('S', 'T', '1', '2')
 #define V4L2_PIX_FMT_NV12MT v4l2_fourcc('T', 'M', '1', '2')
 #define V4L2_PIX_FMT_NV12MT_16X16 v4l2_fourcc('V', 'M', '1', '2')
+#define V4L2_PIX_FMT_NV12M_8L128 v4l2_fourcc('N', 'A', '1', '2')
+#define V4L2_PIX_FMT_NV12M_10BE_8L128 v4l2_fourcc_be('N', 'T', '1', '2')
 #define V4L2_PIX_FMT_SBGGR8 v4l2_fourcc('B', 'A', '8', '1')
 #define V4L2_PIX_FMT_SGBRG8 v4l2_fourcc('G', 'B', 'R', 'G')
 #define V4L2_PIX_FMT_SGRBG8 v4l2_fourcc('G', 'R', 'B', 'G')
diff --git a/libc/kernel/uapi/linux/virtio_config.h b/libc/kernel/uapi/linux/virtio_config.h
index 6198fd1..30e552b 100644
--- a/libc/kernel/uapi/linux/virtio_config.h
+++ b/libc/kernel/uapi/linux/virtio_config.h
@@ -35,6 +35,7 @@
 #define VIRTIO_F_ACCESS_PLATFORM 33
 #define VIRTIO_F_IOMMU_PLATFORM VIRTIO_F_ACCESS_PLATFORM
 #define VIRTIO_F_RING_PACKED 34
+#define VIRTIO_F_IN_ORDER 35
 #define VIRTIO_F_ORDER_PLATFORM 36
 #define VIRTIO_F_SR_IOV 37
 #endif
diff --git a/libc/kernel/uapi/linux/virtio_crypto.h b/libc/kernel/uapi/linux/virtio_crypto.h
index 2ce760f..7d7561d 100644
--- a/libc/kernel/uapi/linux/virtio_crypto.h
+++ b/libc/kernel/uapi/linux/virtio_crypto.h
@@ -26,6 +26,7 @@
 #define VIRTIO_CRYPTO_SERVICE_HASH 1
 #define VIRTIO_CRYPTO_SERVICE_MAC 2
 #define VIRTIO_CRYPTO_SERVICE_AEAD 3
+#define VIRTIO_CRYPTO_SERVICE_AKCIPHER 4
 #define VIRTIO_CRYPTO_OPCODE(service,op) (((service) << 8) | (op))
 struct virtio_crypto_ctrl_header {
 #define VIRTIO_CRYPTO_CIPHER_CREATE_SESSION VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_CIPHER, 0x02)
@@ -36,6 +37,8 @@
 #define VIRTIO_CRYPTO_MAC_DESTROY_SESSION VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_MAC, 0x03)
 #define VIRTIO_CRYPTO_AEAD_CREATE_SESSION VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AEAD, 0x02)
 #define VIRTIO_CRYPTO_AEAD_DESTROY_SESSION VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AEAD, 0x03)
+#define VIRTIO_CRYPTO_AKCIPHER_CREATE_SESSION VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AKCIPHER, 0x04)
+#define VIRTIO_CRYPTO_AKCIPHER_DESTROY_SESSION VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AKCIPHER, 0x05)
   __le32 opcode;
   __le32 algo;
   __le32 flag;
@@ -137,6 +140,51 @@
   struct virtio_crypto_aead_session_para para;
   __u8 padding[32];
 };
+struct virtio_crypto_rsa_session_para {
+#define VIRTIO_CRYPTO_RSA_RAW_PADDING 0
+#define VIRTIO_CRYPTO_RSA_PKCS1_PADDING 1
+  __le32 padding_algo;
+#define VIRTIO_CRYPTO_RSA_NO_HASH 0
+#define VIRTIO_CRYPTO_RSA_MD2 1
+#define VIRTIO_CRYPTO_RSA_MD3 2
+#define VIRTIO_CRYPTO_RSA_MD4 3
+#define VIRTIO_CRYPTO_RSA_MD5 4
+#define VIRTIO_CRYPTO_RSA_SHA1 5
+#define VIRTIO_CRYPTO_RSA_SHA256 6
+#define VIRTIO_CRYPTO_RSA_SHA384 7
+#define VIRTIO_CRYPTO_RSA_SHA512 8
+#define VIRTIO_CRYPTO_RSA_SHA224 9
+  __le32 hash_algo;
+};
+struct virtio_crypto_ecdsa_session_para {
+#define VIRTIO_CRYPTO_CURVE_UNKNOWN 0
+#define VIRTIO_CRYPTO_CURVE_NIST_P192 1
+#define VIRTIO_CRYPTO_CURVE_NIST_P224 2
+#define VIRTIO_CRYPTO_CURVE_NIST_P256 3
+#define VIRTIO_CRYPTO_CURVE_NIST_P384 4
+#define VIRTIO_CRYPTO_CURVE_NIST_P521 5
+  __le32 curve_id;
+  __le32 padding;
+};
+struct virtio_crypto_akcipher_session_para {
+#define VIRTIO_CRYPTO_NO_AKCIPHER 0
+#define VIRTIO_CRYPTO_AKCIPHER_RSA 1
+#define VIRTIO_CRYPTO_AKCIPHER_DSA 2
+#define VIRTIO_CRYPTO_AKCIPHER_ECDSA 3
+  __le32 algo;
+#define VIRTIO_CRYPTO_AKCIPHER_KEY_TYPE_PUBLIC 1
+#define VIRTIO_CRYPTO_AKCIPHER_KEY_TYPE_PRIVATE 2
+  __le32 keytype;
+  __le32 keylen;
+  union {
+    struct virtio_crypto_rsa_session_para rsa;
+    struct virtio_crypto_ecdsa_session_para ecdsa;
+  } u;
+};
+struct virtio_crypto_akcipher_create_session_req {
+  struct virtio_crypto_akcipher_session_para para;
+  __u8 padding[36];
+};
 struct virtio_crypto_alg_chain_session_para {
 #define VIRTIO_CRYPTO_SYM_ALG_CHAIN_ORDER_HASH_THEN_CIPHER 1
 #define VIRTIO_CRYPTO_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH 2
@@ -180,6 +228,7 @@
     struct virtio_crypto_hash_create_session_req hash_create_session;
     struct virtio_crypto_mac_create_session_req mac_create_session;
     struct virtio_crypto_aead_create_session_req aead_create_session;
+    struct virtio_crypto_akcipher_create_session_req akcipher_create_session;
     struct virtio_crypto_destroy_session_req destroy_session;
     __u8 padding[56];
   } u;
@@ -191,6 +240,10 @@
 #define VIRTIO_CRYPTO_MAC VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_MAC, 0x00)
 #define VIRTIO_CRYPTO_AEAD_ENCRYPT VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AEAD, 0x00)
 #define VIRTIO_CRYPTO_AEAD_DECRYPT VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AEAD, 0x01)
+#define VIRTIO_CRYPTO_AKCIPHER_ENCRYPT VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AKCIPHER, 0x00)
+#define VIRTIO_CRYPTO_AKCIPHER_DECRYPT VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AKCIPHER, 0x01)
+#define VIRTIO_CRYPTO_AKCIPHER_SIGN VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AKCIPHER, 0x02)
+#define VIRTIO_CRYPTO_AKCIPHER_VERIFY VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AKCIPHER, 0x03)
   __le32 opcode;
   __le32 algo;
   __le64 session_id;
@@ -256,6 +309,14 @@
   struct virtio_crypto_aead_para para;
   __u8 padding[32];
 };
+struct virtio_crypto_akcipher_para {
+  __le32 src_data_len;
+  __le32 dst_data_len;
+};
+struct virtio_crypto_akcipher_data_req {
+  struct virtio_crypto_akcipher_para para;
+  __u8 padding[40];
+};
 struct virtio_crypto_op_data_req {
   struct virtio_crypto_op_header header;
   union {
@@ -263,6 +324,7 @@
     struct virtio_crypto_hash_data_req hash_req;
     struct virtio_crypto_mac_data_req mac_req;
     struct virtio_crypto_aead_data_req aead_req;
+    struct virtio_crypto_akcipher_data_req akcipher_req;
     __u8 padding[48];
   } u;
 };
@@ -271,6 +333,8 @@
 #define VIRTIO_CRYPTO_BADMSG 2
 #define VIRTIO_CRYPTO_NOTSUPP 3
 #define VIRTIO_CRYPTO_INVSESS 4
+#define VIRTIO_CRYPTO_NOSPC 5
+#define VIRTIO_CRYPTO_KEY_REJECTED 6
 #define VIRTIO_CRYPTO_S_HW_READY (1 << 0)
 struct virtio_crypto_config {
   __le32 status;
@@ -284,7 +348,7 @@
   __le32 aead_algo;
   __le32 max_cipher_key_len;
   __le32 max_auth_key_len;
-  __le32 reserve;
+  __le32 akcipher_algo;
   __le64 max_size;
 };
 struct virtio_crypto_inhdr {
diff --git a/libc/kernel/uapi/linux/virtio_ids.h b/libc/kernel/uapi/linux/virtio_ids.h
index 2894700..b31ed93 100644
--- a/libc/kernel/uapi/linux/virtio_ids.h
+++ b/libc/kernel/uapi/linux/virtio_ids.h
@@ -57,11 +57,11 @@
 #define VIRTIO_ID_AUDIO_POLICY 39
 #define VIRTIO_ID_BT 40
 #define VIRTIO_ID_GPIO 41
-#define VIRTIO_TRANS_ID_NET 1000
-#define VIRTIO_TRANS_ID_BLOCK 1001
-#define VIRTIO_TRANS_ID_BALLOON 1002
-#define VIRTIO_TRANS_ID_CONSOLE 1003
-#define VIRTIO_TRANS_ID_SCSI 1004
-#define VIRTIO_TRANS_ID_RNG 1005
-#define VIRTIO_TRANS_ID_9P 1009
+#define VIRTIO_TRANS_ID_NET 0x1000
+#define VIRTIO_TRANS_ID_BLOCK 0x1001
+#define VIRTIO_TRANS_ID_BALLOON 0x1002
+#define VIRTIO_TRANS_ID_CONSOLE 0x1003
+#define VIRTIO_TRANS_ID_SCSI 0x1004
+#define VIRTIO_TRANS_ID_RNG 0x1005
+#define VIRTIO_TRANS_ID_9P 0x1009
 #endif
diff --git a/libc/kernel/uapi/misc/fastrpc.h b/libc/kernel/uapi/misc/fastrpc.h
index 62955ec..e82b961 100644
--- a/libc/kernel/uapi/misc/fastrpc.h
+++ b/libc/kernel/uapi/misc/fastrpc.h
@@ -27,11 +27,32 @@
 #define FASTRPC_IOCTL_MMAP _IOWR('R', 6, struct fastrpc_req_mmap)
 #define FASTRPC_IOCTL_MUNMAP _IOWR('R', 7, struct fastrpc_req_munmap)
 #define FASTRPC_IOCTL_INIT_ATTACH_SNS _IO('R', 8)
+#define FASTRPC_IOCTL_MEM_MAP _IOWR('R', 10, struct fastrpc_mem_map)
+#define FASTRPC_IOCTL_MEM_UNMAP _IOWR('R', 11, struct fastrpc_mem_unmap)
+#define FASTRPC_IOCTL_GET_DSP_INFO _IOWR('R', 13, struct fastrpc_ioctl_capability)
+enum fastrpc_map_flags {
+  FASTRPC_MAP_STATIC = 0,
+  FASTRPC_MAP_RESERVED,
+  FASTRPC_MAP_FD = 2,
+  FASTRPC_MAP_FD_DELAYED,
+  FASTRPC_MAP_FD_NOMAP = 16,
+  FASTRPC_MAP_MAX,
+};
+enum fastrpc_proc_attr {
+  FASTRPC_MODE_DEBUG = (1 << 0),
+  FASTRPC_MODE_PTRACE = (1 << 1),
+  FASTRPC_MODE_CRC = (1 << 2),
+  FASTRPC_MODE_UNSIGNED_MODULE = (1 << 3),
+  FASTRPC_MODE_ADAPTIVE_QOS = (1 << 4),
+  FASTRPC_MODE_SYSTEM_PROCESS = (1 << 5),
+  FASTRPC_MODE_PRIVILEGED = (1 << 6),
+};
+#define FASTRPC_ATTR_SECUREMAP (1)
 struct fastrpc_invoke_args {
   __u64 ptr;
   __u64 length;
   __s32 fd;
-  __u32 reserved;
+  __u32 attr;
 };
 struct fastrpc_invoke {
   __u32 handle;
@@ -57,8 +78,32 @@
   __u64 size;
   __u64 vaddrout;
 };
+struct fastrpc_mem_map {
+  __s32 version;
+  __s32 fd;
+  __s32 offset;
+  __u32 flags;
+  __u64 vaddrin;
+  __u64 length;
+  __u64 vaddrout;
+  __s32 attrs;
+  __s32 reserved[4];
+};
 struct fastrpc_req_munmap {
   __u64 vaddrout;
   __u64 size;
 };
+struct fastrpc_mem_unmap {
+  __s32 vesion;
+  __s32 fd;
+  __u64 vaddr;
+  __u64 length;
+  __s32 reserved[5];
+};
+struct fastrpc_ioctl_capability {
+  __u32 domain;
+  __u32 attribute_id;
+  __u32 capability;
+  __u32 reserved[4];
+};
 #endif
diff --git a/libc/kernel/uapi/misc/habanalabs.h b/libc/kernel/uapi/misc/habanalabs.h
index 6e3439a..f9e1bb9 100644
--- a/libc/kernel/uapi/misc/habanalabs.h
+++ b/libc/kernel/uapi/misc/habanalabs.h
@@ -24,6 +24,7 @@
 #define GAUDI_DRIVER_SRAM_RESERVED_SIZE_FROM_START 0x80
 #define GAUDI_FIRST_AVAILABLE_W_S_SYNC_OBJECT 144
 #define GAUDI_FIRST_AVAILABLE_W_S_MONITOR 72
+#define TS_MAX_ELEMENTS_NUM (1 << 20)
 enum goya_queue_id {
   GOYA_QUEUE_ID_DMA_0 = 0,
   GOYA_QUEUE_ID_DMA_1 = 1,
@@ -294,6 +295,9 @@
   __u8 card_name[HL_INFO_CARD_NAME_MAX_LEN];
   __u64 reserved2;
   __u64 dram_page_size;
+  __u32 reserved3;
+  __u16 number_of_user_interrupts;
+  __u16 pad2;
 };
 struct hl_info_dram_usage {
   __u64 dram_free_mem;
@@ -512,6 +516,7 @@
 #define HL_WAIT_CS_FLAGS_INTERRUPT_MASK 0xFFF00000
 #define HL_WAIT_CS_FLAGS_MULTI_CS 0x4
 #define HL_WAIT_CS_FLAGS_INTERRUPT_KERNEL_CQ 0x10
+#define HL_WAIT_CS_FLAGS_REGISTER_INTERRUPT 0x20
 #define HL_WAIT_MULTI_CS_LIST_MAX_LEN 32
 struct hl_wait_cs_in {
   union {
@@ -537,6 +542,8 @@
     __u64 interrupt_timeout_us;
   };
   __u64 cq_counters_offset;
+  __u64 timestamp_handle;
+  __u64 timestamp_offset;
 };
 #define HL_WAIT_CS_STATUS_COMPLETED 0
 #define HL_WAIT_CS_STATUS_BUSY 1
@@ -561,6 +568,7 @@
 #define HL_MEM_OP_UNMAP 3
 #define HL_MEM_OP_MAP_BLOCK 4
 #define HL_MEM_OP_EXPORT_DMABUF_FD 5
+#define HL_MEM_OP_TS_ALLOC 6
 #define HL_MEM_CONTIGUOUS 0x1
 #define HL_MEM_SHARED 0x2
 #define HL_MEM_USERPTR 0x4
@@ -569,6 +577,7 @@
   union {
     struct {
       __u64 mem_size;
+      __u64 page_size;
     } alloc;
     struct {
       __u64 handle;
@@ -596,7 +605,7 @@
   __u32 op;
   __u32 flags;
   __u32 ctx_id;
-  __u32 pad;
+  __u32 num_of_elements;
 };
 struct hl_mem_out {
   union {
diff --git a/libc/kernel/uapi/sound/sof/abi.h b/libc/kernel/uapi/sound/sof/abi.h
index 3af3c9d..810a0b4 100644
--- a/libc/kernel/uapi/sound/sof/abi.h
+++ b/libc/kernel/uapi/sound/sof/abi.h
@@ -19,8 +19,8 @@
 #ifndef __INCLUDE_UAPI_SOUND_SOF_ABI_H__
 #define __INCLUDE_UAPI_SOUND_SOF_ABI_H__
 #define SOF_ABI_MAJOR 3
-#define SOF_ABI_MINOR 18
-#define SOF_ABI_PATCH 0
+#define SOF_ABI_MINOR 19
+#define SOF_ABI_PATCH 1
 #define SOF_ABI_MAJOR_SHIFT 24
 #define SOF_ABI_MAJOR_MASK 0xff
 #define SOF_ABI_MINOR_SHIFT 12
diff --git a/libc/stdio/stdio.cpp b/libc/stdio/stdio.cpp
index 08df2eb..27813a6 100644
--- a/libc/stdio/stdio.cpp
+++ b/libc/stdio/stdio.cpp
@@ -1129,7 +1129,9 @@
 
   // Read directly into the caller's buffer.
   while (total > 0) {
-    ssize_t bytes_read = (*fp->_read)(fp->_cookie, dst, total);
+    // The _read function pointer takes an int instead of a size_t.
+    int chunk_size = MIN(total, INT_MAX);
+    ssize_t bytes_read = (*fp->_read)(fp->_cookie, dst, chunk_size);
     if (bytes_read <= 0) {
       fp->_flags |= (bytes_read == 0) ? __SEOF : __SERR;
       break;
diff --git a/libc/tools/Android.bp b/libc/tools/Android.bp
index 116b853..c7fce64 100644
--- a/libc/tools/Android.bp
+++ b/libc/tools/Android.bp
@@ -8,8 +8,8 @@
     default_applicable_licenses: ["bionic_libc_license"],
 }
 
-filegroup {
-    name: "bionic-gensyscalls",
+python_binary_host {
+    name: "gensyscalls",
     srcs: ["gensyscalls.py"],
 }
 
diff --git a/libc/tzcode/asctime.c b/libc/tzcode/asctime.c
index 337a313..ce5d4be 100644
--- a/libc/tzcode/asctime.c
+++ b/libc/tzcode/asctime.c
@@ -1,3 +1,5 @@
+/* asctime and asctime_r a la POSIX and ISO C, except pad years before 1000.  */
+
 /*
 ** This file is in the public domain, so clarified as of
 ** 1996-06-05 by Arthur David Olson.
@@ -12,7 +14,7 @@
 /*LINTLIBRARY*/
 
 #include "private.h"
-#include "tzfile.h"
+#include <stdio.h>
 
 /*
 ** Some systems only handle "%.2d"; others only handle "%02d";
@@ -29,13 +31,13 @@
 ** leading zeroes to get the newline in the traditional place.
 ** The -4 ensures that we get four characters of output even if
 ** we call a strftime variant that produces fewer characters for some years.
-** The ISO C 1999 and POSIX 1003.1-2004 standards prohibit padding the year,
+** The ISO C and POSIX standards prohibit padding the year,
 ** but many implementations pad anyway; most likely the standards are buggy.
 */
 #ifdef __GNUC__
-#define ASCTIME_FMT	"%.3s %.3s%3d %2.2d:%2.2d:%2.2d %-4s\n"
+#define ASCTIME_FMT	"%s %s%3d %2.2d:%2.2d:%2.2d %-4s\n"
 #else /* !defined __GNUC__ */
-#define ASCTIME_FMT	"%.3s %.3s%3d %02.2d:%02.2d:%02.2d %-4s\n"
+#define ASCTIME_FMT	"%s %s%3d %02.2d:%02.2d:%02.2d %-4s\n"
 #endif /* !defined __GNUC__ */
 /*
 ** For years that are more than four digits we put extra spaces before the year
@@ -44,9 +46,9 @@
 ** that no output is better than wrong output).
 */
 #ifdef __GNUC__
-#define ASCTIME_FMT_B	"%.3s %.3s%3d %2.2d:%2.2d:%2.2d     %s\n"
+#define ASCTIME_FMT_B	"%s %s%3d %2.2d:%2.2d:%2.2d     %s\n"
 #else /* !defined __GNUC__ */
-#define ASCTIME_FMT_B	"%.3s %.3s%3d %02.2d:%02.2d:%02.2d     %s\n"
+#define ASCTIME_FMT_B	"%s %s%3d %02.2d:%02.2d:%02.2d     %s\n"
 #endif /* !defined __GNUC__ */
 
 #define STD_ASCTIME_BUF_SIZE	26
@@ -64,17 +66,13 @@
 
 static char	buf_asctime[MAX_ASCTIME_BUF_SIZE];
 
-/*
-** A la ISO/IEC 9945-1, ANSI/IEEE Std 1003.1, 2004 Edition.
-*/
-
 char *
 asctime_r(register const struct tm *timeptr, char *buf)
 {
-	static const char	wday_name[][3] = {
+	static const char	wday_name[][4] = {
 		"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
 	};
-	static const char	mon_name[][3] = {
+	static const char	mon_name[][4] = {
 		"Jan", "Feb", "Mar", "Apr", "May", "Jun",
 		"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
 	};
@@ -117,10 +115,6 @@
 	}
 }
 
-/*
-** A la ISO/IEC 9945-1, ANSI/IEEE Std 1003.1, 2004 Edition.
-*/
-
 char *
 asctime(register const struct tm *timeptr)
 {
diff --git a/libc/tzcode/bionic.cpp b/libc/tzcode/bionic.cpp
index e134aaa..d2b5d80 100644
--- a/libc/tzcode/bionic.cpp
+++ b/libc/tzcode/bionic.cpp
@@ -190,6 +190,18 @@
     // Give up now, and don't try fallback tzdata files. We don't log here
     // because for all we know the given olson id was nonsense.
     close(fd);
+    // This file descriptor (-1) is passed to localtime.c. In invalid fd case
+    // upstream passes errno value around methods and having 0 there will
+    // indicate that time zone was found and read successfully and localtime's
+    // internal state was properly initialized (which wasn't as we couldn't find
+    // requested time zone in the tzdata file).
+    // If we reached this point errno is unlikely to be touched. It is only
+    // close(fd) which can do it, but that is very unlikely to happen. And
+    // even if it happens we can't extract any useful insights from it.
+    // We are overriding it to ENOENT as it matches upstream expectations -
+    // time zone is absent in the tzdata file == there is no TZif file in
+    // /usr/share/zoneinfo.
+    errno = ENOENT;
     return -1;
   }
 
@@ -206,24 +218,14 @@
 int __bionic_open_tzdata(const char* olson_id, int32_t* entry_length) {
   int fd;
 
-  // Try the three locations for the tzdata file in a strict order:
-  // 1: The O-MR1 time zone updates via APK update mechanism. This is
-  //    tried first because it allows us to test that the time zone updates
-  //    via APK mechanism still works even on devices with the time zone
-  //    module.
-  //    TODO: remove this when those devices are no longer supported.
-  // 2: The time zone data module which contains the main copy. This is the
+  // Try the two locations for the tzdata file in a strict order:
+  // 1: The time zone data module which contains the main copy. This is the
   //    common case for current devices.
-  // 3: The ultimate fallback: the non-updatable copy in /system.
+  // 2: The ultimate fallback: the non-updatable copy in /system.
 
 #if defined(__ANDROID__)
   // On Android devices, bionic has to work even if exec takes place without
   // environment variables set. So, all paths are hardcoded here.
-
-  fd = __bionic_open_tzdata_path("/data/misc/zoneinfo/current/tzdata",
-                                 olson_id, entry_length);
-  if (fd >= -1) return fd;
-
   fd = __bionic_open_tzdata_path("/apex/com.android.tzdata/etc/tz/tzdata",
                                  olson_id, entry_length);
   if (fd >= -1) return fd;
@@ -233,16 +235,10 @@
   if (fd >= -1) return fd;
 #else
   // On the host, we don't expect the hard-coded locations above to exist, and
-  // we're not worried about security so we trust $ANDROID_DATA,
-  // $ANDROID_TZDATA_ROOT, and $ANDROID_ROOT to point us in the right direction
-  // instead.
+  // we're not worried about security so we trust $ANDROID_TZDATA_ROOT, and
+  // $ANDROID_ROOT to point us in the right direction instead.
 
-  char* path = make_path("ANDROID_DATA", "/misc/zoneinfo/current/tzdata");
-  fd = __bionic_open_tzdata_path(path, olson_id, entry_length);
-  free(path);
-  if (fd >= -1) return fd;
-
-  path = make_path("ANDROID_TZDATA_ROOT", "/etc/tz/tzdata");
+  char* path = make_path("ANDROID_TZDATA_ROOT", "/etc/tz/tzdata");
   fd = __bionic_open_tzdata_path(path, olson_id, entry_length);
   free(path);
   if (fd >= -1) return fd;
diff --git a/libc/tzcode/difftime.c b/libc/tzcode/difftime.c
index ba2fd03..ff78f03 100644
--- a/libc/tzcode/difftime.c
+++ b/libc/tzcode/difftime.c
@@ -1,3 +1,5 @@
+/* Return the difference between two timestamps.  */
+
 /*
 ** This file is in the public domain, so clarified as of
 ** 1996-06-05 by Arthur David Olson.
@@ -14,14 +16,14 @@
   return -x;
 }
 
-double ATTRIBUTE_CONST
+double
 difftime(time_t time1, time_t time0)
 {
 	/*
 	** If double is large enough, simply convert and subtract
 	** (assuming that the larger type has more precision).
 	*/
-	if (sizeof (time_t) < sizeof (double)) {
+	if (sizeof(time_t) < sizeof(double)) {
 	  double t1 = time1, t0 = time0;
 	  return t1 - t0;
 	}
@@ -34,7 +36,7 @@
 	  return time0 <= time1 ? time1 - time0 : dminus(time0 - time1);
 
 	/* Use uintmax_t if wide enough.  */
-	if (sizeof (time_t) <= sizeof (uintmax_t)) {
+	if (sizeof(time_t) <= sizeof(uintmax_t)) {
 	  uintmax_t t1 = time1, t0 = time0;
 	  return time0 <= time1 ? t1 - t0 : dminus(t0 - t1);
 	}
diff --git a/libc/tzcode/localtime.c b/libc/tzcode/localtime.c
index 091bab0..8ff5cee 100644
--- a/libc/tzcode/localtime.c
+++ b/libc/tzcode/localtime.c
@@ -1,3 +1,5 @@
+/* Convert timestamp from time_t to struct tm.  */
+
 /*
 ** This file is in the public domain, so clarified as of
 ** 1996-06-05 by Arthur David Olson.
@@ -14,9 +16,9 @@
 #include "private.h"
 
 #include "tzfile.h"
-#include "fcntl.h"
+#include <fcntl.h>
 
-#if THREAD_SAFE
+#if defined THREAD_SAFE && THREAD_SAFE
 # include <pthread.h>
 static pthread_mutex_t locallock = PTHREAD_MUTEX_INITIALIZER;
 static int lock(void) { return pthread_mutex_lock(&locallock); }
@@ -26,14 +28,6 @@
 static void unlock(void) { }
 #endif
 
-/* NETBSD_INSPIRED_EXTERN functions are exported to callers if
-   NETBSD_INSPIRED is defined, and are private otherwise.  */
-#if NETBSD_INSPIRED
-# define NETBSD_INSPIRED_EXTERN
-#else
-# define NETBSD_INSPIRED_EXTERN static
-#endif
-
 #ifndef TZ_ABBR_MAX_LEN
 #define TZ_ABBR_MAX_LEN 16
 #endif /* !defined TZ_ABBR_MAX_LEN */
@@ -87,31 +81,39 @@
 
 /*
 ** The DST rules to use if TZ has no rules and we can't load TZDEFRULES.
-** We default to US rules as of 1999-08-17.
-** POSIX 1003.1 section 8.1.1 says that the default DST rules are
-** implementation dependent; for historical reasons, US rules are a
-** common default.
+** Default to US rules as of 2017-05-07.
+** POSIX does not specify the default DST rules;
+** for historical reasons, US rules are a common default.
 */
 #ifndef TZDEFRULESTRING
-#define TZDEFRULESTRING ",M4.1.0,M10.5.0"
-#endif /* !defined TZDEFDST */
+#define TZDEFRULESTRING ",M3.2.0,M11.1.0"
+#endif
 
 struct ttinfo {              /* time type information */
-    int_fast32_t tt_gmtoff;  /* UT offset in seconds */
+    int_fast32_t tt_utoff; /* UT offset in seconds */
     bool         tt_isdst;   /* used to set tm_isdst */
-    int          tt_abbrind; /* abbreviation list index */
+    int          tt_desigidx; /* abbreviation list index */
     bool         tt_ttisstd; /* transition is std time */
-    bool         tt_ttisgmt; /* transition is UT */
+    bool         tt_ttisut; /* transition is UT */
 };
 
 struct lsinfo {              /* leap second information */
     time_t       ls_trans;   /* transition time */
-    int_fast64_t ls_corr;    /* correction to apply */
+    int_fast32_t ls_corr;    /* correction to apply */
 };
 
 #define SMALLEST(a, b)	(((a) < (b)) ? (a) : (b))
 #define BIGGEST(a, b)   (((a) > (b)) ? (a) : (b))
 
+/* This abbreviation means local time is unspecified.  */
+static char const UNSPEC[] = "-00";
+
+/* How many extra bytes are needed at the end of struct state's chars array.
+   This needs to be at least 1 for null termination in case the input
+   data isn't properly terminated, and it also needs to be big enough
+   for ttunspecified to work without crashing.  */
+enum { CHARS_EXTRA = BIGGEST(sizeof UNSPEC, 2) - 1 };
+
 #ifdef TZNAME_MAX
 #define MY_TZNAME_MAX   TZNAME_MAX
 #endif /* defined TZNAME_MAX */
@@ -129,10 +131,14 @@
     time_t        ats[TZ_MAX_TIMES];
     unsigned char types[TZ_MAX_TIMES];
     struct ttinfo ttis[TZ_MAX_TYPES];
-    char          chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof gmt),
+    char          chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + CHARS_EXTRA,
+                            sizeof gmt),
                   (2 * (MY_TZNAME_MAX + 1)))];
     struct lsinfo lsis[TZ_MAX_LEAPS];
-    int           defaulttype; /* for early times or if no transitions */
+    /* The time type to use for early times or if no transitions.
+       It is always zero for recent tzdb releases.
+       It might be nonzero for data from tzdb 2018e or earlier.  */
+    int defaulttype;
 };
 
 enum r_type {
@@ -153,11 +159,12 @@
 			 struct tm *);
 static bool increment_overflow(int *, int);
 static bool increment_overflow_time(time_t *, int_fast32_t);
+static int_fast32_t leapcorr(struct state const *, time_t);
 static bool normalize_overflow32(int_fast32_t *, int *, int);
 static struct tm *timesub(time_t const *, int_fast32_t, struct state const *,
 			  struct tm *);
 static bool typesequiv(struct state const *, int, int);
-static bool tzparse(char const *, struct state *, bool);
+static bool tzparse(char const *, struct state *, struct state *);
 
 #ifdef ALL_STATE
 static struct state * lclptr;
@@ -188,30 +195,39 @@
 
 static struct tm	tm;
 
-#if !HAVE_POSIX_DECLS
+#if 2 <= HAVE_TZNAME + TZ_TIME_T
 char *			tzname[2] = {
 	(char *) wildabbr,
 	(char *) wildabbr
 };
-#ifdef USG_COMPAT
+#endif
+#if 2 <= USG_COMPAT + TZ_TIME_T
 long			timezone;
 int			daylight;
-# endif
 #endif
 
-#ifdef ALTZONE
+#if 2 <= ALTZONE + TZ_TIME_T
 long			altzone;
-#endif /* defined ALTZONE */
+#endif
 
-/* Initialize *S to a value based on GMTOFF, ISDST, and ABBRIND.  */
+/* Initialize *S to a value based on UTOFF, ISDST, and DESIGIDX.  */
 static void
-init_ttinfo(struct ttinfo *s, int_fast32_t gmtoff, bool isdst, int abbrind)
+init_ttinfo(struct ttinfo *s, int_fast32_t utoff, bool isdst, int desigidx)
 {
-  s->tt_gmtoff = gmtoff;
+  s->tt_utoff = utoff;
   s->tt_isdst = isdst;
-  s->tt_abbrind = abbrind;
+  s->tt_desigidx = desigidx;
   s->tt_ttisstd = false;
-  s->tt_ttisgmt = false;
+  s->tt_ttisut = false;
+}
+
+/* Return true if SP's time type I does not specify local time.  */
+static bool
+ttunspecified(struct state const *sp, int i)
+{
+  char const *abbr = &sp->chars[sp->ttis[i].tt_desigidx];
+  /* memcmp is likely faster than strcmp, and is safe due to CHARS_EXTRA.  */
+  return memcmp(abbr, UNSPEC, sizeof UNSPEC) == 0;
 }
 
 static int_fast32_t
@@ -240,7 +256,7 @@
 static int_fast64_t
 detzcode64(const char *const codep)
 {
-	register uint_fast64_t result;
+	register int_fast64_t result;
 	register int	i;
 	int_fast64_t one = 1;
 	int_fast64_t halfmaxval = one << (64 - 2);
@@ -263,52 +279,71 @@
 static void
 update_tzname_etc(struct state const *sp, struct ttinfo const *ttisp)
 {
-  tzname[ttisp->tt_isdst] = (char *) &sp->chars[ttisp->tt_abbrind];
-#ifdef USG_COMPAT
+#if HAVE_TZNAME
+  tzname[ttisp->tt_isdst] = (char *) &sp->chars[ttisp->tt_desigidx];
+#endif
+#if USG_COMPAT
   if (!ttisp->tt_isdst)
-    timezone = - ttisp->tt_gmtoff;
+    timezone = - ttisp->tt_utoff;
 #endif
-#ifdef ALTZONE
+#if ALTZONE
   if (ttisp->tt_isdst)
-    altzone = - ttisp->tt_gmtoff;
+    altzone = - ttisp->tt_utoff;
 #endif
 }
 
+/* If STDDST_MASK indicates that SP's TYPE provides useful info,
+   update tzname, timezone, and/or altzone and return STDDST_MASK,
+   diminished by the provided info if it is a specified local time.
+   Otherwise, return STDDST_MASK.  See settzname for STDDST_MASK.  */
+static int
+may_update_tzname_etc(int stddst_mask, struct state *sp, int type)
+{
+  struct ttinfo *ttisp = &sp->ttis[type];
+  int this_bit = 1 << ttisp->tt_isdst;
+  if (stddst_mask & this_bit) {
+    update_tzname_etc(sp, ttisp);
+    if (!ttunspecified(sp, type))
+      return stddst_mask & ~this_bit;
+  }
+  return stddst_mask;
+}
+
 static void
 settzname(void)
 {
 	register struct state * const	sp = lclptr;
 	register int			i;
 
-	tzname[0] = tzname[1] = (char *) wildabbr;
-#ifdef USG_COMPAT
-	daylight = 0;
+	/* If STDDST_MASK & 1 we need info about a standard time.
+	   If STDDST_MASK & 2 we need info about a daylight saving time.
+	   When STDDST_MASK becomes zero we can stop looking.  */
+	int stddst_mask = 0;
+
+#if HAVE_TZNAME
+	tzname[0] = tzname[1] = (char *) (sp ? wildabbr : gmt);
+	stddst_mask = 3;
+#endif
+#if USG_COMPAT
 	timezone = 0;
-#endif /* defined USG_COMPAT */
-#ifdef ALTZONE
+	stddst_mask = 3;
+#endif
+#if ALTZONE
 	altzone = 0;
-#endif /* defined ALTZONE */
-	if (sp == NULL) {
-		tzname[0] = tzname[1] = (char *) gmt;
-		return;
-	}
+	stddst_mask |= 2;
+#endif
 	/*
-	** And to get the latest zone names into tzname. . .
+	** And to get the latest time zone abbreviations into tzname. . .
 	*/
-	for (i = 0; i < sp->typecnt; ++i) {
-		register const struct ttinfo * const	ttisp = &sp->ttis[i];
-		update_tzname_etc(sp, ttisp);
+	if (sp) {
+	  for (i = sp->timecnt - 1; stddst_mask && 0 <= i; i--)
+	    stddst_mask = may_update_tzname_etc(stddst_mask, sp, sp->types[i]);
+	  for (i = sp->typecnt - 1; stddst_mask && 0 <= i; i--)
+	    stddst_mask = may_update_tzname_etc(stddst_mask, sp, i);
 	}
-	for (i = 0; i < sp->timecnt; ++i) {
-		register const struct ttinfo * const	ttisp =
-							&sp->ttis[
-								sp->types[i]];
-		update_tzname_etc(sp, ttisp);
-#ifdef USG_COMPAT
-		if (ttisp->tt_isdst)
-			daylight = 1;
-#endif /* defined USG_COMPAT */
-	}
+#if USG_COMPAT
+	daylight = stddst_mask >> 1 ^ 1;
+#endif
 }
 
 static void
@@ -326,7 +361,7 @@
 	*/
 	for (i = 0; i < sp->typecnt; ++i) {
 		register const struct ttinfo * const	ttisp = &sp->ttis[i];
-		register char *				cp = &sp->chars[ttisp->tt_abbrind];
+		char *cp = &sp->chars[ttisp->tt_desigidx];
 
 		if (strlen(cp) > TZ_ABBR_MAX_LEN &&
 			strcmp(cp, GRANDPARENTED) != 0)
@@ -334,39 +369,39 @@
 	}
 }
 
-static bool
-differ_by_repeat(const time_t t1, const time_t t0)
-{
-    if (TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS)
-        return 0;
-#if defined(__LP64__) // 32-bit Android/glibc has a signed 32-bit time_t; 64-bit doesn't.
-    return t1 - t0 == SECSPERREPEAT;
-#endif
-}
-
 /* Input buffer for data read from a compiled tz file.  */
 union input_buffer {
   /* The first part of the buffer, interpreted as a header.  */
   struct tzhead tzhead;
 
   /* The entire buffer.  */
-  char buf[2 * sizeof(struct tzhead) + 2 * sizeof (struct state)
-	   + 4 * TZ_MAX_TIMES];
+  char buf[2 * sizeof(struct tzhead) + 2 * sizeof(struct state)
+     + 4 * TZ_MAX_TIMES];
 };
 
+// Android-removed: There is no directory with file-per-time zone on Android.
+#ifndef __BIONIC__
+/* TZDIR with a trailing '/' rather than a trailing '\0'.  */
+static char const tzdirslash[sizeof TZDIR] = TZDIR "/";
+#endif
+
 /* Local storage needed for 'tzloadbody'.  */
 union local_storage {
-  /* The file name to be opened.  */
-  char fullname[FILENAME_MAX + 1];
-
   /* The results of analyzing the file's contents after it is opened.  */
-  struct {
+  struct file_analysis {
     /* The input buffer.  */
     union input_buffer u;
 
     /* A temporary state used for parsing a TZ string in the file.  */
     struct state st;
   } u;
+
+  // Android-removed: There is no directory with file-per-time zone on Android.
+  #ifndef __BIONIC__
+  /* The file name to be opened.  */
+  char fullname[BIGGEST(sizeof(struct file_analysis),
+      sizeof tzdirslash + 1024)];
+  #endif
 };
 
 /* Load tz data from the file named NAME into *SP.  Read extended
@@ -385,7 +420,7 @@
 	register char *fullname = lsp->fullname;
 #endif
 	register union input_buffer *up = &lsp->u.u;
-	register int tzheadsize = sizeof (struct tzhead);
+	register int tzheadsize = sizeof(struct tzhead);
 
 	sp->goback = sp->goahead = false;
 
@@ -402,20 +437,36 @@
 #else
 	if (name[0] == ':')
 		++name;
+#ifdef SUPPRESS_TZDIR
+	/* Do not prepend TZDIR.  This is intended for specialized
+	   applications only, due to its security implications.  */
+	doaccess = true;
+#else
 	doaccess = name[0] == '/';
+#endif
 	if (!doaccess) {
-		char const *p = TZDIR;
-		if (! p)
-		  return EINVAL;
-		if (sizeof lsp->fullname - 1 <= strlen(p) + strlen(name))
+		char const *dot;
+		size_t namelen = strlen(name);
+		if (sizeof lsp->fullname - sizeof tzdirslash <= namelen)
 		  return ENAMETOOLONG;
-		strcpy(fullname, p);
-		strcat(fullname, "/");
-		strcat(fullname, name);
-		/* Set doaccess if '.' (as in "../") shows up in name.  */
-		if (strchr(name, '.'))
-			doaccess = true;
-		name = fullname;
+
+		/* Create a string "TZDIR/NAME".  Using sprintf here
+		   would pull in stdio (and would fail if the
+		   resulting string length exceeded INT_MAX!).  */
+		memcpy(lsp->fullname, tzdirslash, sizeof tzdirslash);
+		strcpy(lsp->fullname + sizeof tzdirslash, name);
+
+		/* Set doaccess if NAME contains a ".." file name
+		   component, as such a name could read a file outside
+		   the TZDIR virtual subtree.  */
+		for (dot = name; (dot = strchr(dot, '.')); dot++)
+		  if ((dot == name || dot[-1] == '/') && dot[1] == '.'
+		      && (dot[2] == '/' || !dot[2])) {
+		    doaccess = true;
+		    break;
+		  }
+
+		name = lsp->fullname;
 	}
 	if (doaccess && access(name, R_OK) != 0)
 	  return errno;
@@ -437,47 +488,62 @@
 	if (close(fid) < 0)
 	  return errno;
 	for (stored = 4; stored <= 8; stored *= 2) {
-		int_fast32_t ttisstdcnt = detzcode(up->tzhead.tzh_ttisstdcnt);
-		int_fast32_t ttisgmtcnt = detzcode(up->tzhead.tzh_ttisgmtcnt);
-		int_fast32_t leapcnt = detzcode(up->tzhead.tzh_leapcnt);
-		int_fast32_t timecnt = detzcode(up->tzhead.tzh_timecnt);
-		int_fast32_t typecnt = detzcode(up->tzhead.tzh_typecnt);
-		int_fast32_t charcnt = detzcode(up->tzhead.tzh_charcnt);
-		char const *p = up->buf + tzheadsize;
-		if (! (0 <= leapcnt && leapcnt < TZ_MAX_LEAPS
-		       && 0 < typecnt && typecnt < TZ_MAX_TYPES
-		       && 0 <= timecnt && timecnt < TZ_MAX_TIMES
-		       && 0 <= charcnt && charcnt < TZ_MAX_CHARS
-		       && (ttisstdcnt == typecnt || ttisstdcnt == 0)
-		       && (ttisgmtcnt == typecnt || ttisgmtcnt == 0)))
-		  return EINVAL;
-		if (nread
-		    < (tzheadsize		/* struct tzhead */
-		       + timecnt * stored	/* ats */
+	    char version = up->tzhead.tzh_version[0];
+	    bool skip_datablock = stored == 4 && version;
+	    int_fast32_t datablock_size;
+	    int_fast32_t ttisstdcnt = detzcode(up->tzhead.tzh_ttisstdcnt);
+	    int_fast32_t ttisutcnt = detzcode(up->tzhead.tzh_ttisutcnt);
+	    int_fast64_t prevtr = -1;
+	    int_fast32_t prevcorr;
+	    int_fast32_t leapcnt = detzcode(up->tzhead.tzh_leapcnt);
+	    int_fast32_t timecnt = detzcode(up->tzhead.tzh_timecnt);
+	    int_fast32_t typecnt = detzcode(up->tzhead.tzh_typecnt);
+	    int_fast32_t charcnt = detzcode(up->tzhead.tzh_charcnt);
+	    char const *p = up->buf + tzheadsize;
+	    /* Although tzfile(5) currently requires typecnt to be nonzero,
+	       support future formats that may allow zero typecnt
+	       in files that have a TZ string and no transitions.  */
+	    if (! (0 <= leapcnt && leapcnt < TZ_MAX_LEAPS
+		   && 0 <= typecnt && typecnt < TZ_MAX_TYPES
+		   && 0 <= timecnt && timecnt < TZ_MAX_TIMES
+		   && 0 <= charcnt && charcnt < TZ_MAX_CHARS
+		   && 0 <= ttisstdcnt && ttisstdcnt < TZ_MAX_TYPES
+		   && 0 <= ttisutcnt && ttisutcnt < TZ_MAX_TYPES))
+	      return EINVAL;
+	    datablock_size
+		    = (timecnt * stored		/* ats */
 		       + timecnt		/* types */
 		       + typecnt * 6		/* ttinfos */
 		       + charcnt		/* chars */
 		       + leapcnt * (stored + 4)	/* lsinfos */
 		       + ttisstdcnt		/* ttisstds */
-		       + ttisgmtcnt))		/* ttisgmts */
+		       + ttisutcnt);		/* ttisuts */
+	    if (nread < tzheadsize + datablock_size)
+	      return EINVAL;
+	    if (skip_datablock)
+		p += datablock_size;
+	    else {
+		if (! ((ttisstdcnt == typecnt || ttisstdcnt == 0)
+		       && (ttisutcnt == typecnt || ttisutcnt == 0)))
 		  return EINVAL;
+
 		sp->leapcnt = leapcnt;
 		sp->timecnt = timecnt;
 		sp->typecnt = typecnt;
 		sp->charcnt = charcnt;
 
 		/* Read transitions, discarding those out of time_t range.
-		   But pretend the last transition before time_t_min
-		   occurred at time_t_min.  */
+		   But pretend the last transition before TIME_T_MIN
+		   occurred at TIME_T_MIN.  */
 		timecnt = 0;
 		for (i = 0; i < sp->timecnt; ++i) {
 			int_fast64_t at
 			  = stored == 4 ? detzcode(p) : detzcode64(p);
-			sp->types[i] = at <= time_t_max;
+			sp->types[i] = at <= TIME_T_MAX;
 			if (sp->types[i]) {
 			  time_t attime
-			    = ((TYPE_SIGNED(time_t) ? at < time_t_min : at < 0)
-			       ? time_t_min : at);
+			    = ((TYPE_SIGNED(time_t) ? at < TIME_T_MIN : at < 0)
+			       ? TIME_T_MIN : at);
 			  if (timecnt && attime <= sp->ats[timecnt - 1]) {
 			    if (attime < sp->ats[timecnt - 1])
 			      return EINVAL;
@@ -500,23 +566,25 @@
 		sp->timecnt = timecnt;
 		for (i = 0; i < sp->typecnt; ++i) {
 			register struct ttinfo *	ttisp;
-			unsigned char isdst, abbrind;
+			unsigned char isdst, desigidx;
 
 			ttisp = &sp->ttis[i];
-			ttisp->tt_gmtoff = detzcode(p);
+			ttisp->tt_utoff = detzcode(p);
 			p += 4;
 			isdst = *p++;
 			if (! (isdst < 2))
 			  return EINVAL;
 			ttisp->tt_isdst = isdst;
-			abbrind = *p++;
-			if (! (abbrind < sp->charcnt))
+			desigidx = *p++;
+			if (! (desigidx < sp->charcnt))
 			  return EINVAL;
-			ttisp->tt_abbrind = abbrind;
+			ttisp->tt_desigidx = desigidx;
 		}
 		for (i = 0; i < sp->charcnt; ++i)
 			sp->chars[i] = *p++;
-		sp->chars[i] = '\0';	/* ensure '\0' at end */
+		/* Ensure '\0'-terminated, and make it safe to call
+		   ttunspecified later.  */
+		memset(&sp->chars[i], 0, CHARS_EXTRA);
 
 		/* Read leap seconds, discarding those out of time_t range.  */
 		leapcnt = 0;
@@ -524,16 +592,28 @@
 		  int_fast64_t tr = stored == 4 ? detzcode(p) : detzcode64(p);
 		  int_fast32_t corr = detzcode(p + stored);
 		  p += stored + 4;
-		  if (tr <= time_t_max) {
-		    time_t trans
-		      = ((TYPE_SIGNED(time_t) ? tr < time_t_min : tr < 0)
-			 ? time_t_min : tr);
-		    if (leapcnt && trans <= sp->lsis[leapcnt - 1].ls_trans) {
-		      if (trans < sp->lsis[leapcnt - 1].ls_trans)
-			return EINVAL;
-		      leapcnt--;
-		    }
-		    sp->lsis[leapcnt].ls_trans = trans;
+
+		  /* Leap seconds cannot occur before the Epoch,
+		     or out of order.  */
+		  if (tr <= prevtr)
+		    return EINVAL;
+
+		  /* To avoid other botches in this code, each leap second's
+		     correction must differ from the previous one's by 1
+		     second or less, except that the first correction can be
+		     any value; these requirements are more generous than
+		     RFC 8536, to allow future RFC extensions.  */
+		  if (! (i == 0
+			 || (prevcorr < corr
+			     ? corr == prevcorr + 1
+			     : (corr == prevcorr
+				|| corr == prevcorr - 1))))
+		    return EINVAL;
+		  prevtr = tr;
+		  prevcorr = corr;
+
+		  if (tr <= TIME_T_MAX) {
+		    sp->lsis[leapcnt].ls_trans = tr;
 		    sp->lsis[leapcnt].ls_corr = corr;
 		    leapcnt++;
 		  }
@@ -556,21 +636,22 @@
 			register struct ttinfo *	ttisp;
 
 			ttisp = &sp->ttis[i];
-			if (ttisgmtcnt == 0)
-				ttisp->tt_ttisgmt = false;
+			if (ttisutcnt == 0)
+				ttisp->tt_ttisut = false;
 			else {
 				if (*p != true && *p != false)
 						return EINVAL;
-				ttisp->tt_ttisgmt = *p++;
+				ttisp->tt_ttisut = *p++;
 			}
 		}
-		/*
-		** If this is an old file, we're done.
-		*/
-		if (up->tzhead.tzh_version[0] == '\0')
-			break;
-		nread -= p - up->buf;
-		memmove(up->buf, p, nread);
+	    }
+
+	    nread -= p - up->buf;
+	    memmove(up->buf, p, nread);
+
+	    /* If this is an old file, we're done.  */
+	    if (!version)
+	      break;
 	}
 	if (doextend && nread > 2 &&
 		up->buf[0] == '\n' && up->buf[nread - 1] == '\n' &&
@@ -578,24 +659,23 @@
 			struct state	*ts = &lsp->u.st;
 
 			up->buf[nread - 1] = '\0';
-			if (tzparse(&up->buf[1], ts, false)
-			    && ts->typecnt == 2) {
+			if (tzparse(&up->buf[1], ts, sp)) {
 
 			  /* Attempt to reuse existing abbreviations.
-			     Without this, America/Anchorage would stop
-			     working after 2037 when TZ_MAX_CHARS is 50, as
-			     sp->charcnt equals 42 (for LMT CAT CAWT CAPT AHST
+			     Without this, America/Anchorage would be right on
+			     the edge after 2037 when TZ_MAX_CHARS is 50, as
+			     sp->charcnt equals 40 (for LMT AST AWT APT AHST
 			     AHDT YST AKDT AKST) and ts->charcnt equals 10
 			     (for AKST AKDT).  Reusing means sp->charcnt can
-			     stay 42 in this example.  */
+			     stay 40 in this example.  */
 			  int gotabbr = 0;
 			  int charcnt = sp->charcnt;
-			  for (i = 0; i < 2; i++) {
-			    char *tsabbr = ts->chars + ts->ttis[i].tt_abbrind;
+			  for (i = 0; i < ts->typecnt; i++) {
+			    char *tsabbr = ts->chars + ts->ttis[i].tt_desigidx;
 			    int j;
 			    for (j = 0; j < charcnt; j++)
 			      if (strcmp(sp->chars + j, tsabbr) == 0) {
-				ts->ttis[i].tt_abbrind = j;
+				ts->ttis[i].tt_desigidx = j;
 				gotabbr++;
 				break;
 			      }
@@ -604,53 +684,83 @@
 			      if (j + tsabbrlen < TZ_MAX_CHARS) {
 				strcpy(sp->chars + j, tsabbr);
 				charcnt = j + tsabbrlen + 1;
-				ts->ttis[i].tt_abbrind = j;
+				ts->ttis[i].tt_desigidx = j;
 				gotabbr++;
 			      }
 			    }
 			  }
-			  if (gotabbr == 2) {
+			  if (gotabbr == ts->typecnt) {
 			    sp->charcnt = charcnt;
-			    for (i = 0; i < ts->timecnt; i++)
-			      if (sp->ats[sp->timecnt - 1] < ts->ats[i])
-				break;
-			    while (i < ts->timecnt
-				   && sp->timecnt < TZ_MAX_TIMES) {
-			      sp->ats[sp->timecnt] = ts->ats[i];
+
+			    /* Ignore any trailing, no-op transitions generated
+			       by zic as they don't help here and can run afoul
+			       of bugs in zic 2016j or earlier.  */
+			    while (1 < sp->timecnt
+				   && (sp->types[sp->timecnt - 1]
+				       == sp->types[sp->timecnt - 2]))
+			      sp->timecnt--;
+
+			    for (i = 0;
+				 i < ts->timecnt && sp->timecnt < TZ_MAX_TIMES;
+				 i++) {
+			      time_t t = ts->ats[i];
+			      if (increment_overflow_time(&t, leapcorr(sp, t))
+				  || (0 < sp->timecnt
+				      && t <= sp->ats[sp->timecnt - 1]))
+				continue;
+			      sp->ats[sp->timecnt] = t;
 			      sp->types[sp->timecnt] = (sp->typecnt
 							+ ts->types[i]);
 			      sp->timecnt++;
-			      i++;
 			    }
-			    sp->ttis[sp->typecnt++] = ts->ttis[0];
-			    sp->ttis[sp->typecnt++] = ts->ttis[1];
+			    for (i = 0; i < ts->typecnt; i++)
+			      sp->ttis[sp->typecnt++] = ts->ttis[i];
 			  }
 			}
 	}
+	if (sp->typecnt == 0)
+	  return EINVAL;
 	if (sp->timecnt > 1) {
+	    if (sp->ats[0] <= TIME_T_MAX - SECSPERREPEAT) {
+		time_t repeatat = sp->ats[0] + SECSPERREPEAT;
+		int repeattype = sp->types[0];
 		for (i = 1; i < sp->timecnt; ++i)
-			if (typesequiv(sp, sp->types[i], sp->types[0]) &&
-				differ_by_repeat(sp->ats[i], sp->ats[0])) {
+		  if (sp->ats[i] == repeatat
+		      && typesequiv(sp, sp->types[i], repeattype)) {
 					sp->goback = true;
 					break;
-				}
+		  }
+	    }
+	    if (TIME_T_MIN + SECSPERREPEAT <= sp->ats[sp->timecnt - 1]) {
+		time_t repeatat = sp->ats[sp->timecnt - 1] - SECSPERREPEAT;
+		int repeattype = sp->types[sp->timecnt - 1];
 		for (i = sp->timecnt - 2; i >= 0; --i)
-			if (typesequiv(sp, sp->types[sp->timecnt - 1],
-				sp->types[i]) &&
-				differ_by_repeat(sp->ats[sp->timecnt - 1],
-				sp->ats[i])) {
+		  if (sp->ats[i] == repeatat
+		      && typesequiv(sp, sp->types[i], repeattype)) {
 					sp->goahead = true;
 					break;
-		}
+		  }
+	    }
 	}
+
+	/* Infer sp->defaulttype from the data.  Although this default
+	   type is always zero for data from recent tzdb releases,
+	   things are trickier for data from tzdb 2018e or earlier.
+
+	   The first set of heuristics work around bugs in 32-bit data
+	   generated by tzdb 2013c or earlier.  The workaround is for
+	   zones like Australia/Macquarie where timestamps before the
+	   first transition have a time type that is not the earliest
+	   standard-time type.  See:
+	   https://mm.icann.org/pipermail/tz/2013-May/019368.html */
 	/*
-	** If type 0 is is unused in transitions,
+	** If type 0 does not specify local time, or is unused in transitions,
 	** it's the type to use for early times.
 	*/
 	for (i = 0; i < sp->timecnt; ++i)
 		if (sp->types[i] == 0)
 			break;
-	i = i < sp->timecnt ? -1 : 0;
+	i = i < sp->timecnt && ! ttunspecified(sp, 0) ? -1 : 0;
 	/*
 	** Absent the above,
 	** if there are transition times
@@ -664,6 +774,9 @@
 			if (!sp->ttis[i].tt_isdst)
 				break;
 	}
+	/* The next heuristics are for data generated by tzdb 2018e or
+	   earlier, for zones like EST5EDT where the first transition
+	   is to DST.  */
 	/*
 	** If no result yet, find the first standard type.
 	** If there is none, punt to type zero.
@@ -676,7 +789,12 @@
 				break;
 			}
 	}
+	/* A simple 'sp->defaulttype = 0;' would suffice here if we
+	   didn't have to worry about 2018e-or-earlier data.  Even
+	   simpler would be to remove the defaulttype member and just
+	   use 0 in its place.  */
 	sp->defaulttype = i;
+
 	return 0;
 }
 
@@ -687,9 +805,9 @@
 {
 #ifdef ALL_STATE
   union local_storage *lsp = malloc(sizeof *lsp);
-  if (!lsp)
-    return errno;
-  else {
+  if (!lsp) {
+    return HAVE_MALLOC_ERRNO ? errno : ENOMEM;
+  } else {
     int err = tzloadbody(name, sp, doextend, lsp);
     free(lsp);
     return err;
@@ -712,12 +830,13 @@
 	else {
 		register const struct ttinfo *	ap = &sp->ttis[a];
 		register const struct ttinfo *	bp = &sp->ttis[b];
-		result = ap->tt_gmtoff == bp->tt_gmtoff &&
-			ap->tt_isdst == bp->tt_isdst &&
-			ap->tt_ttisstd == bp->tt_ttisstd &&
-			ap->tt_ttisgmt == bp->tt_ttisgmt &&
-			strcmp(&sp->chars[ap->tt_abbrind],
-			&sp->chars[bp->tt_abbrind]) == 0;
+		result = (ap->tt_utoff == bp->tt_utoff
+			  && ap->tt_isdst == bp->tt_isdst
+			  && ap->tt_ttisstd == bp->tt_ttisstd
+			  && ap->tt_ttisut == bp->tt_ttisut
+			  && (strcmp(&sp->chars[ap->tt_desigidx],
+				     &sp->chars[bp->tt_desigidx])
+			      == 0));
 	}
 	return result;
 }
@@ -731,13 +850,20 @@
 	DAYSPERNYEAR, DAYSPERLYEAR
 };
 
+/* Is C an ASCII digit?  */
+static bool
+is_digit(char c)
+{
+  return '0' <= c && c <= '9';
+}
+
 /*
-** Given a pointer into a time zone string, scan until a character that is not
-** a valid character in a zone name is found. Return a pointer to that
-** character.
+** Given a pointer into a timezone string, scan until a character that is not
+** a valid character in a time zone abbreviation is found.
+** Return a pointer to that character.
 */
 
-static const char * ATTRIBUTE_PURE
+static ATTRIBUTE_PURE const char *
 getzname(register const char *strp)
 {
 	register char	c;
@@ -749,15 +875,16 @@
 }
 
 /*
-** Given a pointer into an extended time zone string, scan until the ending
-** delimiter of the zone name is located. Return a pointer to the delimiter.
+** Given a pointer into an extended timezone string, scan until the ending
+** delimiter of the time zone abbreviation is located.
+** Return a pointer to the delimiter.
 **
 ** As with getzname above, the legal character set is actually quite
 ** restricted, with other characters producing undefined results.
 ** We don't do any checking here; checking is done later in common-case code.
 */
 
-static const char * ATTRIBUTE_PURE
+static ATTRIBUTE_PURE const char *
 getqzname(register const char *strp, const int delim)
 {
 	register int	c;
@@ -768,7 +895,7 @@
 }
 
 /*
-** Given a pointer into a time zone string, extract a number from that string.
+** Given a pointer into a timezone string, extract a number from that string.
 ** Check that the number is within a specified range; if it is not, return
 ** NULL.
 ** Otherwise, return a pointer to the first character not part of the number.
@@ -796,7 +923,7 @@
 }
 
 /*
-** Given a pointer into a time zone string, extract a number of seconds,
+** Given a pointer into a timezone string, extract a number of seconds,
 ** in hh[:mm[:ss]] form, from the string.
 ** If any error occurs, return NULL.
 ** Otherwise, return a pointer to the first character not part of the number
@@ -807,6 +934,7 @@
 getsecs(register const char *strp, int_fast32_t *const secsp)
 {
 	int	num;
+	int_fast32_t secsperhour = SECSPERHOUR;
 
 	/*
 	** 'HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
@@ -817,7 +945,7 @@
 	strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
 	if (strp == NULL)
 		return NULL;
-	*secsp = num * (int_fast32_t) SECSPERHOUR;
+	*secsp = num * secsperhour;
 	if (*strp == ':') {
 		++strp;
 		strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
@@ -837,7 +965,7 @@
 }
 
 /*
-** Given a pointer into a time zone string, extract an offset, in
+** Given a pointer into a timezone string, extract an offset, in
 ** [+-]hh[:mm[:ss]] form, from the string.
 ** If any error occurs, return NULL.
 ** Otherwise, return a pointer to the first character not part of the time.
@@ -862,7 +990,7 @@
 }
 
 /*
-** Given a pointer into a time zone string, extract a rule in the form
+** Given a pointer into a timezone string, extract a rule in the form
 ** date[/time]. See POSIX section 8 for the format of "date" and "time".
 ** If a valid rule is not found, return NULL.
 ** Otherwise, return a pointer to the first character not part of the rule.
@@ -919,7 +1047,7 @@
 ** effect, calculate the year-relative time that rule takes effect.
 */
 
-static int_fast32_t ATTRIBUTE_PURE
+static int_fast32_t
 transtime(const int year, register const struct rule *const rulep,
           const int_fast32_t offset)
 {
@@ -928,7 +1056,6 @@
     register int          i;
     int d, m1, yy0, yy1, yy2, dow;
 
-    INITIALIZE(value);
     leapyear = isleap(year);
     switch (rulep->r_type) {
 
@@ -994,6 +1121,8 @@
         for (i = 0; i < rulep->r_mon - 1; ++i)
             value += mon_lengths[leapyear][i] * SECSPERDAY;
         break;
+
+        default: UNREACHABLE();
     }
 
     /*
@@ -1011,7 +1140,7 @@
 */
 
 static bool
-tzparse(const char *name, struct state *sp, bool lastditch)
+tzparse(const char *name, struct state *sp, struct state *basep)
 {
 	const char *			stdname;
 	const char *			dstname;
@@ -1022,37 +1151,42 @@
 	int_fast32_t			dstoffset;
 	register char *			cp;
 	register bool			load_ok;
+	time_t atlo = TIME_T_MIN, leaplo = TIME_T_MIN;
 
 	stdname = name;
-	if (lastditch) {
-		stdlen = sizeof gmt - 1;
-		name += stdlen;
-		stdoffset = 0;
+	if (*name == '<') {
+	  name++;
+	  stdname = name;
+	  name = getqzname(name, '>');
+	  if (*name != '>')
+	    return false;
+	  stdlen = name - stdname;
+	  name++;
 	} else {
-		if (*name == '<') {
-			name++;
-			stdname = name;
-			name = getqzname(name, '>');
-			if (*name != '>')
-			  return false;
-			stdlen = name - stdname;
-			name++;
-		} else {
-			name = getzname(name);
-			stdlen = name - stdname;
-		}
-		if (!stdlen)
-		  return false;
-		name = getoffset(name, &stdoffset);
-		if (name == NULL)
-		  return false;
+	  name = getzname(name);
+	  stdlen = name - stdname;
 	}
+	if (!stdlen)
+	  return false;
+	name = getoffset(name, &stdoffset);
+	if (name == NULL)
+	  return false;
 	charcnt = stdlen + 1;
 	if (sizeof sp->chars < charcnt)
 	  return false;
-	load_ok = tzload(TZDEFRULES, sp, false) == 0;
-	if (!load_ok)
-		sp->leapcnt = 0;		/* so, we're off a little */
+	if (basep) {
+	  if (0 < basep->timecnt)
+	    atlo = basep->ats[basep->timecnt - 1];
+	  load_ok = false;
+	  sp->leapcnt = basep->leapcnt;
+	  memcpy(sp->lsis, basep->lsis, sp->leapcnt * sizeof *sp->lsis);
+	} else {
+	  load_ok = tzload(TZDEFRULES, sp, false) == 0;
+	  if (!load_ok)
+	    sp->leapcnt = 0;	/* So, we're off a little.  */
+	}
+	if (0 < sp->leapcnt)
+	  leaplo = sp->lsis[sp->leapcnt - 1].ls_trans;
 	if (*name != '\0') {
 		if (*name == '<') {
 			dstname = ++name;
@@ -1064,7 +1198,7 @@
 		} else {
 			dstname = name;
 			name = getzname(name);
-			dstlen = name - dstname; /* length of DST zone name */
+			dstlen = name - dstname; /* length of DST abbr. */
 		}
 		if (!dstlen)
 		  return false;
@@ -1082,9 +1216,10 @@
 			struct rule	start;
 			struct rule	end;
 			register int	year;
-			register int	yearlim;
 			register int	timecnt;
 			time_t		janfirst;
+			int_fast32_t janoffset = 0;
+			int yearbeg, yearlim;
 
 			++name;
 			if ((name = getrule(name, &start)) == NULL)
@@ -1099,13 +1234,41 @@
 			/*
 			** Two transitions per year, from EPOCH_YEAR forward.
 			*/
-			init_ttinfo(&sp->ttis[0], -dstoffset, true, stdlen + 1);
-			init_ttinfo(&sp->ttis[1], -stdoffset, false, 0);
+			init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
+			init_ttinfo(&sp->ttis[1], -dstoffset, true, stdlen + 1);
 			sp->defaulttype = 0;
 			timecnt = 0;
 			janfirst = 0;
-			yearlim = EPOCH_YEAR + YEARSPERREPEAT;
-			for (year = EPOCH_YEAR; year < yearlim; year++) {
+			yearbeg = EPOCH_YEAR;
+
+			do {
+			  int_fast32_t yearsecs
+			    = year_lengths[isleap(yearbeg - 1)] * SECSPERDAY;
+			  yearbeg--;
+			  if (increment_overflow_time(&janfirst, -yearsecs)) {
+			    janoffset = -yearsecs;
+			    break;
+			  }
+			} while (atlo < janfirst
+				 && EPOCH_YEAR - YEARSPERREPEAT / 2 < yearbeg);
+
+			while (true) {
+			  int_fast32_t yearsecs
+			    = year_lengths[isleap(yearbeg)] * SECSPERDAY;
+			  int yearbeg1 = yearbeg;
+			  time_t janfirst1 = janfirst;
+			  if (increment_overflow_time(&janfirst1, yearsecs)
+			      || increment_overflow(&yearbeg1, 1)
+			      || atlo <= janfirst1)
+			    break;
+			  yearbeg = yearbeg1;
+			  janfirst = janfirst1;
+			}
+
+			yearlim = yearbeg;
+			if (increment_overflow(&yearlim, YEARSPERREPEAT + 1))
+			  yearlim = INT_MAX;
+			for (year = yearbeg; year < yearlim; year++) {
 				int_fast32_t
 				  starttime = transtime(year, &start, stdoffset),
 				  endtime = transtime(year, &end, dstoffset);
@@ -1120,29 +1283,40 @@
 				}
 				if (reversed
 				    || (starttime < endtime
-					&& (endtime - starttime
-					    < (yearsecs
-					       + (stdoffset - dstoffset))))) {
+					&& endtime - starttime < yearsecs)) {
 					if (TZ_MAX_TIMES - 2 < timecnt)
 						break;
-					yearlim = year + YEARSPERREPEAT + 1;
 					sp->ats[timecnt] = janfirst;
-					if (increment_overflow_time
-					    (&sp->ats[timecnt], starttime))
-						break;
-					sp->types[timecnt++] = reversed;
+					if (! increment_overflow_time
+					    (&sp->ats[timecnt],
+					     janoffset + starttime)
+					    && atlo <= sp->ats[timecnt])
+					  sp->types[timecnt++] = !reversed;
 					sp->ats[timecnt] = janfirst;
-					if (increment_overflow_time
-					    (&sp->ats[timecnt], endtime))
-						break;
-					sp->types[timecnt++] = !reversed;
+					if (! increment_overflow_time
+					    (&sp->ats[timecnt],
+					     janoffset + endtime)
+					    && atlo <= sp->ats[timecnt]) {
+					  sp->types[timecnt++] = reversed;
+					}
 				}
-				if (increment_overflow_time(&janfirst, yearsecs))
+				if (endtime < leaplo) {
+				  yearlim = year;
+				  if (increment_overflow(&yearlim,
+							 YEARSPERREPEAT + 1))
+				    yearlim = INT_MAX;
+				}
+				if (increment_overflow_time
+				    (&janfirst, janoffset + yearsecs))
 					break;
+				janoffset = 0;
 			}
 			sp->timecnt = timecnt;
-			if (!timecnt)
+			if (! timecnt) {
+				sp->ttis[0] = sp->ttis[1];
 				sp->typecnt = 1;	/* Perpetual DST.  */
+			} else if (YEARSPERREPEAT < year - yearbeg)
+				sp->goback = sp->goahead = true;
 		} else {
 			register int_fast32_t	theirstdoffset;
 			register int_fast32_t	theirdstoffset;
@@ -1161,7 +1335,7 @@
 				j = sp->types[i];
 				if (!sp->ttis[j].tt_isdst) {
 					theirstdoffset =
-						-sp->ttis[j].tt_gmtoff;
+						- sp->ttis[j].tt_utoff;
 					break;
 				}
 			}
@@ -1170,7 +1344,7 @@
 				j = sp->types[i];
 				if (sp->ttis[j].tt_isdst) {
 					theirdstoffset =
-						-sp->ttis[j].tt_gmtoff;
+						- sp->ttis[j].tt_utoff;
 					break;
 				}
 			}
@@ -1178,7 +1352,6 @@
 			** Initially we're assumed to be in standard time.
 			*/
 			isdst = false;
-			theiroffset = theirstdoffset;
 			/*
 			** Now juggle transition times and types
 			** tracking offsets as you do.
@@ -1186,16 +1359,17 @@
 			for (i = 0; i < sp->timecnt; ++i) {
 				j = sp->types[i];
 				sp->types[i] = sp->ttis[j].tt_isdst;
-				if (sp->ttis[j].tt_ttisgmt) {
+				if (sp->ttis[j].tt_ttisut) {
 					/* No adjustment to transition time */
 				} else {
 					/*
-					** If summer time is in effect, and the
-					** transition time was not specified as
-					** standard time, add the summer time
-					** offset to the transition time;
-					** otherwise, add the standard time
-					** offset to the transition time.
+					** If daylight saving time is in
+					** effect, and the transition time was
+					** not specified as standard time, add
+					** the daylight saving time offset to
+					** the transition time; otherwise, add
+					** the standard time offset to the
+					** transition time.
 					*/
 					/*
 					** Transitions from DST to DDST
@@ -1211,7 +1385,7 @@
 							theirstdoffset;
 					}
 				}
-				theiroffset = -sp->ttis[j].tt_gmtoff;
+				theiroffset = -sp->ttis[j].tt_utoff;
 				if (sp->ttis[j].tt_isdst)
 					theirdstoffset = theiroffset;
 				else	theirstdoffset = theiroffset;
@@ -1247,7 +1421,7 @@
 gmtload(struct state *const sp)
 {
 	if (tzload(gmt, sp, true) != 0)
-		tzparse(gmt, sp, true);
+	  tzparse("GMT0", sp, NULL);
 }
 
 /* Initialize *SP to a value appropriate for the TZ setting NAME.
@@ -1270,7 +1444,7 @@
     return 0;
   } else {
     int err = tzload(name, sp, true);
-    if (err != 0 && name && name[0] != ':' && tzparse(name, sp, false))
+    if (err != 0 && name && name[0] != ':' && tzparse(name, sp, NULL))
       err = 0;
     if (err == 0)
       scrub_abbrs(sp);
@@ -1301,17 +1475,6 @@
   lcl_is_set = lcl;
 }
 
-#ifdef STD_INSPIRED
-void
-tzsetwall(void)
-{
-  if (lock() != 0)
-    return;
-  tzsetlcl(NULL);
-  unlock();
-}
-#endif
-
 #if defined(__BIONIC__)
 extern void tzset_unlocked(void);
 #else
@@ -1361,7 +1524,8 @@
       errno = err;
       return NULL;
     }
-  }
+  } else if (!HAVE_MALLOC_ERRNO)
+    errno = ENOMEM;
   return sp;
 }
 
@@ -1391,7 +1555,7 @@
 **
 ** If successful and SETNAME is nonzero,
 ** set the applicable parts of tzname, timezone and altzone;
-** however, it's OK to omit this step if the time zone is POSIX-compatible,
+** however, it's OK to omit this step if the timezone is POSIX-compatible,
 ** since in that case tzset should have already done this step correctly.
 ** SETNAME's type is intfast32_t for compatibility with gmtsub,
 ** but it is actually a boolean and its value should be 0 or 1.
@@ -1413,7 +1577,7 @@
 	}
 	if ((sp->goback && t < sp->ats[0]) ||
 		(sp->goahead && t > sp->ats[sp->timecnt - 1])) {
-			time_t			newt = t;
+			time_t newt;
 			register time_t		seconds;
 			register time_t		years;
 
@@ -1421,11 +1585,17 @@
 				seconds = sp->ats[0] - t;
 			else	seconds = t - sp->ats[sp->timecnt - 1];
 			--seconds;
-			years = (seconds / SECSPERREPEAT + 1) * YEARSPERREPEAT;
+
+			/* Beware integer overflow, as SECONDS might
+			   be close to the maximum time_t.  */
+			years = seconds / SECSPERREPEAT * YEARSPERREPEAT;
 			seconds = years * AVGSECSPERYEAR;
+			years += YEARSPERREPEAT;
 			if (t < sp->ats[0])
-				newt += seconds;
-			else	newt -= seconds;
+			  newt = t + seconds + SECSPERREPEAT;
+			else
+			  newt = t - seconds - SECSPERREPEAT;
+
 			if (newt < sp->ats[0] ||
 				newt > sp->ats[sp->timecnt - 1])
 					return NULL;	/* "cannot happen" */
@@ -1456,20 +1626,20 @@
 				hi = mid;
 			else	lo = mid + 1;
 		}
-		i = (int) sp->types[lo - 1];
+		i = sp->types[lo - 1];
 	}
 	ttisp = &sp->ttis[i];
 	/*
 	** To get (wrong) behavior that's compatible with System V Release 2.0
 	** you'd replace the statement below with
-	**	t += ttisp->tt_gmtoff;
+	**	t += ttisp->tt_utoff;
 	**	timesub(&t, 0L, sp, tmp);
 	*/
-	result = timesub(&t, ttisp->tt_gmtoff, sp, tmp);
+	result = timesub(&t, ttisp->tt_utoff, sp, tmp);
 	if (result) {
 	  result->tm_isdst = ttisp->tt_isdst;
 #ifdef TM_ZONE
-	  result->TM_ZONE = (char *) &sp->chars[ttisp->tt_abbrind];
+	  result->TM_ZONE = (char *) &sp->chars[ttisp->tt_desigidx];
 #endif /* defined TM_ZONE */
 	  if (setname)
 	    update_tzname_etc(sp, ttisp);
@@ -1534,7 +1704,7 @@
 #ifdef TM_ZONE
 	/*
 	** Could get fancy here and deliver something such as
-	** "UT+xxxx" or "UT-xxxx" if offset is non-zero,
+	** "+xx" or "-xx" if offset is non-zero,
 	** but this is no time for a treasure hunt.
 	*/
 	tmp->TM_ZONE = ((char *)
@@ -1576,11 +1746,18 @@
 ** where, to make the math easy, the answer for year zero is defined as zero.
 */
 
-static int ATTRIBUTE_PURE
-leaps_thru_end_of(register const int y)
+static time_t
+leaps_thru_end_of_nonneg(time_t y)
 {
-	return (y >= 0) ? (y / 4 - y / 100 + y / 400) :
-		-(leaps_thru_end_of(-(y + 1)) + 1);
+  return y / 4 - y / 100 + y / 400;
+}
+
+static time_t
+leaps_thru_end_of(time_t y)
+{
+  return (y < 0
+	  ? -1 - leaps_thru_end_of_nonneg(-1 - y)
+	  : leaps_thru_end_of_nonneg(y));
 }
 
 static struct tm *
@@ -1589,122 +1766,106 @@
 {
 	register const struct lsinfo *	lp;
 	register time_t			tdays;
-	register int			idays;	/* unsigned would be so 2003 */
-	register int_fast64_t		rem;
-	int				y;
 	register const int *		ip;
-	register int_fast64_t		corr;
-	register bool			hit;
+	register int_fast32_t		corr;
 	register int			i;
+	int_fast32_t idays, rem, dayoff, dayrem;
+	time_t y;
+
+	/* If less than SECSPERMIN, the number of seconds since the
+	   most recent positive leap second; otherwise, do not add 1
+	   to localtime tm_sec because of leap seconds.  */
+	time_t secs_since_posleap = SECSPERMIN;
 
 	corr = 0;
-	hit = false;
 	i = (sp == NULL) ? 0 : sp->leapcnt;
 	while (--i >= 0) {
 		lp = &sp->lsis[i];
 		if (*timep >= lp->ls_trans) {
-			if (*timep == lp->ls_trans) {
-				hit = ((i == 0 && lp->ls_corr > 0) ||
-					lp->ls_corr > sp->lsis[i - 1].ls_corr);
-				if (hit)
-					while (i > 0 &&
-						sp->lsis[i].ls_trans ==
-						sp->lsis[i - 1].ls_trans + 1 &&
-						sp->lsis[i].ls_corr ==
-						sp->lsis[i - 1].ls_corr + 1) {
-							++hit;
-							--i;
-					}
-			}
 			corr = lp->ls_corr;
+			if ((i == 0 ? 0 : lp[-1].ls_corr) < corr)
+			  secs_since_posleap = *timep - lp->ls_trans;
 			break;
 		}
 	}
-	y = EPOCH_YEAR;
+
+	/* Calculate the year, avoiding integer overflow even if
+	   time_t is unsigned.  */
 	tdays = *timep / SECSPERDAY;
 	rem = *timep % SECSPERDAY;
-	while (tdays < 0 || tdays >= year_lengths[isleap(y)]) {
-		int		newy;
-		register time_t	tdelta;
-		register int	idelta;
+	rem += offset % SECSPERDAY - corr % SECSPERDAY + 3 * SECSPERDAY;
+	dayoff = offset / SECSPERDAY - corr / SECSPERDAY + rem / SECSPERDAY - 3;
+	rem %= SECSPERDAY;
+	/* y = (EPOCH_YEAR
+	        + floor((tdays + dayoff) / DAYSPERREPEAT) * YEARSPERREPEAT),
+	   sans overflow.  But calculate against 1570 (EPOCH_YEAR -
+	   YEARSPERREPEAT) instead of against 1970 so that things work
+	   for localtime values before 1970 when time_t is unsigned.  */
+	dayrem = tdays % DAYSPERREPEAT;
+	dayrem += dayoff % DAYSPERREPEAT;
+	y = (EPOCH_YEAR - YEARSPERREPEAT
+	     + ((1 + dayoff / DAYSPERREPEAT + dayrem / DAYSPERREPEAT
+		 - ((dayrem % DAYSPERREPEAT) < 0)
+		 + tdays / DAYSPERREPEAT)
+		* YEARSPERREPEAT));
+	/* idays = (tdays + dayoff) mod DAYSPERREPEAT, sans overflow.  */
+	idays = tdays % DAYSPERREPEAT;
+	idays += dayoff % DAYSPERREPEAT + 2 * DAYSPERREPEAT;
+	idays %= DAYSPERREPEAT;
+	/* Increase Y and decrease IDAYS until IDAYS is in range for Y.  */
+	while (year_lengths[isleap(y)] <= idays) {
+		int tdelta = idays / DAYSPERLYEAR;
+		int_fast32_t ydelta = tdelta + !tdelta;
+		time_t newy = y + ydelta;
 		register int	leapdays;
-
-		tdelta = tdays / DAYSPERLYEAR;
-		if (! ((! TYPE_SIGNED(time_t) || INT_MIN <= tdelta)
-		       && tdelta <= INT_MAX))
-		  goto out_of_range;
-		idelta = tdelta;
-		if (idelta == 0)
-			idelta = (tdays < 0) ? -1 : 1;
-		newy = y;
-		if (increment_overflow(&newy, idelta))
-		  goto out_of_range;
 		leapdays = leaps_thru_end_of(newy - 1) -
 			leaps_thru_end_of(y - 1);
-		tdays -= ((time_t) newy - y) * DAYSPERNYEAR;
-		tdays -= leapdays;
+		idays -= ydelta * DAYSPERNYEAR;
+		idays -= leapdays;
 		y = newy;
 	}
-	/*
-	** Given the range, we can now fearlessly cast...
-	*/
-	idays = tdays;
-	rem += offset - corr;
-	while (rem < 0) {
-		rem += SECSPERDAY;
-		--idays;
+
+	if (!TYPE_SIGNED(time_t) && y < TM_YEAR_BASE) {
+	  int signed_y = y;
+	  tmp->tm_year = signed_y - TM_YEAR_BASE;
+	} else if ((!TYPE_SIGNED(time_t) || INT_MIN + TM_YEAR_BASE <= y)
+		   && y - TM_YEAR_BASE <= INT_MAX)
+	  tmp->tm_year = y - TM_YEAR_BASE;
+	else {
+	  errno = EOVERFLOW;
+	  return NULL;
 	}
-	while (rem >= SECSPERDAY) {
-		rem -= SECSPERDAY;
-		++idays;
-	}
-	while (idays < 0) {
-		if (increment_overflow(&y, -1))
-		  goto out_of_range;
-		idays += year_lengths[isleap(y)];
-	}
-	while (idays >= year_lengths[isleap(y)]) {
-		idays -= year_lengths[isleap(y)];
-		if (increment_overflow(&y, 1))
-		  goto out_of_range;
-	}
-	tmp->tm_year = y;
-	if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE))
-	  goto out_of_range;
 	tmp->tm_yday = idays;
 	/*
 	** The "extra" mods below avoid overflow problems.
 	*/
-	tmp->tm_wday = EPOCH_WDAY +
-		((y - EPOCH_YEAR) % DAYSPERWEEK) *
-		(DAYSPERNYEAR % DAYSPERWEEK) +
-		leaps_thru_end_of(y - 1) -
-		leaps_thru_end_of(EPOCH_YEAR - 1) +
-		idays;
+	tmp->tm_wday = (TM_WDAY_BASE
+			+ ((tmp->tm_year % DAYSPERWEEK)
+			   * (DAYSPERNYEAR % DAYSPERWEEK))
+			+ leaps_thru_end_of(y - 1)
+			- leaps_thru_end_of(TM_YEAR_BASE - 1)
+			+ idays);
 	tmp->tm_wday %= DAYSPERWEEK;
 	if (tmp->tm_wday < 0)
 		tmp->tm_wday += DAYSPERWEEK;
-	tmp->tm_hour = (int) (rem / SECSPERHOUR);
+	tmp->tm_hour = rem / SECSPERHOUR;
 	rem %= SECSPERHOUR;
-	tmp->tm_min = (int) (rem / SECSPERMIN);
-	/*
-	** A positive leap second requires a special
-	** representation. This uses "... ??:59:60" et seq.
-	*/
-	tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
+	tmp->tm_min = rem / SECSPERMIN;
+	tmp->tm_sec = rem % SECSPERMIN;
+
+	/* Use "... ??:??:60" at the end of the localtime minute containing
+	   the second just before the positive leap second.  */
+	tmp->tm_sec += secs_since_posleap <= tmp->tm_sec;
+
 	ip = mon_lengths[isleap(y)];
 	for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon))
 		idays -= ip[tmp->tm_mon];
-	tmp->tm_mday = (int) (idays + 1);
+	tmp->tm_mday = idays + 1;
 	tmp->tm_isdst = 0;
 #ifdef TM_GMTOFF
 	tmp->TM_GMTOFF = offset;
 #endif /* defined TM_GMTOFF */
 	return tmp;
-
- out_of_range:
-	errno = EOVERFLOW;
-	return NULL;
 }
 
 char *
@@ -1778,12 +1939,12 @@
 {
 	/*
 	** This is like
-	** 'if (! (time_t_min <= *tp + j && *tp + j <= time_t_max)) ...',
+	** 'if (! (TIME_T_MIN <= *tp + j && *tp + j <= TIME_T_MAX)) ...',
 	** except that it does the right thing even if *tp + j would overflow.
 	*/
 	if (! (j < 0
-	       ? (TYPE_SIGNED(time_t) ? time_t_min - j <= *tp : -1 - j < *tp)
-	       : *tp <= time_t_max - j))
+	       ? (TYPE_SIGNED(time_t) ? TIME_T_MIN - j <= *tp : -1 - j < *tp)
+	       : *tp <= TIME_T_MAX - j))
 		return true;
 	*tp += j;
 	return false;
@@ -1919,8 +2080,8 @@
 	/*
 	** Do a binary search (this works whatever time_t's type is).
 	*/
-	lo = time_t_min;
-	hi = time_t_max;
+	lo = TIME_T_MIN;
+	hi = TIME_T_MAX;
 	for ( ; ; ) {
 		t = lo / 2 + hi / 2;
 		if (t < lo)
@@ -1937,12 +2098,12 @@
 		} else	dir = tmcomp(&mytm, &yourtm);
 		if (dir != 0) {
 			if (t == lo) {
-				if (t == time_t_max)
+				if (t == TIME_T_MAX)
 					return WRONG;
 				++t;
 				++lo;
 			} else if (t == hi) {
-				if (t == time_t_min)
+				if (t == TIME_T_MIN)
 					return WRONG;
 				--t;
 				--hi;
@@ -1959,13 +2120,13 @@
 		    && (yourtm.TM_GMTOFF < 0
 			? (-SECSPERDAY <= yourtm.TM_GMTOFF
 			   && (mytm.TM_GMTOFF <=
-			       (SMALLEST (INT_FAST32_MAX, LONG_MAX)
+			       (SMALLEST(INT_FAST32_MAX, LONG_MAX)
 				+ yourtm.TM_GMTOFF)))
 			: (yourtm.TM_GMTOFF <= SECSPERDAY
-			   && ((BIGGEST (INT_FAST32_MIN, LONG_MIN)
+			   && ((BIGGEST(INT_FAST32_MIN, LONG_MIN)
 				+ yourtm.TM_GMTOFF)
 			       <= mytm.TM_GMTOFF)))) {
-		  /* MYTM matches YOURTM except with the wrong UTC offset.
+		  /* MYTM matches YOURTM except with the wrong UT offset.
 		     YOURTM.TM_GMTOFF is plausible, so try it instead.
 		     It's OK if YOURTM.TM_GMTOFF contains uninitialized data,
 		     since the guess gets checked.  */
@@ -1999,8 +2160,10 @@
 			for (j = sp->typecnt - 1; j >= 0; --j) {
 				if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)
 					continue;
-				newt = t + sp->ttis[j].tt_gmtoff -
-					sp->ttis[i].tt_gmtoff;
+				if (ttunspecified(sp, j))
+				  continue;
+				newt = (t + sp->ttis[j].tt_utoff
+					- sp->ttis[i].tt_utoff);
 				if (! funcp(sp, &newt, offset, &mytm))
 					continue;
 				if (tmcomp(&mytm, &yourtm) != 0)
@@ -2047,8 +2210,8 @@
 
 static time_t
 time1(struct tm *const tmp,
-      struct tm *(*funcp) (struct state const *, time_t const *,
-			   int_fast32_t, struct tm *),
+      struct tm *(*funcp)(struct state const *, time_t const *,
+			  int_fast32_t, struct tm *),
       struct state const *sp,
       const int_fast32_t offset)
 {
@@ -2091,7 +2254,7 @@
 		seen[i] = false;
 	nseen = 0;
 	for (i = sp->timecnt - 1; i >= 0; --i)
-		if (!seen[sp->types[i]]) {
+		if (!seen[sp->types[i]] && !ttunspecified(sp, sp->types[i])) {
 			seen[sp->types[i]] = true;
 			types[nseen++] = sp->types[i];
 		}
@@ -2103,14 +2266,14 @@
 			otheri = types[otherind];
 			if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
 				continue;
-			tmp->tm_sec += sp->ttis[otheri].tt_gmtoff -
-					sp->ttis[samei].tt_gmtoff;
+			tmp->tm_sec += (sp->ttis[otheri].tt_utoff
+					- sp->ttis[samei].tt_utoff);
 			tmp->tm_isdst = !tmp->tm_isdst;
 			t = time2(tmp, funcp, sp, offset, &okay);
 			if (okay)
 				return t;
-			tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff -
-					sp->ttis[samei].tt_gmtoff;
+			tmp->tm_sec -= (sp->ttis[otheri].tt_utoff
+					- sp->ttis[samei].tt_utoff);
 			tmp->tm_isdst = !tmp->tm_isdst;
 		}
 	}
@@ -2188,21 +2351,7 @@
 
 #endif /* defined STD_INSPIRED */
 
-/*
-** XXX--is the below the right way to conditionalize??
-*/
-
-#ifdef STD_INSPIRED
-
-/*
-** IEEE Std 1003.1-1988 (POSIX) legislates that 536457599
-** shall correspond to "Wed Dec 31 23:59:59 UTC 1986", which
-** is not the case if we are accounting for leap seconds.
-** So, we provide the following conversion routines for use
-** when exchanging timestamps with POSIX conforming systems.
-*/
-
-static int_fast64_t
+static int_fast32_t
 leapcorr(struct state const *sp, time_t t)
 {
 	register struct lsinfo const *	lp;
@@ -2217,7 +2366,29 @@
 	return 0;
 }
 
-NETBSD_INSPIRED_EXTERN time_t ATTRIBUTE_PURE
+/*
+** XXX--is the below the right way to conditionalize??
+*/
+
+#ifdef STD_INSPIRED
+
+/* NETBSD_INSPIRED_EXTERN functions are exported to callers if
+   NETBSD_INSPIRED is defined, and are private otherwise.  */
+# if NETBSD_INSPIRED
+#  define NETBSD_INSPIRED_EXTERN
+# else
+#  define NETBSD_INSPIRED_EXTERN static
+# endif
+
+/*
+** IEEE Std 1003.1 (POSIX) says that 536457599
+** shall correspond to "Wed Dec 31 23:59:59 UTC 1986", which
+** is not the case if we are accounting for leap seconds.
+** So, we provide the following conversion routines for use
+** when exchanging timestamps with POSIX conforming systems.
+*/
+
+NETBSD_INSPIRED_EXTERN time_t
 time2posix_z(struct state *sp, time_t t)
 {
   return t - leapcorr(sp, t);
@@ -2239,7 +2410,7 @@
   return t;
 }
 
-NETBSD_INSPIRED_EXTERN time_t ATTRIBUTE_PURE
+NETBSD_INSPIRED_EXTERN time_t
 posix2time_z(struct state *sp, time_t t)
 {
 	time_t	x;
@@ -2286,15 +2457,39 @@
 
 #endif /* defined STD_INSPIRED */
 
-#ifdef time_tz
+#if TZ_TIME_T
+
+# if !USG_COMPAT
+#  define daylight 0
+#  define timezone 0
+# endif
+# if !ALTZONE
+#  define altzone 0
+# endif
 
 /* Convert from the underlying system's time_t to the ersatz time_tz,
-   which is called 'time_t' in this file.  */
+   which is called 'time_t' in this file.  Typically, this merely
+   converts the time's integer width.  On some platforms, the system
+   time is local time not UT, or uses some epoch other than the POSIX
+   epoch.
+
+   Although this code appears to define a function named 'time' that
+   returns time_t, the macros in private.h cause this code to actually
+   define a function named 'tz_time' that returns tz_time_t.  The call
+   to sys_time invokes the underlying system's 'time' function.  */
 
 time_t
 time(time_t *p)
 {
   time_t r = sys_time(0);
+  if (r != (time_t) -1) {
+    int_fast32_t offset = EPOCH_LOCAL ? (daylight ? timezone : altzone) : 0;
+    if (increment_overflow32(&offset, -EPOCH_OFFSET)
+	|| increment_overflow_time(&r, offset)) {
+      errno = EOVERFLOW;
+      r = -1;
+    }
+  }
   if (p)
     *p = r;
   return r;
diff --git a/libc/tzcode/private.h b/libc/tzcode/private.h
index 941e91b..4c03324 100644
--- a/libc/tzcode/private.h
+++ b/libc/tzcode/private.h
@@ -1,3 +1,5 @@
+/* Private header for tzdb code.  */
+
 #ifndef PRIVATE_H
 
 #define PRIVATE_H
@@ -15,6 +17,17 @@
 ** Thank you!
 */
 
+/*
+** zdump has been made independent of the rest of the time
+** conversion package to increase confidence in the verification it provides.
+** You can use zdump to help in verifying other implementations.
+** To do this, compile with -DUSE_LTZ=0 and link without the tz library.
+*/
+#ifndef USE_LTZ
+# define USE_LTZ 1
+#endif
+
+/* This string was in the Factory zone through version 2016f.  */
 #define GRANDPARENTED	"Local time zone must be set--see zic manual page"
 
 /*
@@ -26,26 +39,53 @@
 #define HAVE_DECL_ASCTIME_R 1
 #endif
 
+#if !defined HAVE_GENERIC && defined __has_extension
+# if __has_extension(c_generic_selections)
+#  define HAVE_GENERIC 1
+# else
+#  define HAVE_GENERIC 0
+# endif
+#endif
+/* _Generic is buggy in pre-4.9 GCC.  */
+#if !defined HAVE_GENERIC && defined __GNUC__
+# define HAVE_GENERIC (4 < __GNUC__ + (9 <= __GNUC_MINOR__))
+#endif
+#ifndef HAVE_GENERIC
+# define HAVE_GENERIC (201112 <= __STDC_VERSION__)
+#endif
+
 #ifndef HAVE_GETTEXT
 #define HAVE_GETTEXT		0
 #endif /* !defined HAVE_GETTEXT */
 
 #ifndef HAVE_INCOMPATIBLE_CTIME_R
 #define HAVE_INCOMPATIBLE_CTIME_R	0
-#endif /* !defined INCOMPATIBLE_CTIME_R */
+#endif
 
 #ifndef HAVE_LINK
 #define HAVE_LINK		1
 #endif /* !defined HAVE_LINK */
 
+#ifndef HAVE_MALLOC_ERRNO
+#define HAVE_MALLOC_ERRNO 1
+#endif
+
 #ifndef HAVE_POSIX_DECLS
 #define HAVE_POSIX_DECLS 1
 #endif
 
+#ifndef HAVE_STDBOOL_H
+#define HAVE_STDBOOL_H (199901 <= __STDC_VERSION__)
+#endif
+
 #ifndef HAVE_STRDUP
 #define HAVE_STRDUP 1
 #endif
 
+#ifndef HAVE_STRTOLL
+#define HAVE_STRTOLL 1
+#endif
+
 #ifndef HAVE_SYMLINK
 #define HAVE_SYMLINK		1
 #endif /* !defined HAVE_SYMLINK */
@@ -54,10 +94,6 @@
 #define HAVE_SYS_STAT_H		1
 #endif /* !defined HAVE_SYS_STAT_H */
 
-#ifndef HAVE_SYS_WAIT_H
-#define HAVE_SYS_WAIT_H		1
-#endif /* !defined HAVE_SYS_WAIT_H */
-
 #ifndef HAVE_UNISTD_H
 #define HAVE_UNISTD_H		1
 #endif /* !defined HAVE_UNISTD_H */
@@ -75,22 +111,37 @@
 #define ctime_r _incompatible_ctime_r
 #endif /* HAVE_INCOMPATIBLE_CTIME_R */
 
-/* Enable tm_gmtoff and tm_zone on GNUish systems.  */
+/* Enable tm_gmtoff, tm_zone, and environ on GNUish systems.  */
 #define _GNU_SOURCE 1
-/* Fix asctime_r on Solaris 10.  */
+/* Fix asctime_r on Solaris 11.  */
 #define _POSIX_PTHREAD_SEMANTICS 1
-/* Enable strtoimax on Solaris 10.  */
+/* Enable strtoimax on pre-C99 Solaris 11.  */
 #define __EXTENSIONS__ 1
 
+/* To avoid having 'stat' fail unnecessarily with errno == EOVERFLOW,
+   enable large files on GNUish systems ...  */
+#ifndef _FILE_OFFSET_BITS
+# define _FILE_OFFSET_BITS 64
+#endif
+/* ... and on AIX ...  */
+#define _LARGE_FILES 1
+/* ... and enable large inode numbers on Mac OS X 10.5 and later.  */
+#define _DARWIN_USE_64_BIT_INODE 1
+
 /*
 ** Nested includes
 */
 
-/* Avoid clashes with NetBSD by renaming NetBSD's declarations.  */
+/* Avoid clashes with NetBSD by renaming NetBSD's declarations.
+   If defining the 'timezone' variable, avoid a clash with FreeBSD's
+   'timezone' function by renaming its declaration.  */
 #define localtime_rz sys_localtime_rz
 #define mktime_z sys_mktime_z
 #define posix2time_z sys_posix2time_z
 #define time2posix_z sys_time2posix_z
+#if defined USG_COMPAT && USG_COMPAT == 2
+# define timezone sys_timezone
+#endif
 #define timezone_t sys_timezone_t
 #define tzalloc sys_tzalloc
 #define tzfree sys_tzfree
@@ -99,21 +150,30 @@
 #undef mktime_z
 #undef posix2time_z
 #undef time2posix_z
+#if defined USG_COMPAT && USG_COMPAT == 2
+# undef timezone
+#endif
 #undef timezone_t
 #undef tzalloc
 #undef tzfree
 
-#include "sys/types.h"	/* for time_t */
-#include "stdio.h"
-#include "string.h"
-#include "limits.h"	/* for CHAR_BIT et al. */
-#include "stdlib.h"
+#include <sys/types.h>	/* for time_t */
+#include <string.h>
+#include <limits.h>	/* for CHAR_BIT et al. */
+#include <stdlib.h>
 
-#include "errno.h"
+#include <errno.h>
+
+#ifndef EINVAL
+# define EINVAL ERANGE
+#endif
 
 #ifndef ENAMETOOLONG
 # define ENAMETOOLONG EINVAL
 #endif
+#ifndef ENOMEM
+# define ENOMEM EINVAL
+#endif
 #ifndef ENOTSUP
 # define ENOTSUP EINVAL
 #endif
@@ -122,22 +182,11 @@
 #endif
 
 #if HAVE_GETTEXT
-#include "libintl.h"
+#include <libintl.h>
 #endif /* HAVE_GETTEXT */
 
-#if HAVE_SYS_WAIT_H
-#include <sys/wait.h>	/* for WIFEXITED and WEXITSTATUS */
-#endif /* HAVE_SYS_WAIT_H */
-
-#ifndef WIFEXITED
-#define WIFEXITED(status)	(((status) & 0xff) == 0)
-#endif /* !defined WIFEXITED */
-#ifndef WEXITSTATUS
-#define WEXITSTATUS(status)	(((status) >> 8) & 0xff)
-#endif /* !defined WEXITSTATUS */
-
 #if HAVE_UNISTD_H
-#include "unistd.h"	/* for F_OK, R_OK, and other POSIX goodness */
+#include <unistd.h>	/* for R_OK, and other POSIX goodness */
 #endif /* HAVE_UNISTD_H */
 
 #ifndef HAVE_STRFTIME_L
@@ -148,31 +197,49 @@
 # endif
 #endif
 
-#ifndef F_OK
-#define F_OK	0
-#endif /* !defined F_OK */
+#ifndef USG_COMPAT
+# ifndef _XOPEN_VERSION
+#  define USG_COMPAT 0
+# else
+#  define USG_COMPAT 1
+# endif
+#endif
+
+#ifndef HAVE_TZNAME
+# if _POSIX_VERSION < 198808 && !USG_COMPAT
+#  define HAVE_TZNAME 0
+# else
+#  define HAVE_TZNAME 1
+# endif
+#endif
+
+#ifndef ALTZONE
+# if defined __sun || defined _M_XENIX
+#  define ALTZONE 1
+# else
+#  define ALTZONE 0
+# endif
+#endif
+
 #ifndef R_OK
 #define R_OK	4
 #endif /* !defined R_OK */
 
-/* Unlike <ctype.h>'s isdigit, this also works if c < 0 | c > UCHAR_MAX. */
-#define is_digit(c) ((unsigned)(c) - '0' <= 9)
-
 /*
 ** Define HAVE_STDINT_H's default value here, rather than at the
-** start, since __GLIBC__'s value depends on previously-included
-** files.
-** (glibc 2.1 and later have stdint.h, even with pre-C99 compilers.)
+** start, since __GLIBC__ and INTMAX_MAX's values depend on
+** previously-included files.  glibc 2.1 and Solaris 10 and later have
+** stdint.h, even with pre-C99 compilers.
 */
 #ifndef HAVE_STDINT_H
 #define HAVE_STDINT_H \
    (199901 <= __STDC_VERSION__ \
     || 2 < __GLIBC__ + (1 <= __GLIBC_MINOR__)	\
-    || __CYGWIN__)
+    || __CYGWIN__ || INTMAX_MAX)
 #endif /* !defined HAVE_STDINT_H */
 
 #if HAVE_STDINT_H
-#include "stdint.h"
+#include <stdint.h>
 #endif /* !HAVE_STDINT_H */
 
 #ifndef HAVE_INTTYPES_H
@@ -208,14 +275,18 @@
 # endif
 #endif
 
-#ifndef SCNdFAST64
+#ifndef PRIdFAST64
 # if INT_FAST64_MAX == LLONG_MAX
-#  define SCNdFAST64 "lld"
+#  define PRIdFAST64 "lld"
 # else
-#  define SCNdFAST64 "ld"
+#  define PRIdFAST64 "ld"
 # endif
 #endif
 
+#ifndef SCNdFAST64
+# define SCNdFAST64 PRIdFAST64
+#endif
+
 #ifndef INT_FAST32_MAX
 # if INT_MAX >> 31 == 0
 typedef long int_fast32_t;
@@ -231,15 +302,19 @@
 #ifndef INTMAX_MAX
 # ifdef LLONG_MAX
 typedef long long intmax_t;
-#  define strtoimax strtoll
+#  if HAVE_STRTOLL
+#   define strtoimax strtoll
+#  endif
 #  define INTMAX_MAX LLONG_MAX
 #  define INTMAX_MIN LLONG_MIN
 # else
 typedef long intmax_t;
-#  define strtoimax strtol
 #  define INTMAX_MAX LONG_MAX
 #  define INTMAX_MIN LONG_MIN
 # endif
+# ifndef strtoimax
+#  define strtoimax strtol
+# endif
 #endif
 
 #ifndef PRIdMAX
@@ -250,6 +325,10 @@
 # endif
 #endif
 
+#ifndef UINT_FAST32_MAX
+typedef unsigned long uint_fast32_t;
+#endif
+
 #ifndef UINT_FAST64_MAX
 # if defined ULLONG_MAX || defined __LONG_LONG_MAX__
 typedef unsigned long long uint_fast64_t;
@@ -289,19 +368,21 @@
 #define SIZE_MAX ((size_t) -1)
 #endif
 
-#if 2 < __GNUC__ + (96 <= __GNUC_MINOR__)
-# define ATTRIBUTE_CONST __attribute__ ((const))
-# define ATTRIBUTE_PURE __attribute__ ((__pure__))
-# define ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec))
+#if 3 <= __GNUC__
+# define ATTRIBUTE_CONST __attribute__((const))
+# define ATTRIBUTE_MALLOC __attribute__((__malloc__))
+# define ATTRIBUTE_PURE __attribute__((__pure__))
+# define ATTRIBUTE_FORMAT(spec) __attribute__((__format__ spec))
 #else
 # define ATTRIBUTE_CONST /* empty */
+# define ATTRIBUTE_MALLOC /* empty */
 # define ATTRIBUTE_PURE /* empty */
 # define ATTRIBUTE_FORMAT(spec) /* empty */
 #endif
 
 #if !defined _Noreturn && __STDC_VERSION__ < 201112
 # if 2 < __GNUC__ + (8 <= __GNUC_MINOR__)
-#  define _Noreturn __attribute__ ((__noreturn__))
+#  define _Noreturn __attribute__((__noreturn__))
 # else
 #  define _Noreturn
 # endif
@@ -315,6 +396,23 @@
 ** Workarounds for compilers/systems.
 */
 
+#ifndef EPOCH_LOCAL
+# define EPOCH_LOCAL 0
+#endif
+#ifndef EPOCH_OFFSET
+# define EPOCH_OFFSET 0
+#endif
+#ifndef RESERVE_STD_EXT_IDS
+# define RESERVE_STD_EXT_IDS 0
+#endif
+
+/* If standard C identifiers with external linkage (e.g., localtime)
+   are reserved and are not already being renamed anyway, rename them
+   as if compiling with '-Dtime_tz=time_t'.  */
+#if !defined time_tz && RESERVE_STD_EXT_IDS && USE_LTZ
+# define time_tz time_t
+#endif
+
 /*
 ** Compile with -Dtime_tz=T to build the tz package with a private
 ** time_t type equivalent to T rather than the system-supplied time_t.
@@ -322,13 +420,24 @@
 ** (e.g., time_t wider than 'long', or unsigned time_t) even on
 ** typical platforms.
 */
-#ifdef time_tz
-# ifdef LOCALTIME_IMPLEMENTATION
+#if defined time_tz || EPOCH_LOCAL || EPOCH_OFFSET != 0
+# define TZ_TIME_T 1
+#else
+# define TZ_TIME_T 0
+#endif
+
+#if defined LOCALTIME_IMPLEMENTATION && TZ_TIME_T
 static time_t sys_time(time_t *x) { return time(x); }
-# endif
+#endif
+
+#if TZ_TIME_T
 
 typedef time_tz tz_time_t;
 
+# undef  asctime
+# define asctime tz_asctime
+# undef  asctime_r
+# define asctime_r tz_asctime_r
 # undef  ctime
 # define ctime tz_ctime
 # undef  ctime_r
@@ -355,6 +464,8 @@
 # define posix2time tz_posix2time
 # undef  posix2time_z
 # define posix2time_z tz_posix2time_z
+# undef  strftime
+# define strftime tz_strftime
 # undef  time
 # define time tz_time
 # undef  time2posix
@@ -375,12 +486,36 @@
 # define tzfree tz_tzfree
 # undef  tzset
 # define tzset tz_tzset
-# undef  tzsetwall
-# define tzsetwall tz_tzsetwall
+# if HAVE_STRFTIME_L
+#  undef  strftime_l
+#  define strftime_l tz_strftime_l
+# endif
+# if HAVE_TZNAME
+#  undef  tzname
+#  define tzname tz_tzname
+# endif
+# if USG_COMPAT
+#  undef  daylight
+#  define daylight tz_daylight
+#  undef  timezone
+#  define timezone tz_timezone
+# endif
+# if ALTZONE
+#  undef  altzone
+#  define altzone tz_altzone
+# endif
 
+char *asctime(struct tm const *);
+char *asctime_r(struct tm const *restrict, char *restrict);
 char *ctime(time_t const *);
 char *ctime_r(time_t const *, char *);
-double difftime(time_t, time_t);
+double difftime(time_t, time_t) ATTRIBUTE_CONST;
+size_t strftime(char *restrict, size_t, char const *restrict,
+		struct tm const *restrict);
+# if HAVE_STRFTIME_L
+size_t strftime_l(char *restrict, size_t, char const *restrict,
+		  struct tm const *restrict, locale_t);
+# endif
 struct tm *gmtime(time_t const *);
 struct tm *gmtime_r(time_t const *restrict, struct tm *restrict);
 struct tm *localtime(time_t const *);
@@ -394,18 +529,26 @@
 extern char *asctime_r(struct tm const *restrict, char *restrict);
 #endif
 
-#if !HAVE_POSIX_DECLS
-# ifdef USG_COMPAT
-#  ifndef timezone
-extern long timezone;
-#  endif
-#  ifndef daylight
-extern int daylight;
-#  endif
+#ifndef HAVE_DECL_ENVIRON
+# if defined environ || defined __USE_GNU
+#  define HAVE_DECL_ENVIRON 1
+# else
+#  define HAVE_DECL_ENVIRON 0
 # endif
 #endif
 
-#if defined ALTZONE && !defined altzone
+#if !HAVE_DECL_ENVIRON
+extern char **environ;
+#endif
+
+#if 2 <= HAVE_TZNAME + (TZ_TIME_T || !HAVE_POSIX_DECLS)
+extern char *tzname[];
+#endif
+#if 2 <= USG_COMPAT + (TZ_TIME_T || !HAVE_POSIX_DECLS)
+extern long timezone;
+extern int daylight;
+#endif
+#if 2 <= ALTZONE + (TZ_TIME_T || !HAVE_POSIX_DECLS)
 extern long altzone;
 #endif
 
@@ -415,25 +558,22 @@
 */
 
 #ifdef STD_INSPIRED
-# if !defined tzsetwall || defined time_tz
-void tzsetwall(void);
-# endif
-# if !defined offtime || defined time_tz
+# if TZ_TIME_T || !defined offtime
 struct tm *offtime(time_t const *, long);
 # endif
-# if !defined timegm || defined time_tz
+# if TZ_TIME_T || !defined timegm
 time_t timegm(struct tm *);
 # endif
-# if !defined timelocal || defined time_tz
+# if TZ_TIME_T || !defined timelocal
 time_t timelocal(struct tm *);
 # endif
-# if !defined timeoff || defined time_tz
+# if TZ_TIME_T || !defined timeoff
 time_t timeoff(struct tm *, long);
 # endif
-# if !defined time2posix || defined time_tz
+# if TZ_TIME_T || !defined time2posix
 time_t time2posix(time_t);
 # endif
-# if !defined posix2time || defined time_tz
+# if TZ_TIME_T || !defined posix2time
 time_t posix2time(time_t);
 # endif
 #endif
@@ -467,10 +607,10 @@
 timezone_t tzalloc(char const *);
 void tzfree(timezone_t);
 # ifdef STD_INSPIRED
-#  if !defined posix2time_z || defined time_tz
+#  if TZ_TIME_T || !defined posix2time_z
 time_t posix2time_z(timezone_t, time_t) ATTRIBUTE_PURE;
 #  endif
-#  if !defined time2posix_z || defined time_tz
+#  if TZ_TIME_T || !defined time2posix_z
 time_t time2posix_z(timezone_t, time_t) ATTRIBUTE_PURE;
 #  endif
 # endif
@@ -480,22 +620,16 @@
 ** Finally, some convenience items.
 */
 
-#if __STDC_VERSION__ < 199901
+#if HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
 # define true 1
 # define false 0
 # define bool int
-#else
-# include <stdbool.h>
 #endif
 
-#ifndef TYPE_BIT
-#define TYPE_BIT(type)	(sizeof (type) * CHAR_BIT)
-#endif /* !defined TYPE_BIT */
-
-#ifndef TYPE_SIGNED
+#define TYPE_BIT(type)	(sizeof(type) * CHAR_BIT)
 #define TYPE_SIGNED(type) (((type) -1) < 0)
-#endif /* !defined TYPE_SIGNED */
-
 #define TWOS_COMPLEMENT(t) ((t) ~ (t) 0 < 0)
 
 /* Max and min values of the integer type T, of which only the bottom
@@ -507,11 +641,34 @@
 #define MINVAL(t, b)						\
   ((t) (TYPE_SIGNED(t) ? - TWOS_COMPLEMENT(t) - MAXVAL(t, b) : 0))
 
-/* The minimum and maximum finite time values.  This assumes no padding.  */
-static time_t const time_t_min = MINVAL(time_t, TYPE_BIT(time_t));
-static time_t const time_t_max = MAXVAL(time_t, TYPE_BIT(time_t));
+/* The extreme time values, assuming no padding.  */
+#define TIME_T_MIN_NO_PADDING MINVAL(time_t, TYPE_BIT(time_t))
+#define TIME_T_MAX_NO_PADDING MAXVAL(time_t, TYPE_BIT(time_t))
 
-#ifndef INT_STRLEN_MAXIMUM
+/* The extreme time values.  These are macros, not constants, so that
+   any portability problems occur only when compiling .c files that use
+   the macros, which is safer for applications that need only zdump and zic.
+   This implementation assumes no padding if time_t is signed and
+   either the compiler lacks support for _Generic or time_t is not one
+   of the standard signed integer types.  */
+#if HAVE_GENERIC
+# define TIME_T_MIN \
+    _Generic((time_t) 0, \
+	     signed char: SCHAR_MIN, short: SHRT_MIN, \
+	     int: INT_MIN, long: LONG_MIN, long long: LLONG_MIN, \
+	     default: TIME_T_MIN_NO_PADDING)
+# define TIME_T_MAX \
+    (TYPE_SIGNED(time_t) \
+     ? _Generic((time_t) 0, \
+		signed char: SCHAR_MAX, short: SHRT_MAX, \
+		int: INT_MAX, long: LONG_MAX, long long: LLONG_MAX, \
+		default: TIME_T_MAX_NO_PADDING)			    \
+     : (time_t) -1)
+#else
+# define TIME_T_MIN TIME_T_MIN_NO_PADDING
+# define TIME_T_MAX TIME_T_MAX_NO_PADDING
+#endif
+
 /*
 ** 302 / 1000 is log10(2.0) rounded up.
 ** Subtract one for the sign bit if the type is signed;
@@ -521,13 +678,12 @@
 #define INT_STRLEN_MAXIMUM(type) \
 	((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 1000 + \
 	1 + TYPE_SIGNED(type))
-#endif /* !defined INT_STRLEN_MAXIMUM */
 
 /*
 ** INITIALIZE(x)
 */
 
-#ifdef lint
+#ifdef GCC_LINT
 # define INITIALIZE(x)	((x) = 0)
 #else
 # define INITIALIZE(x)
@@ -537,19 +693,30 @@
 # define UNINIT_TRAP 0
 #endif
 
+#ifdef DEBUG
+# define UNREACHABLE() abort()
+#elif 4 < __GNUC__ + (5 <= __GNUC_MINOR__)
+# define UNREACHABLE() __builtin_unreachable()
+#elif defined __has_builtin
+# if __has_builtin(__builtin_unreachable)
+#  define UNREACHABLE() __builtin_unreachable()
+# endif
+#endif
+#ifndef UNREACHABLE
+# define UNREACHABLE() ((void) 0)
+#endif
+
 /*
 ** For the benefit of GNU folk...
 ** '_(MSGID)' uses the current locale's message library string for MSGID.
 ** The default is to use gettext if available, and use MSGID otherwise.
 */
 
-#ifndef _
 #if HAVE_GETTEXT
 #define _(msgid) gettext(msgid)
 #else /* !HAVE_GETTEXT */
 #define _(msgid) msgid
 #endif /* !HAVE_GETTEXT */
-#endif /* !defined _ */
 
 #if !defined TZ_DOMAIN && defined HAVE_GETTEXT
 # define TZ_DOMAIN "tz"
@@ -562,24 +729,64 @@
 char *ctime_r(time_t const *, char *);
 #endif /* HAVE_INCOMPATIBLE_CTIME_R */
 
-#ifndef YEARSPERREPEAT
+/* Handy macros that are independent of tzfile implementation.  */
+
+#define SECSPERMIN	60
+#define MINSPERHOUR	60
+#define HOURSPERDAY	24
+#define DAYSPERWEEK	7
+#define DAYSPERNYEAR	365
+#define DAYSPERLYEAR	366
+#define SECSPERHOUR	(SECSPERMIN * MINSPERHOUR)
+#define SECSPERDAY	((int_fast32_t) SECSPERHOUR * HOURSPERDAY)
+#define MONSPERYEAR	12
+
 #define YEARSPERREPEAT		400	/* years before a Gregorian repeat */
-#endif /* !defined YEARSPERREPEAT */
+#define DAYSPERREPEAT		((int_fast32_t) 400 * 365 + 100 - 4 + 1)
+#define SECSPERREPEAT		((int_fast64_t) DAYSPERREPEAT * SECSPERDAY)
+#define AVGSECSPERYEAR		(SECSPERREPEAT / YEARSPERREPEAT)
+
+#define TM_SUNDAY	0
+#define TM_MONDAY	1
+#define TM_TUESDAY	2
+#define TM_WEDNESDAY	3
+#define TM_THURSDAY	4
+#define TM_FRIDAY	5
+#define TM_SATURDAY	6
+
+#define TM_JANUARY	0
+#define TM_FEBRUARY	1
+#define TM_MARCH	2
+#define TM_APRIL	3
+#define TM_MAY		4
+#define TM_JUNE		5
+#define TM_JULY		6
+#define TM_AUGUST	7
+#define TM_SEPTEMBER	8
+#define TM_OCTOBER	9
+#define TM_NOVEMBER	10
+#define TM_DECEMBER	11
+
+#define TM_YEAR_BASE	1900
+#define TM_WDAY_BASE	TM_MONDAY
+
+#define EPOCH_YEAR	1970
+#define EPOCH_WDAY	TM_THURSDAY
+
+#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
 
 /*
-** The Gregorian year averages 365.2425 days, which is 31556952 seconds.
+** Since everything in isleap is modulo 400 (or a factor of 400), we know that
+**	isleap(y) == isleap(y % 400)
+** and so
+**	isleap(a + b) == isleap((a + b) % 400)
+** or
+**	isleap(a + b) == isleap(a % 400 + b % 400)
+** This is true even if % means modulo rather than Fortran remainder
+** (which is allowed by C89 but not by C99 or later).
+** We use this to avoid addition overflow problems.
 */
 
-#ifndef AVGSECSPERYEAR
-#define AVGSECSPERYEAR		31556952L
-#endif /* !defined AVGSECSPERYEAR */
-
-#ifndef SECSPERREPEAT
-#define SECSPERREPEAT		((int_fast64_t) YEARSPERREPEAT * (int_fast64_t) AVGSECSPERYEAR)
-#endif /* !defined SECSPERREPEAT */
-
-#ifndef SECSPERREPEAT_BITS
-#define SECSPERREPEAT_BITS	34	/* ceil(log2(SECSPERREPEAT)) */
-#endif /* !defined SECSPERREPEAT_BITS */
+#define isleap_sum(a, b)	isleap((a) % 400 + (b) % 400)
 
 #endif /* !defined PRIVATE_H */
diff --git a/libc/tzcode/strftime.c b/libc/tzcode/strftime.c
index 7c4be49..d04c5ba 100644
--- a/libc/tzcode/strftime.c
+++ b/libc/tzcode/strftime.c
@@ -1,4 +1,4 @@
-/* Convert a broken-down time stamp to a string.  */
+/* Convert a broken-down timestamp to a string.  */
 
 /* Copyright 1989 The Regents of the University of California.
    All rights reserved.
@@ -35,9 +35,13 @@
 
 #include "private.h"
 
-#include "tzfile.h"
-#include "fcntl.h"
-#include "locale.h"
+#include <fcntl.h>
+#include <locale.h>
+#include <stdio.h>
+
+#ifndef DEPRECATE_TWO_DIGIT_YEARS
+# define DEPRECATE_TWO_DIGIT_YEARS false
+#endif
 
 #if defined(__BIONIC__)
 
@@ -45,6 +49,7 @@
 #if defined(__LP64__)
 #define time64_t time_t
 #define mktime64 mktime
+#define localtime64_r localtime_r
 #else
 #include <time64.h>
 #endif
@@ -88,7 +93,7 @@
 
     /*
     ** x_fmt
-    ** C99 requires this format.
+    ** C99 and later require this format.
     ** Using just numbers (as here) makes Quakers happier;
     ** it's also compatible with SVR4.
     */
@@ -96,7 +101,7 @@
 
     /*
     ** c_fmt
-    ** C99 requires this format.
+    ** C99 and later require this format.
     ** Previously this code used "%D %X", but we now conform to C99.
     ** Note that
     **  "%a %b %d %H:%M:%S %Y"
@@ -114,25 +119,18 @@
     "%a %b %e %H:%M:%S %Z %Y"
 };
 
+enum warn { IN_NONE, IN_SOME, IN_THIS, IN_ALL };
+
 static char *   _add(const char *, char *, const char *, int);
 static char *   _conv(int, const char *, char *, const char *);
 static char *   _fmt(const char *, const struct tm *, char *, const char *,
-            int *);
+            enum warn *);
 static char *   _yconv(int, int, bool, bool, char *, const char *, int);
 
-#if !HAVE_POSIX_DECLS
-extern char *   tzname[];
-#endif
-
 #ifndef YEAR_2000_NAME
 #define YEAR_2000_NAME  "CHECK_STRFTIME_FORMATS_FOR_TWO_DIGIT_YEARS"
 #endif /* !defined YEAR_2000_NAME */
 
-#define IN_NONE 0
-#define IN_SOME 1
-#define IN_THIS 2
-#define IN_ALL  3
-
 #if HAVE_STRFTIME_L
 size_t
 strftime_l(char *s, size_t maxsize, char const *format, struct tm const *t,
@@ -149,18 +147,19 @@
 strftime(char *s, size_t maxsize, const char *format, const struct tm *t)
 {
     char *  p;
-    int warn;
+    int saved_errno = errno;
+    enum warn warn = IN_NONE;
 
     tzset();
-    warn = IN_NONE;
-    p = _fmt(((format == NULL) ? "%c" : format), t, s, s + maxsize, &warn);
-#ifndef NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU
-    if (warn != IN_NONE && getenv(YEAR_2000_NAME) != NULL) {
+    p = _fmt(format, t, s, s + maxsize, &warn);
+    if (!p) {
+       errno = EOVERFLOW;
+       return 0;
+    }
+    if (DEPRECATE_TWO_DIGIT_YEARS
+          && warn != IN_NONE && getenv(YEAR_2000_NAME)) {
         fprintf(stderr, "\n");
-        if (format == NULL)
-            fprintf(stderr, "NULL strftime format ");
-        else    fprintf(stderr, "strftime format \"%s\" ",
-                format);
+        fprintf(stderr, "strftime format \"%s\" ", format);
         fprintf(stderr, "yields only two digits of years in ");
         if (warn == IN_SOME)
             fprintf(stderr, "some locales");
@@ -169,10 +168,12 @@
         else    fprintf(stderr, "all locales");
         fprintf(stderr, "\n");
     }
-#endif /* !defined NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU */
-    if (p == s + maxsize)
+    if (p == s + maxsize) {
+        errno = ERANGE;
         return 0;
+    }
     *p = '\0';
+    errno = saved_errno;
     return p - s;
 }
 
@@ -189,9 +190,32 @@
     return normal;
 }
 
+// Android-added: fall back mechanism when TM_ZONE is not initialized.
+#ifdef TM_ZONE
+static const char* _safe_tm_zone(const struct tm* tm) {
+  const char* zone = tm->TM_ZONE;
+  if (!zone || !*zone) {
+    // "The value of tm_isdst shall be positive if Daylight Savings Time is
+    // in effect, 0 if Daylight Savings Time is not in effect, and negative
+    // if the information is not available."
+    if (tm->tm_isdst == 0) {
+      zone = tzname[0];
+    } else if (tm->tm_isdst > 0) {
+      zone = tzname[1];
+    }
+
+    // "Replaced by the timezone name or abbreviation, or by no bytes if no
+    // timezone information exists."
+    if (!zone || !*zone) zone = "";
+  }
+
+  return zone;
+}
+#endif
+
 static char *
 _fmt(const char *format, const struct tm *t, char *pt,
-        const char *ptlim, int *warnp)
+        const char *ptlim, enum warn *warnp)
 {
     for ( ; *format; ++format) {
         if (*format == '%') {
@@ -239,7 +263,7 @@
                 continue;
             case 'c':
                 {
-                int warn2 = IN_SOME;
+                enum warn warn2 = IN_SOME;
 
                 pt = _fmt(Locale->c_fmt, t, pt, ptlim, &warn2);
                 if (warn2 == IN_ALL)
@@ -257,12 +281,12 @@
             case 'E':
             case 'O':
                 /*
-                ** C99 locale modifiers.
+                ** Locale modifiers of C99 and later.
                 ** The sequences
                 **  %Ec %EC %Ex %EX %Ey %EY
                 **  %Od %oe %OH %OI %Om %OM
                 **  %OS %Ou %OU %OV %Ow %OW %Oy
-                ** are supposed to provide alternate
+                ** are supposed to provide alternative
                 ** representations.
                 */
                 goto label;
@@ -356,11 +380,17 @@
 
                     tm = *t;
                     mkt = mktime64(&tm);
-                    if (TYPE_SIGNED(time64_t))
-                        snprintf(buf, sizeof(buf), "%"PRIdMAX,
-                                 (intmax_t) mkt);
-                    else    snprintf(buf, sizeof(buf), "%"PRIuMAX,
-                                     (uintmax_t) mkt);
+					/* There is no portable, definitive
+					   test for whether whether mktime
+					   succeeded, so treat (time_t) -1 as
+					   the success that it might be.  */
+                    if (TYPE_SIGNED(time64_t)) {
+                      intmax_t n = mkt;
+                      sprintf(buf, "%"PRIdMAX, n);
+                    } else {
+                      uintmax_t n = mkt;
+                      sprintf(buf, "%"PRIuMAX, n);
+                    }
                     pt = _add(buf, pt, ptlim, modifier);
                 }
                 continue;
@@ -392,7 +422,7 @@
 ** (01-53)."
 ** (ado, 1993-05-24)
 **
-** From <http://www.ft.uni-erlangen.de/~mskuhn/iso-time.html> by Markus Kuhn:
+** From <https://www.cl.cam.ac.uk/~mgk25/iso-time.html> by Markus Kuhn:
 ** "Week 01 of a year is per definition the first week which has the
 ** Thursday in this year, which is equivalent to the week which contains
 ** the fourth day of January. In other words, the first week of a new year
@@ -494,7 +524,7 @@
                 continue;
             case 'x':
                 {
-                int warn2 = IN_SOME;
+                enum warn warn2 = IN_SOME;
 
                 pt = _fmt(Locale->x_fmt, t, pt, ptlim, &warn2);
                 if (warn2 == IN_ALL)
@@ -517,45 +547,32 @@
             case 'Z':
 #ifdef TM_ZONE
                 // BEGIN: Android-changed.
-                {
-                    const char* zone = t->TM_ZONE;
-                    if (!zone || !*zone) {
-                        // "The value of tm_isdst shall be positive if Daylight Savings Time is
-                        // in effect, 0 if Daylight Savings Time is not in effect, and negative
-                        // if the information is not available."
-                        if (t->tm_isdst == 0) zone = tzname[0];
-                        else if (t->tm_isdst > 0) zone = tzname[1];
-
-                        // "Replaced by the timezone name or abbreviation, or by no bytes if no
-                        // timezone information exists."
-                        if (!zone || !*zone) zone = "";
-                    }
-                    pt = _add(zone, pt, ptlim, modifier);
-                }
+                pt = _add(_safe_tm_zone(t), pt, ptlim, modifier);
                 // END: Android-changed.
-#else
+#elif HAVE_TZNAME
                 if (t->tm_isdst >= 0)
                     pt = _add(tzname[t->tm_isdst != 0],
                         pt, ptlim);
 #endif
                 /*
-                ** C99 says that %Z must be replaced by the
-                ** empty string if the time zone is not
+                ** C99 and later say that %Z must be
+                ** replaced by the empty string if the
+                ** time zone abbreviation is not
                 ** determinable.
                 */
                 continue;
             case 'z':
+#if defined TM_GMTOFF || USG_COMPAT || ALTZONE
                 {
                 long     diff;
                 char const *    sign;
+                bool negative;
 
-                if (t->tm_isdst < 0)
-                    continue;
-#ifdef TM_GMTOFF
+# ifdef TM_GMTOFF
                 diff = t->TM_GMTOFF;
-#else /* !defined TM_GMTOFF */
+# else
                 /*
-                ** C99 says that the UT offset must
+                ** C99 and later say that the UT offset must
                 ** be computed by looking only at
                 ** tm_isdst. This requirement is
                 ** incorrect, since it means the code
@@ -563,30 +580,48 @@
                 ** altzone and timezone), and the
                 ** magic might not have the correct
                 ** offset. Doing things correctly is
-                ** tricky and requires disobeying C99;
+                ** tricky and requires disobeying the standard;
                 ** see GNU C strftime for details.
                 ** For now, punt and conform to the
                 ** standard, even though it's incorrect.
                 **
-                ** C99 says that %z must be replaced by the
-                ** empty string if the time zone is not
+                ** C99 and later say that %z must be replaced by
+                ** the empty string if the time zone is not
                 ** determinable, so output nothing if the
                 ** appropriate variables are not available.
                 */
+                if (t->tm_isdst < 0)
+                    continue;
                 if (t->tm_isdst == 0)
-#ifdef USG_COMPAT
+#  if USG_COMPAT
                     diff = -timezone;
-#else /* !defined USG_COMPAT */
+#  else
                     continue;
-#endif /* !defined USG_COMPAT */
+#  endif
                 else
-#ifdef ALTZONE
+#  if ALTZONE
                     diff = -altzone;
-#else /* !defined ALTZONE */
+#  else
                     continue;
-#endif /* !defined ALTZONE */
-#endif /* !defined TM_GMTOFF */
-                if (diff < 0) {
+#  endif
+# endif
+                negative = diff < 0;
+                if (diff == 0) {
+#ifdef TM_ZONE
+                  // Android-changed: do not use TM_ZONE as it is as it may be null.
+                  {
+                    const char* zone = _safe_tm_zone(t);
+                    negative = zone[0] == '-';
+                  }
+#else
+                    negative = t->tm_isdst < 0;
+# if HAVE_TZNAME
+                    if (tzname[t->tm_isdst != 0][0] == '-')
+                        negative = true;
+# endif
+#endif
+                }
+                if (negative) {
                     sign = "-";
                     diff = -diff;
                 } else  sign = "+";
@@ -596,6 +631,7 @@
                     (diff % MINSPERHOUR);
                 pt = _conv(diff, getformat(modifier, "04", " 4", "  ", "04"), pt, ptlim);
                 }
+#endif
                 continue;
             case '+':
                 pt = _fmt(Locale->date_fmt, t, pt, ptlim,
diff --git a/libc/tzcode/tzfile.h b/libc/tzcode/tzfile.h
index ebecd68..c5f9967 100644
--- a/libc/tzcode/tzfile.h
+++ b/libc/tzcode/tzfile.h
@@ -1,3 +1,5 @@
+/* Layout and location of TZif files.  */
+
 #ifndef TZFILE_H
 
 #define TZFILE_H
@@ -20,17 +22,20 @@
 */
 
 #ifndef TZDIR
-#define TZDIR	"/usr/local/etc/zoneinfo" /* Time zone object file directory */
+#define TZDIR	"/usr/share/zoneinfo" /* Time zone object file directory */
 #endif /* !defined TZDIR */
 
 #ifndef TZDEFAULT
-#define TZDEFAULT	"localtime"
+#define TZDEFAULT	"/etc/localtime"
 #endif /* !defined TZDEFAULT */
 
 #ifndef TZDEFRULES
 #define TZDEFRULES	"posixrules"
 #endif /* !defined TZDEFRULES */
 
+
+/* See Internet RFC 8536 for more details about the following format.  */
+
 /*
 ** Each file begins with. . .
 */
@@ -39,9 +44,9 @@
 
 struct tzhead {
 	char	tzh_magic[4];		/* TZ_MAGIC */
-	char	tzh_version[1];		/* '\0' or '2' or '3' as of 2013 */
+	char	tzh_version[1];		/* '\0' or '2'-'4' as of 2021 */
 	char	tzh_reserved[15];	/* reserved; must be zero */
-	char	tzh_ttisgmtcnt[4];	/* coded number of trans. time flags */
+	char	tzh_ttisutcnt[4];	/* coded number of trans. time flags */
 	char	tzh_ttisstdcnt[4];	/* coded number of trans. time flags */
 	char	tzh_leapcnt[4];		/* coded number of leap seconds */
 	char	tzh_timecnt[4];		/* coded number of transition times */
@@ -64,14 +69,15 @@
 **		one (char [4])		total correction after above
 **	tzh_ttisstdcnt (char)s		indexed by type; if 1, transition
 **					time is standard time, if 0,
-**					transition time is wall clock time
-**					if absent, transition times are
-**					assumed to be wall clock time
-**	tzh_ttisgmtcnt (char)s		indexed by type; if 1, transition
-**					time is UT, if 0,
-**					transition time is local time
-**					if absent, transition times are
+**					transition time is local (wall clock)
+**					time; if absent, transition times are
 **					assumed to be local time
+**	tzh_ttisutcnt (char)s		indexed by type; if 1, transition
+**					time is UT, if 0, transition time is
+**					local time; if absent, transition
+**					times are assumed to be local time.
+**					When this is 1, the corresponding
+**					std/wall indicator must also be 1.
 */
 
 /*
diff --git a/libc/upstream-openbsd/lib/libc/gdtoa/misc.c b/libc/upstream-openbsd/lib/libc/gdtoa/misc.c
index 79a3104..fef51a9 100644
--- a/libc/upstream-openbsd/lib/libc/gdtoa/misc.c
+++ b/libc/upstream-openbsd/lib/libc/gdtoa/misc.c
@@ -41,7 +41,7 @@
 #endif
 
 #ifdef MULTIPLE_THREADS
-extern void *__dtoa_locks[];
+static void *__dtoa_locks[] = { NULL, NULL };
 #endif
 
  Bigint *
diff --git a/libc/upstream-openbsd/lib/libc/gen/alarm.c b/libc/upstream-openbsd/lib/libc/gen/alarm.c
index f15dd15..ac17f9d 100644
--- a/libc/upstream-openbsd/lib/libc/gen/alarm.c
+++ b/libc/upstream-openbsd/lib/libc/gen/alarm.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: alarm.c,v 1.9 2019/06/28 13:32:41 deraadt Exp $ */
+/*	$OpenBSD: alarm.c,v 1.10 2021/06/24 22:43:31 cheloha Exp $ */
 /*
  * Copyright (c) 1983, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -34,13 +34,12 @@
 unsigned int
 alarm(unsigned int secs)
 {
-	struct itimerval it, oitv;
-	struct itimerval *itp = &it;
+	struct itimerval itv, oitv;
 
-	timerclear(&itp->it_interval);
-	itp->it_value.tv_sec = secs;
-	itp->it_value.tv_usec = 0;
-	if (setitimer(ITIMER_REAL, itp, &oitv) == -1)
+	timerclear(&itv.it_interval);
+	itv.it_value.tv_sec = secs;
+	itv.it_value.tv_usec = 0;
+	if (setitimer(ITIMER_REAL, &itv, &oitv) == -1)
 		return ((unsigned int) -1);
 	if (oitv.it_value.tv_usec)
 		oitv.it_value.tv_sec++;
diff --git a/libc/upstream-openbsd/lib/libc/gen/charclass.h b/libc/upstream-openbsd/lib/libc/gen/charclass.h
index 073baf6..1d1ec07 100644
--- a/libc/upstream-openbsd/lib/libc/gen/charclass.h
+++ b/libc/upstream-openbsd/lib/libc/gen/charclass.h
@@ -1,13 +1,13 @@
 /*
  * Public domain, 2008, Todd C. Miller <millert@openbsd.org>
  *
- * $OpenBSD: charclass.h,v 1.2 2019/01/25 00:19:25 millert Exp $
+ * $OpenBSD: charclass.h,v 1.3 2020/10/13 04:42:28 guenther Exp $
  */
 
 /*
  * POSIX character class support for fnmatch() and glob().
  */
-static struct cclass {
+static const struct cclass {
 	const char *name;
 	int (*isctype)(int);
 } cclasses[] = {
diff --git a/libc/upstream-openbsd/lib/libc/gen/daemon.c b/libc/upstream-openbsd/lib/libc/gen/daemon.c
index 79f4264..b84cb4f 100644
--- a/libc/upstream-openbsd/lib/libc/gen/daemon.c
+++ b/libc/upstream-openbsd/lib/libc/gen/daemon.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: daemon.c,v 1.7 2010/07/27 22:29:09 marco Exp $ */
+/*	$OpenBSD: daemon.c,v 1.8 2021/10/24 21:24:20 deraadt Exp $ */
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -53,7 +53,7 @@
 	if (!nochdir)
 		(void)chdir("/");
 
-	if (!noclose && (fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
+	if (!noclose && (fd = open(_PATH_DEVNULL, O_RDWR)) != -1) {
 		(void)dup2(fd, STDIN_FILENO);
 		(void)dup2(fd, STDOUT_FILENO);
 		(void)dup2(fd, STDERR_FILENO);
diff --git a/libc/upstream-openbsd/lib/libc/gen/fnmatch.c b/libc/upstream-openbsd/lib/libc/gen/fnmatch.c
index d7afd5f..ff6b26e 100644
--- a/libc/upstream-openbsd/lib/libc/gen/fnmatch.c
+++ b/libc/upstream-openbsd/lib/libc/gen/fnmatch.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: fnmatch.c,v 1.22 2020/03/13 03:25:45 djm Exp $	*/
+/*	$OpenBSD: fnmatch.c,v 1.23 2020/10/13 04:42:28 guenther Exp $	*/
 
 /* Copyright (c) 2011, VMware, Inc.
  * All rights reserved.
@@ -100,7 +100,7 @@
 {
 	const char * const mismatch = pattern;
 	const char *colon;
-	struct cclass *cc;
+	const struct cclass *cc;
 	int rval = RANGE_NOMATCH;
 	size_t len;
 
diff --git a/libc/upstream-openbsd/lib/libc/gen/ftok.c b/libc/upstream-openbsd/lib/libc/gen/ftok.c
index ea1edf1..9edcd30 100644
--- a/libc/upstream-openbsd/lib/libc/gen/ftok.c
+++ b/libc/upstream-openbsd/lib/libc/gen/ftok.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: ftok.c,v 1.9 2019/06/28 13:32:41 deraadt Exp $ */
+/*	$OpenBSD: ftok.c,v 1.10 2022/04/13 16:23:53 millert Exp $ */
 /*
  * Copyright (c) 1994 SigmaSoft, Th. Lockert <tholo@sigmasoft.com>
  * All rights reserved.
@@ -32,11 +32,12 @@
 key_t
 ftok(const char *path, int id)
 {
+	const unsigned int u_id = id;
 	struct stat st;
 
 	if (stat(path, &st) == -1)
 		return (key_t)-1;
 
 	return (key_t)
-	    ((id & 0xff) << 24 | (st.st_dev & 0xff) << 16 | (st.st_ino & 0xffff));
+	    ((u_id & 0xff) << 24 | (st.st_dev & 0xff) << 16 | (st.st_ino & 0xffff));
 }
diff --git a/libc/upstream-openbsd/lib/libc/net/base64.c b/libc/upstream-openbsd/lib/libc/net/base64.c
index e90696d..f36c11a 100644
--- a/libc/upstream-openbsd/lib/libc/net/base64.c
+++ b/libc/upstream-openbsd/lib/libc/net/base64.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: base64.c,v 1.8 2015/01/16 16:48:51 deraadt Exp $	*/
+/*	$OpenBSD: base64.c,v 1.15 2021/10/25 14:41:09 jca Exp $	*/
 
 /*
  * Copyright (c) 1996 by Internet Software Consortium.
@@ -46,11 +46,9 @@
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
-#include <arpa/nameser.h>
 
 #include <ctype.h>
 #include <resolv.h>
-#include <stdio.h>
 
 #include <stdlib.h>
 #include <string.h>
@@ -107,9 +105,9 @@
    end of the data is performed using the '=' character.
 
    Since all base64 input is an integral number of octets, only the
-         -------------------------------------------------                       
+         -------------------------------------------------
    following cases can arise:
-   
+
        (1) the final quantum of encoding input is an integral
            multiple of 24 bits; here, the final unit of encoded
 	   output will be an integral multiple of 4 characters
@@ -123,15 +121,12 @@
    */
 
 int
-b64_ntop(src, srclength, target, targsize)
-	u_char const *src;
-	size_t srclength;
-	char *target;
-	size_t targsize;
+b64_ntop(unsigned char const *src, size_t srclength, char *target,
+    size_t targsize)
 {
 	size_t datalength = 0;
-	u_char input[3];
-	u_char output[4];
+	unsigned char input[3];
+	unsigned char output[4];
 	int i;
 
 	while (2 < srclength) {
@@ -152,14 +147,14 @@
 		target[datalength++] = Base64[output[2]];
 		target[datalength++] = Base64[output[3]];
 	}
-    
+
 	/* Now we worry about padding. */
 	if (0 != srclength) {
 		/* Get what's left. */
 		input[0] = input[1] = input[2] = '\0';
 		for (i = 0; i < srclength; i++)
 			input[i] = *src++;
-	
+
 		output[0] = input[0] >> 2;
 		output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
 		output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
@@ -187,13 +182,10 @@
  */
 
 int
-b64_pton(src, target, targsize)
-	char const *src;
-	u_char *target;
-	size_t targsize;
+b64_pton(char const *src, unsigned char *target, size_t targsize)
 {
 	int tarindex, state, ch;
-	u_char nextbyte;
+	unsigned char nextbyte;
 	char *pos;
 
 	state = 0;
@@ -207,7 +199,7 @@
 			break;
 
 		pos = strchr(Base64, ch);
-		if (pos == 0) 		/* A non-base64 character. */
+		if (pos == 0)		/* A non-base64 character. */
 			return (-1);
 
 		switch (state) {
diff --git a/libc/upstream-openbsd/lib/libc/stdio/fputws.c b/libc/upstream-openbsd/lib/libc/stdio/fputws.c
index 8961571..4f619b6 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/fputws.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/fputws.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: fputws.c,v 1.8 2015/08/31 02:53:57 guenther Exp $	*/
+/*	$OpenBSD: fputws.c,v 1.9 2021/10/24 10:05:23 jsg Exp $	*/
 /* $NetBSD: fputws.c,v 1.1 2003/03/07 07:11:37 tshiozak Exp $ */
 
 /*-
@@ -37,9 +37,7 @@
 #include "fvwrite.h"
 
 int
-fputws(ws, fp)
-	const wchar_t * __restrict ws;
-	FILE * __restrict fp;
+fputws(const wchar_t * __restrict ws, FILE * __restrict fp)
 {
 	FLOCKFILE(fp);
 	_SET_ORIENTATION(fp, 1);
diff --git a/libc/upstream-openbsd/lib/libc/stdio/setvbuf.c b/libc/upstream-openbsd/lib/libc/stdio/setvbuf.c
index da68b90..9a08d13 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/setvbuf.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/setvbuf.c
@@ -131,7 +131,8 @@
 		flags |= __SNPT;
 
 	/*
-	 * Fix up the FILE fields.
+	 * Fix up the FILE fields, and set __cleanup for output flush on
+	 * exit (since we are buffered in some way).
 	 */
 	if (mode == _IOLBF)
 		flags |= __SLBF;
diff --git a/libc/upstream-openbsd/lib/libc/stdlib/lsearch.c b/libc/upstream-openbsd/lib/libc/stdlib/lsearch.c
index 8cad05f..95ebf49 100644
--- a/libc/upstream-openbsd/lib/libc/stdlib/lsearch.c
+++ b/libc/upstream-openbsd/lib/libc/stdlib/lsearch.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: lsearch.c,v 1.5 2014/07/18 04:16:09 matthew Exp $	*/
+/*	$OpenBSD: lsearch.c,v 1.7 2021/12/08 22:06:28 cheloha Exp $	*/
 
 /*
  * Copyright (c) 1989, 1993
@@ -37,48 +37,34 @@
 #include <search.h>
 
 typedef int (*cmp_fn_t)(const void *, const void *);
-static void *linear_base(const void *, const void *, size_t *, size_t,
-    cmp_fn_t, int);
 
 void *
 lsearch(const void *key, void *base, size_t *nelp, size_t width,
     	cmp_fn_t compar)
 {
+	void *element = lfind(key, base, nelp, width, compar);
 
-	return(linear_base(key, base, nelp, width, compar, 1));
+	/*
+	 * Use memmove(3) to ensure the key is copied cleanly into the
+	 * array, even if the key overlaps with the end of the array.
+	 */
+	if (element == NULL) {
+		element = memmove((char *)base + *nelp * width, key, width);
+		*nelp += 1;
+	}
+	return element;
 }
 
 void *
 lfind(const void *key, const void *base, size_t *nelp, size_t width,
 	cmp_fn_t compar)
 {
-	return(linear_base(key, base, nelp, width, compar, 0));
-}
-
-static void *
-linear_base(const void *key, const void *base, size_t *nelp, size_t width,
-	cmp_fn_t compar, int add_flag)
-{
 	const char *element, *end;
 
 	end = (const char *)base + *nelp * width;
 	for (element = base; element < end; element += width)
 		if (!compar(key, element))		/* key found */
 			return((void *)element);
-
-	if (!add_flag)					/* key not found */
-		return(NULL);
-
-	/*
-	 * The UNIX System User's Manual, 1986 edition claims that
-	 * a NULL pointer is returned by lsearch with errno set
-	 * appropriately, if there is not enough room in the table
-	 * to add a new item.  This can't be done as none of these
-	 * routines have any method of determining the size of the
-	 * table.  This comment isn't in the 1986-87 System V
-	 * manual.
-	 */
-	++*nelp;
-	memcpy((void *)end, key, width);
-	return((void *)end);
+	return NULL;
 }
+DEF_WEAK(lfind);
diff --git a/libc/upstream-openbsd/lib/libc/stdlib/recallocarray.c b/libc/upstream-openbsd/lib/libc/stdlib/recallocarray.c
index a2f37fe..81059e6 100644
--- a/libc/upstream-openbsd/lib/libc/stdlib/recallocarray.c
+++ b/libc/upstream-openbsd/lib/libc/stdlib/recallocarray.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: recallocarray.c,v 1.1 2017/03/06 18:44:21 otto Exp $	*/
+/*	$OpenBSD: recallocarray.c,v 1.2 2021/03/18 11:16:58 claudio Exp $	*/
 /*
  * Copyright (c) 2008, 2017 Otto Moerbeek <otto@drijf.net>
  *
@@ -57,7 +57,7 @@
 	if (newsize <= oldsize) {
 		size_t d = oldsize - newsize;
 
-		if (d < oldsize / 2 && d < getpagesize()) {
+		if (d < oldsize / 2 && d < (size_t)getpagesize()) {
 			memset((char *)ptr + newsize, 0, d);
 			return ptr;
 		}
diff --git a/libdl/Android.bp b/libdl/Android.bp
index 750a6e2..9714af5 100644
--- a/libdl/Android.bp
+++ b/libdl/Android.bp
@@ -241,30 +241,30 @@
     name: "libdl.arm.map",
     out: ["libdl.arm.map"],
     srcs: ["libdl.map.txt"],
-    tool_files: [":bionic-generate-version-script"],
-    cmd: "$(location :bionic-generate-version-script) arm $(in) $(out)",
+    tools: ["generate-version-script"],
+    cmd: "$(location generate-version-script) arm $(in) $(out)",
 }
 
 genrule {
     name: "libdl.arm64.map",
     out: ["libdl.arm64.map"],
     srcs: ["libdl.map.txt"],
-    tool_files: [":bionic-generate-version-script"],
-    cmd: "$(location :bionic-generate-version-script) arm64 $(in) $(out)",
+    tools: ["generate-version-script"],
+    cmd: "$(location generate-version-script) arm64 $(in) $(out)",
 }
 
 genrule {
     name: "libdl.x86.map",
     out: ["libdl.x86.map"],
     srcs: ["libdl.map.txt"],
-    tool_files: [":bionic-generate-version-script"],
-    cmd: "$(location :bionic-generate-version-script) x86 $(in) $(out)",
+    tools: ["generate-version-script"],
+    cmd: "$(location generate-version-script) x86 $(in) $(out)",
 }
 
 genrule {
     name: "libdl.x86_64.map",
     out: ["libdl.x86_64.map"],
     srcs: ["libdl.map.txt"],
-    tool_files: [":bionic-generate-version-script"],
-    cmd: "$(location :bionic-generate-version-script) x86_64 $(in) $(out)",
+    tools: ["generate-version-script"],
+    cmd: "$(location generate-version-script) x86_64 $(in) $(out)",
 }
diff --git a/libm/Android.bp b/libm/Android.bp
index 7469cde..641956c 100644
--- a/libm/Android.bp
+++ b/libm/Android.bp
@@ -560,30 +560,30 @@
     name: "libm.arm.map",
     out: ["libm.arm.map"],
     srcs: ["libm.map.txt"],
-    tool_files: [":bionic-generate-version-script"],
-    cmd: "$(location :bionic-generate-version-script) arm $(in) $(out)",
+    tools: ["generate-version-script"],
+    cmd: "$(location generate-version-script) arm $(in) $(out)",
 }
 
 genrule {
     name: "libm.arm64.map",
     out: ["libm.arm64.map"],
     srcs: ["libm.map.txt"],
-    tool_files: [":bionic-generate-version-script"],
-    cmd: "$(location :bionic-generate-version-script) arm64 $(in) $(out)",
+    tools: ["generate-version-script"],
+    cmd: "$(location generate-version-script) arm64 $(in) $(out)",
 }
 
 genrule {
     name: "libm.x86.map",
     out: ["libm.x86.map"],
     srcs: ["libm.map.txt"],
-    tool_files: [":bionic-generate-version-script"],
-    cmd: "$(location :bionic-generate-version-script) x86 $(in) $(out)",
+    tools: ["generate-version-script"],
+    cmd: "$(location generate-version-script) x86 $(in) $(out)",
 }
 
 genrule {
     name: "libm.x86_64.map",
     out: ["libm.x86_64.map"],
     srcs: ["libm.map.txt"],
-    tool_files: [":bionic-generate-version-script"],
-    cmd: "$(location :bionic-generate-version-script) x86_64 $(in) $(out)",
+    tools: ["generate-version-script"],
+    cmd: "$(location generate-version-script) x86_64 $(in) $(out)",
 }
diff --git a/libm/upstream-freebsd/lib/msun/src/math_private.h b/libm/upstream-freebsd/lib/msun/src/math_private.h
index b91b54c..df526e7 100644
--- a/libm/upstream-freebsd/lib/msun/src/math_private.h
+++ b/libm/upstream-freebsd/lib/msun/src/math_private.h
@@ -460,7 +460,7 @@
  * or by having |c| a few percent smaller than |a|.  Pre-normalization of
  * (a, b) may help.
  *
- * This is is a variant of an algorithm of Kahan (see Knuth (1981) 4.2.2
+ * This is a variant of an algorithm of Kahan (see Knuth (1981) 4.2.2
  * exercise 19).  We gain considerable efficiency by requiring the terms to
  * be sufficiently normalized and sufficiently increasing.
  */
@@ -644,7 +644,7 @@
  * return type provided their arg is a floating point integer.  They can
  * sometimes be more efficient because no rounding is required.
  */
-#if (defined(amd64) || defined(__i386__)) && defined(__GNUCLIKE_ASM)
+#if defined(amd64) || defined(__i386__)
 #define	irint(x)						\
     (sizeof(x) == sizeof(float) &&				\
     sizeof(__float_t) == sizeof(long double) ? irintf(x) :	\
@@ -657,7 +657,7 @@
 
 #define	i64rint(x)	((int64_t)(x))	/* only needed for ld128 so not opt. */
 
-#if defined(__i386__) && defined(__GNUCLIKE_ASM)
+#if defined(__i386__)
 static __inline int
 irintf(float x)
 {
@@ -677,7 +677,7 @@
 }
 #endif
 
-#if (defined(__amd64__) || defined(__i386__)) && defined(__GNUCLIKE_ASM)
+#if defined(__amd64__) || defined(__i386__)
 static __inline int
 irintl(long double x)
 {
diff --git a/libm/upstream-freebsd/lib/msun/src/w_cabsf.c b/libm/upstream-freebsd/lib/msun/src/w_cabsf.c
index e7bfe22..b5065c8 100644
--- a/libm/upstream-freebsd/lib/msun/src/w_cabsf.c
+++ b/libm/upstream-freebsd/lib/msun/src/w_cabsf.c
@@ -15,8 +15,7 @@
 #include "math_private.h"
 
 float
-cabsf(z)
-	float complex z;
+cabsf(float complex z)
 {
 
 	return hypotf(crealf(z), cimagf(z));
diff --git a/libm/upstream-freebsd/lib/msun/src/w_drem.c b/libm/upstream-freebsd/lib/msun/src/w_drem.c
index 0f68409..74008a5 100644
--- a/libm/upstream-freebsd/lib/msun/src/w_drem.c
+++ b/libm/upstream-freebsd/lib/msun/src/w_drem.c
@@ -8,8 +8,7 @@
 #include <math.h>
 
 double
-drem(x, y)
-	double x, y;
+drem(double x, double y)
 {
 	return remainder(x, y);
 }
diff --git a/tests/Android.bp b/tests/Android.bp
index 6a41cf2..8f4ba2f 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -479,6 +479,7 @@
         "uchar_test.cpp",
         "unistd_nofortify_test.cpp",
         "unistd_test.cpp",
+        "utils.cpp",
         "utmp_test.cpp",
         "wchar_test.cpp",
         "wctype_test.cpp",
@@ -598,18 +599,6 @@
     ],
 }
 
-cc_test_library {
-    name: "libBionicGwpAsanTests",
-    defaults: ["bionic_tests_defaults"],
-    srcs: [
-        "gwp_asan_test.cpp",
-    ],
-    include_dirs: [
-        "bionic/libc",
-    ],
-    static_libs: ["libbase"],
-}
-
 // -----------------------------------------------------------------------------
 // Fortify tests.
 // -----------------------------------------------------------------------------
@@ -770,7 +759,6 @@
         "libBionicStandardTests",
         "libBionicElfTlsTests",
         "libBionicFramePointerTests",
-        "libBionicGwpAsanTests",
         "libfortify1-tests-clang",
         "libfortify1-new-tests-clang",
         "libfortify2-tests-clang",
@@ -872,6 +860,7 @@
         "__cxa_thread_atexit_test.cpp",
         "gtest_globals.cpp",
         "gtest_main.cpp",
+        "gwp_asan_test.cpp",
         "thread_local_test.cpp",
     ],
 
diff --git a/tests/gwp_asan_test.cpp b/tests/gwp_asan_test.cpp
index b2c7780..5f5e3dd 100644
--- a/tests/gwp_asan_test.cpp
+++ b/tests/gwp_asan_test.cpp
@@ -28,26 +28,28 @@
 
 #include <gtest/gtest.h>
 #include <stdio.h>
+#include <sys/file.h>
 #include <string>
 
 #if defined(__BIONIC__)
 
+#include "android-base/file.h"
 #include "gwp_asan/options.h"
 #include "platform/bionic/malloc.h"
+#include "sys/system_properties.h"
 #include "utils.h"
 
-void RunGwpAsanTest(const char* test_name) {
-  ExecTestHelper eh;
-  eh.SetEnv({"GWP_ASAN_SAMPLE_RATE=1", "GWP_ASAN_PROCESS_SAMPLING=1", "GWP_ASAN_MAX_ALLOCS=40000",
-             nullptr});
-  std::string filter_arg = "--gtest_filter=";
-  filter_arg += test_name;
-  std::string exec(testing::internal::GetArgvs()[0]);
-  eh.SetArgs({exec.c_str(), "--gtest_also_run_disabled_tests", filter_arg.c_str(), nullptr});
-  eh.Run([&]() { execve(exec.c_str(), eh.GetArgs(), eh.GetEnv()); },
-         /* expected_exit_status */ 0,
-         // |expected_output_regex|, ensure at least one test ran:
-         R"(\[  PASSED  \] [1-9]+0? test)");
+// basename is a mess, use gnu basename explicitly to avoid the need for string
+// mutation.
+extern "C" const char* __gnu_basename(const char* path);
+
+// GWP-ASan tests can run much slower, especially when combined with HWASan.
+// Triple the deadline to avoid flakes (b/238585984).
+extern "C" bool GetInitialArgs(const char*** args, size_t* num_args) {
+  static const char* initial_args[] = {"--deadline_threshold_ms=270000"};
+  *args = initial_args;
+  *num_args = 1;
+  return true;
 }
 
 // This file implements "torture testing" under GWP-ASan, where we sample every
@@ -58,4 +60,191 @@
   RunGwpAsanTest("malloc.*:-malloc.mallinfo*");
 }
 
+class SyspropRestorer {
+ private:
+  std::vector<std::pair<std::string, std::string>> props_to_restore_;
+  // System properties are global for a device, so the tests that mutate the
+  // GWP-ASan system properties must be run mutually exclusive. Because
+  // bionic-unit-tests is run in an isolated gtest fashion (each test is run in
+  // its own process), we have to use flocks to synchronise between tests.
+  int flock_fd_;
+
+ public:
+  SyspropRestorer() {
+    std::string path = testing::internal::GetArgvs()[0];
+    flock_fd_ = open(path.c_str(), O_RDONLY);
+    EXPECT_NE(flock_fd_, -1) << "failed to open self for a flock";
+    EXPECT_NE(flock(flock_fd_, LOCK_EX), -1) << "failed to flock myself";
+
+    const char* basename = __gnu_basename(path.c_str());
+    std::vector<std::string> props = {
+        std::string("libc.debug.gwp_asan.sample_rate.") + basename,
+        std::string("libc.debug.gwp_asan.process_sampling.") + basename,
+        std::string("libc.debug.gwp_asan.max_allocs.") + basename,
+        "libc.debug.gwp_asan.sample_rate.system_default",
+        "libc.debug.gwp_asan.sample_rate.app_default",
+        "libc.debug.gwp_asan.process_sampling.system_default",
+        "libc.debug.gwp_asan.process_sampling.app_default",
+        "libc.debug.gwp_asan.max_allocs.system_default",
+        "libc.debug.gwp_asan.max_allocs.app_default",
+    };
+
+    size_t base_props_size = props.size();
+    for (size_t i = 0; i < base_props_size; ++i) {
+      props.push_back("persist." + props[i]);
+    }
+
+    std::string reset_log;
+
+    for (const std::string& prop : props) {
+      std::string value = GetSysprop(prop);
+      props_to_restore_.emplace_back(prop, value);
+      if (!value.empty()) {
+        __system_property_set(prop.c_str(), "");
+      }
+    }
+  }
+
+  ~SyspropRestorer() {
+    for (const auto& kv : props_to_restore_) {
+      if (kv.second != GetSysprop(kv.first)) {
+        __system_property_set(kv.first.c_str(), kv.second.c_str());
+      }
+    }
+    close(flock_fd_);
+  }
+
+  static std::string GetSysprop(const std::string& name) {
+    std::string value;
+    const prop_info* pi = __system_property_find(name.c_str());
+    if (pi == nullptr) return value;
+    __system_property_read_callback(
+        pi,
+        [](void* cookie, const char* /* name */, const char* value, uint32_t /* serial */) {
+          std::string* v = static_cast<std::string*>(cookie);
+          *v = value;
+        },
+        &value);
+    return value;
+  }
+};
+
+TEST(gwp_asan_integration, DISABLED_assert_gwp_asan_enabled) {
+  std::string maps;
+  EXPECT_TRUE(android::base::ReadFileToString("/proc/self/maps", &maps));
+  EXPECT_TRUE(maps.find("GWP-ASan") != std::string::npos) << maps;
+
+  volatile int* x = new int;
+  delete x;
+  EXPECT_DEATH({ *x = 7; }, "");
+}
+
+TEST(gwp_asan_integration, DISABLED_assert_gwp_asan_disabled) {
+  std::string maps;
+  EXPECT_TRUE(android::base::ReadFileToString("/proc/self/maps", &maps));
+  EXPECT_TRUE(maps.find("GWP-ASan") == std::string::npos);
+}
+
+TEST(gwp_asan_integration, sysprops_program_specific) {
+  SyspropRestorer restorer;
+
+  std::string path = testing::internal::GetArgvs()[0];
+  const char* basename = __gnu_basename(path.c_str());
+  __system_property_set((std::string("libc.debug.gwp_asan.sample_rate.") + basename).c_str(), "1");
+  __system_property_set((std::string("libc.debug.gwp_asan.process_sampling.") + basename).c_str(),
+                        "1");
+  __system_property_set((std::string("libc.debug.gwp_asan.max_allocs.") + basename).c_str(),
+                        "40000");
+
+  RunSubtestNoEnv("gwp_asan_integration.DISABLED_assert_gwp_asan_enabled");
+}
+
+TEST(gwp_asan_integration, sysprops_persist_program_specific) {
+  SyspropRestorer restorer;
+
+  std::string path = testing::internal::GetArgvs()[0];
+  const char* basename = __gnu_basename(path.c_str());
+  __system_property_set(
+      (std::string("persist.libc.debug.gwp_asan.sample_rate.") + basename).c_str(), "1");
+  __system_property_set(
+      (std::string("persist.libc.debug.gwp_asan.process_sampling.") + basename).c_str(), "1");
+  __system_property_set((std::string("persist.libc.debug.gwp_asan.max_allocs.") + basename).c_str(),
+                        "40000");
+
+  RunSubtestNoEnv("gwp_asan_integration.DISABLED_assert_gwp_asan_enabled");
+}
+
+TEST(gwp_asan_integration, sysprops_system) {
+  SyspropRestorer restorer;
+
+  __system_property_set("libc.debug.gwp_asan.sample_rate.system_default", "1");
+  __system_property_set("libc.debug.gwp_asan.process_sampling.system_default", "1");
+  __system_property_set("libc.debug.gwp_asan.max_allocs.system_default", "40000");
+
+  RunSubtestNoEnv("gwp_asan_integration.DISABLED_assert_gwp_asan_enabled");
+}
+
+TEST(gwp_asan_integration, sysprops_persist_system) {
+  SyspropRestorer restorer;
+
+  __system_property_set("persist.libc.debug.gwp_asan.sample_rate.system_default", "1");
+  __system_property_set("persist.libc.debug.gwp_asan.process_sampling.system_default", "1");
+  __system_property_set("persist.libc.debug.gwp_asan.max_allocs.system_default", "40000");
+
+  RunSubtestNoEnv("gwp_asan_integration.DISABLED_assert_gwp_asan_enabled");
+}
+
+TEST(gwp_asan_integration, sysprops_non_persist_overrides_persist) {
+  SyspropRestorer restorer;
+
+  __system_property_set("libc.debug.gwp_asan.sample_rate.system_default", "1");
+  __system_property_set("libc.debug.gwp_asan.process_sampling.system_default", "1");
+  __system_property_set("libc.debug.gwp_asan.max_allocs.system_default", "40000");
+
+  __system_property_set("persist.libc.debug.gwp_asan.sample_rate.system_default", "0");
+  __system_property_set("persist.libc.debug.gwp_asan.process_sampling.system_default", "0");
+  __system_property_set("persist.libc.debug.gwp_asan.max_allocs.system_default", "0");
+
+  RunSubtestNoEnv("gwp_asan_integration.DISABLED_assert_gwp_asan_enabled");
+}
+
+TEST(gwp_asan_integration, sysprops_program_specific_overrides_default) {
+  SyspropRestorer restorer;
+
+  std::string path = testing::internal::GetArgvs()[0];
+  const char* basename = __gnu_basename(path.c_str());
+  __system_property_set(
+      (std::string("persist.libc.debug.gwp_asan.sample_rate.") + basename).c_str(), "1");
+  __system_property_set(
+      (std::string("persist.libc.debug.gwp_asan.process_sampling.") + basename).c_str(), "1");
+  __system_property_set((std::string("persist.libc.debug.gwp_asan.max_allocs.") + basename).c_str(),
+                        "40000");
+
+  __system_property_set("libc.debug.gwp_asan.sample_rate.system_default", "0");
+  __system_property_set("libc.debug.gwp_asan.process_sampling.system_default", "0");
+  __system_property_set("libc.debug.gwp_asan.max_allocs.system_default", "0");
+
+  RunSubtestNoEnv("gwp_asan_integration.DISABLED_assert_gwp_asan_enabled");
+}
+
+TEST(gwp_asan_integration, sysprops_can_disable) {
+  SyspropRestorer restorer;
+
+  __system_property_set("libc.debug.gwp_asan.sample_rate.system_default", "0");
+  __system_property_set("libc.debug.gwp_asan.process_sampling.system_default", "0");
+  __system_property_set("libc.debug.gwp_asan.max_allocs.system_default", "0");
+
+  RunSubtestNoEnv("gwp_asan_integration.DISABLED_assert_gwp_asan_disabled");
+}
+
+TEST(gwp_asan_integration, env_overrides_sysprop) {
+  SyspropRestorer restorer;
+
+  __system_property_set("libc.debug.gwp_asan.sample_rate.system_default", "0");
+  __system_property_set("libc.debug.gwp_asan.process_sampling.system_default", "0");
+  __system_property_set("libc.debug.gwp_asan.max_allocs.system_default", "0");
+
+  RunGwpAsanTest("gwp_asan_integration.DISABLED_assert_gwp_asan_enabled");
+}
+
 #endif  // defined(__BIONIC__)
diff --git a/tests/stdio_test.cpp b/tests/stdio_test.cpp
index 87031f6..5bc6567 100644
--- a/tests/stdio_test.cpp
+++ b/tests/stdio_test.cpp
@@ -25,6 +25,7 @@
 #include <sys/cdefs.h>
 #include <sys/socket.h>
 #include <sys/stat.h>
+#include <sys/sysinfo.h>
 #include <sys/types.h>
 #include <unistd.h>
 #include <wchar.h>
@@ -2938,3 +2939,27 @@
 
   fclose(fp);
 }
+
+static int64_t GetTotalRamGiB() {
+  struct sysinfo si;
+  sysinfo(&si);
+  return (static_cast<int64_t>(si.totalram) * si.mem_unit) / 1024 / 1024 / 1024;
+}
+
+TEST(STDIO_TEST, fread_int_overflow) {
+  if (GetTotalRamGiB() <= 4) GTEST_SKIP() << "not enough memory";
+
+  const size_t too_big_for_an_int = 0x80000000ULL;
+  std::vector<char> buf(too_big_for_an_int);
+  std::unique_ptr<FILE, decltype(&fclose)> fp{fopen("/dev/zero", "re"), fclose};
+  ASSERT_EQ(too_big_for_an_int, fread(&buf[0], 1, too_big_for_an_int, fp.get()));
+}
+
+TEST(STDIO_TEST, fwrite_int_overflow) {
+  if (GetTotalRamGiB() <= 4) GTEST_SKIP() << "not enough memory";
+
+  const size_t too_big_for_an_int = 0x80000000ULL;
+  std::vector<char> buf(too_big_for_an_int);
+  std::unique_ptr<FILE, decltype(&fclose)> fp{fopen("/dev/null", "we"), fclose};
+  ASSERT_EQ(too_big_for_an_int, fwrite(&buf[0], 1, too_big_for_an_int, fp.get()));
+}
diff --git a/tests/time_test.cpp b/tests/time_test.cpp
index 5fc4cad..40e5c6d 100644
--- a/tests/time_test.cpp
+++ b/tests/time_test.cpp
@@ -84,6 +84,16 @@
   ASSERT_EQ(1970, broken_down->tm_year + 1900);
 }
 
+TEST(time, mktime_TZ_as_UTC_and_offset) {
+  struct tm tm = {.tm_year = 70, .tm_mon = 0, .tm_mday = 1};
+
+  // This TZ value is not a valid Olson ID and is not present in tzdata file,
+  // but is a valid TZ string according to POSIX standard.
+  setenv("TZ", "UTC+08:00:00", 1);
+  tzset();
+  ASSERT_EQ(static_cast<time_t>(8 * 60 * 60), mktime(&tm));
+}
+
 static void* gmtime_no_stack_overflow_14313703_fn(void*) {
   const char* original_tz = getenv("TZ");
   // Ensure we'll actually have to enter tzload by using a time zone that doesn't exist.
@@ -134,15 +144,11 @@
 }
 
 TEST(time, mktime_10310929) {
-  struct tm t;
-  memset(&t, 0, sizeof(tm));
-  t.tm_year = 200;
-  t.tm_mon = 2;
-  t.tm_mday = 10;
+  struct tm tm = {.tm_year = 2100 - 1900, .tm_mon = 2, .tm_mday = 10};
 
 #if !defined(__LP64__)
   // 32-bit bionic has a signed 32-bit time_t.
-  ASSERT_EQ(-1, mktime(&t));
+  ASSERT_EQ(-1, mktime(&tm));
   ASSERT_EQ(EOVERFLOW, errno);
 #else
   // Everyone else should be using a signed 64-bit time_t.
@@ -151,13 +157,12 @@
   setenv("TZ", "America/Los_Angeles", 1);
   tzset();
   errno = 0;
-  ASSERT_EQ(static_cast<time_t>(4108348800U), mktime(&t));
-  ASSERT_EQ(0, errno);
 
-  setenv("TZ", "UTC", 1);
-  tzset();
-  errno = 0;
-  ASSERT_EQ(static_cast<time_t>(4108320000U), mktime(&t));
+  // On the date/time specified by tm America/Los_Angeles
+  // follows DST. But tm_isdst is set to 0, which forces
+  // mktime to interpret that time as local standard, hence offset
+  // is 8 hours, not 7.
+  ASSERT_EQ(static_cast<time_t>(4108348800U), mktime(&tm));
   ASSERT_EQ(0, errno);
 #endif
 }
@@ -184,6 +189,43 @@
   ASSERT_EQ(EOVERFLOW, errno);
 }
 
+TEST(time, mktime_invalid_tm_TZ_combination) {
+  setenv("TZ", "UTC", 1);
+
+  struct tm t;
+  memset(&t, 0, sizeof(tm));
+  t.tm_year = 2022 - 1900;
+  t.tm_mon = 11;
+  t.tm_mday = 31;
+  // UTC does not observe DST
+  t.tm_isdst = 1;
+
+  errno = 0;
+
+  EXPECT_EQ(static_cast<time_t>(-1), mktime(&t));
+  // mktime sets errno to EOVERFLOW if result is unrepresentable.
+  EXPECT_EQ(EOVERFLOW, errno);
+}
+
+// Transitions in the tzdata file are generated up to the year 2100. Testing
+// that dates beyond that are handled properly too.
+TEST(time, mktime_after_2100) {
+  struct tm tm = {.tm_year = 2150 - 1900, .tm_mon = 2, .tm_mday = 10, .tm_isdst = -1};
+
+#if !defined(__LP64__)
+  // 32-bit bionic has a signed 32-bit time_t.
+  ASSERT_EQ(-1, mktime(&tm));
+  ASSERT_EQ(EOVERFLOW, errno);
+#else
+  setenv("TZ", "Europe/London", 1);
+  tzset();
+  errno = 0;
+
+  ASSERT_EQ(static_cast<time_t>(5686156800U), mktime(&tm));
+  ASSERT_EQ(0, errno);
+#endif
+}
+
 TEST(time, strftime) {
   setenv("TZ", "UTC", 1);
 
@@ -206,7 +248,25 @@
   EXPECT_STREQ("Sun Mar 10 00:00:00 2100", buf);
 }
 
-TEST(time, strftime_null_tm_zone) {
+TEST(time, strftime_second_before_epoch) {
+  setenv("TZ", "UTC", 1);
+
+  struct tm t;
+  memset(&t, 0, sizeof(tm));
+  t.tm_year = 1969 - 1900;
+  t.tm_mon = 11;
+  t.tm_mday = 31;
+  t.tm_hour = 23;
+  t.tm_min = 59;
+  t.tm_sec = 59;
+
+  char buf[64];
+
+  EXPECT_EQ(2U, strftime(buf, sizeof(buf), "%s", &t));
+  EXPECT_STREQ("-1", buf);
+}
+
+TEST(time, strftime_Z_null_tm_zone) {
   // Netflix on Nexus Player wouldn't start (http://b/25170306).
   struct tm t;
   memset(&t, 0, sizeof(tm));
@@ -244,6 +304,86 @@
 #endif
 }
 
+// According to C language specification the only tm struct field needed to
+// find out replacement for %z and %Z in strftime is tm_isdst. Which is
+// wrong, as time zones change their standard offset and even DST savings.
+// tzcode deviates from C language specification and requires tm struct either
+// to be output of localtime-like functions or to be modified by mktime call
+// before passing to strftime. See tz mailing discussion for more details
+// https://mm.icann.org/pipermail/tz/2022-July/031674.html
+// But we are testing case when tm.tm_zone is null, which means that tm struct
+// is not coming from localtime and is neither modified by mktime. That's why
+// we are comparing against +0000, even though America/Los_Angeles never
+// observes it.
+TEST(time, strftime_z_null_tm_zone) {
+  char str[64];
+  struct tm tm = {.tm_year = 109, .tm_mon = 4, .tm_mday = 2, .tm_isdst = 0};
+
+  setenv("TZ", "America/Los_Angeles", 1);
+  tzset();
+
+  tm.tm_zone = NULL;
+
+  size_t result = strftime(str, sizeof(str), "%z", &tm);
+
+  EXPECT_EQ(5U, result);
+  EXPECT_STREQ("+0000", str);
+
+  tm.tm_isdst = 1;
+
+  result = strftime(str, sizeof(str), "%z", &tm);
+
+  EXPECT_EQ(5U, result);
+  EXPECT_STREQ("+0000", str);
+
+  setenv("TZ", "UTC", 1);
+  tzset();
+
+  tm.tm_isdst = 0;
+
+  result = strftime(str, sizeof(str), "%z", &tm);
+
+  EXPECT_EQ(5U, result);
+  EXPECT_STREQ("+0000", str);
+
+  tm.tm_isdst = 1;
+
+  result = strftime(str, sizeof(str), "%z", &tm);
+
+  EXPECT_EQ(5U, result);
+  EXPECT_STREQ("+0000", str);
+}
+
+TEST(time, strftime_z_Europe_Lisbon) {
+  char str[64];
+  // During 1992-1996 Europe/Lisbon standard offset was 1 hour.
+  // tm_isdst is not set as it will be overridden by mktime call anyway.
+  struct tm tm = {.tm_year = 1996 - 1900, .tm_mon = 2, .tm_mday = 13};
+
+  setenv("TZ", "Europe/Lisbon", 1);
+  tzset();
+
+  // tzcode's strftime implementation for %z relies on prior mktime call.
+  // At the moment of writing %z value is taken from tm_gmtoff. So without
+  // mktime call %z is replaced with +0000.
+  // See https://mm.icann.org/pipermail/tz/2022-July/031674.html
+  mktime(&tm);
+
+  size_t result = strftime(str, sizeof(str), "%z", &tm);
+
+  EXPECT_EQ(5U, result);
+  EXPECT_STREQ("+0100", str);
+
+  // Now standard offset is 0.
+  tm = {.tm_year = 2022 - 1900, .tm_mon = 2, .tm_mday = 13};
+
+  mktime(&tm);
+  result = strftime(str, sizeof(str), "%z", &tm);
+
+  EXPECT_EQ(5U, result);
+  EXPECT_STREQ("+0000", str);
+}
+
 TEST(time, strftime_l) {
   locale_t cloc = newlocale(LC_ALL, "C.UTF-8", nullptr);
   locale_t old_locale = uselocale(cloc);
diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp
index 02da585..5fce5b8 100644
--- a/tests/unistd_test.cpp
+++ b/tests/unistd_test.cpp
@@ -1103,6 +1103,10 @@
   ASSERT_EQ(4, GetCpuCountFromString("0, 1-2, 4\n"));
 }
 
+TEST(UNISTD_TEST, sysconf_SC_NPROCESSORS_make_sense) {
+  ASSERT_LE(sysconf(_SC_NPROCESSORS_ONLN), sysconf(_SC_NPROCESSORS_CONF));
+}
+
 TEST(UNISTD_TEST, sysconf_SC_NPROCESSORS_ONLN) {
   std::string line;
   ASSERT_TRUE(android::base::ReadFileToString("/sys/devices/system/cpu/online", &line));
diff --git a/tests/utils.cpp b/tests/utils.cpp
new file mode 100644
index 0000000..8258833
--- /dev/null
+++ b/tests/utils.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2022 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 "utils.h"
+
+void RunGwpAsanTest(const char* test_name) {
+  ExecTestHelper eh;
+  eh.SetEnv({"GWP_ASAN_SAMPLE_RATE=1", "GWP_ASAN_PROCESS_SAMPLING=1", "GWP_ASAN_MAX_ALLOCS=40000",
+             nullptr});
+  std::string filter_arg = "--gtest_filter=";
+  filter_arg += test_name;
+  std::string exec(testing::internal::GetArgvs()[0]);
+  eh.SetArgs({exec.c_str(), "--gtest_also_run_disabled_tests", filter_arg.c_str(), nullptr});
+  eh.Run([&]() { execve(exec.c_str(), eh.GetArgs(), eh.GetEnv()); },
+         /* expected_exit_status */ 0,
+         // |expected_output_regex|, ensure at least one test ran:
+         R"(\[  PASSED  \] [1-9][0-9]* test)");
+}
+
+void RunSubtestNoEnv(const char* test_name) {
+  ExecTestHelper eh;
+  std::string filter_arg = "--gtest_filter=";
+  filter_arg += test_name;
+  std::string exec(testing::internal::GetArgvs()[0]);
+  eh.SetArgs({exec.c_str(), "--gtest_also_run_disabled_tests", filter_arg.c_str(), nullptr});
+  eh.Run([&]() { execve(exec.c_str(), eh.GetArgs(), eh.GetEnv()); },
+         /* expected_exit_status */ 0,
+         // |expected_output_regex|, ensure at least one test ran:
+         R"(\[  PASSED  \] [1-9]+0? test)");
+}
diff --git a/tests/utils.h b/tests/utils.h
index 72214c2..81869e3 100644
--- a/tests/utils.h
+++ b/tests/utils.h
@@ -19,6 +19,7 @@
 #include <dirent.h>
 #include <dlfcn.h>
 #include <fcntl.h>
+#include <gtest/gtest.h>
 #include <inttypes.h>
 #include <sys/mman.h>
 #include <sys/prctl.h>
@@ -264,6 +265,7 @@
 };
 
 void RunGwpAsanTest(const char* test_name);
+void RunSubtestNoEnv(const char* test_name);
 #endif
 
 class FdLeakChecker {
diff --git a/tools/Android.bp b/tools/Android.bp
index dcd2a7d..d3ca28a 100644
--- a/tools/Android.bp
+++ b/tools/Android.bp
@@ -15,7 +15,7 @@
 
 subdirs = ["*"]
 
-filegroup {
-    name: "bionic-generate-version-script",
+python_binary_host {
+    name: "generate-version-script",
     srcs: ["generate-version-script.py"],
 }