summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Lobdell <slobdell@google.com>2019-08-25 12:20:54 -0700
committerScott Lobdell <slobdell@google.com>2019-08-25 12:20:54 -0700
commit4f9bfdcaca2414c8959986f0a4d73f16cb15e1c4 (patch)
tree540bab5498d276cbbfad24c48a7ff989ee8b920a
parentbfda022dd6fbbcea60e9f52496d90ece514b32da (diff)
parentf77cc9b224c35fa7d1d71e7c374ef19e47b5f6a5 (diff)
Merge RP1A.190822.001
Change-Id: Iaf90835a99d87f6246798efd2cea6fe9f750ea18
-rw-r--r--README.md3
-rw-r--r--android-changes-for-ndk-developers.md17
-rw-r--r--docs/native_allocator.md348
-rw-r--r--docs/status.md13
-rw-r--r--libc/Android.bp30
-rw-r--r--libc/NOTICE44
-rw-r--r--libc/SECCOMP_WHITELIST_COMMON.TXT60
-rw-r--r--libc/SYSCALLS.TXT37
-rw-r--r--libc/arch-common/bionic/crtbegin.c39
-rw-r--r--libc/arch-x86/dynamic_function_dispatch.cpp7
-rw-r--r--libc/arch-x86/generic/string/wmemset.c (renamed from libc/bionic/socket.cpp)14
-rw-r--r--libc/arch-x86/kabylake/string/avx2-wmemset-kbl.S148
-rw-r--r--libc/arch-x86/static_function_dispatch.S1
-rw-r--r--libc/arch-x86_64/string/avx2-wmemset-kbl.S140
-rw-r--r--libc/bionic/NetdClient.cpp23
-rw-r--r--libc/bionic/NetdClientDispatch.cpp33
-rw-r--r--libc/bionic/__cxa_guard.cpp2
-rw-r--r--libc/bionic/__libc_init_main_thread.cpp3
-rw-r--r--libc/bionic/accept4.cpp23
-rw-r--r--libc/bionic/bionic_systrace.cpp3
-rw-r--r--libc/bionic/clock_nanosleep.cpp4
-rw-r--r--libc/bionic/connect.cpp23
-rw-r--r--libc/bionic/faccessat.cpp4
-rw-r--r--libc/bionic/fchmod.cpp4
-rw-r--r--libc/bionic/fchmodat.cpp4
-rw-r--r--libc/bionic/fdsan.cpp71
-rw-r--r--libc/bionic/fgetxattr.cpp4
-rw-r--r--libc/bionic/flistxattr.cpp4
-rw-r--r--libc/bionic/fork.cpp4
-rw-r--r--libc/bionic/fortify.cpp31
-rw-r--r--libc/bionic/fsetxattr.cpp4
-rw-r--r--libc/bionic/grp_pwd.cpp211
-rw-r--r--libc/bionic/grp_pwd_file.cpp4
-rw-r--r--libc/bionic/jemalloc.h2
-rw-r--r--libc/bionic/libc_init_dynamic.cpp15
-rw-r--r--libc/bionic/malloc_heapprofd.cpp1
-rw-r--r--libc/bionic/malloc_limit.cpp2
-rw-r--r--libc/bionic/mremap.cpp4
-rw-r--r--libc/bionic/ndk_cruft.cpp16
-rw-r--r--libc/bionic/open.cpp2
-rw-r--r--libc/bionic/pthread_cond.cpp12
-rw-r--r--libc/bionic/pthread_create.cpp24
-rw-r--r--libc/bionic/pthread_internal.h8
-rw-r--r--libc/bionic/pthread_mutex.cpp18
-rw-r--r--libc/bionic/pthread_rwlock.cpp24
-rw-r--r--libc/bionic/semaphore.cpp11
-rw-r--r--libc/bionic/signal.cpp4
-rw-r--r--libc/include/android/fdsan.h4
-rw-r--r--libc/include/android/legacy_signal_inlines.h2
-rw-r--r--libc/include/arpa/nameser.h50
-rw-r--r--libc/include/bits/elf_arm64.h6
-rw-r--r--libc/include/bits/fortify/fcntl.h46
-rw-r--r--libc/include/bits/fortify/stdio.h15
-rw-r--r--libc/include/bits/fortify/stdlib.h5
-rw-r--r--libc/include/bits/fortify/string.h44
-rw-r--r--libc/include/bits/fortify/strings.h59
-rw-r--r--libc/include/bits/fortify/unistd.h3
-rw-r--r--libc/include/bits/glibc-syscalls.h18
-rw-r--r--libc/include/bits/stdatomic.h286
-rw-r--r--libc/include/bits/timespec.h2
-rw-r--r--libc/include/pthread.h20
-rw-r--r--libc/include/semaphore.h8
-rw-r--r--libc/include/stdatomic.h258
-rw-r--r--libc/include/stdio.h44
-rw-r--r--libc/include/stdlib.h2
-rw-r--r--libc/include/strings.h20
-rw-r--r--libc/include/sys/cdefs.h3
-rw-r--r--libc/include/sys/mman.h146
-rwxr-xr-xlibc/kernel/tools/update_all.py4
-rw-r--r--libc/kernel/uapi/asm-arm/asm/unistd-common.h6
-rw-r--r--libc/kernel/uapi/asm-arm64/asm/hwcap.h7
-rw-r--r--libc/kernel/uapi/asm-arm64/asm/kvm.h18
-rw-r--r--libc/kernel/uapi/asm-arm64/asm/ptrace.h5
-rw-r--r--libc/kernel/uapi/asm-generic/sockios.h4
-rw-r--r--libc/kernel/uapi/asm-generic/unistd.h8
-rw-r--r--libc/kernel/uapi/asm-mips/asm/inst.h8
-rw-r--r--libc/kernel/uapi/asm-mips/asm/sockios.h4
-rw-r--r--libc/kernel/uapi/asm-mips/asm/unistd_n32.h6
-rw-r--r--libc/kernel/uapi/asm-mips/asm/unistd_n64.h6
-rw-r--r--libc/kernel/uapi/asm-mips/asm/unistd_nr_n32.h2
-rw-r--r--libc/kernel/uapi/asm-mips/asm/unistd_nr_n64.h2
-rw-r--r--libc/kernel/uapi/asm-mips/asm/unistd_nr_o32.h2
-rw-r--r--libc/kernel/uapi/asm-mips/asm/unistd_o32.h6
-rw-r--r--libc/kernel/uapi/asm-x86/asm/kvm.h19
-rw-r--r--libc/kernel/uapi/asm-x86/asm/perf_regs.h18
-rw-r--r--libc/kernel/uapi/asm-x86/asm/unistd_32.h6
-rw-r--r--libc/kernel/uapi/asm-x86/asm/unistd_64.h6
-rw-r--r--libc/kernel/uapi/asm-x86/asm/unistd_x32.h6
-rw-r--r--libc/kernel/uapi/asm-x86/asm/vmx.h1
-rw-r--r--libc/kernel/uapi/drm/amdgpu_drm.h25
-rw-r--r--libc/kernel/uapi/drm/drm.h29
-rw-r--r--libc/kernel/uapi/drm/drm_fourcc.h18
-rw-r--r--libc/kernel/uapi/drm/drm_mode.h1
-rw-r--r--libc/kernel/uapi/drm/i915_drm.h79
-rw-r--r--libc/kernel/uapi/drm/lima_drm.h129
-rw-r--r--libc/kernel/uapi/drm/msm_drm.h12
-rw-r--r--libc/kernel/uapi/drm/panfrost_drm.h80
-rw-r--r--libc/kernel/uapi/linux/aspeed-p2a-ctrl.h33
-rw-r--r--libc/kernel/uapi/linux/audit.h14
-rw-r--r--libc/kernel/uapi/linux/batman_adv.h1
-rw-r--r--libc/kernel/uapi/linux/bpf.h36
-rw-r--r--libc/kernel/uapi/linux/btf.h20
-rw-r--r--libc/kernel/uapi/linux/elf-em.h5
-rw-r--r--libc/kernel/uapi/linux/ethtool.h5
-rw-r--r--libc/kernel/uapi/linux/fcntl.h1
-rw-r--r--libc/kernel/uapi/linux/fou.h6
-rw-r--r--libc/kernel/uapi/linux/fs.h1
-rw-r--r--libc/kernel/uapi/linux/fuse.h7
-rw-r--r--libc/kernel/uapi/linux/icmpv6.h2
-rw-r--r--libc/kernel/uapi/linux/if_ether.h1
-rw-r--r--libc/kernel/uapi/linux/if_tun.h1
-rw-r--r--libc/kernel/uapi/linux/if_vlan.h1
-rw-r--r--libc/kernel/uapi/linux/input-event-codes.h1
-rw-r--r--libc/kernel/uapi/linux/io_uring.h5
-rw-r--r--libc/kernel/uapi/linux/ip_vs.h7
-rw-r--r--libc/kernel/uapi/linux/kfd_ioctl.h6
-rw-r--r--libc/kernel/uapi/linux/kvm.h9
-rw-r--r--libc/kernel/uapi/linux/lirc.h1
-rw-r--r--libc/kernel/uapi/linux/media-bus-format.h1
-rw-r--r--libc/kernel/uapi/linux/media.h8
-rw-r--r--libc/kernel/uapi/linux/mount.h34
-rw-r--r--libc/kernel/uapi/linux/netfilter/nf_tables.h8
-rw-r--r--libc/kernel/uapi/linux/nfs_mount.h6
-rw-r--r--libc/kernel/uapi/linux/nfsd/cld.h1
-rw-r--r--libc/kernel/uapi/linux/nilfs2_ondisk.h13
-rw-r--r--libc/kernel/uapi/linux/nl80211.h17
-rw-r--r--libc/kernel/uapi/linux/openvswitch.h11
-rw-r--r--libc/kernel/uapi/linux/pci_regs.h43
-rw-r--r--libc/kernel/uapi/linux/pkt_sched.h3
-rw-r--r--libc/kernel/uapi/linux/psci.h6
-rw-r--r--libc/kernel/uapi/linux/psp-sev.h5
-rw-r--r--libc/kernel/uapi/linux/sched.h1
-rw-r--r--libc/kernel/uapi/linux/serial_core.h2
-rw-r--r--libc/kernel/uapi/linux/snmp.h1
-rw-r--r--libc/kernel/uapi/linux/sockios.h10
-rw-r--r--libc/kernel/uapi/linux/spi/spidev.h3
-rw-r--r--libc/kernel/uapi/linux/switchtec_ioctl.h11
-rw-r--r--libc/kernel/uapi/linux/tipc.h1
-rw-r--r--libc/kernel/uapi/linux/tipc_netlink.h2
-rw-r--r--libc/kernel/uapi/linux/tls.h13
-rw-r--r--libc/kernel/uapi/linux/v4l2-controls.h6
-rw-r--r--libc/kernel/uapi/linux/version.h2
-rw-r--r--libc/kernel/uapi/linux/vfio.h2
-rw-r--r--libc/kernel/uapi/linux/vfio_ccw.h6
-rw-r--r--libc/kernel/uapi/linux/videodev2.h17
-rw-r--r--libc/kernel/uapi/misc/habanalabs.h65
-rw-r--r--libc/kernel/uapi/rdma/efa-abi.h88
-rw-r--r--libc/kernel/uapi/rdma/mlx5-abi.h2
-rw-r--r--libc/kernel/uapi/rdma/mlx5_user_ioctl_cmds.h2
-rw-r--r--libc/kernel/uapi/rdma/mlx5_user_ioctl_verbs.h6
-rw-r--r--libc/kernel/uapi/rdma/rdma_netlink.h15
-rw-r--r--libc/kernel/uapi/rdma/rdma_user_ioctl_cmds.h1
-rw-r--r--libc/kernel/uapi/scsi/fc/fc_els.h19
-rw-r--r--libc/kernel/uapi/sound/sof/abi.h37
-rw-r--r--libc/kernel/uapi/sound/sof/eq.h67
-rw-r--r--libc/kernel/uapi/sound/sof/fw.h64
-rw-r--r--libc/kernel/uapi/sound/sof/header.h29
-rw-r--r--libc/kernel/uapi/sound/sof/manifest.h128
-rw-r--r--libc/kernel/uapi/sound/sof/tokens.h68
-rw-r--r--libc/kernel/uapi/sound/sof/tone.h29
-rw-r--r--libc/kernel/uapi/sound/sof/trace.h45
-rw-r--r--libc/libc.map.txt14
-rw-r--r--libc/malloc_debug/Android.bp3
-rw-r--r--libc/malloc_debug/PointerData.cpp14
-rw-r--r--libc/malloc_debug/UnwindBacktrace.cpp12
-rw-r--r--libc/malloc_debug/backtrace.cpp12
-rw-r--r--libc/private/NetdClientDispatch.h8
-rw-r--r--libc/private/WriteProtected.h16
-rw-r--r--libc/private/bionic_globals.h4
-rw-r--r--libc/private/bionic_macros.h9
-rw-r--r--libc/private/sigrtmin.h6
-rw-r--r--libc/stdio/stdio.cpp2
-rw-r--r--libc/symbol_ordering210
-rwxr-xr-xlibc/tools/gensyscalls.py3
-rw-r--r--libc/tzcode/bionic.cpp40
l---------libc/versioner-dependencies/common/clang-builtins2
-rw-r--r--libdl/libdl_cfi.cpp3
-rw-r--r--libm/Android.bp78
-rw-r--r--linker/Android.bp5
-rw-r--r--linker/dlfcn.cpp4
-rw-r--r--linker/ld.config.format.md6
-rw-r--r--linker/ldd5
-rw-r--r--linker/linker.cpp145
-rw-r--r--linker/linker.h12
-rw-r--r--linker/linker_main.cpp82
-rw-r--r--linker/linker_namespaces.h9
-rw-r--r--linker/linker_relocs.h6
-rw-r--r--linker/linker_sdk_versions.cpp11
-rw-r--r--linker/linker_soinfo.cpp10
-rw-r--r--linker/linker_soinfo.h3
-rw-r--r--tests/Android.bp92
-rw-r--r--tests/Android.mk22
-rw-r--r--tests/clang_fortify_tests.cpp607
-rw-r--r--tests/dlext_test.cpp10
-rw-r--r--tests/fortify_filecheck_diagnostics_test.cpp323
-rw-r--r--tests/fortify_test.cpp18
-rw-r--r--tests/grp_pwd_test.cpp368
-rw-r--r--tests/leak_test.cpp15
-rw-r--r--tests/libs/Android.bp2
-rw-r--r--tests/libs/segment_gap_outer.lds2
-rw-r--r--tests/make_fortify_compile_test.mk20
-rw-r--r--tests/malloc_test.cpp20
-rw-r--r--tests/pthread_test.cpp304
-rw-r--r--tests/semaphore_test.cpp13
-rw-r--r--tests/stdatomic_test.cpp9
-rw-r--r--tests/stdio_test.cpp83
-rw-r--r--tests/sys_mman_test.cpp61
-rw-r--r--tests/time_test.cpp4
-rwxr-xr-xtests/touch-obj-on-success7
209 files changed, 5275 insertions, 1561 deletions
diff --git a/README.md b/README.md
index f81558a4d..6bece251c 100644
--- a/README.md
+++ b/README.md
@@ -169,8 +169,7 @@ Adding a system call usually involves:
relevant file or files.
3. Add function declarations to the appropriate header file. Don't forget
to include the appropriate `__INTRODUCED_IN()`.
- 4. Add the function name to the correct section in libc/libc.map.txt and
- run `./libc/tools/genversion-scripts.py`.
+ 4. Add the function name to the correct section in libc/libc.map.txt.
5. Add at least basic tests. Even a test that deliberately supplies
an invalid argument helps check that we're generating the right symbol
and have the right declaration in the header file, and that you correctly
diff --git a/android-changes-for-ndk-developers.md b/android-changes-for-ndk-developers.md
index 1fdb1e48f..84456f988 100644
--- a/android-changes-for-ndk-developers.md
+++ b/android-changes-for-ndk-developers.md
@@ -1,8 +1,11 @@
-# Android changes for NDK developers
+# Android linker changes for NDK developers
This document details important changes related to native code
loading in various Android releases.
+See also [bionic status](docs/status.md) for general libc/libm/libdl
+behavior changes.
+
Required tools: the NDK has an _arch_-linux-android-readelf binary
(e.g. arm-linux-androideabi-readelf or i686-linux-android-readelf)
for each architecture (under toolchains/), but you can use readelf for
@@ -46,6 +49,10 @@ versions older than JB-MR2, you might want to consider
[ReLinker](https://github.com/KeepSafe/ReLinker) which claims to solve
these problems automatically.
+Alternatively, if you don't have too many dependencies, it can be easiest to
+simply link all of your code into one big library and sidestep the details of
+library and symbol lookup changes on all past (and future) Android versions.
+
## Changes to library search order
We have made various fixes to library search order when resolving symbols.
@@ -66,6 +73,14 @@ the local group. This allows ASAN, for example, to ensure that it can
intercept any symbol.
+## LD_PRELOAD and 32/64 bit
+
+LD_PRELOAD applies to both 32- and 64-bit processes. This means that you
+should avoid saying something like `/system/lib/libfoo.so` and just say
+`libfoo.so` instead, letting the dynamic linker find the correct library
+on its search path.
+
+
## RTLD_LOCAL (Available in API level >= 23)
The dlopen(3) RTLD_LOCAL flag used to be ignored but is implemented
diff --git a/docs/native_allocator.md b/docs/native_allocator.md
new file mode 100644
index 000000000..82a98fe48
--- /dev/null
+++ b/docs/native_allocator.md
@@ -0,0 +1,348 @@
+# Native Memory Allocator Verification
+This document describes how to verify the native memory allocator on Android.
+This procedure should be followed when upgrading or moving to a new allocator.
+A small minor upgrade might not need to run all of the benchmarks, however,
+at least the
+[SQL Allocation Trace Benchmark](#sql-allocation-trace-benchmark),
+[Memory Replay Benchmarks](#memory-replay-benchmarks) and
+[Performance Trace Benchmarks](#performance-trace-benchmarks) should be run.
+
+It is important to note that there are two modes for a native allocator
+to run in on Android. The first is the normal allocator, the second is
+called the svelte config, which is designed to run on memory constrained
+systems and be a bit slower, but take less RSS. To enable the svelte config,
+add this line to the `BoardConfig.mk` for the given target:
+
+ MALLOC_SVELTE := true
+
+The `BoardConfig.mk` file is usually found in the directory
+`device/<DEVICE_NAME>/` or in a sub directory.
+
+When evaluating a native allocator, make sure that you benchmark both
+versions.
+
+## Android Extensions
+Android supports a few non-standard functions and mallopt controls that
+a native allocator needs to implement.
+
+### Iterator Functions
+These are functions that are used to implement a memory leak detector
+called `libmemunreachable`.
+
+#### malloc\_disable
+This function, when called, should pause all threads that are making a
+call to an allocation function (malloc/free/etc). When a call
+is made to `malloc_enable`, the paused threads should start running again.
+
+#### malloc\_enable
+This function, when called, does nothing unless there was a previous call
+to `malloc_disable`. This call will unpause any thread which is making
+a call to an allocation function (malloc/free/etc) when `malloc_disable`
+was called previously.
+
+#### malloc\_iterate
+This function enumerates all of the allocations currently live in the
+system. It is meant to be called after a call to `malloc_disable` to
+prevent further allocations while this call is being executed. To
+see what is expected for this function, the best description is the
+tests for this funcion in `bionic/tests/malloc_itearte_test.cpp`.
+
+### Mallopt Extensions
+These are mallopt options that Android requires for a native allocator
+to work efficiently.
+
+#### M\_DECAY\_TIME
+When set to zero, `mallopt(M_DECAY_TIME, 0)`, it is expected that an
+allocator will attempt to purge and release any unused memory back to the
+kernel on free calls. This is important in Android to avoid consuming extra
+RSS.
+
+When set to non-zero, `mallopt(M_DECAY_TIME, 1)`, an allocator can delay the
+purge and release action. The amount of delay is up to the allocator
+implementation, but it should be a reasonable amount of time. The jemalloc
+allocator was implemented to have a one second delay.
+
+The drawback to this option is that most allocators do not have a separate
+thread to handle the purge, so the decay is only handled when an
+allocation operation occurs. For server processes, this can mean that
+RSS is slightly higher when the server is waiting for the next connection
+and no other allocation calls are made. The `M_PURGE` option is used to
+force a purge in this case.
+
+For all applications on Android, the call `mallopt(M_DECAY_TIME, 1)` is
+made by default. The idea is that it allows application frees to run a
+bit faster, while only increasing RSS a bit.
+
+#### M\_PURGE
+When called, `mallopt(M_PURGE, 0)`, an allocator should purge and release
+any unused memory immediately. The argument for this call is ignored. If
+possible, this call should clear thread cached memory if it exists. The
+idea is that this can be called to purge memory that has not been
+purged when `M_DECAY_TIME` is set to one. This is useful if you have a
+server application that does a lot of native allocations and the
+application wants to purge that memory before waiting for the next connection.
+
+## Correctness Tests
+These are the tests that should be run to verify an allocator is
+working properly according to Android.
+
+### Bionic Unit Tests
+The bionic unit tests contain a small number of allocator tests. These
+tests are primarily verifying Android extensions and non-standard behavior
+of allocation routines such as what happens when a non-power of two alignment
+is passed to memalign.
+
+To run all of the compliance tests:
+
+ adb shell /data/nativetest64/bionic-unit-tests/bionic-unit-tests --gtest_filter="malloc*"
+ adb shell /data/nativetest/bionic-unit-tests/bionic-unit-tests --gtest_filter="malloc*"
+
+The allocation tests are not meant to be complete, so it is expected
+that a native allocator will have its own set of tests that can be run.
+
+### CTS Entropy Test
+In addition to the bionic tests, there is also a CTS test that is designed
+to verify that the addresses returned by malloc are sufficiently randomized
+to help defeat potential security bugs.
+
+Run this test thusly:
+
+ atest AslrMallocTest
+
+If there are multiple devices connected to the system, use `-s <SERIAL>`
+to specify a device.
+
+## Performance
+There are multiple different ways to evaluate the performance of a native
+allocator on Android. One is allocation speed in various different scenarios,
+another is total RSS taken by the allocator.
+
+The last is virtual address space consumed in 32 bit applications. There is
+a limited amount of address space available in 32 bit apps, and there have
+been allocator bugs that cause memory failures when too much virtual
+address space is consumed. For 64 bit executables, this can be ignored.
+
+### Bionic Benchmarks
+These are the microbenchmarks that are part of the bionic benchmarks suite of
+benchmarks. These benchmarks can be built using this command:
+
+ mmma -j bionic/benchmarks
+
+These benchmarks are only used to verify the speed of the allocator and
+ignore anything related to RSS and virtual address space consumed.
+
+#### Allocate/Free Benchmarks
+These are the benchmarks to verify the allocation speed of a loop doing a
+single allocation, touching every page in the allocation to make it resident
+and then freeing the allocation.
+
+To run the benchmarks with `mallopt(M_DECAY_TIME, 0)`, use these commands:
+
+ adb shell /data/benchmarktest64/bionic-benchmarks/bionic-benchmarks --benchmark_filter=stdlib_malloc_free_default
+ adb shell /data/benchmarktest/bionic-benchmarks/bionic-benchmarks --benchmark_filter=malloc_free_default
+
+To run the benchmarks with `mallopt(M_DECAY_TIME, 1)`, use these commands:
+
+ adb shell /data/benchmarktest64/bionic-benchmarks/bionic-benchmarks --benchmark_filter=stdlib_malloc_free_decay1
+ adb shell /data/benchmarktest/bionic-benchmarks/bionic-benchmarks --benchmark_filter=malloc_free_decay1
+
+The last value in the output is the size of the allocation in bytes. It is
+useful to look at these kinds of benchmarks to make sure that there are
+no outliers, but these numbers should not be used to make a final decision.
+If these numbers are slightly worse than the current allocator, the
+single thread numbers from trace data is a better representative of
+real world situations.
+
+#### Multiple Allocations Retained Benchmarks
+These are the benchmarks that examine how the allocator handles multiple
+allocations of the same size at the same time.
+
+The first set of these benchmarks does a set number of 8192 byte allocations
+in one loop, and then frees all of the allocations at the end of the loop.
+Only the time it takes to do the allocations is recorded, the frees are not
+counted. The value of 8192 was chosen since the jemalloc native allocator
+had issues with this size. It is possible other sizes might show different
+results, but, as mentioned before, these microbenchmark numbers should
+not be used as absolutes for determining if an allocator is worth using.
+
+This benchmark is designed to verify that there is no performance issue
+related to having multiple allocations alive at the same time.
+
+To run the benchmarks with `mallopt(M_DECAY_TIME, 0)`, use these commands:
+
+ adb shell /data/benchmarktest64/bionic-benchmarks/bionic-benchmarks --benchmark_filter=stdlib_malloc_multiple_8192_allocs_default
+ adb shell /data/benchmarktest/bionic-benchmarks/bionic-benchmarks --benchmark_filter=stdlib_malloc_multiple_8192_allocs_default
+
+To run the benchmarks with `mallopt(M_DECAY_TIME, 1)`, use these commands:
+
+ adb shell /data/benchmarktest64/bionic-benchmarks/bionic-benchmarks --benchmark_filter=stdlib_malloc_multiple_8192_allocs_decay1
+ adb shell /data/benchmarktest/bionic-benchmarks/bionic-benchmarks --benchmark_filter=stdlib_malloc_multiple_8192_allocs_decay1
+
+For these benchmarks, the last parameter is the total number of allocations to
+do in each loop.
+
+The other variation of this benchmark is to always do forty allocations in
+each loop, but vary the size of the forty allocations. As with the other
+benchmark, only the time it takes to do the allocations is tracked, the
+frees are not counted. Forty allocations is an arbitrary number that could
+be modified in the future. It was chosen because a version of the native
+allocator, jemalloc, showed a problem at forty allocations.
+
+To run the benchmarks with `mallopt(M_DECAY_TIME, 0)`, use these commands:
+
+ adb shell /data/benchmarktest64/bionic-benchmarks/bionic-benchmarks --benchmark_filter=stdlib_malloc_forty_default
+ adb shell /data/benchmarktest/bionic-benchmarks/bionic-benchmarks --benchmark_filter=stdlib_malloc_forty_default
+
+To run the benchmarks with `mallopt(M_DECAY_TIME, 1)`, use these command:
+
+ adb shell /data/benchmarktest64/bionic-benchmarks/bionic-benchmarks --benchmark_filter=stdlib_malloc_forty_decay1
+ adb shell /data/benchmarktest/bionic-benchmarks/bionic-benchmarks --benchmark_filter=stdlib_malloc_forty_decay1
+
+For these benchmarks, the last parameter in the output is the size of the
+allocation in bytes.
+
+As with the other microbenchmarks, an allocator with numbers in the same
+proximity of the current values is usually sufficient to consider making
+a switch. The trace benchmarks are more important than these benchmarks
+since they simulate real world allocation profiles.
+
+#### SQL Allocation Trace Benchmark
+This benchmark is a trace of the allocations performed when running
+the SQLite BenchMark app.
+
+This benchmark is designed to verify that the allocator will be performant
+in a real world allocation scenario. SQL operations were chosen as a
+benchmark because these operations tend to do lots of malloc/realloc/free
+calls, and they tend to be on the critical path of applications.
+
+To run the benchmarks with `mallopt(M_DECAY_TIME, 0)`, use these commands:
+
+ adb shell /data/benchmarktest64/bionic-benchmarks/bionic-benchmarks --benchmark_filter=malloc_sql_trace_default
+ adb shell /data/benchmarktest/bionic-benchmarks/bionic-benchmarks --benchmark_filter=malloc_sql_trace_default
+
+To run the benchmarks with `mallopt(M_DECAY_TIME, 1)`, use these commands:
+
+ adb shell /data/benchmarktest64/bionic-benchmarks/bionic-benchmarks --benchmark_filter=malloc_sql_trace_decay1
+ adb shell /data/benchmarktest/bionic-benchmarks/bionic-benchmarks --benchmark_filter=malloc_sql_trace_decay1
+
+These numbers should be as performant as the current allocator.
+
+### Memory Trace Benchmarks
+These benchmarks measure all three axes of a native allocator, RSS, virtual
+address space consumed, speed of allocation. They are designed to
+run on a trace of the allocations from a real world application or system
+process.
+
+To build this benchmark:
+
+ mmma -j system/extras/memory_replay
+
+This will build two executables:
+
+ /system/bin/memory_replay32
+ /system/bin/memory_replay64
+
+And these two benchmark executables:
+
+ /data/benchmarktest64/trace_benchmark/trace_benchmark
+ /data/benchmarktest/trace_benchmark/trace_benchmark
+
+#### Memory Replay Benchmarks
+These benchmarks display RSS, virtual memory consumed (VA space), and do a
+bit of performance testing on actual traces taken from running applications.
+
+The trace data includes what thread does each operation, so the replay
+mechanism will simulate this by creating threads and replaying the operations
+on a thread as if it was rerunning the real trace. The only issue is that
+this is a worst case scenario for allocations happening at the same time
+in all threads since it collapses all of the allocation operations to occur
+one after another. This will cause a lot of threads allocating at the same
+time. The trace data does not include timestamps,
+so it is not possible to create a completely accurate replay.
+
+To generate these traces, see the [Malloc Debug documentation](https://android.googlesource.com/platform/bionic/+/master/libc/malloc_debug/README.md),
+the option [record\_allocs](https://android.googlesource.com/platform/bionic/+/master/libc/malloc_debug/README.md#record_allocs_total_entries).
+
+To run these benchmarks, first copy the trace files to the target and
+unzip them using these commands:
+
+ adb shell push system/extras/traces /data/local/tmp
+ adb shell 'cd /data/local/tmp/traces && for name in *.zip; do unzip $name; done'
+
+Since all of the traces come from applications, the `memory_replay` program
+will always call `mallopt(M_DECAY_TIME, 1)' before running the trace.
+
+Run the benchmark thusly:
+
+ adb shell memory_replay64 /data/local/tmp/traces/XXX.txt
+ adb shell memory_replay32 /data/local/tmp/traces/XXX.txt
+
+Where XXX.txt is the name of a trace file.
+
+Every 100000 allocation operations, a dump of the RSS and VA space will be
+performed. At the end, a final RSS and VA space number will be printed.
+For the most part, the intermediate data can be ignored, but it is always
+a good idea to look over the data to verify that no strange spikes are
+occurring.
+
+The performance number is a measure of the time it takes to perform all of
+the allocation calls (malloc/memalign/posix_memalign/realloc/free/etc).
+For any call that allocates a pointer, the time for the call and the time
+it takes to make the pointer completely resident in memory is included.
+
+The performance numbers for these runs tend to have a wide variability so
+they should not be used as absolute value for comparison against the
+current allocator. But, they should be in the same range as the current
+values.
+
+When evaluating an allocator, one of the most important traces is the
+camera.txt trace. The camera application does very large allocations,
+and some allocators might leave large virtual address maps around
+rather than delete them. When that happens, it can lead to allocation
+failures and would cause the camera app to abort/crash. It is
+important to verify that when running this trace using the 32 bit replay
+executable, the virtual address space consumed is not much larger than the
+current allocator. A small increase (on the order of a few MBs) would be okay.
+
+There is no specific benchmark for memory fragmentation, instead, the RSS
+when running the memory traces acts as a proxy for this. An allocator that
+is fragmenting badly will show an increase in RSS. The best trace for
+tracking fragmentation is system\_server.txt which is an extremely long
+trace (~13 million operations). The total number of live allocations goes
+up and down a bit, but stays mostly the same so an allocator that fragments
+badly would likely show an abnormal increase in RSS on this trace.
+
+NOTE: When a native allocator calls mmap, it is expected that the allocator
+will name the map using the call:
+
+ prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, <PTR>, <SIZE>, "libc_malloc");
+
+If the native allocator creates a different name, then it necessary to
+modify the file:
+
+ system/extras/memory_replay/NativeInfo.cpp
+
+The `GetNativeInfo` function needs to be modified to include the name
+of the maps that this allocator includes.
+
+In addition, in order for the frameworks code to keep track of the memory
+of a process, any named maps must be added to the file:
+
+ frameworks/base/core/jni/android_os_Debug.cpp
+
+Modify the `load_maps` function and add a check of the new expected name.
+
+#### Performance Trace Benchmarks
+This is a benchmark that treats the trace data as if all allocations
+occurred in a single thread. This is the scenario that could
+happen if all of the allocations are spaced out in time so no thread
+every does an allocation at the same time as another thread.
+
+Run these benchmarks thusly:
+
+ adb shell /data/benchmarktest64/trace_benchmark/trace_benchmark
+ adb shell /data/benchmarktest/trace_benchmark/trace_benchmark
+
+When run without any arguments, the benchmark will run over all of the
+traces and display data. It takes many minutes to complete these runs in
+order to get as accurate a number as possible.
diff --git a/docs/status.md b/docs/status.md
index e1a5d349d..6968a1800 100644
--- a/docs/status.md
+++ b/docs/status.md
@@ -1,5 +1,11 @@
# Android bionic status
+This document details libc/libm/libdl additions and behavior changes.
+
+See also
+[Android linker changes for NDK developers](../android-changes-for-ndk-developers.md)
+for changes related to native code loading in various Android releases.
+
## Bionic function availability
### POSIX
@@ -39,6 +45,9 @@ Current libc symbols: https://android.googlesource.com/platform/bionic/+/master/
New libc functions in R (API level 30):
* Full C11 `<threads.h>` (available as inlines for older API levels).
+ * `memfd_create` and `mlock2` (GNU extensions).
+ * `renameat2` (GNU extension).
+ * `pthread_cond_clockwait`/`pthread_mutex_clocklock`/`pthread_rwlock_clockrdlock`/`pthread_rwlock_clockwrlock`/`sem_clockwait`
New libc functions in Q (API level 29):
* `timespec_get` (C11 `<time.h>` addition)
@@ -301,7 +310,7 @@ targets N or later.
The `_FORTIFY_SOURCE` macro can be used to enable extra
automatic bounds checking for common libc functions. If a buffer
overrun is detected, the program is safely aborted as in this
-(example)[https://source.android.com/devices/tech/debug/native-crash#fortify].
+[example](https://source.android.com/devices/tech/debug/native-crash#fortify).
Note that in recent releases Android's FORTIFY has been extended to
cover other issues. It can now detect, for example, passing `O_CREAT`
@@ -313,7 +322,7 @@ printf(3) family, or using the scanf(3) `m` modifier incorrectly will
all result in FORTIFY failures even for code not built with FORTIFY.
More background information is available in our
-(FORTIFY in Android)[https://android-developers.googleblog.com/2017/04/fortify-in-android.html]
+[FORTIFY in Android](https://android-developers.googleblog.com/2017/04/fortify-in-android.html)
blog post.
The Android platform is built with `-D_FORTIFY_SOURCE=2`, but NDK users
diff --git a/libc/Android.bp b/libc/Android.bp
index 0c955ad9b..7f1ac5d58 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -73,6 +73,8 @@ cc_defaults {
sanitize: {
address: false,
integer_overflow: false,
+ // TODO(b/132640749): Fix broken fuzzer support.
+ fuzzer: false,
},
native_coverage: false,
recovery_available: true,
@@ -271,6 +273,7 @@ cc_library_static {
"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",
],
},
},
@@ -768,6 +771,7 @@ cc_library_static {
arch: {
arm: {
+ asflags: libc_common_flags + ["-mno-restrict-it"],
srcs: [
"arch-arm/generic/bionic/memcmp.S",
"arch-arm/generic/bionic/memmove.S",
@@ -941,6 +945,7 @@ cc_library_static {
"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",
@@ -989,6 +994,9 @@ cc_library_static {
"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: [
@@ -1011,6 +1019,7 @@ cc_library_static {
"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",
@@ -1052,7 +1061,6 @@ cc_library_static {
"bionic/__libc_current_sigrtmin.cpp",
"bionic/abort.cpp",
"bionic/accept.cpp",
- "bionic/accept4.cpp",
"bionic/access.cpp",
"bionic/arpa_inet.cpp",
"bionic/assert.cpp",
@@ -1073,7 +1081,6 @@ cc_library_static {
"bionic/clock_getcpuclockid.cpp",
"bionic/clock_nanosleep.cpp",
"bionic/clone.cpp",
- "bionic/connect.cpp",
"bionic/ctype.cpp",
"bionic/dirent.cpp",
"bionic/dup2.cpp",
@@ -1166,7 +1173,6 @@ cc_library_static {
"bionic/sigaction.cpp",
"bionic/signal.cpp",
"bionic/sigprocmask.cpp",
- "bionic/socket.cpp",
"bionic/spawn.cpp",
"bionic/stat.cpp",
"bionic/statvfs.cpp",
@@ -1711,7 +1717,9 @@ cc_library {
versions: ["10000"],
},
- symbol_ordering_file: "symbol_ordering",
+ // Sorting bss symbols by size usually results in less dirty pages at run
+ // time, because small symbols are grouped together.
+ sort_bss_symbols_by_size: true,
}
genrule {
@@ -1746,6 +1754,19 @@ genrule {
cmd: "$(location :bionic-generate-version-script) x86_64 $(in) $(out)",
}
+// Makes bionic_tls.h available for art to use in its implementation of Thread::Current().
+cc_library_headers {
+ name: "bionic_libc_private_headers",
+ visibility: [
+ "//art:__subpackages__",
+ ],
+ host_supported: true,
+ export_include_dirs: [
+ "private",
+ ],
+ sdk_version: "current",
+}
+
// libc_headers for libasync_safe and libpropertyinfoparser
cc_library_headers {
name: "libc_headers",
@@ -1756,7 +1777,6 @@ cc_library_headers {
native_bridge_supported: true,
no_libcrt: true,
- no_libgcc: true,
stl: "none",
system_shared_libs: [],
diff --git a/libc/NOTICE b/libc/NOTICE
index ef3173387..d9ac638ba 100644
--- a/libc/NOTICE
+++ b/libc/NOTICE
@@ -1025,6 +1025,22 @@ SUCH DAMAGE.
-------------------------------------------------------------------
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
@@ -1052,6 +1068,34 @@ SUCH DAMAGE.
-------------------------------------------------------------------
+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) 1980, 1983, 1988, 1993
The Regents of the University of California. All rights reserved.
diff --git a/libc/SECCOMP_WHITELIST_COMMON.TXT b/libc/SECCOMP_WHITELIST_COMMON.TXT
index 2faa559a2..07f84a8fb 100644
--- a/libc/SECCOMP_WHITELIST_COMMON.TXT
+++ b/libc/SECCOMP_WHITELIST_COMMON.TXT
@@ -32,6 +32,7 @@ int ioprio_set:ioprio_set(int which, int who, int ioprio) arm64,x86_64,mips64
pid_t gettid:gettid() all
int futex:futex(int *uaddr, int futex_op, int val, const struct timespec *timeout, int *uaddr2, int val3) all
int clone:clone(int (*fn)(void *), void *child_stack, int flags, void *arg, ..) all
+int sigreturn:sigreturn(unsigned long __unused) arm,x86,mips
int rt_sigreturn:rt_sigreturn(unsigned long __unused) all
int rt_tgsigqueueinfo:int rt_tgsigqueueinfo(pid_t tgid, pid_t tid, int sig, siginfo_t *uinfo) all
int restart_syscall:int restart_syscall() all
@@ -54,33 +55,54 @@ int seccomp:seccomp(unsigned int operation, unsigned int flags, void *args) all
# Needed for debugging 32-bit Chrome
int pipe:pipe(int pipefd[2]) arm,x86,mips
-# b/34813887
+# Needed by breakpad (b/34813887).
int open:open(const char *path, int oflag, ... ) arm,x86,x86_64,mips
int getdents:getdents(unsigned int fd, struct linux_dirent *dirp, unsigned int count) arm,x86,x86_64,mips
-# syscalls needed to boot android
-int sigreturn:sigreturn(unsigned long __unused) arm,x86,mips
-
-# Needed by sanitizers (b/34606909)
-# 5 (__NR_open) and 195 (__NR_stat64) are also required, but they are
-# already allowed.
-ssize_t readlink:readlink(const char *path, char *buf, size_t bufsiz) arm,x86,x86_64,mips
-
-# Probed for and conditionally used by ART.
-int membarrier(int cmd, int flags) all
+# Needed by sanitizers (b/34606909, b/136777266).
+int open:open(const char*, int, ...) arm,x86,x86_64
+int stat64:stat64(const char*, struct stat64*) arm,x86
+ssize_t readlink:readlink(const char*, char*, size_t) arm,x86,x86_64
+#
# Useful new syscalls which we don't yet use in bionic.
+#
+
+# Since Linux 2.5, not in glibc.
+int io_setup(unsigned nr, aio_context_t *ctxp) all
+int io_destroy(aio_context_t ctx) all
+int io_submit(aio_context_t ctx, long nr, struct iocb **iocbpp) all
+int io_getevents(aio_context_t ctx, long min_nr, long max_nr, struct io_event *events, struct timespec *timeout) all
+int io_cancel(aio_context_t ctx, struct iocb *, struct io_event *result) all
+# Since Linux 3.14, not in glibc.
int sched_getattr(pid_t pid, struct sched_attr* attr, unsigned int flags) all
int sched_setattr(pid_t pid, struct sched_attr* attr, unsigned int size, unsigned int flags) all
-int memfd_create(const char* name, unsigned int flags) all
-int renameat2(int olddirfd, const char* oldpath, int newdirfd, const char* newpath, unsigned int flags) all
+# Since Linux 3.19, not in glibc (and not really needed to implement fexecve).
int execveat(int dirfd, const char* pathname, char* const* argv, char* const* envp, int flags) all
+# Since Linux 4.3, not in glibc. Probed for and conditionally used by ART.
+int membarrier(int cmd, int flags) all
+# Since Linux 4.5, glibc 2.27.
ssize_t copy_file_range(int fd_in, loff_t* off_in, int fd_out, loff_t* off_out, size_t len, unsigned int flags) all
-int mlock2(const void* addr, size_t len, int flags) all
+# Since Linux 4.6, glibc 2.26.
ssize_t preadv2(int fd, const struct iovec* iov, int iovcnt, off_t offset, int flags) all
ssize_t pwritev2(int fd, const struct iovec* iov, int iovcnt, off_t offset, int flags) all
-int io_setup(unsigned nr, aio_context_t *ctxp) all
-int io_destroy(aio_context_t ctx) all
-int io_submit(aio_context_t ctx, long nr, struct iocb **iocbpp) all
-int io_getevents(aio_context_t ctx, long min_nr, long max_nr, struct io_event *events, struct timespec *timeout) all
-int io_cancel(aio_context_t ctx, struct iocb *, struct io_event *result) all
+# Since Linux 4.11, glibc 2.30.
+int statx(int, const char*, int, unsigned int, statx*) all
+# Since Linux 5.1, not in glibc.
+int clock_gettime64(clockid_t, timespec64*) lp32
+int clock_settime64(clockid_t, const timespec64*) lp32
+int clock_adjtime64(clockid_t, timex64*) lp32
+int clock_getres_time64(clockid_t, timespec64*) lp32
+int clock_nanosleep_time64(clockid_t, int, const timespec64*, timespec*) lp32
+int timer_gettime64(__kernel_timer_t, itimerspec64*) lp32
+int timer_settime64(__kernel_timer_t, int, const itimerspec64*, itimerspec64*) lp32
+int timerfd_gettime64(int, itimerspec64*) lp32
+int timerfd_settime64(int, int, const itimerspec64*, itimerspec64*) lp32
+int utimensat_time64(int, const char*, const timespec64[2], int) lp32
+int pselect6_time64(int, fd_set*, fd_set*, timespec64*, void*) lp32
+int ppoll_time64(pollfd*, unsigned int, timespec64*, const sigset64_t*, size_t) lp32
+int recvmmsg_time64(int, mmsghdr*, unsigned int, int, const timespec64*) lp32
+int semtimedop_time64(int, sembuf*, size_t, const timespec64*) lp32
+int rt_sigtimedwait_time64(const sigset64_t*, siginfo_t*, const timespec64*, size_t) lp32
+int futex_time64(int*, int, int, const timespec64*, int*, int) lp32
+int sched_rr_get_interval_time64(pid_t, timespec64*) lp32
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index e2ea0656b..21ebdbd8e 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -105,14 +105,16 @@ ssize_t preadv|preadv64(int, const struct iovec*, int, off_t) lp64
ssize_t __pwritev64:pwritev(int, const struct iovec*, int, long, long) lp32
ssize_t pwritev|pwritev64(int, const struct iovec*, int, off_t) lp64
-int ___close:close(int) all
+int __close:close(int) all
pid_t __getpid:getpid() all
+int memfd_create(const char*, unsigned) all
int munmap(void*, size_t) all
-void* ___mremap:mremap(void*, size_t, size_t, int, void*) all
+void* __mremap:mremap(void*, size_t, size_t, int, void*) all
int msync(const void*, size_t, int) all
int mprotect(const void*, size_t, int) all
int madvise(void*, size_t, int) all
-int mlock(const void* addr, size_t len) all
+int mlock(const void* addr, size_t len) all
+int mlock2(const void* addr, size_t len, int flags) all
int munlock(const void* addr, size_t len) all
int mlockall(int flags) all
int munlockall() all
@@ -123,7 +125,7 @@ ssize_t writev(int, const struct iovec*, int) all
int __fcntl64:fcntl64(int, int, void*) lp32
int fcntl(int, int, void*) lp64
int flock(int, int) all
-int ___fchmod:fchmod(int, mode_t) all
+int __fchmod:fchmod(int, mode_t) all
int dup(int) all
int pipe2(int*, int) all
int dup3(int, int, int) all
@@ -133,16 +135,16 @@ int fchown:fchown32(int, uid_t, gid_t) arm,x86
int fchown:fchown(int, uid_t, gid_t) arm64,mips,mips64,x86_64
void sync(void) all
int syncfs(int) all
-int ___fsetxattr:fsetxattr(int, const char*, const void*, size_t, int) all
-ssize_t ___fgetxattr:fgetxattr(int, const char*, void*, size_t) all
-ssize_t ___flistxattr:flistxattr(int, char*, size_t) all
+int __fsetxattr:fsetxattr(int, const char*, const void*, size_t, int) all
+ssize_t __fgetxattr:fgetxattr(int, const char*, void*, size_t) all
+ssize_t __flistxattr:flistxattr(int, char*, size_t) all
int fremovexattr(int, const char*) all
int __getdents64:getdents64(unsigned int, struct dirent*, unsigned int) arm,arm64,mips,mips64,x86,x86_64
int __openat:openat(int, const char*, int, mode_t) all
-int ___faccessat:faccessat(int, const char*, int) all
-int ___fchmodat:fchmodat(int, const char*, mode_t) all
+int __faccessat:faccessat(int, const char*, int) all
+int __fchmodat:fchmodat(int, const char*, mode_t) all
int fchownat(int, const char*, uid_t, gid_t, int) all
int fstatat64|fstatat:fstatat64(int, const char*, struct stat*, int) lp32
int fstatat64|fstatat:newfstatat(int, const char*, struct stat*, int) arm64,x86_64
@@ -151,6 +153,7 @@ int mkdirat(int, const char*, mode_t) all
int mknodat(int, const char*, mode_t, dev_t) all
int readlinkat(int, const char*, char*, size_t) all
int renameat(int, const char*, int, const char*) all
+int renameat2(int, const char*, int, const char*, unsigned) all
int symlinkat(const char*, int, const char*) all
int unlinkat(int, const char*, int) all
int utimensat(int, const char*, const struct timespec times[2], int) all
@@ -213,7 +216,7 @@ int settimeofday(const struct timeval*, const struct timezone*) all
clock_t times(struct tms*) all
int nanosleep(const struct timespec*, struct timespec*) all
int clock_settime(clockid_t, const struct timespec*) all
-int ___clock_nanosleep:clock_nanosleep(clockid_t, int, const struct timespec*, struct timespec*) all
+int __clock_nanosleep:clock_nanosleep(clockid_t, int, const struct timespec*, struct timespec*) all
int getitimer(int, const struct itimerval*) all
int setitimer(int, const struct itimerval*, struct itimerval*) all
int __timer_create:timer_create(clockid_t clockid, struct sigevent* evp, __kernel_timer_t* timerid) all
@@ -234,7 +237,7 @@ int __rt_sigpending:rt_sigpending(sigset64_t*, size_t) all
int __rt_sigprocmask:rt_sigprocmask(int, const sigset64_t*, sigset64_t*, size_t) all
int __rt_sigsuspend:rt_sigsuspend(const sigset64_t*, size_t) all
int __rt_sigtimedwait:rt_sigtimedwait(const sigset64_t*, siginfo_t*, const timespec*, size_t) all
-int ___rt_sigqueueinfo:rt_sigqueueinfo(pid_t, int, siginfo_t*) all
+int __rt_sigqueueinfo:rt_sigqueueinfo(pid_t, int, siginfo_t*) all
int __signalfd4:signalfd4(int, const sigset64_t*, size_t, int) all
# sockets
@@ -246,15 +249,15 @@ int listen(int, int) arm,arm64,mips,mips64,x86_64
int __accept4:accept4(int, struct sockaddr*, socklen_t*, int) arm,arm64,mips,mips64,x86_64
int getsockname(int, struct sockaddr*, socklen_t*) arm,arm64,mips,mips64,x86_64
int getpeername(int, struct sockaddr*, socklen_t*) arm,arm64,mips,mips64,x86_64
-int sendto(int, const void*, size_t, int, const struct sockaddr*, socklen_t) arm,arm64,mips,mips64,x86_64
+int __sendto:sendto(int, const void*, size_t, int, const struct sockaddr*, socklen_t) arm,arm64,mips,mips64,x86_64
int recvfrom(int, void*, size_t, unsigned int, struct sockaddr*, socklen_t*) arm,arm64,mips,mips64,x86_64
int shutdown(int, int) arm,arm64,mips,mips64,x86_64
int setsockopt(int, int, int, const void*, socklen_t) arm,arm64,mips,mips64,x86_64
int getsockopt(int, int, int, void*, socklen_t*) arm,arm64,mips,mips64,x86_64
ssize_t recvmsg(int, struct msghdr*, unsigned int) arm,arm64,mips,mips64,x86_64
-ssize_t sendmsg(int, const struct msghdr*, unsigned int) arm,arm64,mips,mips64,x86_64
+ssize_t __sendmsg:sendmsg(int, const struct msghdr*, unsigned int) arm,arm64,mips,mips64,x86_64
int recvmmsg(int, struct mmsghdr*, unsigned int, int, const struct timespec*) arm,arm64,mips,mips64,x86_64
-int sendmmsg(int, struct mmsghdr*, unsigned int, int) arm,arm64,mips,mips64,x86_64
+int __sendmmsg:sendmmsg(int, struct mmsghdr*, unsigned int, int) arm,arm64,mips,mips64,x86_64
# sockets for x86. These are done as an "indexed" call to socketcall syscall.
int __socket:socketcall:1(int, int, int) x86
@@ -264,16 +267,16 @@ int listen:socketcall:4(int, int) x86
int getsockname:socketcall:6(int, struct sockaddr*, socklen_t*) x86
int getpeername:socketcall:7(int, struct sockaddr*, socklen_t*) x86
int socketpair:socketcall:8(int, int, int, int*) x86
-int sendto:socketcall:11(int, const void*, size_t, int, const struct sockaddr*, socklen_t) x86
+int __sendto:socketcall:11(int, const void*, size_t, int, const struct sockaddr*, socklen_t) x86
int recvfrom:socketcall:12(int, void*, size_t, unsigned int, struct sockaddr*, socklen_t*) x86
int shutdown:socketcall:13(int, int) x86
int setsockopt:socketcall:14(int, int, int, const void*, socklen_t) x86
int getsockopt:socketcall:15(int, int, int, void*, socklen_t*) x86
-int sendmsg:socketcall:16(int, const struct msghdr*, unsigned int) x86
+int __sendmsg:socketcall:16(int, const struct msghdr*, unsigned int) x86
int recvmsg:socketcall:17(int, struct msghdr*, unsigned int) x86
int __accept4:socketcall:18(int, struct sockaddr*, socklen_t*, int) x86
int recvmmsg:socketcall:19(int, struct mmsghdr*, unsigned int, int, const struct timespec*) x86
-int sendmmsg:socketcall:20(int, struct mmsghdr*, unsigned int, int) x86
+int __sendmmsg:socketcall:20(int, struct mmsghdr*, unsigned int, int) x86
# scheduler & real-time
int sched_setscheduler(pid_t pid, int policy, const struct sched_param* param) all
diff --git a/libc/arch-common/bionic/crtbegin.c b/libc/arch-common/bionic/crtbegin.c
index c4d2a5a35..3630b5ed0 100644
--- a/libc/arch-common/bionic/crtbegin.c
+++ b/libc/arch-common/bionic/crtbegin.c
@@ -63,6 +63,45 @@ __asm__(PRE "movq %rsp,%rdi; andq $~0xf,%rsp; callq _start_main" POST);
#undef PRE
#undef POST
+// On arm32 and arm64, when targeting Q and up, overalign the TLS segment to
+// (8 * sizeof(void*)), which reserves enough space between the thread pointer
+// and the executable's TLS segment for Bionic's TLS slots. It has the side
+// effect of placing a 0-sized TLS segment into Android executables that don't
+// use TLS, but this should be harmless.
+//
+// To ensure that the .tdata input section isn't deleted, the .text input
+// section (which contains _start) has a relocation to the .tdata input section.
+//
+// TODO: This file currently uses TPREL relocations from .text to ensure that
+// --gc-sections doesn't remove the .tdata input section. The relocations are
+// resolved by the static linker. (They don't appear in the executable.) Replace
+// the TPREL relocations with R_{ARM,AARCH64}_NONE once the toolchain has been
+// updated to support them:
+// - https://reviews.llvm.org/D61992 (Support .reloc *, R_ARM_NONE, *)
+// - https://reviews.llvm.org/D61973 (Support .reloc *, R_AARCH64_NONE, *)
+// - https://reviews.llvm.org/D62052 (lld -r: fix R_*_NONE to section symbols on Elf*_Rel targets)
+#if __ANDROID_API__ >= __ANDROID_API_Q__
+#if defined(__arm__)
+asm(" .section .tdata,\"awT\",%progbits\n"
+ " .p2align 5\n"
+ "__tls_align:\n"
+ " .text\n"
+ " .type __tls_align_reference,%function\n"
+ "__tls_align_reference:\n"
+ " .long __tls_align(TPOFF)\n"
+ " .size __tls_align_reference, .-__tls_align_reference\n");
+#elif defined(__aarch64__)
+asm(" .section .tdata,\"awT\",@progbits\n"
+ " .p2align 6\n"
+ "__tls_align:\n"
+ " .text\n"
+ " .type __tls_align_reference,%function\n"
+ "__tls_align_reference:\n"
+ " add x0, x0, :tprel_lo12_nc:__tls_align\n"
+ " .size __tls_align_reference, .-__tls_align_reference\n");
+#endif
+#endif
+
#include "__dso_handle.h"
#include "atexit.h"
#include "pthread_atfork.h"
diff --git a/libc/arch-x86/dynamic_function_dispatch.cpp b/libc/arch-x86/dynamic_function_dispatch.cpp
index 70f4b3e70..370b37204 100644
--- a/libc/arch-x86/dynamic_function_dispatch.cpp
+++ b/libc/arch-x86/dynamic_function_dispatch.cpp
@@ -107,6 +107,13 @@ DEFINE_IFUNC_FOR(wmemcmp) {
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/bionic/socket.cpp b/libc/arch-x86/generic/string/wmemset.c
index 2f9e14562..eff533c10 100644
--- a/libc/bionic/socket.cpp
+++ b/libc/arch-x86/generic/string/wmemset.c
@@ -1,23 +1,19 @@
/*
- * Copyright (C) 2014 The Android Open Source Project
+ * 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
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
- */
+*/
-#include "private/NetdClientDispatch.h"
+#define wmemset wmemset_freebsd
-#include <sys/socket.h>
-
-int socket(int domain, int type, int protocol) {
- return __netdClientDispatch.socket(domain, type, protocol);
-}
+#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
new file mode 100644
index 000000000..69b66c795
--- /dev/null
+++ b/libc/arch-x86/kabylake/string/avx2-wmemset-kbl.S
@@ -0,0 +1,148 @@
+/*
+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 7e8e63d47..1560c042e 100644
--- a/libc/arch-x86/static_function_dispatch.S
+++ b/libc/arch-x86/static_function_dispatch.S
@@ -45,6 +45,7 @@ FUNCTION_DELEGATE(strcmp, strcmp_generic)
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_64/string/avx2-wmemset-kbl.S b/libc/arch-x86_64/string/avx2-wmemset-kbl.S
new file mode 100644
index 000000000..7c485cf70
--- /dev/null
+++ b/libc/arch-x86_64/string/avx2-wmemset-kbl.S
@@ -0,0 +1,140 @@
+/*
+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/bionic/NetdClient.cpp b/libc/bionic/NetdClient.cpp
index 87eec27b5..d9debbfcd 100644
--- a/libc/bionic/NetdClient.cpp
+++ b/libc/bionic/NetdClient.cpp
@@ -31,7 +31,7 @@ template <typename FunctionType>
static void netdClientInitFunction(void* handle, const char* symbol, FunctionType* function) {
typedef void (*InitFunctionType)(FunctionType*);
InitFunctionType initFunction = reinterpret_cast<InitFunctionType>(dlsym(handle, symbol));
- if (initFunction != NULL) {
+ if (initFunction != nullptr) {
initFunction(function);
}
}
@@ -45,20 +45,23 @@ static void netdClientInitImpl() {
return;
}
- void* netdClientHandle = dlopen("libnetd_client.so", RTLD_NOW);
- if (netdClientHandle == NULL) {
+ void* handle = dlopen("libnetd_client.so", RTLD_NOW);
+ if (handle == nullptr) {
// If the library is not available, it's not an error. We'll just use
// default implementations of functions that it would've overridden.
return;
}
- netdClientInitFunction(netdClientHandle, "netdClientInitAccept4",
- &__netdClientDispatch.accept4);
- netdClientInitFunction(netdClientHandle, "netdClientInitConnect",
- &__netdClientDispatch.connect);
- netdClientInitFunction(netdClientHandle, "netdClientInitNetIdForResolv",
+
+ netdClientInitFunction(handle, "netdClientInitAccept4", &__netdClientDispatch.accept4);
+ netdClientInitFunction(handle, "netdClientInitConnect", &__netdClientDispatch.connect);
+ netdClientInitFunction(handle, "netdClientInitSendmmsg", &__netdClientDispatch.sendmmsg);
+ netdClientInitFunction(handle, "netdClientInitSendmsg", &__netdClientDispatch.sendmsg);
+ netdClientInitFunction(handle, "netdClientInitSendto", &__netdClientDispatch.sendto);
+ netdClientInitFunction(handle, "netdClientInitSocket", &__netdClientDispatch.socket);
+
+ netdClientInitFunction(handle, "netdClientInitNetIdForResolv",
&__netdClientDispatch.netIdForResolv);
- netdClientInitFunction(netdClientHandle, "netdClientInitSocket", &__netdClientDispatch.socket);
- netdClientInitFunction(netdClientHandle, "netdClientInitDnsOpenProxy",
+ netdClientInitFunction(handle, "netdClientInitDnsOpenProxy",
&__netdClientDispatch.dnsOpenProxy);
}
diff --git a/libc/bionic/NetdClientDispatch.cpp b/libc/bionic/NetdClientDispatch.cpp
index a8731730f..463ef3690 100644
--- a/libc/bionic/NetdClientDispatch.cpp
+++ b/libc/bionic/NetdClientDispatch.cpp
@@ -16,6 +16,8 @@
#include "private/NetdClientDispatch.h"
+#include <sys/socket.h>
+
#ifdef __i386__
#define __socketcall __attribute__((__cdecl__))
#else
@@ -24,6 +26,9 @@
extern "C" __socketcall int __accept4(int, sockaddr*, socklen_t*, int);
extern "C" __socketcall int __connect(int, const sockaddr*, socklen_t);
+extern "C" __socketcall int __sendmmsg(int, const mmsghdr*, unsigned int, int);
+extern "C" __socketcall ssize_t __sendmsg(int, const msghdr*, unsigned int);
+extern "C" __socketcall int __sendto(int, const void*, size_t, int, const sockaddr*, socklen_t);
extern "C" __socketcall int __socket(int, int, int);
static unsigned fallBackNetIdForResolv(unsigned netId) {
@@ -39,7 +44,35 @@ static int fallBackDnsOpenProxy() {
__LIBC_HIDDEN__ NetdClientDispatch __netdClientDispatch __attribute__((aligned(32))) = {
__accept4,
__connect,
+ __sendmmsg,
+ __sendmsg,
+ __sendto,
__socket,
fallBackNetIdForResolv,
fallBackDnsOpenProxy,
};
+
+int accept4(int fd, sockaddr* addr, socklen_t* addr_length, int flags) {
+ return __netdClientDispatch.accept4(fd, addr, addr_length, flags);
+}
+
+int connect(int fd, const sockaddr* addr, socklen_t addr_length) {
+ return __netdClientDispatch.connect(fd, addr, addr_length);
+}
+
+int sendmmsg(int fd, const struct mmsghdr* msgs, unsigned int msg_count, int flags) {
+ return __netdClientDispatch.sendmmsg(fd, msgs, msg_count, flags);
+}
+
+ssize_t sendmsg(int fd, const struct msghdr* msg, int flags) {
+ return __netdClientDispatch.sendmsg(fd, msg, flags);
+}
+
+ssize_t sendto(int fd, const void* buf, size_t n, int flags,
+ const struct sockaddr* dst_addr, socklen_t dst_addr_length) {
+ return __netdClientDispatch.sendto(fd, buf, n, flags, dst_addr, dst_addr_length);
+}
+
+int socket(int domain, int type, int protocol) {
+ return __netdClientDispatch.socket(domain, type, protocol);
+}
diff --git a/libc/bionic/__cxa_guard.cpp b/libc/bionic/__cxa_guard.cpp
index 30b5f41bd..e2e747791 100644
--- a/libc/bionic/__cxa_guard.cpp
+++ b/libc/bionic/__cxa_guard.cpp
@@ -16,9 +16,7 @@
#include <endian.h>
#include <limits.h>
-#undef _USING_LIBCXX // Prevent using of <atomic>.
#include <stdatomic.h>
-
#include <stddef.h>
#include "private/bionic_futex.h"
diff --git a/libc/bionic/__libc_init_main_thread.cpp b/libc/bionic/__libc_init_main_thread.cpp
index 4984e38a1..6e1b0de25 100644
--- a/libc/bionic/__libc_init_main_thread.cpp
+++ b/libc/bionic/__libc_init_main_thread.cpp
@@ -135,8 +135,11 @@ extern "C" void __libc_init_main_thread_final() {
main_thread.mmap_base = mapping.mmap_base;
main_thread.mmap_size = mapping.mmap_size;
+ main_thread.mmap_base_unguarded = mapping.mmap_base_unguarded;
+ main_thread.mmap_size_unguarded = mapping.mmap_size_unguarded;
__set_tls(&new_tcb->tls_slot(0));
+ __set_stack_and_tls_vma_name(true);
__free_temp_bionic_tls(temp_tls);
}
diff --git a/libc/bionic/accept4.cpp b/libc/bionic/accept4.cpp
deleted file mode 100644
index 9f58dc192..000000000
--- a/libc/bionic/accept4.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "private/NetdClientDispatch.h"
-
-#include <sys/socket.h>
-
-int accept4(int sockfd, sockaddr* addr, socklen_t* addrlen, int flags) {
- return __netdClientDispatch.accept4(sockfd, addr, addrlen, flags);
-}
diff --git a/libc/bionic/bionic_systrace.cpp b/libc/bionic/bionic_systrace.cpp
index 6182ed801..1140d2d83 100644
--- a/libc/bionic/bionic_systrace.cpp
+++ b/libc/bionic/bionic_systrace.cpp
@@ -24,6 +24,7 @@
#include "private/bionic_systrace.h"
#include "private/CachedProperty.h"
+#include <async_safe/log.h>
#include <cutils/trace.h> // For ATRACE_TAG_BIONIC.
#define WRITE_OFFSET 32
@@ -65,7 +66,7 @@ void bionic_trace_begin(const char* message) {
// kernel trace_marker.
int length = strlen(message);
char buf[length + WRITE_OFFSET];
- size_t len = snprintf(buf, length + WRITE_OFFSET, "B|%d|%s", getpid(), message);
+ size_t len = async_safe_format_buffer(buf, length + WRITE_OFFSET, "B|%d|%s", getpid(), message);
// Tracing may stop just after checking property and before writing the message.
// So the write is acceptable to fail. See b/20666100.
diff --git a/libc/bionic/clock_nanosleep.cpp b/libc/bionic/clock_nanosleep.cpp
index eade850a0..6f77d83ff 100644
--- a/libc/bionic/clock_nanosleep.cpp
+++ b/libc/bionic/clock_nanosleep.cpp
@@ -30,11 +30,11 @@
#include "private/ErrnoRestorer.h"
-extern "C" int ___clock_nanosleep(clockid_t, int, const timespec*, timespec*);
+extern "C" int __clock_nanosleep(clockid_t, int, const timespec*, timespec*);
int clock_nanosleep(clockid_t clock_id, int flags, const timespec* in, timespec* out) {
if (clock_id == CLOCK_THREAD_CPUTIME_ID) return EINVAL;
ErrnoRestorer errno_restorer;
- return (___clock_nanosleep(clock_id, flags, in, out) == 0) ? 0 : errno;
+ return (__clock_nanosleep(clock_id, flags, in, out) == 0) ? 0 : errno;
}
diff --git a/libc/bionic/connect.cpp b/libc/bionic/connect.cpp
deleted file mode 100644
index 1673f4afe..000000000
--- a/libc/bionic/connect.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "private/NetdClientDispatch.h"
-
-#include <sys/socket.h>
-
-int connect(int sockfd, const sockaddr* addr, socklen_t addrlen) {
- return __netdClientDispatch.connect(sockfd, addr, addrlen);
-}
diff --git a/libc/bionic/faccessat.cpp b/libc/bionic/faccessat.cpp
index a86aeb2b6..bfaec51fe 100644
--- a/libc/bionic/faccessat.cpp
+++ b/libc/bionic/faccessat.cpp
@@ -30,7 +30,7 @@
#include <unistd.h>
#include <errno.h>
-extern "C" int ___faccessat(int, const char*, int);
+extern "C" int __faccessat(int, const char*, int);
int faccessat(int dirfd, const char* pathname, int mode, int flags) {
// "The mode specifies the accessibility check(s) to be performed,
@@ -56,5 +56,5 @@ int faccessat(int dirfd, const char* pathname, int mode, int flags) {
return -1;
}
- return ___faccessat(dirfd, pathname, mode);
+ return __faccessat(dirfd, pathname, mode);
}
diff --git a/libc/bionic/fchmod.cpp b/libc/bionic/fchmod.cpp
index a486aaed1..0326fc2a2 100644
--- a/libc/bionic/fchmod.cpp
+++ b/libc/bionic/fchmod.cpp
@@ -35,11 +35,11 @@
#include "private/FdPath.h"
-extern "C" int ___fchmod(int, mode_t);
+extern "C" int __fchmod(int, mode_t);
int fchmod(int fd, mode_t mode) {
int saved_errno = errno;
- int result = ___fchmod(fd, mode);
+ int result = __fchmod(fd, mode);
if (result == 0 || errno != EBADF) {
return result;
}
diff --git a/libc/bionic/fchmodat.cpp b/libc/bionic/fchmodat.cpp
index 1f83c4b9b..c28e15ac7 100644
--- a/libc/bionic/fchmodat.cpp
+++ b/libc/bionic/fchmodat.cpp
@@ -34,7 +34,7 @@
#include "private/ErrnoRestorer.h"
-extern "C" int ___fchmodat(int, const char*, mode_t);
+extern "C" int __fchmodat(int, const char*, mode_t);
int fchmodat(int dirfd, const char* pathname, mode_t mode, int flags) {
if ((flags & ~AT_SYMLINK_NOFOLLOW) != 0) {
@@ -63,5 +63,5 @@ int fchmodat(int dirfd, const char* pathname, mode_t mode, int flags) {
return result;
}
- return ___fchmodat(dirfd, pathname, mode);
+ return __fchmodat(dirfd, pathname, mode);
}
diff --git a/libc/bionic/fdsan.cpp b/libc/bionic/fdsan.cpp
index 6440ae059..4ebc796d2 100644
--- a/libc/bionic/fdsan.cpp
+++ b/libc/bionic/fdsan.cpp
@@ -46,7 +46,7 @@
#include "private/bionic_inline_raise.h"
#include "pthread_internal.h"
-extern "C" int ___close(int fd);
+extern "C" int __close(int fd);
pid_t __get_cached_pid();
static constexpr const char* kFdsanPropertyName = "debug.fdsan";
@@ -106,30 +106,8 @@ FdEntry* FdTableImpl<inline_fds>::at(size_t idx) {
}
void __libc_init_fdsan() {
- constexpr auto default_level = ANDROID_FDSAN_ERROR_LEVEL_WARN_ONCE;
- const prop_info* pi = __system_property_find(kFdsanPropertyName);
- if (!pi) {
- android_fdsan_set_error_level(default_level);
- return;
- }
- __system_property_read_callback(
- pi,
- [](void*, const char*, const char* value, uint32_t) {
- if (strcasecmp(value, "1") == 0 || strcasecmp(value, "fatal") == 0) {
- android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_FATAL);
- } else if (strcasecmp(value, "warn") == 0) {
- android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_WARN_ALWAYS);
- } else if (strcasecmp(value, "warn_once") == 0) {
- android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_WARN_ONCE);
- } else {
- if (strlen(value) != 0 && strcasecmp(value, "0") != 0) {
- async_safe_format_log(ANDROID_LOG_ERROR, "libc",
- "debug.fdsan set to unknown value '%s', disabling", value);
- }
- android_fdsan_set_error_level(default_level);
- }
- },
- nullptr);
+ constexpr auto default_level = ANDROID_FDSAN_ERROR_LEVEL_FATAL;
+ android_fdsan_set_error_level_from_property(default_level);
}
static FdTable& GetFdTable() {
@@ -269,7 +247,7 @@ uint64_t android_fdsan_get_tag_value(uint64_t tag) {
int android_fdsan_close_with_tag(int fd, uint64_t expected_tag) {
FdEntry* fde = GetFdEntry(fd);
if (!fde) {
- return ___close(fd);
+ return __close(fd);
}
uint64_t tag = expected_tag;
@@ -299,7 +277,7 @@ int android_fdsan_close_with_tag(int fd, uint64_t expected_tag) {
}
}
- int rc = ___close(fd);
+ int rc = __close(fd);
// If we were expecting to close with a tag, abort on EBADF.
if (expected_tag && rc == -1 && errno == EBADF) {
fdsan_error("double-close of file descriptor %d detected", fd);
@@ -355,6 +333,45 @@ android_fdsan_error_level android_fdsan_set_error_level(android_fdsan_error_leve
return atomic_exchange(&GetFdTable().error_level, new_level);
}
+android_fdsan_error_level android_fdsan_set_error_level_from_property(
+ android_fdsan_error_level default_level) {
+ const prop_info* pi = __system_property_find(kFdsanPropertyName);
+ if (!pi) {
+ return android_fdsan_set_error_level(default_level);
+ }
+
+ struct callback_data {
+ android_fdsan_error_level default_value;
+ android_fdsan_error_level result;
+ };
+
+ callback_data data;
+ data.default_value = default_level;
+
+ __system_property_read_callback(
+ pi,
+ [](void* arg, const char*, const char* value, uint32_t) {
+ callback_data* data = static_cast<callback_data*>(arg);
+
+ if (strcasecmp(value, "1") == 0 || strcasecmp(value, "fatal") == 0) {
+ data->result = android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_FATAL);
+ } else if (strcasecmp(value, "warn") == 0) {
+ data->result = android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_WARN_ALWAYS);
+ } else if (strcasecmp(value, "warn_once") == 0) {
+ data->result = android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_WARN_ONCE);
+ } else {
+ if (strlen(value) != 0 && strcasecmp(value, "0") != 0) {
+ async_safe_format_log(ANDROID_LOG_ERROR, "libc",
+ "debug.fdsan set to unknown value '%s', disabling", value);
+ }
+ data->result = android_fdsan_set_error_level(data->default_value);
+ }
+ },
+ &data);
+
+ return data.result;
+}
+
int close(int fd) {
int rc = android_fdsan_close_with_tag(fd, 0);
if (rc == -1 && errno == EINTR) {
diff --git a/libc/bionic/fgetxattr.cpp b/libc/bionic/fgetxattr.cpp
index 38b7ac3d5..c7532355b 100644
--- a/libc/bionic/fgetxattr.cpp
+++ b/libc/bionic/fgetxattr.cpp
@@ -35,11 +35,11 @@
#include "private/FdPath.h"
-extern "C" ssize_t ___fgetxattr(int, const char*, void*, size_t);
+extern "C" ssize_t __fgetxattr(int, const char*, void*, size_t);
ssize_t fgetxattr(int fd, const char *name, void *value, size_t size) {
int saved_errno = errno;
- ssize_t result = ___fgetxattr(fd, name, value, size);
+ ssize_t result = __fgetxattr(fd, name, value, size);
if (result != -1 || errno != EBADF) {
return result;
diff --git a/libc/bionic/flistxattr.cpp b/libc/bionic/flistxattr.cpp
index 8ad9b857f..3bad3835d 100644
--- a/libc/bionic/flistxattr.cpp
+++ b/libc/bionic/flistxattr.cpp
@@ -35,11 +35,11 @@
#include "private/FdPath.h"
-extern "C" ssize_t ___flistxattr(int, char*, size_t);
+extern "C" ssize_t __flistxattr(int, char*, size_t);
ssize_t flistxattr(int fd, char *list, size_t size) {
int saved_errno = errno;
- ssize_t result = ___flistxattr(fd, list, size);
+ ssize_t result = __flistxattr(fd, list, size);
if (result != -1 || errno != EBADF) {
return result;
}
diff --git a/libc/bionic/fork.cpp b/libc/bionic/fork.cpp
index fc0020798..cda5e8533 100644
--- a/libc/bionic/fork.cpp
+++ b/libc/bionic/fork.cpp
@@ -55,6 +55,10 @@ int fork() {
// fork, close all of their fds blindly, and then exec.
android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_DISABLED);
+ // Reset the stack_and_tls VMA name so it doesn't end with a tid from the
+ // parent process.
+ __set_stack_and_tls_vma_name(true);
+
__bionic_atfork_run_child();
} else {
__bionic_atfork_run_parent();
diff --git a/libc/bionic/fortify.cpp b/libc/bionic/fortify.cpp
index 20e265e40..3b804b0b2 100644
--- a/libc/bionic/fortify.cpp
+++ b/libc/bionic/fortify.cpp
@@ -249,7 +249,7 @@ extern "C" char* __stpncpy_chk(char* dst, const char* src, size_t len, size_t ds
// This is a variant of __stpncpy_chk, but it also checks to make
// sure we don't read beyond the end of "src". The code for this is
// based on the original version of stpncpy, but modified to check
-// how much we read from "src" at the end of the copy operation.
+// how much we read from "src" during the copy operation.
char* __stpncpy_chk2(char* dst, const char* src, size_t n, size_t dst_len, size_t src_len) {
__check_buffer_access("stpncpy", "write into", n, dst_len);
if (n != 0) {
@@ -257,6 +257,11 @@ char* __stpncpy_chk2(char* dst, const char* src, size_t n, size_t dst_len, size_
const char* s = src;
do {
+ size_t s_copy_len = static_cast<size_t>(s - src);
+ if (__predict_false(s_copy_len >= src_len)) {
+ __fortify_fatal("stpncpy: detected read past end of %zu-byte buffer", src_len);
+ }
+
if ((*d++ = *s++) == 0) {
// NUL pad the remaining n-1 bytes.
while (--n != 0) {
@@ -265,11 +270,6 @@ char* __stpncpy_chk2(char* dst, const char* src, size_t n, size_t dst_len, size_
break;
}
} while (--n != 0);
-
- size_t s_copy_len = static_cast<size_t>(s - src);
- if (__predict_false(s_copy_len > src_len)) {
- __fortify_fatal("stpncpy: detected read past end of %zu-byte buffer", src_len);
- }
}
return dst;
@@ -360,7 +360,7 @@ extern "C" char* __strncpy_chk(char* dst, const char* src, size_t len, size_t ds
// This is a variant of __strncpy_chk, but it also checks to make
// sure we don't read beyond the end of "src". The code for this is
// based on the original version of strncpy, but modified to check
-// how much we read from "src" at the end of the copy operation.
+// how much we read from "src" during the copy operation.
char* __strncpy_chk2(char* dst, const char* src, size_t n, size_t dst_len, size_t src_len) {
__check_buffer_access("strncpy", "write into", n, dst_len);
if (n != 0) {
@@ -368,6 +368,11 @@ char* __strncpy_chk2(char* dst, const char* src, size_t n, size_t dst_len, size_
const char* s = src;
do {
+ size_t s_copy_len = static_cast<size_t>(s - src);
+ if (__predict_false(s_copy_len >= src_len)) {
+ __fortify_fatal("strncpy: detected read past end of %zu-byte buffer", src_len);
+ }
+
if ((*d++ = *s++) == 0) {
// NUL pad the remaining n-1 bytes.
while (--n != 0) {
@@ -376,11 +381,6 @@ char* __strncpy_chk2(char* dst, const char* src, size_t n, size_t dst_len, size_
break;
}
} while (--n != 0);
-
- size_t s_copy_len = static_cast<size_t>(s - src);
- if (__predict_false(s_copy_len > src_len)) {
- __fortify_fatal("strncpy: detected read past end of %zu-byte buffer", src_len);
- }
}
return dst;
@@ -500,3 +500,10 @@ extern "C" void* __memcpy_chk(void* dst, const void* src, size_t count, size_t d
return memcpy(dst, src, count);
}
#endif // NO___MEMCPY_CHK
+
+// Runtime implementation of __mempcpy_chk (used directly by compiler, not in headers).
+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);
+}
diff --git a/libc/bionic/fsetxattr.cpp b/libc/bionic/fsetxattr.cpp
index 9ad0c76d4..00955bd16 100644
--- a/libc/bionic/fsetxattr.cpp
+++ b/libc/bionic/fsetxattr.cpp
@@ -35,11 +35,11 @@
#include "private/FdPath.h"
-extern "C" int ___fsetxattr(int, const char*, const void*, size_t, int);
+extern "C" int __fsetxattr(int, const char*, const void*, size_t, int);
int fsetxattr(int fd, const char* name, const void* value, size_t size, int flags) {
int saved_errno = errno;
- int result = ___fsetxattr(fd, name, value, size, flags);
+ int result = __fsetxattr(fd, name, value, size, flags);
if (result == 0 || errno != EBADF) {
return result;
}
diff --git a/libc/bionic/grp_pwd.cpp b/libc/bionic/grp_pwd.cpp
index bd5c27dd1..6f8c07e48 100644
--- a/libc/bionic/grp_pwd.cpp
+++ b/libc/bionic/grp_pwd.cpp
@@ -26,6 +26,8 @@
* SUCH DAMAGE.
*/
+#include "private/grp_pwd.h"
+
#include <android/api-level.h>
#include <ctype.h>
#include <errno.h>
@@ -37,19 +39,32 @@
#include <stdlib.h>
#include <string.h>
#include <sys/system_properties.h>
+#include <sys/types.h>
#include <unistd.h>
+#include "private/ErrnoRestorer.h"
#include "private/android_filesystem_config.h"
#include "private/bionic_macros.h"
-#include "private/grp_pwd.h"
-#include "private/ErrnoRestorer.h"
// Generated android_ids array
#include "generated_android_ids.h"
#include "grp_pwd_file.h"
-static PasswdFile vendor_passwd("/vendor/etc/passwd", "vendor_");
-static GroupFile vendor_group("/vendor/etc/group", "vendor_");
+static PasswdFile passwd_files[] = {
+ { "/system/etc/passwd", "system_" },
+ { "/vendor/etc/passwd", "vendor_" },
+ { "/odm/etc/passwd", "odm_" },
+ { "/product/etc/passwd", "product_" },
+ { "/system_ext/etc/passwd", "system_ext_" },
+};
+
+static GroupFile group_files[] = {
+ { "/system/etc/group", "system_" },
+ { "/vendor/etc/group", "vendor_" },
+ { "/odm/etc/group", "odm_" },
+ { "/product/etc/group", "product_" },
+ { "/system_ext/etc/group", "system_ext_" },
+};
// POSIX seems to envisage an implementation where the <pwd.h> functions are
// implemented by brute-force searching with getpwent(3), and the <grp.h>
@@ -89,7 +104,7 @@ static passwd* android_iinfo_to_passwd(passwd_state_t* state,
const android_id_info* iinfo) {
snprintf(state->name_buffer_, sizeof(state->name_buffer_), "%s", iinfo->name);
snprintf(state->dir_buffer_, sizeof(state->dir_buffer_), "/");
- snprintf(state->sh_buffer_, sizeof(state->sh_buffer_), "/system/bin/sh");
+ snprintf(state->sh_buffer_, sizeof(state->sh_buffer_), "/bin/sh");
passwd* pw = &state->passwd_;
pw->pw_uid = iinfo->aid;
@@ -127,10 +142,17 @@ static const android_id_info* find_android_id_info(const char* name) {
// These are a list of the reserved app ranges, and should never contain anything below
// AID_APP_START. They exist per user, so a given uid/gid modulo AID_USER_OFFSET will map
// to these ranges.
-static constexpr struct {
- uid_t start;
- uid_t end;
-} user_ranges[] = {
+struct IdRange {
+ id_t start;
+ id_t end;
+};
+
+static constexpr IdRange user_ranges[] = {
+ { AID_APP_START, AID_APP_END },
+ { AID_ISOLATED_START, AID_ISOLATED_END },
+};
+
+static constexpr IdRange group_ranges[] = {
{ AID_APP_START, AID_APP_END },
{ AID_CACHE_GID_START, AID_CACHE_GID_END },
{ AID_EXT_GID_START, AID_EXT_GID_END },
@@ -139,22 +161,40 @@ static constexpr struct {
{ AID_ISOLATED_START, AID_ISOLATED_END },
};
-static constexpr bool verify_user_ranges_ascending() {
- auto array_size = arraysize(user_ranges);
+template <class T, size_t N>
+static constexpr bool verify_user_ranges_ascending(T (&ranges)[N]) {
+ auto array_size = N;
if (array_size < 2) return false;
- if (user_ranges[0].start > user_ranges[0].end) return false;
+ if (ranges[0].start > ranges[0].end) return false;
for (size_t i = 1; i < array_size; ++i) {
- if (user_ranges[i].start > user_ranges[i].end) return false;
- if (user_ranges[i - 1].end > user_ranges[i].start) return false;
+ if (ranges[i].start > ranges[i].end) return false;
+ if (ranges[i - 1].end > ranges[i].start) return false;
}
return true;
}
-static_assert(verify_user_ranges_ascending(), "user_ranges must have ascending ranges");
+static_assert(verify_user_ranges_ascending(user_ranges), "user_ranges must have ascending ranges");
+static_assert(verify_user_ranges_ascending(group_ranges), "user_ranges must have ascending ranges");
-static bool is_valid_app_id(id_t id) {
+// This list comes from PackageManagerService.java, where platform AIDs are added to list of valid
+// AIDs for packages via addSharedUserLPw().
+static constexpr const id_t secondary_user_platform_ids[] = {
+ AID_SYSTEM, AID_RADIO, AID_LOG, AID_NFC, AID_BLUETOOTH,
+ AID_SHELL, AID_SECURE_ELEMENT, AID_NETWORK_STACK,
+};
+
+static bool platform_id_secondary_user_allowed(id_t id) {
+ for (const auto& allowed_id : secondary_user_platform_ids) {
+ if (allowed_id == id) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static bool is_valid_app_id(id_t id, bool is_group) {
id_t appid = id % AID_USER_OFFSET;
// AID_OVERFLOWUID is never a valid app id, so we explicitly return false to ensure this.
@@ -163,15 +203,23 @@ static bool is_valid_app_id(id_t id) {
return false;
}
- // If we've resolved to something before app_start, we have already checked against
- // android_ids, so no need to check again.
- if (appid < user_ranges[0].start) {
+ auto ranges_size = is_group ? arraysize(group_ranges) : arraysize(user_ranges);
+ auto ranges = is_group ? group_ranges : user_ranges;
+
+ // If we're checking an appid that resolves below the user range, then it's a platform AID for a
+ // seconary user. We only allow a reduced set of these, so we must check that it is allowed.
+ if (appid < ranges[0].start && platform_id_secondary_user_allowed(appid)) {
return true;
}
+ // The shared GID range is only valid for the first user.
+ if (appid >= AID_SHARED_GID_START && appid <= AID_SHARED_GID_END && appid != id) {
+ return false;
+ }
+
// Otherwise check that the appid is in one of the reserved ranges.
- for (size_t i = 0; i < arraysize(user_ranges); ++i) {
- if (appid >= user_ranges[i].start && appid <= user_ranges[i].end) {
+ for (size_t i = 0; i < ranges_size; ++i) {
+ if (appid >= ranges[i].start && appid <= ranges[i].end) {
return true;
}
}
@@ -180,26 +228,29 @@ static bool is_valid_app_id(id_t id) {
}
// This provides an iterater for app_ids within the first user's app id's.
-static uid_t get_next_app_id(uid_t current_id) {
- // If current_id is below the first of the user_ranges, then we're uninitialized, and return the
- // first valid id.
- if (current_id < user_ranges[0].start) {
- return user_ranges[0].start;
+static id_t get_next_app_id(id_t current_id, bool is_group) {
+ auto ranges_size = is_group ? arraysize(group_ranges) : arraysize(user_ranges);
+ auto ranges = is_group ? group_ranges : user_ranges;
+
+ // If current_id is below the first of the ranges, then we're uninitialized, and return the first
+ // valid id.
+ if (current_id < ranges[0].start) {
+ return ranges[0].start;
}
- uid_t incremented_id = current_id + 1;
+ id_t incremented_id = current_id + 1;
// Check to see if our incremented_id is between two ranges, and if so, return the beginning of
// the next valid range.
- for (size_t i = 1; i < arraysize(user_ranges); ++i) {
- if (incremented_id > user_ranges[i - 1].end && incremented_id < user_ranges[i].start) {
- return user_ranges[i].start;
+ for (size_t i = 1; i < ranges_size; ++i) {
+ if (incremented_id > ranges[i - 1].end && incremented_id < ranges[i].start) {
+ return ranges[i].start;
}
}
// Check to see if our incremented_id is above final range, and return -1 to indicate that we've
// completed if so.
- if (incremented_id > user_ranges[arraysize(user_ranges) - 1].end) {
+ if (incremented_id > ranges[ranges_size - 1].end) {
return -1;
}
@@ -209,6 +260,8 @@ static uid_t get_next_app_id(uid_t current_id) {
// Translate a user/group name to the corresponding user/group id.
// all_a1234 -> 0 * AID_USER_OFFSET + AID_SHARED_GID_START + 1234 (group name only)
+// u0_a1234_ext_cache -> 0 * AID_USER_OFFSET + AID_EXT_CACHE_GID_START + 1234 (group name only)
+// u0_a1234_ext -> 0 * AID_USER_OFFSET + AID_EXT_GID_START + 1234 (group name only)
// u0_a1234_cache -> 0 * AID_USER_OFFSET + AID_CACHE_GID_START + 1234 (group name only)
// u0_a1234 -> 0 * AID_USER_OFFSET + AID_APP_START + 1234
// u2_i1000 -> 2 * AID_USER_OFFSET + AID_ISOLATED_START + 1000
@@ -247,9 +300,19 @@ static id_t app_id_from_name(const char* name, bool is_group) {
} else {
// end will point to \0 if the strtoul below succeeds.
appid = strtoul(end+2, &end, 10);
- if (is_group && !strcmp(end, "_cache")) {
- end += 6;
- appid += AID_CACHE_GID_START;
+ if (is_group) {
+ if (!strcmp(end, "_ext_cache")) {
+ end += 10;
+ appid += AID_EXT_CACHE_GID_START;
+ } else if (!strcmp(end, "_ext")) {
+ end += 4;
+ appid += AID_EXT_GID_START;
+ } else if (!strcmp(end, "_cache")) {
+ end += 6;
+ appid += AID_CACHE_GID_START;
+ } else {
+ appid += AID_APP_START;
+ }
} else {
appid += AID_APP_START;
}
@@ -260,6 +323,10 @@ static id_t app_id_from_name(const char* name, bool is_group) {
} else if (auto* android_id_info = find_android_id_info(end + 1); android_id_info != nullptr) {
appid = android_id_info->aid;
end += strlen(android_id_info->name) + 1;
+ if (!platform_id_secondary_user_allowed(appid)) {
+ errno = ENOENT;
+ return 0;
+ }
}
// Check that the entire string was consumed by one of the 3 cases above.
@@ -304,6 +371,10 @@ static void print_app_name_from_gid(const gid_t gid, char* buffer, const int buf
snprintf(buffer, bufferlen, "u%u_i%u", userid, appid - AID_ISOLATED_START);
} else if (userid == 0 && appid >= AID_SHARED_GID_START && appid <= AID_SHARED_GID_END) {
snprintf(buffer, bufferlen, "all_a%u", appid - AID_SHARED_GID_START);
+ } else if (appid >= AID_EXT_CACHE_GID_START && appid <= AID_EXT_CACHE_GID_END) {
+ snprintf(buffer, bufferlen, "u%u_a%u_ext_cache", userid, appid - AID_EXT_CACHE_GID_START);
+ } else if (appid >= AID_EXT_GID_START && appid <= AID_EXT_GID_END) {
+ snprintf(buffer, bufferlen, "u%u_a%u_ext", userid, appid - AID_EXT_GID_START);
} else if (appid >= AID_CACHE_GID_START && appid <= AID_CACHE_GID_END) {
snprintf(buffer, bufferlen, "u%u_a%u_cache", userid, appid - AID_CACHE_GID_START);
} else if (appid < AID_APP_START) {
@@ -363,17 +434,19 @@ static id_t oem_id_from_name(const char* name) {
}
static passwd* oem_id_to_passwd(uid_t uid, passwd_state_t* state) {
- if (!is_oem_id(uid)) {
- return nullptr;
+ for (auto& passwd_file : passwd_files) {
+ if (passwd_file.FindById(uid, state)) {
+ return &state->passwd_;
+ }
}
- if (vendor_passwd.FindById(uid, state)) {
- return &state->passwd_;
+ if (!is_oem_id(uid)) {
+ return nullptr;
}
snprintf(state->name_buffer_, sizeof(state->name_buffer_), "oem_%u", uid);
snprintf(state->dir_buffer_, sizeof(state->dir_buffer_), "/");
- snprintf(state->sh_buffer_, sizeof(state->sh_buffer_), "/vendor/bin/sh");
+ snprintf(state->sh_buffer_, sizeof(state->sh_buffer_), "/bin/sh");
passwd* pw = &state->passwd_;
pw->pw_uid = uid;
@@ -382,12 +455,14 @@ static passwd* oem_id_to_passwd(uid_t uid, passwd_state_t* state) {
}
static group* oem_id_to_group(gid_t gid, group_state_t* state) {
- if (!is_oem_id(gid)) {
- return nullptr;
+ for (auto& group_file : group_files) {
+ if (group_file.FindById(gid, state)) {
+ return &state->group_;
+ }
}
- if (vendor_group.FindById(gid, state)) {
- return &state->group_;
+ if (!is_oem_id(gid)) {
+ return nullptr;
}
snprintf(state->group_name_buffer_, sizeof(state->group_name_buffer_),
@@ -405,7 +480,7 @@ static group* oem_id_to_group(gid_t gid, group_state_t* state) {
// AID_USER_OFFSET+ -> u1_radio, u1_a1234, u2_i1234, etc.
// returns a passwd structure (sets errno to ENOENT on failure).
static passwd* app_id_to_passwd(uid_t uid, passwd_state_t* state) {
- if (uid < AID_APP_START || !is_valid_app_id(uid)) {
+ if (uid < AID_APP_START || !is_valid_app_id(uid, false)) {
errno = ENOENT;
return nullptr;
}
@@ -419,7 +494,7 @@ static passwd* app_id_to_passwd(uid_t uid, passwd_state_t* state) {
snprintf(state->dir_buffer_, sizeof(state->dir_buffer_), "/data");
}
- snprintf(state->sh_buffer_, sizeof(state->sh_buffer_), "/system/bin/sh");
+ snprintf(state->sh_buffer_, sizeof(state->sh_buffer_), "/bin/sh");
passwd* pw = &state->passwd_;
pw->pw_uid = uid;
@@ -430,7 +505,7 @@ static passwd* app_id_to_passwd(uid_t uid, passwd_state_t* state) {
// Translate a gid into the corresponding app_<gid>
// group structure (sets errno to ENOENT on failure).
static group* app_id_to_group(gid_t gid, group_state_t* state) {
- if (gid < AID_APP_START || !is_valid_app_id(gid)) {
+ if (gid < AID_APP_START || !is_valid_app_id(gid, true)) {
errno = ENOENT;
return nullptr;
}
@@ -465,8 +540,8 @@ passwd* getpwnam_internal(const char* login, passwd_state_t* state) {
return android_iinfo_to_passwd(state, android_id_info);
}
- if (vendor_passwd.FindByName(login, state)) {
- if (is_oem_id(state->passwd_.pw_uid)) {
+ for (auto& passwd_file : passwd_files) {
+ if (passwd_file.FindByName(login, state)) {
return &state->passwd_;
}
}
@@ -575,7 +650,23 @@ passwd* getpwent() {
state->getpwent_idx++ - start + AID_OEM_RESERVED_2_START, state);
}
- state->getpwent_idx = get_next_app_id(state->getpwent_idx);
+ start = end;
+ end += AID_SYSTEM_EXT_RESERVED_END - AID_SYSTEM_RESERVED_START + 1;
+
+ if (state->getpwent_idx < end) {
+ // No one calls this enough to worry about how inefficient the below is.
+ auto* oem_passwd =
+ oem_id_to_passwd(state->getpwent_idx++ - start + AID_SYSTEM_RESERVED_START, state);
+ while (oem_passwd == nullptr && state->getpwent_idx < end) {
+ oem_passwd =
+ oem_id_to_passwd(state->getpwent_idx++ - start + AID_SYSTEM_RESERVED_START, state);
+ }
+ if (oem_passwd != nullptr) {
+ return oem_passwd;
+ }
+ }
+
+ state->getpwent_idx = get_next_app_id(state->getpwent_idx, false);
if (state->getpwent_idx != -1) {
return app_id_to_passwd(state->getpwent_idx, state);
@@ -608,8 +699,8 @@ static group* getgrnam_internal(const char* name, group_state_t* state) {
return android_iinfo_to_group(state, android_id_info);
}
- if (vendor_group.FindByName(name, state)) {
- if (is_oem_id(state->group_.gr_gid)) {
+ for (auto& group_file : group_files) {
+ if (group_file.FindByName(name, state)) {
return &state->group_;
}
}
@@ -696,9 +787,25 @@ group* getgrent() {
}
start = end;
+ end += AID_SYSTEM_EXT_RESERVED_END - AID_SYSTEM_RESERVED_START + 1;
+
+ if (state->getgrent_idx < end) {
+ // No one calls this enough to worry about how inefficient the below is.
+ init_group_state(state);
+ auto* oem_group =
+ oem_id_to_group(state->getgrent_idx++ - start + AID_SYSTEM_RESERVED_START, state);
+ while (oem_group == nullptr && state->getgrent_idx < end) {
+ oem_group = oem_id_to_group(state->getgrent_idx++ - start + AID_SYSTEM_RESERVED_START, state);
+ }
+ if (oem_group != nullptr) {
+ return oem_group;
+ }
+ }
+
+ start = end;
end += AID_USER_OFFSET - AID_APP_START; // Do not expose higher groups
- state->getgrent_idx = get_next_app_id(state->getgrent_idx);
+ state->getgrent_idx = get_next_app_id(state->getgrent_idx, true);
if (state->getgrent_idx != -1) {
return app_id_to_group(state->getgrent_idx, state);
diff --git a/libc/bionic/grp_pwd_file.cpp b/libc/bionic/grp_pwd_file.cpp
index 201c9d084..e13604e68 100644
--- a/libc/bionic/grp_pwd_file.cpp
+++ b/libc/bionic/grp_pwd_file.cpp
@@ -270,8 +270,8 @@ bool MmapFile::Find(Line* line, Predicate predicate) {
while (line_beginning < end) {
line_beginning = ParseLine(line_beginning, end, line->fields, line->kNumFields);
- // To comply with Treble, users/groups from the vendor partition need to be prefixed with
- // vendor_.
+ // To comply with Treble, users/groups from each partition need to be prefixed with
+ // the partition name.
if (required_prefix_ != nullptr) {
if (strncmp(line->fields[0], required_prefix_, strlen(required_prefix_)) != 0) {
char name[kGrpPwdBufferSize];
diff --git a/libc/bionic/jemalloc.h b/libc/bionic/jemalloc.h
index b9a4e993c..ef77c9c99 100644
--- a/libc/bionic/jemalloc.h
+++ b/libc/bionic/jemalloc.h
@@ -30,7 +30,7 @@ __BEGIN_DECLS
void* je_aligned_alloc_wrapper(size_t, size_t);
int je_iterate(uintptr_t, size_t, void (*)(uintptr_t, size_t, void*), void*);
-int je_mallctl(const char *name, void *oldp, size_t *oldlenp, void *newp, size_t newlen);
+int je_mallctl(const char *name, void *oldp, size_t *oldlenp, void *newp, size_t newlen) __attribute__((nothrow));
struct mallinfo je_mallinfo();
void je_malloc_disable();
void je_malloc_enable();
diff --git a/libc/bionic/libc_init_dynamic.cpp b/libc/bionic/libc_init_dynamic.cpp
index 4f3b4f7d1..d6d5552d1 100644
--- a/libc/bionic/libc_init_dynamic.cpp
+++ b/libc/bionic/libc_init_dynamic.cpp
@@ -69,6 +69,13 @@ extern "C" {
__LIBC_HIDDEN__ void* __libc_sysinfo = reinterpret_cast<void*>(__libc_int0x80);
#endif
+extern "C" __attribute__((weak)) void __hwasan_library_loaded(ElfW(Addr) base,
+ const ElfW(Phdr)* phdr,
+ ElfW(Half) phnum);
+extern "C" __attribute__((weak)) void __hwasan_library_unloaded(ElfW(Addr) base,
+ const ElfW(Phdr)* phdr,
+ ElfW(Half) phnum);
+
// We need a helper function for __libc_preinit because compiling with LTO may
// inline functions requiring a stack protector check, but __stack_chk_guard is
// not initialized at the start of __libc_preinit. __libc_preinit_impl will run
@@ -91,6 +98,14 @@ static void __libc_preinit_impl() {
// Hooks for various libraries to let them know that we're starting up.
__libc_globals.mutate(__libc_init_malloc);
+
+#if __has_feature(hwaddress_sanitizer)
+ // Notify the HWASan runtime library whenever a library is loaded or unloaded
+ // so that it can update its shadow memory.
+ __libc_shared_globals()->load_hook = __hwasan_library_loaded;
+ __libc_shared_globals()->unload_hook = __hwasan_library_unloaded;
+#endif
+
netdClientInit();
}
diff --git a/libc/bionic/malloc_heapprofd.cpp b/libc/bionic/malloc_heapprofd.cpp
index 5d3735d27..d0117f382 100644
--- a/libc/bionic/malloc_heapprofd.cpp
+++ b/libc/bionic/malloc_heapprofd.cpp
@@ -116,6 +116,7 @@ static void MaybeInstallInitHeapprofdHook(int) {
// Zygote child processes must be marked profileable.
if (gZygoteChild &&
!atomic_load_explicit(&gZygoteChildProfileable, memory_order_acquire)) {
+ error_log("%s: not enabling heapprofd, not marked profileable.", getprogname());
return;
}
diff --git a/libc/bionic/malloc_limit.cpp b/libc/bionic/malloc_limit.cpp
index b42865bf1..6a67cae95 100644
--- a/libc/bionic/malloc_limit.cpp
+++ b/libc/bionic/malloc_limit.cpp
@@ -113,7 +113,7 @@ static inline void* IncrementLimit(void* mem) {
void* LimitCalloc(size_t n_elements, size_t elem_size) {
size_t total;
- if (__builtin_add_overflow(n_elements, elem_size, &total) || !CheckLimit(total)) {
+ if (__builtin_mul_overflow(n_elements, elem_size, &total) || !CheckLimit(total)) {
warning_log("malloc_limit: calloc(%zu, %zu) exceeds limit %" PRId64, n_elements, elem_size,
gAllocLimit);
return nullptr;
diff --git a/libc/bionic/mremap.cpp b/libc/bionic/mremap.cpp
index 896ccef16..a4e5323f7 100644
--- a/libc/bionic/mremap.cpp
+++ b/libc/bionic/mremap.cpp
@@ -34,7 +34,7 @@
#include "private/bionic_macros.h"
-extern "C" void* ___mremap(void*, size_t, size_t, int, void*);
+extern "C" void* __mremap(void*, size_t, size_t, int, void*);
void* mremap(void* old_address, size_t old_size, size_t new_size, int flags, ...) {
// prevent allocations large enough for `end - start` to overflow
@@ -53,5 +53,5 @@ void* mremap(void* old_address, size_t old_size, size_t new_size, int flags, ...
new_address = va_arg(ap, void*);
va_end(ap);
}
- return ___mremap(old_address, old_size, new_size, flags, new_address);
+ return __mremap(old_address, old_size, new_size, flags, new_address);
}
diff --git a/libc/bionic/ndk_cruft.cpp b/libc/bionic/ndk_cruft.cpp
index 2c3299f7b..f0a7026c7 100644
--- a/libc/bionic/ndk_cruft.cpp
+++ b/libc/bionic/ndk_cruft.cpp
@@ -243,15 +243,23 @@ sighandler_t bsd_signal(int signum, sighandler_t handler) {
return signal(signum, handler);
}
+// bcopy/bzero were previously `#define`d, so we only have `static` wrappers in
+// Bionic headers. Since we have header definitions, we need some way to
+// overload these implementations; __never_call will ensure that any calls to
+// bcopy/bzero call the in-header implementation. Since the implementations
+// should end up functionally identical, it doesn't matter which we actually
+// call.
+#define __never_call __attribute__((enable_if(false, "never selected")))
+
// This was removed from POSIX 2008.
-#undef bcopy
-void bcopy(const void* src, void* dst, size_t n) {
+void bcopy(const void* src, void* dst, size_t n) __never_call __RENAME(bcopy);
+void bcopy(const void* src, void* dst, size_t n) __never_call {
memmove(dst, src, n);
}
// This was removed from POSIX 2008.
-#undef bzero
-void bzero(void* dst, size_t n) {
+void bzero(void* dst, size_t n) __never_call __RENAME(bzero);
+void bzero(void* dst, size_t n) __never_call {
memset(dst, 0, n);
}
diff --git a/libc/bionic/open.cpp b/libc/bionic/open.cpp
index 222e5d3f4..df5ab215b 100644
--- a/libc/bionic/open.cpp
+++ b/libc/bionic/open.cpp
@@ -70,6 +70,7 @@ 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 __openat(AT_FDCWD, pathname, force_O_LARGEFILE(flags), 0);
}
+__strong_alias(__open64_2, __open_2);
int openat(int fd, const char *pathname, int flags, ...) {
mode_t mode = 0;
@@ -89,3 +90,4 @@ int __openat_2(int fd, const char* pathname, int flags) {
if (needs_mode(flags)) __fortify_fatal("open: called with O_CREAT/O_TMPFILE but no mode");
return __openat(fd, pathname, force_O_LARGEFILE(flags), 0);
}
+__strong_alias(__openat64_2, __openat_2);
diff --git a/libc/bionic/pthread_cond.cpp b/libc/bionic/pthread_cond.cpp
index 9f0f8fa3c..e85706902 100644
--- a/libc/bionic/pthread_cond.cpp
+++ b/libc/bionic/pthread_cond.cpp
@@ -215,6 +215,18 @@ extern "C" int pthread_cond_timedwait_monotonic_np(pthread_cond_t* cond_interfac
return __pthread_cond_timedwait(__get_internal_cond(cond_interface), mutex, false, abs_timeout);
}
+int pthread_cond_clockwait(pthread_cond_t* cond_interface, pthread_mutex_t* mutex, clockid_t clock,
+ const struct timespec* abs_timeout) {
+ switch (clock) {
+ case CLOCK_MONOTONIC:
+ return pthread_cond_timedwait_monotonic_np(cond_interface, mutex, abs_timeout);
+ case CLOCK_REALTIME:
+ return __pthread_cond_timedwait(__get_internal_cond(cond_interface), mutex, true, abs_timeout);
+ default:
+ return EINVAL;
+ }
+}
+
#if !defined(__LP64__)
// TODO: this exists only for backward binary compatibility on 32 bit platforms.
extern "C" int pthread_cond_timedwait_monotonic(pthread_cond_t* cond_interface,
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index 4cf14ad72..0dbf53949 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -254,6 +254,8 @@ ThreadMapping __allocate_thread_mapping(size_t stack_size, size_t stack_guard_si
ThreadMapping result = {};
result.mmap_base = space;
result.mmap_size = mmap_size;
+ result.mmap_base_unguarded = space + stack_guard_size;
+ result.mmap_size_unguarded = mmap_size - stack_guard_size - PTHREAD_GUARD_SIZE;
result.static_tls = space + mmap_size - PTHREAD_GUARD_SIZE - layout.size();
result.stack_base = space;
result.stack_top = result.static_tls;
@@ -315,12 +317,33 @@ static int __allocate_thread(pthread_attr_t* attr, bionic_tcb** tcbp, void** chi
thread->attr = *attr;
thread->mmap_base = mapping.mmap_base;
thread->mmap_size = mapping.mmap_size;
+ thread->mmap_base_unguarded = mapping.mmap_base_unguarded;
+ thread->mmap_size_unguarded = mapping.mmap_size_unguarded;
*tcbp = tcb;
*child_stack = stack_top;
return 0;
}
+void __set_stack_and_tls_vma_name(bool is_main_thread) {
+ // Name the thread's stack-and-tls area to help with debugging. This mapped area also includes
+ // static TLS data, which is typically a few pages (e.g. bionic_tls).
+ pthread_internal_t* thread = __get_thread();
+ const char* name;
+ if (is_main_thread) {
+ name = "stack_and_tls:main";
+ } else {
+ // The kernel doesn't copy the name string, but this variable will last at least as long as the
+ // mapped area. The mapped area's VMAs are unmapped with a single call to munmap.
+ auto& name_buffer = thread->vma_name_buffer;
+ static_assert(arraysize(name_buffer) >= arraysize("stack_and_tls:") + 11 + 1);
+ async_safe_format_buffer(name_buffer, arraysize(name_buffer), "stack_and_tls:%d", thread->tid);
+ name = name_buffer;
+ }
+ prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, thread->mmap_base_unguarded, thread->mmap_size_unguarded,
+ name);
+}
+
__attribute__((no_sanitize("hwaddress")))
static int __pthread_start(void* arg) {
pthread_internal_t* thread = reinterpret_cast<pthread_internal_t*>(arg);
@@ -333,6 +356,7 @@ static int __pthread_start(void* arg) {
// accesses previously made by the creating thread are visible to us.
thread->startup_handshake_lock.lock();
+ __set_stack_and_tls_vma_name(false);
__init_additional_stacks(thread);
void* result = thread->start_routine(thread->start_routine_arg);
diff --git a/libc/bionic/pthread_internal.h b/libc/bionic/pthread_internal.h
index a1e0c450a..22cc4000d 100644
--- a/libc/bionic/pthread_internal.h
+++ b/libc/bionic/pthread_internal.h
@@ -129,6 +129,11 @@ class pthread_internal_t {
void* mmap_base;
size_t mmap_size;
+ // The location of the VMA to label as the thread's stack_and_tls.
+ void* mmap_base_unguarded;
+ size_t mmap_size_unguarded;
+ char vma_name_buffer[32];
+
thread_local_dtor* thread_local_dtors;
/*
@@ -147,6 +152,8 @@ class pthread_internal_t {
struct ThreadMapping {
char* mmap_base;
size_t mmap_size;
+ char* mmap_base_unguarded;
+ size_t mmap_size_unguarded;
char* static_tls;
char* stack_base;
@@ -162,6 +169,7 @@ __LIBC_HIDDEN__ void __free_temp_bionic_tls(bionic_tls* tls);
__LIBC_HIDDEN__ void __init_additional_stacks(pthread_internal_t*);
__LIBC_HIDDEN__ int __init_thread(pthread_internal_t* thread);
__LIBC_HIDDEN__ ThreadMapping __allocate_thread_mapping(size_t stack_size, size_t stack_guard_size);
+__LIBC_HIDDEN__ void __set_stack_and_tls_vma_name(bool is_main_thread);
__LIBC_HIDDEN__ pthread_t __pthread_internal_add(pthread_internal_t* thread);
__LIBC_HIDDEN__ pthread_internal_t* __pthread_internal_find(pthread_t pthread_id, const char* caller);
diff --git a/libc/bionic/pthread_mutex.cpp b/libc/bionic/pthread_mutex.cpp
index 37031ad6b..de62a5c01 100644
--- a/libc/bionic/pthread_mutex.cpp
+++ b/libc/bionic/pthread_mutex.cpp
@@ -989,6 +989,24 @@ int pthread_mutex_timedlock_monotonic_np(pthread_mutex_t* mutex_interface,
return __pthread_mutex_timedlock(mutex_interface, false, abs_timeout, __FUNCTION__);
}
+int pthread_mutex_clocklock(pthread_mutex_t* mutex_interface, clockid_t clock,
+ const struct timespec* abs_timeout) {
+ switch (clock) {
+ case CLOCK_MONOTONIC:
+ return __pthread_mutex_timedlock(mutex_interface, false, abs_timeout, __FUNCTION__);
+ case CLOCK_REALTIME:
+ return __pthread_mutex_timedlock(mutex_interface, true, abs_timeout, __FUNCTION__);
+ default: {
+ pthread_mutex_internal_t* mutex = __get_internal_mutex(mutex_interface);
+ uint16_t old_state = atomic_load_explicit(&mutex->state, memory_order_relaxed);
+ if (IsMutexDestroyed(old_state)) {
+ return HandleUsingDestroyedMutex(mutex_interface, __FUNCTION__);
+ }
+ return EINVAL;
+ }
+ }
+}
+
int pthread_mutex_destroy(pthread_mutex_t* mutex_interface) {
pthread_mutex_internal_t* mutex = __get_internal_mutex(mutex_interface);
uint16_t old_state = atomic_load_explicit(&mutex->state, memory_order_relaxed);
diff --git a/libc/bionic/pthread_rwlock.cpp b/libc/bionic/pthread_rwlock.cpp
index 2b9be98d7..ebf6697a0 100644
--- a/libc/bionic/pthread_rwlock.cpp
+++ b/libc/bionic/pthread_rwlock.cpp
@@ -429,6 +429,18 @@ int pthread_rwlock_timedrdlock_monotonic_np(pthread_rwlock_t* rwlock_interface,
return __pthread_rwlock_timedrdlock(rwlock, false, abs_timeout);
}
+int pthread_rwlock_clockrdlock(pthread_rwlock_t* rwlock_interface, clockid_t clock,
+ const struct timespec* abs_timeout) {
+ switch (clock) {
+ case CLOCK_MONOTONIC:
+ return pthread_rwlock_timedrdlock_monotonic_np(rwlock_interface, abs_timeout);
+ case CLOCK_REALTIME:
+ return pthread_rwlock_timedrdlock(rwlock_interface, abs_timeout);
+ default:
+ return EINVAL;
+ }
+}
+
int pthread_rwlock_tryrdlock(pthread_rwlock_t* rwlock_interface) {
return __pthread_rwlock_tryrdlock(__get_internal_rwlock(rwlock_interface));
}
@@ -455,6 +467,18 @@ int pthread_rwlock_timedwrlock_monotonic_np(pthread_rwlock_t* rwlock_interface,
return __pthread_rwlock_timedwrlock(rwlock, false, abs_timeout);
}
+int pthread_rwlock_clockwrlock(pthread_rwlock_t* rwlock_interface, clockid_t clock,
+ const struct timespec* abs_timeout) {
+ switch (clock) {
+ case CLOCK_MONOTONIC:
+ return pthread_rwlock_timedwrlock_monotonic_np(rwlock_interface, abs_timeout);
+ case CLOCK_REALTIME:
+ return pthread_rwlock_timedwrlock(rwlock_interface, abs_timeout);
+ default:
+ return EINVAL;
+ }
+}
+
int pthread_rwlock_trywrlock(pthread_rwlock_t* rwlock_interface) {
return __pthread_rwlock_trywrlock(__get_internal_rwlock(rwlock_interface));
}
diff --git a/libc/bionic/semaphore.cpp b/libc/bionic/semaphore.cpp
index e0486b4dd..455e36b27 100644
--- a/libc/bionic/semaphore.cpp
+++ b/libc/bionic/semaphore.cpp
@@ -275,6 +275,17 @@ int sem_timedwait_monotonic_np(sem_t* sem, const timespec* abs_timeout) {
return __sem_timedwait(sem, abs_timeout, false);
}
+int sem_clockwait(sem_t* sem, clockid_t clock, const timespec* abs_timeout) {
+ switch (clock) {
+ case CLOCK_MONOTONIC:
+ return sem_timedwait_monotonic_np(sem, abs_timeout);
+ case CLOCK_REALTIME:
+ return sem_timedwait(sem, abs_timeout);
+ default:
+ return EINVAL;
+ }
+}
+
int sem_post(sem_t* sem) {
atomic_uint* sem_count_ptr = SEM_TO_ATOMIC_POINTER(sem);
unsigned int shared = SEM_GET_SHARED(sem_count_ptr);
diff --git a/libc/bionic/signal.cpp b/libc/bionic/signal.cpp
index d6be09a6f..8246cb4af 100644
--- a/libc/bionic/signal.cpp
+++ b/libc/bionic/signal.cpp
@@ -41,7 +41,7 @@
#include "private/sigrtmin.h"
extern "C" int __rt_sigpending(const sigset64_t*, size_t);
-extern "C" int ___rt_sigqueueinfo(pid_t, int, siginfo_t*);
+extern "C" int __rt_sigqueueinfo(pid_t, int, siginfo_t*);
extern "C" int __rt_sigsuspend(const sigset64_t*, size_t);
extern "C" int __rt_sigtimedwait(const sigset64_t*, siginfo_t*, const timespec*, size_t);
@@ -216,7 +216,7 @@ int sigqueue(pid_t pid, int sig, const sigval value) {
info.si_pid = getpid();
info.si_uid = getuid();
info.si_value = value;
- return ___rt_sigqueueinfo(pid, sig, &info);
+ return __rt_sigqueueinfo(pid, sig, &info);
}
int sigrelse(int sig) {
diff --git a/libc/include/android/fdsan.h b/libc/include/android/fdsan.h
index 1169ed046..83b9318ba 100644
--- a/libc/include/android/fdsan.h
+++ b/libc/include/android/fdsan.h
@@ -197,4 +197,8 @@ enum android_fdsan_error_level android_fdsan_get_error_level() __INTRODUCED_IN(2
*/
enum android_fdsan_error_level android_fdsan_set_error_level(enum android_fdsan_error_level new_level) __INTRODUCED_IN(29) __attribute__((__weak__));
+/*
+ * Set the error level to the global setting if available, or a default value.
+ */
+enum android_fdsan_error_level android_fdsan_set_error_level_from_property(enum android_fdsan_error_level default_level) __INTRODUCED_IN(30) __attribute__((__weak__));
__END_DECLS
diff --git a/libc/include/android/legacy_signal_inlines.h b/libc/include/android/legacy_signal_inlines.h
index 5ca9813f3..d2c767703 100644
--- a/libc/include/android/legacy_signal_inlines.h
+++ b/libc/include/android/legacy_signal_inlines.h
@@ -52,7 +52,7 @@ static __inline int __ndk_legacy___libc_current_sigrtmax() {
static __inline int __ndk_legacy___libc_current_sigrtmin() {
if (__libc_current_sigrtmin) return __libc_current_sigrtmin();
- return __SIGRTMIN + 6; /* Should match __libc_current_sigrtmin. */
+ return __SIGRTMIN + 7; /* Should match __libc_current_sigrtmin. */
}
#undef SIGRTMAX
diff --git a/libc/include/arpa/nameser.h b/libc/include/arpa/nameser.h
index e0b5c4514..89ece1c5e 100644
--- a/libc/include/arpa/nameser.h
+++ b/libc/include/arpa/nameser.h
@@ -591,33 +591,29 @@ int ns_samename(const char* __lhs, const char* __rhs);
/* The names of these symbols were accidentally prefixed with __ in L. */
/* The duplication here is intentional to avoid declaring different symbols with the same
* declaration. */
-int ns_msg_getflag(ns_msg __handle, int __flag) __INTRODUCED_IN_64(23);
-uint16_t ns_get16(const u_char* __src) __INTRODUCED_IN_64(23);
-uint32_t ns_get32(const u_char* __src) __INTRODUCED_IN_64(23);
-void ns_put16(uint16_t __src, u_char* __dst) __INTRODUCED_IN_64(23);
-void ns_put32(uint32_t __src, u_char* __dst) __INTRODUCED_IN_64(23);
-int ns_initparse(const u_char* __msg, int __msg_size, ns_msg* __handle) __INTRODUCED_IN_64(23);
-int ns_skiprr(const u_char* __ptr, const u_char* __eom, ns_sect __section, int __count) __INTRODUCED_IN_64(23);
-int ns_parserr(ns_msg* __handle, ns_sect __section, int __rr_number, ns_rr* __rr) __INTRODUCED_IN_64(23);
-int ns_sprintrr(const ns_msg* __handle, const ns_rr* __rr, const char* __name_ctx, const char* __origin, char* __buf, size_t __buf_size)
- __INTRODUCED_IN_64(23);
-int ns_sprintrrf(const u_char* __msg, size_t __msg_size, const char* __name, ns_class __class, ns_type __type, u_long __ttl, const u_char* __rdata, size_t __rdata_size, const char* __name_ctx, const char* __origin, char* __buf, size_t __buf_size) __INTRODUCED_IN_64(23);
-int ns_format_ttl(u_long __ttl, char* __dst, size_t __dst_size) __INTRODUCED_IN_64(23);
-int ns_name_ntol(const u_char* __src, u_char* __dst, size_t __dst_size) __INTRODUCED_IN_64(23);
-int ns_name_ntop(const u_char* __src, char* __dst, size_t __dst_size) __INTRODUCED_IN_64(23);
-int ns_name_pton(const char* __src, u_char* __dst, size_t __dst_size) __INTRODUCED_IN_64(23);
-int ns_name_unpack(const u_char* __msg, const u_char* __eom, const u_char* __src, u_char* __dst, size_t __dst_size)
- __INTRODUCED_IN_64(23);
-int ns_name_pack(const u_char* __src, u_char* __dst, int __dst_size, const u_char** __dn_ptrs, const u_char** __last_dn_ptr) __INTRODUCED_IN_64(23);
-int ns_name_uncompress(const u_char* __msg, const u_char* __eom, const u_char* __src, char* __dst, size_t __dst_size)
- __INTRODUCED_IN_64(23);
-int ns_name_compress(const char* __src, u_char* __dst, size_t __dst_size, const u_char** __dn_ptrs, const u_char** __last_dn_ptr)
- __INTRODUCED_IN_64(23);
-int ns_name_skip(const u_char** __ptr_ptr, const u_char* __eom) __INTRODUCED_IN_64(23);
-void ns_name_rollback(const u_char* __src, const u_char** __dn_ptrs, const u_char** __last_dn_ptr) __INTRODUCED_IN_64(23);
-
-int ns_makecanon(const char* __src, char* __dst, size_t __dst_size) __INTRODUCED_IN_64(23);
-int ns_samename(const char* __lhs, const char* __rhs) __INTRODUCED_IN_64(23);
+int ns_msg_getflag(ns_msg __handle, int __flag) __INTRODUCED_IN_64(22);
+uint16_t ns_get16(const u_char* __src) __INTRODUCED_IN_64(22);
+uint32_t ns_get32(const u_char* __src) __INTRODUCED_IN_64(22);
+void ns_put16(uint16_t __src, u_char* __dst) __INTRODUCED_IN_64(22);
+void ns_put32(uint32_t __src, u_char* __dst) __INTRODUCED_IN_64(22);
+int ns_initparse(const u_char* __msg, int __msg_size, ns_msg* __handle) __INTRODUCED_IN_64(22);
+int ns_skiprr(const u_char* __ptr, const u_char* __eom, ns_sect __section, int __count) __INTRODUCED_IN_64(22);
+int ns_parserr(ns_msg* __handle, ns_sect __section, int __rr_number, ns_rr* __rr) __INTRODUCED_IN_64(22);
+int ns_sprintrr(const ns_msg* __handle, const ns_rr* __rr, const char* __name_ctx, const char* __origin, char* __buf, size_t __buf_size) __INTRODUCED_IN_64(22);
+int ns_sprintrrf(const u_char* __msg, size_t __msg_size, const char* __name, ns_class __class, ns_type __type, u_long __ttl, const u_char* __rdata, size_t __rdata_size, const char* __name_ctx, const char* __origin, char* __buf, size_t __buf_size) __INTRODUCED_IN_64(22);
+int ns_format_ttl(u_long __ttl, char* __dst, size_t __dst_size) __INTRODUCED_IN_64(22);
+int ns_name_ntol(const u_char* __src, u_char* __dst, size_t __dst_size) __INTRODUCED_IN_64(22);
+int ns_name_ntop(const u_char* __src, char* __dst, size_t __dst_size) __INTRODUCED_IN_64(22);
+int ns_name_pton(const char* __src, u_char* __dst, size_t __dst_size) __INTRODUCED_IN_64(22);
+int ns_name_unpack(const u_char* __msg, const u_char* __eom, const u_char* __src, u_char* __dst, size_t __dst_size) __INTRODUCED_IN_64(22);
+int ns_name_pack(const u_char* __src, u_char* __dst, int __dst_size, const u_char** __dn_ptrs, const u_char** __last_dn_ptr) __INTRODUCED_IN_64(22);
+int ns_name_uncompress(const u_char* __msg, const u_char* __eom, const u_char* __src, char* __dst, size_t __dst_size) __INTRODUCED_IN_64(22);
+int ns_name_compress(const char* __src, u_char* __dst, size_t __dst_size, const u_char** __dn_ptrs, const u_char** __last_dn_ptr) __INTRODUCED_IN_64(22);
+int ns_name_skip(const u_char** __ptr_ptr, const u_char* __eom) __INTRODUCED_IN_64(22);
+void ns_name_rollback(const u_char* __src, const u_char** __dn_ptrs, const u_char** __last_dn_ptr) __INTRODUCED_IN_64(22);
+
+int ns_makecanon(const char* __src, char* __dst, size_t __dst_size) __INTRODUCED_IN_64(22);
+int ns_samename(const char* __lhs, const char* __rhs) __INTRODUCED_IN_64(22);
#endif /* !defined(__LP64__) */
__END_DECLS
diff --git a/libc/include/bits/elf_arm64.h b/libc/include/bits/elf_arm64.h
index d838c0b2d..6bb8384e4 100644
--- a/libc/include/bits/elf_arm64.h
+++ b/libc/include/bits/elf_arm64.h
@@ -83,9 +83,9 @@
#define R_AARCH64_GLOB_DAT 1025 /* Create GOT entry. */
#define R_AARCH64_JUMP_SLOT 1026 /* Create PLT entry. */
#define R_AARCH64_RELATIVE 1027 /* Adjust by program base. */
-#define R_AARCH64_TLS_DTPREL64 1028 /* Module-relative offset. */
-#define R_AARCH64_TLS_DTPMOD64 1029 /* Module index. */
-#define R_AARCH64_TLS_TPREL64 1030 /* TP-relative offset. */
+#define R_AARCH64_TLS_DTPMOD 1028 /* Module index. */
+#define R_AARCH64_TLS_DTPREL 1029 /* Module-relative offset. */
+#define R_AARCH64_TLS_TPREL 1030 /* TP-relative offset. */
#define R_AARCH64_TLSDESC 1031 /* 16-byte descriptor: resolver func + arg. */
#define R_AARCH64_IRELATIVE 1032
diff --git a/libc/include/bits/fortify/fcntl.h b/libc/include/bits/fortify/fcntl.h
index e7f2c8263..4bb441eee 100644
--- a/libc/include/bits/fortify/fcntl.h
+++ b/libc/include/bits/fortify/fcntl.h
@@ -92,6 +92,52 @@ int openat(int dirfd, const char* const __pass_object_size pathname, int flags,
}
#endif /* __ANDROID_API__ >= __ANDROID_API_J_MR1__ */
+#if __ANDROID_API__ >= __ANDROID_API_R__
+int __open64_2(const char*, int) __INTRODUCED_IN(30);
+int __openat64_2(int, const char*, int) __INTRODUCED_IN(30);
+int __open64_real(const char* __path, int __flags, ...) __RENAME(open64);
+int __openat64_real(int, const char*, int, ...) __RENAME(openat64);
+
+__BIONIC_ERROR_FUNCTION_VISIBILITY
+int open64(const char* pathname, int flags, mode_t modes, ...) __overloadable
+ __errorattr(__open_too_many_args_error);
+
+__BIONIC_FORTIFY_INLINE
+int open64(const char* const __pass_object_size pathname, int flags)
+ __overloadable
+ __clang_error_if(__open_modes_useful(flags), "'open64' " __open_too_few_args_error) {
+ return __open64_2(pathname, flags);
+}
+
+__BIONIC_FORTIFY_INLINE
+int open64(const char* const __pass_object_size pathname, int flags, mode_t modes)
+ __overloadable
+ __clang_warning_if(!__open_modes_useful(flags) && modes,
+ "'open64' " __open_useless_modes_warning) {
+ return __open64_real(pathname, flags, modes);
+}
+
+__BIONIC_ERROR_FUNCTION_VISIBILITY
+int openat64(int dirfd, const char* pathname, int flags, mode_t modes, ...)
+ __overloadable
+ __errorattr(__open_too_many_args_error);
+
+__BIONIC_FORTIFY_INLINE
+int openat64(int dirfd, const char* const __pass_object_size pathname, int flags)
+ __overloadable
+ __clang_error_if(__open_modes_useful(flags), "'openat64' " __open_too_few_args_error) {
+ return __openat64_2(dirfd, pathname, flags);
+}
+
+__BIONIC_FORTIFY_INLINE
+int openat64(int dirfd, const char* const __pass_object_size pathname, int flags, mode_t modes)
+ __overloadable
+ __clang_warning_if(!__open_modes_useful(flags) && modes,
+ "'openat64' " __open_useless_modes_warning) {
+ return __openat64_real(dirfd, pathname, flags, modes);
+}
+#endif /* __ANDROID_API__ >= __ANDROID_API_R__ */
+
#undef __open_too_many_args_error
#undef __open_too_few_args_error
#undef __open_useless_modes_warning
diff --git a/libc/include/bits/fortify/stdio.h b/libc/include/bits/fortify/stdio.h
index 6e47dafee..e766b2007 100644
--- a/libc/include/bits/fortify/stdio.h
+++ b/libc/include/bits/fortify/stdio.h
@@ -39,6 +39,8 @@ size_t __fwrite_chk(const void*, size_t, size_t, FILE*, size_t) __INTRODUCED_IN(
#if __ANDROID_API__ >= __ANDROID_API_J_MR1__
__BIONIC_FORTIFY_INLINE __printflike(3, 0)
int vsnprintf(char* const __pass_object_size dest, size_t size, const char* format, va_list ap)
+ __clang_error_if(__bos_unevaluated_lt(__bos(dest), size),
+ "in call to 'vsnprintf', size is larger than the destination buffer")
__overloadable {
return __builtin___vsnprintf_chk(dest, size, 0, __bos(dest), format, ap);
}
@@ -50,19 +52,10 @@ int vsprintf(char* const __pass_object_size dest, const char* format, va_list ap
#endif /* __ANDROID_API__ >= __ANDROID_API_J_MR1__ */
#if __ANDROID_API__ >= __ANDROID_API_J_MR1__
-/*
- * Simple case: `format` can't have format specifiers, so we can just compare
- * its length to the length of `dest`
- */
-__BIONIC_ERROR_FUNCTION_VISIBILITY
-int snprintf(char* dest, size_t size, const char* format)
- __overloadable
- __enable_if(__bos_unevaluated_lt(__bos(dest), __builtin_strlen(format)),
- "format string will always overflow destination buffer")
- __errorattr("format string will always overflow destination buffer");
-
__BIONIC_FORTIFY_VARIADIC __printflike(3, 4)
int snprintf(char* const __pass_object_size dest, size_t size, const char* format, ...)
+ __clang_error_if(__bos_unevaluated_lt(__bos(dest), size),
+ "in call to 'snprintf', size is larger than the destination buffer")
__overloadable {
va_list va;
va_start(va, format);
diff --git a/libc/include/bits/fortify/stdlib.h b/libc/include/bits/fortify/stdlib.h
index 0bb3d0d66..623be583b 100644
--- a/libc/include/bits/fortify/stdlib.h
+++ b/libc/include/bits/fortify/stdlib.h
@@ -36,10 +36,11 @@
#define __PATH_MAX 4096
char* realpath(const char* path, char* resolved)
+ __clang_error_if(!path, "'realpath': NULL path is never correct; flipped arguments?")
__clang_error_if(__bos_unevaluated_lt(__bos(resolved), __PATH_MAX),
"'realpath' output parameter must be NULL or a pointer to a buffer "
- "with >= PATH_MAX bytes")
- __clang_error_if(!path, "'realpath': NULL path is never correct; flipped arguments?");
+ "with >= PATH_MAX bytes");
+
/* No need for a definition; the only issues we can catch are at compile-time. */
#undef __PATH_MAX
diff --git a/libc/include/bits/fortify/string.h b/libc/include/bits/fortify/string.h
index 1e129868c..70e4476b4 100644
--- a/libc/include/bits/fortify/string.h
+++ b/libc/include/bits/fortify/string.h
@@ -66,6 +66,22 @@ void* memmove(void* const dst __pass_object_size0, const void* src, size_t len)
}
#endif /* __ANDROID_API__ >= __ANDROID_API_J_MR1__ */
+#if defined(__USE_GNU)
+#if __ANDROID_API__ >= __ANDROID_API_R__
+__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") {
+ size_t bos_dst = __bos0(dst);
+ if (__bos_trivially_not_lt(bos_dst, copy_amount)) {
+ return __builtin_mempcpy(dst, src, copy_amount);
+ }
+ return __builtin___mempcpy_chk(dst, src, copy_amount, bos_dst);
+}
+#endif /* __ANDROID_API__ >= __ANDROID_API_R__ */
+#endif
+
#if __ANDROID_API__ >= __ANDROID_API_L__
__BIONIC_FORTIFY_INLINE
char* stpcpy(char* const dst __pass_object_size, const char* src)
@@ -94,12 +110,18 @@ char* strcpy(char* const dst __pass_object_size, const char* src)
}
__BIONIC_FORTIFY_INLINE
-char* strcat(char* const dst __pass_object_size, const char* src) __overloadable {
+char* strcat(char* const dst __pass_object_size, const char* src)
+ __overloadable
+ __clang_error_if(__bos_unevaluated_le(__bos(dst), __builtin_strlen(src)),
+ "'strcat' called with string bigger than buffer") {
return __builtin___strcat_chk(dst, src, __bos(dst));
}
__BIONIC_FORTIFY_INLINE
-char* strncat(char* const dst __pass_object_size, const char* src, size_t n) __overloadable {
+char* strncat(char* const dst __pass_object_size, const char* src, size_t n)
+ __overloadable
+ __clang_error_if(__bos_unevaluated_lt(__bos(dst), n),
+ "'strncat' called with size bigger than buffer") {
return __builtin___strncat_chk(dst, src, n, __bos(dst));
}
@@ -145,7 +167,9 @@ void* __memrchr_fortify(const void* const __pass_object_size s, int c, size_t n)
#if __ANDROID_API__ >= __ANDROID_API_L__
__BIONIC_FORTIFY_INLINE
char* stpncpy(char* const dst __pass_object_size, const char* const src __pass_object_size, size_t n)
- __overloadable {
+ __overloadable
+ __clang_error_if(__bos_unevaluated_lt(__bos(dst), n),
+ "'stpncpy' called with size bigger than buffer") {
size_t bos_dst = __bos(dst);
size_t bos_src = __bos(src);
@@ -159,7 +183,9 @@ char* stpncpy(char* const dst __pass_object_size, const char* const src __pass_o
__BIONIC_FORTIFY_INLINE
char* strncpy(char* const dst __pass_object_size, const char* const src __pass_object_size, size_t n)
- __overloadable {
+ __overloadable
+ __clang_error_if(__bos_unevaluated_lt(__bos(dst), n),
+ "'strncpy' called with size bigger than buffer") {
size_t bos_dst = __bos(dst);
size_t bos_src = __bos(src);
@@ -174,7 +200,10 @@ char* strncpy(char* const dst __pass_object_size, const char* const src __pass_o
#if __ANDROID_API__ >= __ANDROID_API_J_MR1__
__BIONIC_FORTIFY_INLINE
-size_t strlcpy(char* const dst __pass_object_size, const char* src, size_t size) __overloadable {
+size_t strlcpy(char* const dst __pass_object_size, const char* src, size_t size)
+ __overloadable
+ __clang_error_if(__bos_unevaluated_lt(__bos(dst), size),
+ "'strlcpy' called with size bigger than buffer") {
size_t bos = __bos(dst);
if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
@@ -185,7 +214,10 @@ size_t strlcpy(char* const dst __pass_object_size, const char* src, size_t size)
}
__BIONIC_FORTIFY_INLINE
-size_t strlcat(char* const dst __pass_object_size, const char* src, size_t size) __overloadable {
+size_t strlcat(char* const dst __pass_object_size, const char* src, size_t size)
+ __overloadable
+ __clang_error_if(__bos_unevaluated_lt(__bos(dst), size),
+ "'strlcat' called with size bigger than buffer") {
size_t bos = __bos(dst);
if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
diff --git a/libc/include/bits/fortify/strings.h b/libc/include/bits/fortify/strings.h
new file mode 100644
index 000000000..6bda295f3
--- /dev/null
+++ b/libc/include/bits/fortify/strings.h
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+#if defined(__BIONIC_FORTIFY)
+
+#if __ANDROID_API__ >= __ANDROID_API_J_MR1__
+__BIONIC_FORTIFY_INLINE
+void bcopy(const void *src, void* const dst __pass_object_size0, size_t len)
+ __overloadable
+ __clang_error_if(__bos_unevaluated_lt(__bos0(dst), len),
+ "'bcopy' called with size bigger than buffer") {
+ size_t bos = __bos0(dst);
+ if (__bos_trivially_not_lt(bos, len)) {
+ __builtin_memmove(dst, src, len);
+ } else {
+ __builtin___memmove_chk(dst, src, len, bos);
+ }
+}
+
+__BIONIC_FORTIFY_INLINE
+void bzero(void* const b __pass_object_size0, size_t len)
+ __overloadable
+ __clang_error_if(__bos_unevaluated_lt(__bos0(b), len),
+ "'bzero' called with size bigger than buffer") {
+ size_t bos = __bos0(b);
+ if (__bos_trivially_not_lt(bos, len)) {
+ __builtin_memset(b, 0, len);
+ } else {
+ __builtin___memset_chk(b, 0, len, bos);
+ }
+}
+#endif /* __ANDROID_API__ >= __ANDROID_API_J_MR1__ */
+
+#endif /* defined(__BIONIC_FORTIFY) */
diff --git a/libc/include/bits/fortify/unistd.h b/libc/include/bits/fortify/unistd.h
index 543c3c748..547a1686c 100644
--- a/libc/include/bits/fortify/unistd.h
+++ b/libc/include/bits/fortify/unistd.h
@@ -67,7 +67,8 @@ ssize_t __readlinkat_chk(int dirfd, const char*, char*, size_t, size_t) __INTROD
"in call to '" #fn "', '" #what "' bytes overflows the given object")
#define __bos_trivially_not_lt_no_overflow(bos_val, index) \
- __bos_dynamic_check_impl_and((bos_val), >=, (index), (bos_val) <= SSIZE_MAX)
+ ((__bos_dynamic_check_impl_and((bos_val), >=, (index), (bos_val) <= SSIZE_MAX) && \
+ __builtin_constant_p(index) && (index) <= SSIZE_MAX))
#if __ANDROID_API__ >= __ANDROID_API_N__
__BIONIC_FORTIFY_INLINE
diff --git a/libc/include/bits/glibc-syscalls.h b/libc/include/bits/glibc-syscalls.h
index 6940b3e1c..6b3e347c2 100644
--- a/libc/include/bits/glibc-syscalls.h
+++ b/libc/include/bits/glibc-syscalls.h
@@ -243,9 +243,21 @@
#if defined(__NR_fremovexattr)
#define SYS_fremovexattr __NR_fremovexattr
#endif
+#if defined(__NR_fsconfig)
+ #define SYS_fsconfig __NR_fsconfig
+#endif
#if defined(__NR_fsetxattr)
#define SYS_fsetxattr __NR_fsetxattr
#endif
+#if defined(__NR_fsmount)
+ #define SYS_fsmount __NR_fsmount
+#endif
+#if defined(__NR_fsopen)
+ #define SYS_fsopen __NR_fsopen
+#endif
+#if defined(__NR_fspick)
+ #define SYS_fspick __NR_fspick
+#endif
#if defined(__NR_fstat)
#define SYS_fstat __NR_fstat
#endif
@@ -582,6 +594,9 @@
#if defined(__NR_mount)
#define SYS_mount __NR_mount
#endif
+#if defined(__NR_move_mount)
+ #define SYS_move_mount __NR_move_mount
+#endif
#if defined(__NR_move_pages)
#define SYS_move_pages __NR_move_pages
#endif
@@ -678,6 +693,9 @@
#if defined(__NR_open_by_handle_at)
#define SYS_open_by_handle_at __NR_open_by_handle_at
#endif
+#if defined(__NR_open_tree)
+ #define SYS_open_tree __NR_open_tree
+#endif
#if defined(__NR_openat)
#define SYS_openat __NR_openat
#endif
diff --git a/libc/include/bits/stdatomic.h b/libc/include/bits/stdatomic.h
new file mode 100644
index 000000000..633cb8665
--- /dev/null
+++ b/libc/include/bits/stdatomic.h
@@ -0,0 +1,286 @@
+/*-
+ * Copyright (c) 2011 Ed Schouten <ed@FreeBSD.org>
+ * David Chisnall <theraven@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD$
+ */
+
+#pragma once
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <stdbool.h>
+
+/*
+ * C: Do it ourselves.
+ * Note that the runtime representation defined here should be compatible
+ * with the C++ one, i.e. an _Atomic(T) needs to contain the same
+ * bits as a T.
+ */
+
+#include <stddef.h> /* For ptrdiff_t. */
+#include <stdint.h> /* TODO: don't drag in all the macros, just the types. */
+// Include uchar.h only when available. Bionic's stdatomic.h is also used for
+// the host (via a copy in prebuilts/clang) and uchar.h is not available in the
+// glibc used for the host.
+#if defined(__BIONIC__)
+# include <uchar.h> /* For char16_t and char32_t. */
+#endif
+
+/*
+ * 7.17.1 Atomic lock-free macros.
+ */
+
+#ifdef __GCC_ATOMIC_BOOL_LOCK_FREE
+#define ATOMIC_BOOL_LOCK_FREE __GCC_ATOMIC_BOOL_LOCK_FREE
+#endif
+#ifdef __GCC_ATOMIC_CHAR_LOCK_FREE
+#define ATOMIC_CHAR_LOCK_FREE __GCC_ATOMIC_CHAR_LOCK_FREE
+#endif
+#ifdef __GCC_ATOMIC_CHAR16_T_LOCK_FREE
+#define ATOMIC_CHAR16_T_LOCK_FREE __GCC_ATOMIC_CHAR16_T_LOCK_FREE
+#endif
+#ifdef __GCC_ATOMIC_CHAR32_T_LOCK_FREE
+#define ATOMIC_CHAR32_T_LOCK_FREE __GCC_ATOMIC_CHAR32_T_LOCK_FREE
+#endif
+#ifdef __GCC_ATOMIC_WCHAR_T_LOCK_FREE
+#define ATOMIC_WCHAR_T_LOCK_FREE __GCC_ATOMIC_WCHAR_T_LOCK_FREE
+#endif
+#ifdef __GCC_ATOMIC_SHORT_LOCK_FREE
+#define ATOMIC_SHORT_LOCK_FREE __GCC_ATOMIC_SHORT_LOCK_FREE
+#endif
+#ifdef __GCC_ATOMIC_INT_LOCK_FREE
+#define ATOMIC_INT_LOCK_FREE __GCC_ATOMIC_INT_LOCK_FREE
+#endif
+#ifdef __GCC_ATOMIC_LONG_LOCK_FREE
+#define ATOMIC_LONG_LOCK_FREE __GCC_ATOMIC_LONG_LOCK_FREE
+#endif
+#ifdef __GCC_ATOMIC_LLONG_LOCK_FREE
+#define ATOMIC_LLONG_LOCK_FREE __GCC_ATOMIC_LLONG_LOCK_FREE
+#endif
+#ifdef __GCC_ATOMIC_POINTER_LOCK_FREE
+#define ATOMIC_POINTER_LOCK_FREE __GCC_ATOMIC_POINTER_LOCK_FREE
+#endif
+
+/*
+ * 7.17.2 Initialization.
+ */
+
+#define ATOMIC_VAR_INIT(value) (value)
+#define atomic_init(obj, value) __c11_atomic_init(obj, value)
+
+/*
+ * Clang and recent GCC both provide predefined macros for the memory
+ * orderings. If we are using a compiler that doesn't define them, use the
+ * clang values - these will be ignored in the fallback path.
+ */
+
+#ifndef __ATOMIC_RELAXED
+#define __ATOMIC_RELAXED 0
+#endif
+#ifndef __ATOMIC_CONSUME
+#define __ATOMIC_CONSUME 1
+#endif
+#ifndef __ATOMIC_ACQUIRE
+#define __ATOMIC_ACQUIRE 2
+#endif
+#ifndef __ATOMIC_RELEASE
+#define __ATOMIC_RELEASE 3
+#endif
+#ifndef __ATOMIC_ACQ_REL
+#define __ATOMIC_ACQ_REL 4
+#endif
+#ifndef __ATOMIC_SEQ_CST
+#define __ATOMIC_SEQ_CST 5
+#endif
+
+/*
+ * 7.17.3 Order and consistency.
+ *
+ * The memory_order_* constants that denote the barrier behaviour of the
+ * atomic operations.
+ * The enum values must be identical to those used by the
+ * C++ <atomic> header.
+ */
+
+typedef enum {
+ memory_order_relaxed = __ATOMIC_RELAXED,
+ memory_order_consume = __ATOMIC_CONSUME,
+ memory_order_acquire = __ATOMIC_ACQUIRE,
+ memory_order_release = __ATOMIC_RELEASE,
+ memory_order_acq_rel = __ATOMIC_ACQ_REL,
+ memory_order_seq_cst = __ATOMIC_SEQ_CST
+} memory_order;
+
+/*
+ * 7.17.4 Fences.
+ */
+
+static __inline void atomic_thread_fence(memory_order __order __attribute__((unused))) {
+ __c11_atomic_thread_fence(__order);
+}
+
+static __inline void atomic_signal_fence(memory_order __order __attribute__((unused))) {
+ __c11_atomic_signal_fence(__order);
+}
+
+/*
+ * 7.17.5 Lock-free property.
+ */
+
+#define atomic_is_lock_free(obj) __c11_atomic_is_lock_free(sizeof(*(obj)))
+
+/*
+ * 7.17.6 Atomic integer types.
+ */
+
+typedef _Atomic(bool) atomic_bool;
+typedef _Atomic(char) atomic_char;
+typedef _Atomic(signed char) atomic_schar;
+typedef _Atomic(unsigned char) atomic_uchar;
+typedef _Atomic(short) atomic_short;
+typedef _Atomic(unsigned short) atomic_ushort;
+typedef _Atomic(int) atomic_int;
+typedef _Atomic(unsigned int) atomic_uint;
+typedef _Atomic(long) atomic_long;
+typedef _Atomic(unsigned long) atomic_ulong;
+typedef _Atomic(long long) atomic_llong;
+typedef _Atomic(unsigned long long) atomic_ullong;
+#if defined(__BIONIC__) || (defined(__cplusplus) && __cplusplus >= 201103L)
+ typedef _Atomic(char16_t) atomic_char16_t;
+ typedef _Atomic(char32_t) atomic_char32_t;
+#endif
+typedef _Atomic(wchar_t) atomic_wchar_t;
+typedef _Atomic(int_least8_t) atomic_int_least8_t;
+typedef _Atomic(uint_least8_t) atomic_uint_least8_t;
+typedef _Atomic(int_least16_t) atomic_int_least16_t;
+typedef _Atomic(uint_least16_t) atomic_uint_least16_t;
+typedef _Atomic(int_least32_t) atomic_int_least32_t;
+typedef _Atomic(uint_least32_t) atomic_uint_least32_t;
+typedef _Atomic(int_least64_t) atomic_int_least64_t;
+typedef _Atomic(uint_least64_t) atomic_uint_least64_t;
+typedef _Atomic(int_fast8_t) atomic_int_fast8_t;
+typedef _Atomic(uint_fast8_t) atomic_uint_fast8_t;
+typedef _Atomic(int_fast16_t) atomic_int_fast16_t;
+typedef _Atomic(uint_fast16_t) atomic_uint_fast16_t;
+typedef _Atomic(int_fast32_t) atomic_int_fast32_t;
+typedef _Atomic(uint_fast32_t) atomic_uint_fast32_t;
+typedef _Atomic(int_fast64_t) atomic_int_fast64_t;
+typedef _Atomic(uint_fast64_t) atomic_uint_fast64_t;
+typedef _Atomic(intptr_t) atomic_intptr_t;
+typedef _Atomic(uintptr_t) atomic_uintptr_t;
+typedef _Atomic(size_t) atomic_size_t;
+typedef _Atomic(ptrdiff_t) atomic_ptrdiff_t;
+typedef _Atomic(intmax_t) atomic_intmax_t;
+typedef _Atomic(uintmax_t) atomic_uintmax_t;
+
+/*
+ * 7.17.7 Operations on atomic types.
+ */
+
+/*
+ * Compiler-specific operations.
+ */
+
+#define atomic_compare_exchange_strong_explicit(object, expected, \
+ desired, success, failure) \
+ __c11_atomic_compare_exchange_strong(object, expected, desired, \
+ success, failure)
+#define atomic_compare_exchange_weak_explicit(object, expected, \
+ desired, success, failure) \
+ __c11_atomic_compare_exchange_weak(object, expected, desired, \
+ success, failure)
+#define atomic_exchange_explicit(object, desired, order) \
+ __c11_atomic_exchange(object, desired, order)
+#define atomic_fetch_add_explicit(object, operand, order) \
+ __c11_atomic_fetch_add(object, operand, order)
+#define atomic_fetch_and_explicit(object, operand, order) \
+ __c11_atomic_fetch_and(object, operand, order)
+#define atomic_fetch_or_explicit(object, operand, order) \
+ __c11_atomic_fetch_or(object, operand, order)
+#define atomic_fetch_sub_explicit(object, operand, order) \
+ __c11_atomic_fetch_sub(object, operand, order)
+#define atomic_fetch_xor_explicit(object, operand, order) \
+ __c11_atomic_fetch_xor(object, operand, order)
+#define atomic_load_explicit(object, order) \
+ __c11_atomic_load(object, order)
+#define atomic_store_explicit(object, desired, order) \
+ __c11_atomic_store(object, desired, order)
+
+/*
+ * Convenience functions.
+ */
+
+#define atomic_compare_exchange_strong(object, expected, desired) \
+ atomic_compare_exchange_strong_explicit(object, expected, \
+ desired, memory_order_seq_cst, memory_order_seq_cst)
+#define atomic_compare_exchange_weak(object, expected, desired) \
+ atomic_compare_exchange_weak_explicit(object, expected, \
+ desired, memory_order_seq_cst, memory_order_seq_cst)
+#define atomic_exchange(object, desired) \
+ atomic_exchange_explicit(object, desired, memory_order_seq_cst)
+#define atomic_fetch_add(object, operand) \
+ atomic_fetch_add_explicit(object, operand, memory_order_seq_cst)
+#define atomic_fetch_and(object, operand) \
+ atomic_fetch_and_explicit(object, operand, memory_order_seq_cst)
+#define atomic_fetch_or(object, operand) \
+ atomic_fetch_or_explicit(object, operand, memory_order_seq_cst)
+#define atomic_fetch_sub(object, operand) \
+ atomic_fetch_sub_explicit(object, operand, memory_order_seq_cst)
+#define atomic_fetch_xor(object, operand) \
+ atomic_fetch_xor_explicit(object, operand, memory_order_seq_cst)
+#define atomic_load(object) \
+ atomic_load_explicit(object, memory_order_seq_cst)
+#define atomic_store(object, desired) \
+ atomic_store_explicit(object, desired, memory_order_seq_cst)
+
+/*
+ * 7.17.8 Atomic flag type and operations.
+ *
+ * XXX: Assume atomic_bool can be used as an atomic_flag. Is there some
+ * kind of compiler built-in type we could use?
+ */
+
+typedef struct {
+ atomic_bool __flag;
+} atomic_flag;
+
+#define ATOMIC_FLAG_INIT { ATOMIC_VAR_INIT(false) }
+
+static __inline bool atomic_flag_test_and_set_explicit(volatile atomic_flag *__object, memory_order __order) {
+ return (atomic_exchange_explicit(&__object->__flag, 1, __order));
+}
+
+static __inline void atomic_flag_clear_explicit(volatile atomic_flag *__object, memory_order __order) {
+ atomic_store_explicit(&__object->__flag, 0, __order);
+}
+
+static __inline bool atomic_flag_test_and_set(volatile atomic_flag *__object) {
+ return (atomic_flag_test_and_set_explicit(__object, memory_order_seq_cst));
+}
+
+static __inline void atomic_flag_clear(volatile atomic_flag *__object) {
+ atomic_flag_clear_explicit(__object, memory_order_seq_cst);
+}
diff --git a/libc/include/bits/timespec.h b/libc/include/bits/timespec.h
index 0497cfe1f..daad03f52 100644
--- a/libc/include/bits/timespec.h
+++ b/libc/include/bits/timespec.h
@@ -46,7 +46,7 @@
struct timespec {
/** Number of seconds. */
time_t tv_sec;
- /** Number of nanoseconds. Must be less than 1,000,000. */
+ /** Number of nanoseconds. Must be less than 1,000,000,000. */
long tv_nsec;
};
#endif
diff --git a/libc/include/pthread.h b/libc/include/pthread.h
index 724e5b71d..31509b49f 100644
--- a/libc/include/pthread.h
+++ b/libc/include/pthread.h
@@ -121,6 +121,8 @@ int pthread_condattr_setclock(pthread_condattr_t* __attr, clockid_t __clock) __I
int pthread_condattr_setpshared(pthread_condattr_t* __attr, int __shared);
int pthread_cond_broadcast(pthread_cond_t* __cond);
+int pthread_cond_clockwait(pthread_cond_t* __cond, pthread_mutex_t* __mutex, clockid_t __clock,
+ const struct timespec* __timeout) __INTRODUCED_IN(30);
int pthread_cond_destroy(pthread_cond_t* __cond);
int pthread_cond_init(pthread_cond_t* __cond, const pthread_condattr_t* __attr);
int pthread_cond_signal(pthread_cond_t* __cond);
@@ -130,8 +132,10 @@ int pthread_cond_timedwait(pthread_cond_t* __cond, pthread_mutex_t* __mutex, con
* typically inappropriate, since that clock can change dramatically, causing the timeout to
* either expire earlier or much later than intended.
* Condition variables have an initialization option to use CLOCK_MONOTONIC, and in addition,
- * Android provides this API to use CLOCK_MONOTONIC on a condition variable for this single wait
- * no matter how it was initialized.
+ * Android provides pthread_cond_timedwait_monotonic_np to use CLOCK_MONOTONIC on a condition
+ * variable for this single wait no matter how it was initialized.
+ * Note that pthread_cond_clockwait() allows specifying an arbitrary clock and has superseded this
+ * function.
*/
int pthread_cond_timedwait_monotonic_np(pthread_cond_t* __cond, pthread_mutex_t* __mutex,
const struct timespec* __timeout) __INTRODUCED_IN_64(28);
@@ -181,6 +185,8 @@ int pthread_mutexattr_setpshared(pthread_mutexattr_t* __attr, int __shared);
int pthread_mutexattr_settype(pthread_mutexattr_t* __attr, int __type);
int pthread_mutexattr_setprotocol(pthread_mutexattr_t* __attr, int __protocol) __INTRODUCED_IN(28);
+int pthread_mutex_clocklock(pthread_mutex_t* __mutex, clockid_t __clock,
+ const struct timespec* __abstime) __INTRODUCED_IN(30);
int pthread_mutex_destroy(pthread_mutex_t* __mutex);
int pthread_mutex_init(pthread_mutex_t* __mutex, const pthread_mutexattr_t* __attr);
int pthread_mutex_lock(pthread_mutex_t* __mutex);
@@ -188,11 +194,13 @@ int pthread_mutex_timedlock(pthread_mutex_t* __mutex, const struct timespec* __t
__INTRODUCED_IN(21);
/*
- * POSIX only supports using pthread_mutex_timedlock() with CLOCK_REALTIME, however that is
- * typically inappropriate, since that clock can change dramatically, causing the timeout to
+ * POSIX historically only supported using pthread_mutex_timedlock() with CLOCK_REALTIME, however
+ * that is typically inappropriate, since that clock can change dramatically, causing the timeout to
* either expire earlier or much later than intended.
* This function is added to use a timespec based on CLOCK_MONOTONIC that does not suffer
* from this issue.
+ * Note that pthread_mutex_clocklock() allows specifying an arbitrary clock and has superseded this
+ * function.
*/
int pthread_mutex_timedlock_monotonic_np(pthread_mutex_t* __mutex, const struct timespec* __timeout)
__INTRODUCED_IN(28);
@@ -226,6 +234,10 @@ int pthread_rwlockattr_getkind_np(const pthread_rwlockattr_t* __attr, int* __kin
__INTRODUCED_IN(23);
int pthread_rwlockattr_setkind_np(pthread_rwlockattr_t* __attr, int __kind) __INTRODUCED_IN(23);
+int pthread_rwlock_clockrdlock(pthread_rwlock_t* __rwlock, clockid_t __clock,
+ const struct timespec* __timeout) __INTRODUCED_IN(30);
+int pthread_rwlock_clockwrlock(pthread_rwlock_t* __rwlock, clockid_t __clock,
+ const struct timespec* __timeout) __INTRODUCED_IN(30);
int pthread_rwlock_destroy(pthread_rwlock_t* __rwlock);
int pthread_rwlock_init(pthread_rwlock_t* __rwlock, const pthread_rwlockattr_t* __attr);
int pthread_rwlock_rdlock(pthread_rwlock_t* __rwlock);
diff --git a/libc/include/semaphore.h b/libc/include/semaphore.h
index 01d685b4b..5d66f7ec0 100644
--- a/libc/include/semaphore.h
+++ b/libc/include/semaphore.h
@@ -30,6 +30,7 @@
#define _SEMAPHORE_H
#include <sys/cdefs.h>
+#include <sys/types.h>
__BEGIN_DECLS
@@ -44,16 +45,19 @@ typedef struct {
#define SEM_FAILED __BIONIC_CAST(reinterpret_cast, sem_t*, 0)
+int sem_clockwait(sem_t* __sem, clockid_t __clock, const struct timespec* __ts) __INTRODUCED_IN(30);
int sem_destroy(sem_t* __sem);
int sem_getvalue(sem_t* __sem, int* __value);
int sem_init(sem_t* __sem, int __shared, unsigned int __value);
int sem_post(sem_t* __sem);
int sem_timedwait(sem_t* __sem, const struct timespec* __ts);
/*
- * POSIX only supports using sem_timedwait() with CLOCK_REALTIME, however that is typically
- * inappropriate, since that clock can change dramatically, causing the timeout to either
+ * POSIX historically only supported using sem_timedwait() with CLOCK_REALTIME, however that is
+ * typically inappropriate, since that clock can change dramatically, causing the timeout to either
* expire earlier or much later than intended. This function is added to use a timespec based
* on CLOCK_MONOTONIC that does not suffer from this issue.
+ * Note that sem_clockwait() allows specifying an arbitrary clock and has superseded this
+ * function.
*/
int sem_timedwait_monotonic_np(sem_t* __sem, const struct timespec* __ts) __INTRODUCED_IN(28);
int sem_trywait(sem_t* __sem);
diff --git a/libc/include/stdatomic.h b/libc/include/stdatomic.h
index 3c613346d..b7dac4a44 100644
--- a/libc/include/stdatomic.h
+++ b/libc/include/stdatomic.h
@@ -32,7 +32,7 @@
#include <sys/cdefs.h>
-#if defined(__cplusplus) && __cplusplus >= 201103L && defined(_USING_LIBCXX)
+#if defined(__cplusplus) && __cplusplus >= 201103L && __has_include(<atomic>)
# if __has_feature(cxx_atomic)
# define _STDATOMIC_HAVE_ATOMIC
# endif
@@ -127,260 +127,8 @@ using std::atomic_uintmax_t;
#else /* <atomic> unavailable, possibly because this is C, not C++ */
-#include <sys/types.h>
-#include <stdbool.h>
-
-/*
- * C: Do it ourselves.
- * Note that the runtime representation defined here should be compatible
- * with the C++ one, i.e. an _Atomic(T) needs to contain the same
- * bits as a T.
- */
-
-#include <stddef.h> /* For ptrdiff_t. */
-#include <stdint.h> /* TODO: don't drag in all the macros, just the types. */
-// Include uchar.h only when available. Bionic's stdatomic.h is also used for
-// the host (via a copy in prebuilts/clang) and uchar.h is not available in the
-// glibc used for the host.
-#if defined(__BIONIC__)
-# include <uchar.h> /* For char16_t and char32_t. */
-#endif
-
-/*
- * 7.17.1 Atomic lock-free macros.
- */
-
-#ifdef __GCC_ATOMIC_BOOL_LOCK_FREE
-#define ATOMIC_BOOL_LOCK_FREE __GCC_ATOMIC_BOOL_LOCK_FREE
-#endif
-#ifdef __GCC_ATOMIC_CHAR_LOCK_FREE
-#define ATOMIC_CHAR_LOCK_FREE __GCC_ATOMIC_CHAR_LOCK_FREE
-#endif
-#ifdef __GCC_ATOMIC_CHAR16_T_LOCK_FREE
-#define ATOMIC_CHAR16_T_LOCK_FREE __GCC_ATOMIC_CHAR16_T_LOCK_FREE
-#endif
-#ifdef __GCC_ATOMIC_CHAR32_T_LOCK_FREE
-#define ATOMIC_CHAR32_T_LOCK_FREE __GCC_ATOMIC_CHAR32_T_LOCK_FREE
-#endif
-#ifdef __GCC_ATOMIC_WCHAR_T_LOCK_FREE
-#define ATOMIC_WCHAR_T_LOCK_FREE __GCC_ATOMIC_WCHAR_T_LOCK_FREE
-#endif
-#ifdef __GCC_ATOMIC_SHORT_LOCK_FREE
-#define ATOMIC_SHORT_LOCK_FREE __GCC_ATOMIC_SHORT_LOCK_FREE
-#endif
-#ifdef __GCC_ATOMIC_INT_LOCK_FREE
-#define ATOMIC_INT_LOCK_FREE __GCC_ATOMIC_INT_LOCK_FREE
-#endif
-#ifdef __GCC_ATOMIC_LONG_LOCK_FREE
-#define ATOMIC_LONG_LOCK_FREE __GCC_ATOMIC_LONG_LOCK_FREE
-#endif
-#ifdef __GCC_ATOMIC_LLONG_LOCK_FREE
-#define ATOMIC_LLONG_LOCK_FREE __GCC_ATOMIC_LLONG_LOCK_FREE
-#endif
-#ifdef __GCC_ATOMIC_POINTER_LOCK_FREE
-#define ATOMIC_POINTER_LOCK_FREE __GCC_ATOMIC_POINTER_LOCK_FREE
-#endif
-
-/*
- * 7.17.2 Initialization.
- */
-
-#define ATOMIC_VAR_INIT(value) (value)
-#define atomic_init(obj, value) __c11_atomic_init(obj, value)
-
-/*
- * Clang and recent GCC both provide predefined macros for the memory
- * orderings. If we are using a compiler that doesn't define them, use the
- * clang values - these will be ignored in the fallback path.
- */
-
-#ifndef __ATOMIC_RELAXED
-#define __ATOMIC_RELAXED 0
-#endif
-#ifndef __ATOMIC_CONSUME
-#define __ATOMIC_CONSUME 1
-#endif
-#ifndef __ATOMIC_ACQUIRE
-#define __ATOMIC_ACQUIRE 2
-#endif
-#ifndef __ATOMIC_RELEASE
-#define __ATOMIC_RELEASE 3
-#endif
-#ifndef __ATOMIC_ACQ_REL
-#define __ATOMIC_ACQ_REL 4
-#endif
-#ifndef __ATOMIC_SEQ_CST
-#define __ATOMIC_SEQ_CST 5
-#endif
-
-/*
- * 7.17.3 Order and consistency.
- *
- * The memory_order_* constants that denote the barrier behaviour of the
- * atomic operations.
- * The enum values must be identical to those used by the
- * C++ <atomic> header.
- */
-
-typedef enum {
- memory_order_relaxed = __ATOMIC_RELAXED,
- memory_order_consume = __ATOMIC_CONSUME,
- memory_order_acquire = __ATOMIC_ACQUIRE,
- memory_order_release = __ATOMIC_RELEASE,
- memory_order_acq_rel = __ATOMIC_ACQ_REL,
- memory_order_seq_cst = __ATOMIC_SEQ_CST
-} memory_order;
-
-/*
- * 7.17.4 Fences.
- */
-
-static __inline void atomic_thread_fence(memory_order __order __attribute__((unused))) {
- __c11_atomic_thread_fence(__order);
-}
-
-static __inline void atomic_signal_fence(memory_order __order __attribute__((unused))) {
- __c11_atomic_signal_fence(__order);
-}
-
-/*
- * 7.17.5 Lock-free property.
- */
-
-#define atomic_is_lock_free(obj) __c11_atomic_is_lock_free(sizeof(*(obj)))
-
-/*
- * 7.17.6 Atomic integer types.
- */
-
-typedef _Atomic(bool) atomic_bool;
-typedef _Atomic(char) atomic_char;
-typedef _Atomic(signed char) atomic_schar;
-typedef _Atomic(unsigned char) atomic_uchar;
-typedef _Atomic(short) atomic_short;
-typedef _Atomic(unsigned short) atomic_ushort;
-typedef _Atomic(int) atomic_int;
-typedef _Atomic(unsigned int) atomic_uint;
-typedef _Atomic(long) atomic_long;
-typedef _Atomic(unsigned long) atomic_ulong;
-typedef _Atomic(long long) atomic_llong;
-typedef _Atomic(unsigned long long) atomic_ullong;
-#if defined(__BIONIC__) || (defined(__cplusplus) && __cplusplus >= 201103L)
- typedef _Atomic(char16_t) atomic_char16_t;
- typedef _Atomic(char32_t) atomic_char32_t;
-#endif
-typedef _Atomic(wchar_t) atomic_wchar_t;
-typedef _Atomic(int_least8_t) atomic_int_least8_t;
-typedef _Atomic(uint_least8_t) atomic_uint_least8_t;
-typedef _Atomic(int_least16_t) atomic_int_least16_t;
-typedef _Atomic(uint_least16_t) atomic_uint_least16_t;
-typedef _Atomic(int_least32_t) atomic_int_least32_t;
-typedef _Atomic(uint_least32_t) atomic_uint_least32_t;
-typedef _Atomic(int_least64_t) atomic_int_least64_t;
-typedef _Atomic(uint_least64_t) atomic_uint_least64_t;
-typedef _Atomic(int_fast8_t) atomic_int_fast8_t;
-typedef _Atomic(uint_fast8_t) atomic_uint_fast8_t;
-typedef _Atomic(int_fast16_t) atomic_int_fast16_t;
-typedef _Atomic(uint_fast16_t) atomic_uint_fast16_t;
-typedef _Atomic(int_fast32_t) atomic_int_fast32_t;
-typedef _Atomic(uint_fast32_t) atomic_uint_fast32_t;
-typedef _Atomic(int_fast64_t) atomic_int_fast64_t;
-typedef _Atomic(uint_fast64_t) atomic_uint_fast64_t;
-typedef _Atomic(intptr_t) atomic_intptr_t;
-typedef _Atomic(uintptr_t) atomic_uintptr_t;
-typedef _Atomic(size_t) atomic_size_t;
-typedef _Atomic(ptrdiff_t) atomic_ptrdiff_t;
-typedef _Atomic(intmax_t) atomic_intmax_t;
-typedef _Atomic(uintmax_t) atomic_uintmax_t;
-
-/*
- * 7.17.7 Operations on atomic types.
- */
-
-/*
- * Compiler-specific operations.
- */
-
-#define atomic_compare_exchange_strong_explicit(object, expected, \
- desired, success, failure) \
- __c11_atomic_compare_exchange_strong(object, expected, desired, \
- success, failure)
-#define atomic_compare_exchange_weak_explicit(object, expected, \
- desired, success, failure) \
- __c11_atomic_compare_exchange_weak(object, expected, desired, \
- success, failure)
-#define atomic_exchange_explicit(object, desired, order) \
- __c11_atomic_exchange(object, desired, order)
-#define atomic_fetch_add_explicit(object, operand, order) \
- __c11_atomic_fetch_add(object, operand, order)
-#define atomic_fetch_and_explicit(object, operand, order) \
- __c11_atomic_fetch_and(object, operand, order)
-#define atomic_fetch_or_explicit(object, operand, order) \
- __c11_atomic_fetch_or(object, operand, order)
-#define atomic_fetch_sub_explicit(object, operand, order) \
- __c11_atomic_fetch_sub(object, operand, order)
-#define atomic_fetch_xor_explicit(object, operand, order) \
- __c11_atomic_fetch_xor(object, operand, order)
-#define atomic_load_explicit(object, order) \
- __c11_atomic_load(object, order)
-#define atomic_store_explicit(object, desired, order) \
- __c11_atomic_store(object, desired, order)
-
-/*
- * Convenience functions.
- */
-
-#define atomic_compare_exchange_strong(object, expected, desired) \
- atomic_compare_exchange_strong_explicit(object, expected, \
- desired, memory_order_seq_cst, memory_order_seq_cst)
-#define atomic_compare_exchange_weak(object, expected, desired) \
- atomic_compare_exchange_weak_explicit(object, expected, \
- desired, memory_order_seq_cst, memory_order_seq_cst)
-#define atomic_exchange(object, desired) \
- atomic_exchange_explicit(object, desired, memory_order_seq_cst)
-#define atomic_fetch_add(object, operand) \
- atomic_fetch_add_explicit(object, operand, memory_order_seq_cst)
-#define atomic_fetch_and(object, operand) \
- atomic_fetch_and_explicit(object, operand, memory_order_seq_cst)
-#define atomic_fetch_or(object, operand) \
- atomic_fetch_or_explicit(object, operand, memory_order_seq_cst)
-#define atomic_fetch_sub(object, operand) \
- atomic_fetch_sub_explicit(object, operand, memory_order_seq_cst)
-#define atomic_fetch_xor(object, operand) \
- atomic_fetch_xor_explicit(object, operand, memory_order_seq_cst)
-#define atomic_load(object) \
- atomic_load_explicit(object, memory_order_seq_cst)
-#define atomic_store(object, desired) \
- atomic_store_explicit(object, desired, memory_order_seq_cst)
-
-/*
- * 7.17.8 Atomic flag type and operations.
- *
- * XXX: Assume atomic_bool can be used as an atomic_flag. Is there some
- * kind of compiler built-in type we could use?
- */
-
-typedef struct {
- atomic_bool __flag;
-} atomic_flag;
-
-#define ATOMIC_FLAG_INIT { ATOMIC_VAR_INIT(false) }
-
-static __inline bool atomic_flag_test_and_set_explicit(volatile atomic_flag *__object, memory_order __order) {
- return (atomic_exchange_explicit(&__object->__flag, 1, __order));
-}
-
-static __inline void atomic_flag_clear_explicit(volatile atomic_flag *__object, memory_order __order) {
- atomic_store_explicit(&__object->__flag, 0, __order);
-}
-
-static __inline bool atomic_flag_test_and_set(volatile atomic_flag *__object) {
- return (atomic_flag_test_and_set_explicit(__object, memory_order_seq_cst));
-}
-
-static __inline void atomic_flag_clear(volatile atomic_flag *__object) {
- atomic_flag_clear_explicit(__object, memory_order_seq_cst);
-}
+/* Actual implementation is in bits/stdatomic.h since our test code is C++. */
+#include <bits/stdatomic.h>
#endif /* <atomic> unavailable */
diff --git a/libc/include/stdio.h b/libc/include/stdio.h
index 8bd690fec..6632c0170 100644
--- a/libc/include/stdio.h
+++ b/libc/include/stdio.h
@@ -165,9 +165,53 @@ char* tmpnam(char* __s)
char* tempnam(const char* __dir, const char* __prefix)
__warnattr("tempnam is unsafe, use mkstemp or tmpfile instead");
+/**
+ * [rename(2)](http://man7.org/linux/man-pages/man2/rename.2.html) changes
+ * the name or location of a file.
+ *
+ * Returns 0 on success, and returns -1 and sets `errno` on failure.
+ */
int rename(const char* __old_path, const char* __new_path);
+
+/**
+ * [renameat(2)](http://man7.org/linux/man-pages/man2/renameat.2.html) changes
+ * the name or location of a file, interpreting relative paths using an fd.
+ *
+ * Returns 0 on success, and returns -1 and sets `errno` on failure.
+ */
int renameat(int __old_dir_fd, const char* __old_path, int __new_dir_fd, const char* __new_path);
+#if defined(__USE_GNU)
+
+/**
+ * Flag for [renameat2(2)](http://man7.org/linux/man-pages/man2/renameat2.2.html)
+ * to fail if the new path already exists.
+ */
+#define RENAME_NOREPLACE (1<<0)
+
+/**
+ * Flag for [renameat2(2)](http://man7.org/linux/man-pages/man2/renameat2.2.html)
+ * to atomically exchange the two paths.
+ */
+#define RENAME_EXCHANGE (1<<1)
+
+/**
+ * Flag for [renameat2(2)](http://man7.org/linux/man-pages/man2/renameat2.2.html)
+ * to create a union/overlay filesystem object.
+ */
+#define RENAME_WHITEOUT (1<<2)
+
+/**
+ * [renameat2(2)](http://man7.org/linux/man-pages/man2/renameat2.2.html) changes
+ * the name or location of a file, interpreting relative paths using an fd,
+ * with optional `RENAME_` flags.
+ *
+ * Returns 0 on success, and returns -1 and sets `errno` on failure.
+ */
+int renameat2(int __old_dir_fd, const char* __old_path, int __new_dir_fd, const char* __new_path, unsigned __flags) __INTRODUCED_IN(30);
+
+#endif
+
int fseek(FILE* __fp, long __offset, int __whence);
long ftell(FILE* __fp);
diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h
index d5b861983..b66e3c64e 100644
--- a/libc/include/stdlib.h
+++ b/libc/include/stdlib.h
@@ -90,7 +90,7 @@ int atoi(const char* __s) __attribute_pure__;
long atol(const char* __s) __attribute_pure__;
long long atoll(const char* __s) __attribute_pure__;
-char* realpath(const char* __path, char* __resolved);
+__wur char* realpath(const char* __path, char* __resolved);
int system(const char* __command);
void* bsearch(const void* __key, const void* __base, size_t __nmemb, size_t __size, int (*__comparator)(const void* __lhs, const void* __rhs));
diff --git a/libc/include/strings.h b/libc/include/strings.h
index ccdac044c..a054aed55 100644
--- a/libc/include/strings.h
+++ b/libc/include/strings.h
@@ -51,17 +51,15 @@
__BEGIN_DECLS
-#if defined(__BIONIC_FORTIFY)
/** Deprecated. Use memmove() instead. */
-#define bcopy(b1, b2, len) (void)(__builtin___memmove_chk((b2), (b1), (len), __bos0(b2)))
-/** Deprecated. Use memset() instead. */
-#define bzero(b, len) (void)(__builtin___memset_chk((b), '\0', (len), __bos0(b)))
-#else
-/** Deprecated. Use memmove() instead. */
-#define bcopy(b1, b2, len) (void)(__builtin_memmove((b2), (b1), (len)))
+static __inline__ __always_inline void bcopy(const void* b1, void* b2, size_t len) {
+ __builtin_memmove(b2, b1, len);
+}
+
/** Deprecated. Use memset() instead. */
-#define bzero(b, len) (void)(__builtin_memset((b), '\0', (len)))
-#endif
+static __inline__ __always_inline void bzero(void* b, size_t len) {
+ __builtin_memset(b, 0, len);
+}
#if !defined(__i386__) || __ANDROID_API__ >= __ANDROID_API_J_MR2__
/**
@@ -72,6 +70,10 @@ __BEGIN_DECLS
int ffs(int __i) __INTRODUCED_IN_X86(18);
#endif
+#if defined(__BIONIC_INCLUDE_FORTIFY_HEADERS)
+#include <bits/fortify/strings.h>
+#endif
+
__END_DECLS
#include <android/legacy_strings_inlines.h>
diff --git a/libc/include/sys/cdefs.h b/libc/include/sys/cdefs.h
index dceb1165c..689b65031 100644
--- a/libc/include/sys/cdefs.h
+++ b/libc/include/sys/cdefs.h
@@ -361,3 +361,6 @@ int __size_mul_overflow(__SIZE_TYPE__ a, __SIZE_TYPE__ b, __SIZE_TYPE__ *result)
#include <android/versioning.h>
#include <android/api-level.h>
+#if __has_include(<android/ndk-version.h>)
+#include <android/ndk-version.h>
+#endif
diff --git a/libc/include/sys/mman.h b/libc/include/sys/mman.h
index 89d6d07c3..3b83229d7 100644
--- a/libc/include/sys/mman.h
+++ b/libc/include/sys/mman.h
@@ -26,34 +26,27 @@
* SUCH DAMAGE.
*/
-#ifndef _SYS_MMAN_H_
-#define _SYS_MMAN_H_
+#pragma once
#include <sys/cdefs.h>
#include <sys/types.h>
+#include <linux/memfd.h>
#include <linux/mman.h>
__BEGIN_DECLS
-#ifndef MAP_ANON
-#define MAP_ANON MAP_ANONYMOUS
-#endif
+/** Alternative spelling of the `MAP_ANONYMOUS` flag for mmap(). */
+#define MAP_ANON MAP_ANONYMOUS
+/** Return value for mmap(). */
#define MAP_FAILED __BIONIC_CAST(reinterpret_cast, void*, -1)
-#define MREMAP_MAYMOVE 1
-#define MREMAP_FIXED 2
-
-/*
- * See https://android.googlesource.com/platform/bionic/+/master/docs/32-bit-abi.md
- *
- * mmap64 wasn't really around until L, but we added an inline for it since it
- * allows a lot more code to compile with _FILE_OFFSET_BITS=64.
+/**
+ * [mmap(2)](http://man7.org/linux/man-pages/man2/mmap.2.html)
+ * creates a memory mapping for the given range.
*
- * GCC removes the static inline unless it is explicitly used. We can get around
- * this with __attribute__((used)), but that needlessly adds a definition of
- * mmap64 to every translation unit that includes this header. Instead, just
- * preserve the old behavior for GCC and emit a useful diagnostic.
+ * Returns the address of the mapping on success,
+ * and returns `MAP_FAILED` and sets `errno` on failure.
*/
#if defined(__USE_FILE_OFFSET64)
void* mmap(void* __addr, size_t __size, int __prot, int __flags, int __fd, off_t __offset) __RENAME(mmap64);
@@ -62,25 +55,126 @@ void* mmap(void* __addr, size_t __size, int __prot, int __flags, int __fd, off_t
#endif
#if __ANDROID_API__ >= __ANDROID_API_L__
+/**
+ * mmap64() is a variant of mmap() that takes a 64-bit offset even on LP32.
+ *
+ * See https://android.googlesource.com/platform/bionic/+/master/docs/32-bit-abi.md
+ *
+ * mmap64 wasn't really around until L, but we added an inline for it since it
+ * allows a lot more code to compile with _FILE_OFFSET_BITS=64.
+ */
void* mmap64(void* __addr, size_t __size, int __prot, int __flags, int __fd, off64_t __offset) __INTRODUCED_IN(21);
#endif
+/**
+ * [munmap(2)](http://man7.org/linux/man-pages/man2/munmap.2.html)
+ * deletes a memory mapping for the given range.
+ *
+ * Returns 0 on success, and returns -1 and sets `errno` on failure.
+ */
int munmap(void* __addr, size_t __size);
+
+/**
+ * [msync(2)](http://man7.org/linux/man-pages/man2/msync.2.html)
+ * flushes changes to a memory-mapped file to disk.
+ *
+ * Returns 0 on success, and returns -1 and sets `errno` on failure.
+ */
int msync(void* __addr, size_t __size, int __flags);
+
+/**
+ * [mprotect(2)](http://man7.org/linux/man-pages/man2/mprotect.2.html)
+ * sets the protection on a memory region.
+ *
+ * Returns 0 on success, and returns -1 and sets `errno` on failure.
+ */
int mprotect(void* __addr, size_t __size, int __prot);
+
+/** Flag for mremap(). */
+#define MREMAP_MAYMOVE 1
+
+/** Flag for mremap(). */
+#define MREMAP_FIXED 2
+
+/**
+ * [mremap(2)](http://man7.org/linux/man-pages/man2/mremap.2.html)
+ * expands or shrinks an existing memory mapping.
+ *
+ * Returns the address of the mapping on success,
+ * and returns `MAP_FAILED` and sets `errno` on failure.
+ */
void* mremap(void* __old_addr, size_t __old_size, size_t __new_size, int __flags, ...);
+/**
+ * [mlockall(2)](http://man7.org/linux/man-pages/man2/mlockall.2.html)
+ * locks pages (preventing swapping).
+ *
+ * Returns 0 on success, and returns -1 and sets `errno` on failure.
+ */
int mlockall(int __flags) __INTRODUCED_IN(17);
+
+/**
+ * [munlockall(2)](http://man7.org/linux/man-pages/man2/munlockall.2.html)
+ * unlocks pages (allowing swapping).
+ *
+ * Returns 0 on success, and returns -1 and sets `errno` on failure.
+ */
int munlockall(void) __INTRODUCED_IN(17);
+/**
+ * [mlock(2)](http://man7.org/linux/man-pages/man2/mlock.2.html)
+ * locks pages (preventing swapping).
+ *
+ * Returns 0 on success, and returns -1 and sets `errno` on failure.
+ */
int mlock(const void* __addr, size_t __size);
+
+/**
+ * [mlock2(2)](http://man7.org/linux/man-pages/man2/mlock.2.html)
+ * locks pages (preventing swapping), with optional flags.
+ *
+ * Returns 0 on success, and returns -1 and sets `errno` on failure.
+ */
+int mlock2(const void* __addr, size_t __size, int __flags) __INTRODUCED_IN(30);
+
+/**
+ * [munlock(2)](http://man7.org/linux/man-pages/man2/munlock.2.html)
+ * unlocks pages (allowing swapping).
+ *
+ * Returns 0 on success, and returns -1 and sets `errno` on failure.
+ */
int munlock(const void* __addr, size_t __size);
+/**
+ * [mincore(2)](http://man7.org/linux/man-pages/man2/mincore.2.html)
+ * tests whether pages are resident in memory.
+ *
+ * Returns 0 on success, and returns -1 and sets `errno` on failure.
+ */
int mincore(void* __addr, size_t __size, unsigned char* __vector);
+/**
+ * [madvise(2)](http://man7.org/linux/man-pages/man2/madvise.2.html)
+ * gives the kernel advice about future usage patterns.
+ *
+ * Returns 0 on success, and returns -1 and sets `errno` on failure.
+ */
int madvise(void* __addr, size_t __size, int __advice);
+#if defined(__USE_GNU)
+
+/**
+ * [memfd_create(2)](http://man7.org/linux/man-pages/man2/memfd_create.2.html)
+ * creates an anonymous file.
+ *
+ * Returns an fd on success, and returns -1 and sets `errno` on failure.
+ */
+int memfd_create(const char* __name, unsigned __flags) __INTRODUCED_IN(30);
+
+#endif
+
#if __ANDROID_API__ >= __ANDROID_API_M__
+
/*
* Some third-party code uses the existence of POSIX_MADV_NORMAL to detect the
* availability of posix_madvise. This is not correct, since having up-to-date
@@ -89,16 +183,30 @@ int madvise(void* __addr, size_t __size, int __advice);
*
* https://github.com/android-ndk/ndk/issues/395
*/
+
+/** Flag for posix_madvise(). */
#define POSIX_MADV_NORMAL MADV_NORMAL
+/** Flag for posix_madvise(). */
#define POSIX_MADV_RANDOM MADV_RANDOM
+/** Flag for posix_madvise(). */
#define POSIX_MADV_SEQUENTIAL MADV_SEQUENTIAL
+/** Flag for posix_madvise(). */
#define POSIX_MADV_WILLNEED MADV_WILLNEED
+/** Flag for posix_madvise(). */
#define POSIX_MADV_DONTNEED MADV_DONTNEED
+
#endif
+
+/**
+ * [posix_madvise(3)](http://man7.org/linux/man-pages/man3/posix_madvise.3.html)
+ * gives the kernel advice about future usage patterns.
+ *
+ * Returns 0 on success, and returns a positive error number on failure.
+ *
+ * See also madvise() which has been available much longer.
+ */
int posix_madvise(void* __addr, size_t __size, int __advice) __INTRODUCED_IN(23);
__END_DECLS
#include <android/legacy_sys_mman_inlines.h>
-
-#endif
diff --git a/libc/kernel/tools/update_all.py b/libc/kernel/tools/update_all.py
index 9d5b02dee..cef24dd4c 100755
--- a/libc/kernel/tools/update_all.py
+++ b/libc/kernel/tools/update_all.py
@@ -110,7 +110,9 @@ def GenerateGlibcSyscallsHeader(updater):
content += ' #define SYS_%s %s\n' % (syscall, nr_name)
content += '#endif\n'
- updater.editFile('%s/include/bits/glibc-syscalls.h' % libc_root, content)
+ syscall_file = os.path.join(libc_root, 'include/bits/glibc-syscalls.h')
+ updater.readFile(syscall_file)
+ updater.editFile(syscall_file, content)
try:
diff --git a/libc/kernel/uapi/asm-arm/asm/unistd-common.h b/libc/kernel/uapi/asm-arm/asm/unistd-common.h
index e7abfeb33..d9e73dc18 100644
--- a/libc/kernel/uapi/asm-arm/asm/unistd-common.h
+++ b/libc/kernel/uapi/asm-arm/asm/unistd-common.h
@@ -399,4 +399,10 @@
#define __NR_io_uring_setup (__NR_SYSCALL_BASE + 425)
#define __NR_io_uring_enter (__NR_SYSCALL_BASE + 426)
#define __NR_io_uring_register (__NR_SYSCALL_BASE + 427)
+#define __NR_open_tree (__NR_SYSCALL_BASE + 428)
+#define __NR_move_mount (__NR_SYSCALL_BASE + 429)
+#define __NR_fsopen (__NR_SYSCALL_BASE + 430)
+#define __NR_fsconfig (__NR_SYSCALL_BASE + 431)
+#define __NR_fsmount (__NR_SYSCALL_BASE + 432)
+#define __NR_fspick (__NR_SYSCALL_BASE + 433)
#endif
diff --git a/libc/kernel/uapi/asm-arm64/asm/hwcap.h b/libc/kernel/uapi/asm-arm64/asm/hwcap.h
index 44853a486..80935fc5d 100644
--- a/libc/kernel/uapi/asm-arm64/asm/hwcap.h
+++ b/libc/kernel/uapi/asm-arm64/asm/hwcap.h
@@ -50,4 +50,11 @@
#define HWCAP_SB (1 << 29)
#define HWCAP_PACA (1 << 30)
#define HWCAP_PACG (1UL << 31)
+#define HWCAP2_DCPODP (1 << 0)
+#define HWCAP2_SVE2 (1 << 1)
+#define HWCAP2_SVEAES (1 << 2)
+#define HWCAP2_SVEPMULL (1 << 3)
+#define HWCAP2_SVEBITPERM (1 << 4)
+#define HWCAP2_SVESHA3 (1 << 5)
+#define HWCAP2_SVESM4 (1 << 6)
#endif
diff --git a/libc/kernel/uapi/asm-arm64/asm/kvm.h b/libc/kernel/uapi/asm-arm64/asm/kvm.h
index e79562cd2..b62d9efb3 100644
--- a/libc/kernel/uapi/asm-arm64/asm/kvm.h
+++ b/libc/kernel/uapi/asm-arm64/asm/kvm.h
@@ -29,6 +29,7 @@
#include <linux/psci.h>
#include <linux/types.h>
#include <asm/ptrace.h>
+#include <asm/sve_context.h>
#define __KVM_HAVE_GUEST_DEBUG
#define __KVM_HAVE_IRQ_LINE
#define __KVM_HAVE_READONLY_MEM
@@ -69,6 +70,9 @@ struct kvm_regs {
#define KVM_ARM_VCPU_EL1_32BIT 1
#define KVM_ARM_VCPU_PSCI_0_2 2
#define KVM_ARM_VCPU_PMU_V3 3
+#define KVM_ARM_VCPU_SVE 4
+#define KVM_ARM_VCPU_PTRAUTH_ADDRESS 5
+#define KVM_ARM_VCPU_PTRAUTH_GENERIC 6
struct kvm_vcpu_init {
__u32 target;
__u32 features[7];
@@ -137,6 +141,20 @@ struct kvm_vcpu_events {
#define KVM_REG_ARM_FW (0x0014 << KVM_REG_ARM_COPROC_SHIFT)
#define KVM_REG_ARM_FW_REG(r) (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_FW | ((r) & 0xffff))
#define KVM_REG_ARM_PSCI_VERSION KVM_REG_ARM_FW_REG(0)
+#define KVM_REG_ARM64_SVE (0x15 << KVM_REG_ARM_COPROC_SHIFT)
+#define KVM_REG_ARM64_SVE_ZREG_BASE 0
+#define KVM_REG_ARM64_SVE_PREG_BASE 0x400
+#define KVM_REG_ARM64_SVE_FFR_BASE 0x600
+#define KVM_ARM64_SVE_NUM_ZREGS __SVE_NUM_ZREGS
+#define KVM_ARM64_SVE_NUM_PREGS __SVE_NUM_PREGS
+#define KVM_ARM64_SVE_MAX_SLICES 32
+#define KVM_REG_ARM64_SVE_ZREG(n,i) (KVM_REG_ARM64 | KVM_REG_ARM64_SVE | KVM_REG_ARM64_SVE_ZREG_BASE | KVM_REG_SIZE_U2048 | (((n) & (KVM_ARM64_SVE_NUM_ZREGS - 1)) << 5) | ((i) & (KVM_ARM64_SVE_MAX_SLICES - 1)))
+#define KVM_REG_ARM64_SVE_PREG(n,i) (KVM_REG_ARM64 | KVM_REG_ARM64_SVE | KVM_REG_ARM64_SVE_PREG_BASE | KVM_REG_SIZE_U256 | (((n) & (KVM_ARM64_SVE_NUM_PREGS - 1)) << 5) | ((i) & (KVM_ARM64_SVE_MAX_SLICES - 1)))
+#define KVM_REG_ARM64_SVE_FFR(i) (KVM_REG_ARM64 | KVM_REG_ARM64_SVE | KVM_REG_ARM64_SVE_FFR_BASE | KVM_REG_SIZE_U256 | ((i) & (KVM_ARM64_SVE_MAX_SLICES - 1)))
+#define KVM_ARM64_SVE_VQ_MIN __SVE_VQ_MIN
+#define KVM_ARM64_SVE_VQ_MAX __SVE_VQ_MAX
+#define KVM_REG_ARM64_SVE_VLS (KVM_REG_ARM64 | KVM_REG_ARM64_SVE | KVM_REG_SIZE_U512 | 0xffff)
+#define KVM_ARM64_SVE_VLS_WORDS ((KVM_ARM64_SVE_VQ_MAX - KVM_ARM64_SVE_VQ_MIN) / 64 + 1)
#define KVM_DEV_ARM_VGIC_GRP_ADDR 0
#define KVM_DEV_ARM_VGIC_GRP_DIST_REGS 1
#define KVM_DEV_ARM_VGIC_GRP_CPU_REGS 2
diff --git a/libc/kernel/uapi/asm-arm64/asm/ptrace.h b/libc/kernel/uapi/asm-arm64/asm/ptrace.h
index b8c046b12..c4c574829 100644
--- a/libc/kernel/uapi/asm-arm64/asm/ptrace.h
+++ b/libc/kernel/uapi/asm-arm64/asm/ptrace.h
@@ -46,7 +46,6 @@
#define PSR_x 0x0000ff00
#define PSR_c 0x000000ff
#ifndef __ASSEMBLY__
-#include <linux/prctl.h>
struct user_pt_regs {
__u64 regs[31];
__u64 sp;
@@ -79,8 +78,8 @@ struct user_sve_header {
#define SVE_PT_REGS_MASK (1 << 0)
#define SVE_PT_REGS_FPSIMD 0
#define SVE_PT_REGS_SVE SVE_PT_REGS_MASK
-#define SVE_PT_VL_INHERIT (PR_SVE_VL_INHERIT >> 16)
-#define SVE_PT_VL_ONEXEC (PR_SVE_SET_VL_ONEXEC >> 16)
+#define SVE_PT_VL_INHERIT ((1 << 17) >> 16)
+#define SVE_PT_VL_ONEXEC ((1 << 18) >> 16)
#define SVE_PT_REGS_OFFSET ((sizeof(struct user_sve_header) + (__SVE_VQ_BYTES - 1)) / __SVE_VQ_BYTES * __SVE_VQ_BYTES)
#define SVE_PT_FPSIMD_OFFSET SVE_PT_REGS_OFFSET
#define SVE_PT_FPSIMD_SIZE(vq,flags) (sizeof(struct user_fpsimd_state))
diff --git a/libc/kernel/uapi/asm-generic/sockios.h b/libc/kernel/uapi/asm-generic/sockios.h
index 0725dcc01..afbc6ad35 100644
--- a/libc/kernel/uapi/asm-generic/sockios.h
+++ b/libc/kernel/uapi/asm-generic/sockios.h
@@ -23,6 +23,6 @@
#define FIOGETOWN 0x8903
#define SIOCGPGRP 0x8904
#define SIOCATMARK 0x8905
-#define SIOCGSTAMP 0x8906
-#define SIOCGSTAMPNS 0x8907
+#define SIOCGSTAMP_OLD 0x8906
+#define SIOCGSTAMPNS_OLD 0x8907
#endif
diff --git a/libc/kernel/uapi/asm-generic/unistd.h b/libc/kernel/uapi/asm-generic/unistd.h
index 70d9185c3..73520e16c 100644
--- a/libc/kernel/uapi/asm-generic/unistd.h
+++ b/libc/kernel/uapi/asm-generic/unistd.h
@@ -386,8 +386,14 @@
#define __NR_io_uring_setup 425
#define __NR_io_uring_enter 426
#define __NR_io_uring_register 427
+#define __NR_open_tree 428
+#define __NR_move_mount 429
+#define __NR_fsopen 430
+#define __NR_fsconfig 431
+#define __NR_fsmount 432
+#define __NR_fspick 433
#undef __NR_syscalls
-#define __NR_syscalls 428
+#define __NR_syscalls 434
#if __BITS_PER_LONG == 64 && !defined(__SYSCALL_COMPAT)
#define __NR_fcntl __NR3264_fcntl
#define __NR_statfs __NR3264_statfs
diff --git a/libc/kernel/uapi/asm-mips/asm/inst.h b/libc/kernel/uapi/asm-mips/asm/inst.h
index 090a40b00..8489575fc 100644
--- a/libc/kernel/uapi/asm-mips/asm/inst.h
+++ b/libc/kernel/uapi/asm-mips/asm/inst.h
@@ -146,15 +146,15 @@ enum spec_op {
tlt_op,
tltu_op,
teq_op,
- spec5_unused_op,
+ seleqz_op,
tne_op,
- spec6_unused_op,
+ selnez_op,
dsll_op,
- spec7_unused_op,
+ spec5_unused_op,
dsrl_op,
dsra_op,
dsll32_op,
- spec8_unused_op,
+ spec6_unused_op,
dsrl32_op,
dsra32_op
};
diff --git a/libc/kernel/uapi/asm-mips/asm/sockios.h b/libc/kernel/uapi/asm-mips/asm/sockios.h
index 02261d7fd..42404183a 100644
--- a/libc/kernel/uapi/asm-mips/asm/sockios.h
+++ b/libc/kernel/uapi/asm-mips/asm/sockios.h
@@ -24,6 +24,6 @@
#define SIOCATMARK _IOR('s', 7, int)
#define SIOCSPGRP _IOW('s', 8, pid_t)
#define SIOCGPGRP _IOR('s', 9, pid_t)
-#define SIOCGSTAMP 0x8906
-#define SIOCGSTAMPNS 0x8907
+#define SIOCGSTAMP_OLD 0x8906
+#define SIOCGSTAMPNS_OLD 0x8907
#endif
diff --git a/libc/kernel/uapi/asm-mips/asm/unistd_n32.h b/libc/kernel/uapi/asm-mips/asm/unistd_n32.h
index 8bafcf0bc..ad928ac07 100644
--- a/libc/kernel/uapi/asm-mips/asm/unistd_n32.h
+++ b/libc/kernel/uapi/asm-mips/asm/unistd_n32.h
@@ -374,4 +374,10 @@
#define __NR_io_uring_setup (__NR_Linux + 425)
#define __NR_io_uring_enter (__NR_Linux + 426)
#define __NR_io_uring_register (__NR_Linux + 427)
+#define __NR_open_tree (__NR_Linux + 428)
+#define __NR_move_mount (__NR_Linux + 429)
+#define __NR_fsopen (__NR_Linux + 430)
+#define __NR_fsconfig (__NR_Linux + 431)
+#define __NR_fsmount (__NR_Linux + 432)
+#define __NR_fspick (__NR_Linux + 433)
#endif
diff --git a/libc/kernel/uapi/asm-mips/asm/unistd_n64.h b/libc/kernel/uapi/asm-mips/asm/unistd_n64.h
index 2191c2139..0ffc069a8 100644
--- a/libc/kernel/uapi/asm-mips/asm/unistd_n64.h
+++ b/libc/kernel/uapi/asm-mips/asm/unistd_n64.h
@@ -350,4 +350,10 @@
#define __NR_io_uring_setup (__NR_Linux + 425)
#define __NR_io_uring_enter (__NR_Linux + 426)
#define __NR_io_uring_register (__NR_Linux + 427)
+#define __NR_open_tree (__NR_Linux + 428)
+#define __NR_move_mount (__NR_Linux + 429)
+#define __NR_fsopen (__NR_Linux + 430)
+#define __NR_fsconfig (__NR_Linux + 431)
+#define __NR_fsmount (__NR_Linux + 432)
+#define __NR_fspick (__NR_Linux + 433)
#endif
diff --git a/libc/kernel/uapi/asm-mips/asm/unistd_nr_n32.h b/libc/kernel/uapi/asm-mips/asm/unistd_nr_n32.h
index 3ef3a317b..af3c8502c 100644
--- a/libc/kernel/uapi/asm-mips/asm/unistd_nr_n32.h
+++ b/libc/kernel/uapi/asm-mips/asm/unistd_nr_n32.h
@@ -19,5 +19,5 @@
#ifndef _UAPI_ASM_MIPS_UNISTD_NR_N32_H
#define _UAPI_ASM_MIPS_UNISTD_NR_N32_H
#define __NR_N32_Linux 6000
-#define __NR_N32_Linux_syscalls 428
+#define __NR_N32_Linux_syscalls 434
#endif
diff --git a/libc/kernel/uapi/asm-mips/asm/unistd_nr_n64.h b/libc/kernel/uapi/asm-mips/asm/unistd_nr_n64.h
index ececf3587..c78f3e619 100644
--- a/libc/kernel/uapi/asm-mips/asm/unistd_nr_n64.h
+++ b/libc/kernel/uapi/asm-mips/asm/unistd_nr_n64.h
@@ -19,5 +19,5 @@
#ifndef _UAPI_ASM_MIPS_UNISTD_NR_N64_H
#define _UAPI_ASM_MIPS_UNISTD_NR_N64_H
#define __NR_64_Linux 5000
-#define __NR_64_Linux_syscalls 428
+#define __NR_64_Linux_syscalls 434
#endif
diff --git a/libc/kernel/uapi/asm-mips/asm/unistd_nr_o32.h b/libc/kernel/uapi/asm-mips/asm/unistd_nr_o32.h
index 6fb35396d..444710e63 100644
--- a/libc/kernel/uapi/asm-mips/asm/unistd_nr_o32.h
+++ b/libc/kernel/uapi/asm-mips/asm/unistd_nr_o32.h
@@ -19,5 +19,5 @@
#ifndef _UAPI_ASM_MIPS_UNISTD_NR_O32_H
#define _UAPI_ASM_MIPS_UNISTD_NR_O32_H
#define __NR_O32_Linux 4000
-#define __NR_O32_Linux_syscalls 428
+#define __NR_O32_Linux_syscalls 434
#endif
diff --git a/libc/kernel/uapi/asm-mips/asm/unistd_o32.h b/libc/kernel/uapi/asm-mips/asm/unistd_o32.h
index 8330a8839..5bf392b6a 100644
--- a/libc/kernel/uapi/asm-mips/asm/unistd_o32.h
+++ b/libc/kernel/uapi/asm-mips/asm/unistd_o32.h
@@ -420,4 +420,10 @@
#define __NR_io_uring_setup (__NR_Linux + 425)
#define __NR_io_uring_enter (__NR_Linux + 426)
#define __NR_io_uring_register (__NR_Linux + 427)
+#define __NR_open_tree (__NR_Linux + 428)
+#define __NR_move_mount (__NR_Linux + 429)
+#define __NR_fsopen (__NR_Linux + 430)
+#define __NR_fsconfig (__NR_Linux + 431)
+#define __NR_fsmount (__NR_Linux + 432)
+#define __NR_fspick (__NR_Linux + 433)
#endif
diff --git a/libc/kernel/uapi/asm-x86/asm/kvm.h b/libc/kernel/uapi/asm-x86/asm/kvm.h
index 10b129400..4ec3c10bd 100644
--- a/libc/kernel/uapi/asm-x86/asm/kvm.h
+++ b/libc/kernel/uapi/asm-x86/asm/kvm.h
@@ -318,14 +318,21 @@ struct kvm_sync_regs {
#define KVM_X86_QUIRK_CD_NW_CLEARED (1 << 1)
#define KVM_X86_QUIRK_LAPIC_MMIO_HOLE (1 << 2)
#define KVM_X86_QUIRK_OUT_7E_INC_RIP (1 << 3)
+#define KVM_STATE_NESTED_FORMAT_VMX 0
+#define KVM_STATE_NESTED_FORMAT_SVM 1
#define KVM_STATE_NESTED_GUEST_MODE 0x00000001
#define KVM_STATE_NESTED_RUN_PENDING 0x00000002
#define KVM_STATE_NESTED_EVMCS 0x00000004
#define KVM_STATE_NESTED_SMM_GUEST_MODE 0x00000001
#define KVM_STATE_NESTED_SMM_VMXON 0x00000002
-struct kvm_vmx_nested_state {
+#define KVM_STATE_NESTED_VMX_VMCS_SIZE 0x1000
+struct kvm_vmx_nested_state_data {
+ __u8 vmcs12[KVM_STATE_NESTED_VMX_VMCS_SIZE];
+ __u8 shadow_vmcs12[KVM_STATE_NESTED_VMX_VMCS_SIZE];
+};
+struct kvm_vmx_nested_state_hdr {
__u64 vmxon_pa;
- __u64 vmcs_pa;
+ __u64 vmcs12_pa;
struct {
__u16 flags;
} smm;
@@ -335,9 +342,11 @@ struct kvm_nested_state {
__u16 format;
__u32 size;
union {
- struct kvm_vmx_nested_state vmx;
+ struct kvm_vmx_nested_state_hdr vmx;
__u8 pad[120];
- };
- __u8 data[0];
+ } hdr;
+ union {
+ struct kvm_vmx_nested_state_data vmx[0];
+ } data;
};
#endif
diff --git a/libc/kernel/uapi/asm-x86/asm/perf_regs.h b/libc/kernel/uapi/asm-x86/asm/perf_regs.h
index 6a015ba31..984b7ea9d 100644
--- a/libc/kernel/uapi/asm-x86/asm/perf_regs.h
+++ b/libc/kernel/uapi/asm-x86/asm/perf_regs.h
@@ -45,5 +45,23 @@ enum perf_event_x86_regs {
PERF_REG_X86_R15,
PERF_REG_X86_32_MAX = PERF_REG_X86_GS + 1,
PERF_REG_X86_64_MAX = PERF_REG_X86_R15 + 1,
+ PERF_REG_X86_XMM0 = 32,
+ PERF_REG_X86_XMM1 = 34,
+ PERF_REG_X86_XMM2 = 36,
+ PERF_REG_X86_XMM3 = 38,
+ PERF_REG_X86_XMM4 = 40,
+ PERF_REG_X86_XMM5 = 42,
+ PERF_REG_X86_XMM6 = 44,
+ PERF_REG_X86_XMM7 = 46,
+ PERF_REG_X86_XMM8 = 48,
+ PERF_REG_X86_XMM9 = 50,
+ PERF_REG_X86_XMM10 = 52,
+ PERF_REG_X86_XMM11 = 54,
+ PERF_REG_X86_XMM12 = 56,
+ PERF_REG_X86_XMM13 = 58,
+ PERF_REG_X86_XMM14 = 60,
+ PERF_REG_X86_XMM15 = 62,
+ PERF_REG_X86_XMM_MAX = PERF_REG_X86_XMM15 + 2,
};
+#define PERF_REG_EXTENDED_MASK (~((1ULL << PERF_REG_X86_XMM0) - 1))
#endif
diff --git a/libc/kernel/uapi/asm-x86/asm/unistd_32.h b/libc/kernel/uapi/asm-x86/asm/unistd_32.h
index bccc6f1b9..09f2e7b25 100644
--- a/libc/kernel/uapi/asm-x86/asm/unistd_32.h
+++ b/libc/kernel/uapi/asm-x86/asm/unistd_32.h
@@ -435,4 +435,10 @@
#define __NR_io_uring_setup 425
#define __NR_io_uring_enter 426
#define __NR_io_uring_register 427
+#define __NR_open_tree 428
+#define __NR_move_mount 429
+#define __NR_fsopen 430
+#define __NR_fsconfig 431
+#define __NR_fsmount 432
+#define __NR_fspick 433
#endif
diff --git a/libc/kernel/uapi/asm-x86/asm/unistd_64.h b/libc/kernel/uapi/asm-x86/asm/unistd_64.h
index ddac7db98..36859b541 100644
--- a/libc/kernel/uapi/asm-x86/asm/unistd_64.h
+++ b/libc/kernel/uapi/asm-x86/asm/unistd_64.h
@@ -357,4 +357,10 @@
#define __NR_io_uring_setup 425
#define __NR_io_uring_enter 426
#define __NR_io_uring_register 427
+#define __NR_open_tree 428
+#define __NR_move_mount 429
+#define __NR_fsopen 430
+#define __NR_fsconfig 431
+#define __NR_fsmount 432
+#define __NR_fspick 433
#endif
diff --git a/libc/kernel/uapi/asm-x86/asm/unistd_x32.h b/libc/kernel/uapi/asm-x86/asm/unistd_x32.h
index 9c4ba12c4..d3e2d3fb1 100644
--- a/libc/kernel/uapi/asm-x86/asm/unistd_x32.h
+++ b/libc/kernel/uapi/asm-x86/asm/unistd_x32.h
@@ -310,6 +310,12 @@
#define __NR_io_uring_setup (__X32_SYSCALL_BIT + 425)
#define __NR_io_uring_enter (__X32_SYSCALL_BIT + 426)
#define __NR_io_uring_register (__X32_SYSCALL_BIT + 427)
+#define __NR_open_tree (__X32_SYSCALL_BIT + 428)
+#define __NR_move_mount (__X32_SYSCALL_BIT + 429)
+#define __NR_fsopen (__X32_SYSCALL_BIT + 430)
+#define __NR_fsconfig (__X32_SYSCALL_BIT + 431)
+#define __NR_fsmount (__X32_SYSCALL_BIT + 432)
+#define __NR_fspick (__X32_SYSCALL_BIT + 433)
#define __NR_rt_sigaction (__X32_SYSCALL_BIT + 512)
#define __NR_rt_sigreturn (__X32_SYSCALL_BIT + 513)
#define __NR_ioctl (__X32_SYSCALL_BIT + 514)
diff --git a/libc/kernel/uapi/asm-x86/asm/vmx.h b/libc/kernel/uapi/asm-x86/asm/vmx.h
index 0f7ede3b5..83365f8df 100644
--- a/libc/kernel/uapi/asm-x86/asm/vmx.h
+++ b/libc/kernel/uapi/asm-x86/asm/vmx.h
@@ -78,6 +78,5 @@
#define VMX_EXIT_REASONS { EXIT_REASON_EXCEPTION_NMI, "EXCEPTION_NMI" }, { EXIT_REASON_EXTERNAL_INTERRUPT, "EXTERNAL_INTERRUPT" }, { EXIT_REASON_TRIPLE_FAULT, "TRIPLE_FAULT" }, { EXIT_REASON_PENDING_INTERRUPT, "PENDING_INTERRUPT" }, { EXIT_REASON_NMI_WINDOW, "NMI_WINDOW" }, { EXIT_REASON_TASK_SWITCH, "TASK_SWITCH" }, { EXIT_REASON_CPUID, "CPUID" }, { EXIT_REASON_HLT, "HLT" }, { EXIT_REASON_INVD, "INVD" }, { EXIT_REASON_INVLPG, "INVLPG" }, { EXIT_REASON_RDPMC, "RDPMC" }, { EXIT_REASON_RDTSC, "RDTSC" }, { EXIT_REASON_VMCALL, "VMCALL" }, { EXIT_REASON_VMCLEAR, "VMCLEAR" }, { EXIT_REASON_VMLAUNCH, "VMLAUNCH" }, { EXIT_REASON_VMPTRLD, "VMPTRLD" }, { EXIT_REASON_VMPTRST, "VMPTRST" }, { EXIT_REASON_VMREAD, "VMREAD" }, { EXIT_REASON_VMRESUME, "VMRESUME" }, { EXIT_REASON_VMWRITE, "VMWRITE" }, { EXIT_REASON_VMOFF, "VMOFF" }, { EXIT_REASON_VMON, "VMON" }, { EXIT_REASON_CR_ACCESS, "CR_ACCESS" }, { EXIT_REASON_DR_ACCESS, "DR_ACCESS" }, { EXIT_REASON_IO_INSTRUCTION, "IO_INSTRUCTION" }, { EXIT_REASON_MSR_READ, "MSR_READ" }, { EXIT_REASON_MSR_WRITE, "MSR_WRITE" }, { EXIT_REASON_INVALID_STATE, "INVALID_STATE" }, { EXIT_REASON_MSR_LOAD_FAIL, "MSR_LOAD_FAIL" }, { EXIT_REASON_MWAIT_INSTRUCTION, "MWAIT_INSTRUCTION" }, { EXIT_REASON_MONITOR_TRAP_FLAG, "MONITOR_TRAP_FLAG" }, { EXIT_REASON_MONITOR_INSTRUCTION, "MONITOR_INSTRUCTION" }, { EXIT_REASON_PAUSE_INSTRUCTION, "PAUSE_INSTRUCTION" }, { EXIT_REASON_MCE_DURING_VMENTRY, "MCE_DURING_VMENTRY" }, { EXIT_REASON_TPR_BELOW_THRESHOLD, "TPR_BELOW_THRESHOLD" }, { EXIT_REASON_APIC_ACCESS, "APIC_ACCESS" }, { EXIT_REASON_EOI_INDUCED, "EOI_INDUCED" }, { EXIT_REASON_GDTR_IDTR, "GDTR_IDTR" }, { EXIT_REASON_LDTR_TR, "LDTR_TR" }, { EXIT_REASON_EPT_VIOLATION, "EPT_VIOLATION" }, { EXIT_REASON_EPT_MISCONFIG, "EPT_MISCONFIG" }, { EXIT_REASON_INVEPT, "INVEPT" }, { EXIT_REASON_RDTSCP, "RDTSCP" }, { EXIT_REASON_PREEMPTION_TIMER, "PREEMPTION_TIMER" }, { EXIT_REASON_INVVPID, "INVVPID" }, { EXIT_REASON_WBINVD, "WBINVD" }, { EXIT_REASON_XSETBV, "XSETBV" }, { EXIT_REASON_APIC_WRITE, "APIC_WRITE" }, { EXIT_REASON_RDRAND, "RDRAND" }, { EXIT_REASON_INVPCID, "INVPCID" }, { EXIT_REASON_VMFUNC, "VMFUNC" }, { EXIT_REASON_ENCLS, "ENCLS" }, { EXIT_REASON_RDSEED, "RDSEED" }, { EXIT_REASON_PML_FULL, "PML_FULL" }, { EXIT_REASON_XSAVES, "XSAVES" }, { EXIT_REASON_XRSTORS, "XRSTORS" }
#define VMX_ABORT_SAVE_GUEST_MSR_FAIL 1
#define VMX_ABORT_LOAD_HOST_PDPTE_FAIL 2
-#define VMX_ABORT_VMCS_CORRUPTED 3
#define VMX_ABORT_LOAD_HOST_MSR_FAIL 4
#endif
diff --git a/libc/kernel/uapi/drm/amdgpu_drm.h b/libc/kernel/uapi/drm/amdgpu_drm.h
index 53da9dd6c..193881d16 100644
--- a/libc/kernel/uapi/drm/amdgpu_drm.h
+++ b/libc/kernel/uapi/drm/amdgpu_drm.h
@@ -117,6 +117,8 @@ union drm_amdgpu_bo_list {
#define AMDGPU_CTX_QUERY2_FLAGS_RESET (1 << 0)
#define AMDGPU_CTX_QUERY2_FLAGS_VRAMLOST (1 << 1)
#define AMDGPU_CTX_QUERY2_FLAGS_GUILTY (1 << 2)
+#define AMDGPU_CTX_QUERY2_FLAGS_RAS_CE (1 << 3)
+#define AMDGPU_CTX_QUERY2_FLAGS_RAS_UE (1 << 4)
#define AMDGPU_CTX_PRIORITY_UNSET - 2048
#define AMDGPU_CTX_PRIORITY_VERY_LOW - 1023
#define AMDGPU_CTX_PRIORITY_LOW - 512
@@ -325,6 +327,8 @@ struct drm_amdgpu_gem_va {
#define AMDGPU_CHUNK_ID_SYNCOBJ_OUT 0x05
#define AMDGPU_CHUNK_ID_BO_HANDLES 0x06
#define AMDGPU_CHUNK_ID_SCHEDULED_DEPENDENCIES 0x07
+#define AMDGPU_CHUNK_ID_SYNCOBJ_TIMELINE_WAIT 0x08
+#define AMDGPU_CHUNK_ID_SYNCOBJ_TIMELINE_SIGNAL 0x09
struct drm_amdgpu_cs_chunk {
__u32 chunk_id;
__u32 length_dw;
@@ -372,6 +376,11 @@ struct drm_amdgpu_cs_chunk_fence {
struct drm_amdgpu_cs_chunk_sem {
__u32 handle;
};
+struct drm_amdgpu_cs_chunk_syncobj {
+ __u32 handle;
+ __u32 flags;
+ __u64 point;
+};
#define AMDGPU_FENCE_TO_HANDLE_GET_SYNCOBJ 0
#define AMDGPU_FENCE_TO_HANDLE_GET_SYNCOBJ_FD 1
#define AMDGPU_FENCE_TO_HANDLE_GET_SYNC_FILE_FD 2
@@ -416,6 +425,7 @@ struct drm_amdgpu_cs_chunk_data {
#define AMDGPU_INFO_FW_GFX_RLC_RESTORE_LIST_GPM_MEM 0x10
#define AMDGPU_INFO_FW_GFX_RLC_RESTORE_LIST_SRM_MEM 0x11
#define AMDGPU_INFO_FW_DMCU 0x12
+#define AMDGPU_INFO_FW_TA 0x13
#define AMDGPU_INFO_NUM_BYTES_MOVED 0x0f
#define AMDGPU_INFO_VRAM_USAGE 0x10
#define AMDGPU_INFO_GTT_USAGE 0x11
@@ -443,6 +453,21 @@ struct drm_amdgpu_cs_chunk_data {
#define AMDGPU_INFO_SENSOR_STABLE_PSTATE_GFX_MCLK 0x9
#define AMDGPU_INFO_NUM_VRAM_CPU_PAGE_FAULTS 0x1E
#define AMDGPU_INFO_VRAM_LOST_COUNTER 0x1F
+#define AMDGPU_INFO_RAS_ENABLED_FEATURES 0x20
+#define AMDGPU_INFO_RAS_ENABLED_UMC (1 << 0)
+#define AMDGPU_INFO_RAS_ENABLED_SDMA (1 << 1)
+#define AMDGPU_INFO_RAS_ENABLED_GFX (1 << 2)
+#define AMDGPU_INFO_RAS_ENABLED_MMHUB (1 << 3)
+#define AMDGPU_INFO_RAS_ENABLED_ATHUB (1 << 4)
+#define AMDGPU_INFO_RAS_ENABLED_PCIE (1 << 5)
+#define AMDGPU_INFO_RAS_ENABLED_HDP (1 << 6)
+#define AMDGPU_INFO_RAS_ENABLED_XGMI (1 << 7)
+#define AMDGPU_INFO_RAS_ENABLED_DF (1 << 8)
+#define AMDGPU_INFO_RAS_ENABLED_SMN (1 << 9)
+#define AMDGPU_INFO_RAS_ENABLED_SEM (1 << 10)
+#define AMDGPU_INFO_RAS_ENABLED_MP0 (1 << 11)
+#define AMDGPU_INFO_RAS_ENABLED_MP1 (1 << 12)
+#define AMDGPU_INFO_RAS_ENABLED_FUSE (1 << 13)
#define AMDGPU_INFO_MMR_SE_INDEX_SHIFT 0
#define AMDGPU_INFO_MMR_SE_INDEX_MASK 0xff
#define AMDGPU_INFO_MMR_SH_INDEX_SHIFT 8
diff --git a/libc/kernel/uapi/drm/drm.h b/libc/kernel/uapi/drm/drm.h
index ef64ed712..66adf9911 100644
--- a/libc/kernel/uapi/drm/drm.h
+++ b/libc/kernel/uapi/drm/drm.h
@@ -363,6 +363,7 @@ struct drm_gem_open {
#define DRM_CAP_PAGE_FLIP_TARGET 0x11
#define DRM_CAP_CRTC_IN_VBLANK_EVENT 0x12
#define DRM_CAP_SYNCOBJ 0x13
+#define DRM_CAP_SYNCOBJ_TIMELINE 0x14
struct drm_get_cap {
__u64 capability;
__u64 value;
@@ -400,8 +401,17 @@ struct drm_syncobj_handle {
__s32 fd;
__u32 pad;
};
+struct drm_syncobj_transfer {
+ __u32 src_handle;
+ __u32 dst_handle;
+ __u64 src_point;
+ __u64 dst_point;
+ __u32 flags;
+ __u32 pad;
+};
#define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL (1 << 0)
#define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT (1 << 1)
+#define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE (1 << 2)
struct drm_syncobj_wait {
__u64 handles;
__s64 timeout_nsec;
@@ -410,11 +420,26 @@ struct drm_syncobj_wait {
__u32 first_signaled;
__u32 pad;
};
+struct drm_syncobj_timeline_wait {
+ __u64 handles;
+ __u64 points;
+ __s64 timeout_nsec;
+ __u32 count_handles;
+ __u32 flags;
+ __u32 first_signaled;
+ __u32 pad;
+};
struct drm_syncobj_array {
__u64 handles;
__u32 count_handles;
__u32 pad;
};
+struct drm_syncobj_timeline_array {
+ __u64 handles;
+ __u64 points;
+ __u32 count_handles;
+ __u32 pad;
+};
struct drm_crtc_get_sequence {
__u32 crtc_id;
__u32 active;
@@ -542,6 +567,10 @@ extern "C" {
#define DRM_IOCTL_MODE_LIST_LESSEES DRM_IOWR(0xC7, struct drm_mode_list_lessees)
#define DRM_IOCTL_MODE_GET_LEASE DRM_IOWR(0xC8, struct drm_mode_get_lease)
#define DRM_IOCTL_MODE_REVOKE_LEASE DRM_IOWR(0xC9, struct drm_mode_revoke_lease)
+#define DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT DRM_IOWR(0xCA, struct drm_syncobj_timeline_wait)
+#define DRM_IOCTL_SYNCOBJ_QUERY DRM_IOWR(0xCB, struct drm_syncobj_timeline_array)
+#define DRM_IOCTL_SYNCOBJ_TRANSFER DRM_IOWR(0xCC, struct drm_syncobj_transfer)
+#define DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL DRM_IOWR(0xCD, struct drm_syncobj_timeline_array)
#define DRM_COMMAND_BASE 0x40
#define DRM_COMMAND_END 0xA0
struct drm_event {
diff --git a/libc/kernel/uapi/drm/drm_fourcc.h b/libc/kernel/uapi/drm/drm_fourcc.h
index fd808535e..593d87c6a 100644
--- a/libc/kernel/uapi/drm/drm_fourcc.h
+++ b/libc/kernel/uapi/drm/drm_fourcc.h
@@ -70,16 +70,33 @@ extern "C" {
#define DRM_FORMAT_ABGR2101010 fourcc_code('A', 'B', '3', '0')
#define DRM_FORMAT_RGBA1010102 fourcc_code('R', 'A', '3', '0')
#define DRM_FORMAT_BGRA1010102 fourcc_code('B', 'A', '3', '0')
+#define DRM_FORMAT_XRGB16161616F fourcc_code('X', 'R', '4', 'H')
+#define DRM_FORMAT_XBGR16161616F fourcc_code('X', 'B', '4', 'H')
+#define DRM_FORMAT_ARGB16161616F fourcc_code('A', 'R', '4', 'H')
+#define DRM_FORMAT_ABGR16161616F fourcc_code('A', 'B', '4', 'H')
#define DRM_FORMAT_YUYV fourcc_code('Y', 'U', 'Y', 'V')
#define DRM_FORMAT_YVYU fourcc_code('Y', 'V', 'Y', 'U')
#define DRM_FORMAT_UYVY fourcc_code('U', 'Y', 'V', 'Y')
#define DRM_FORMAT_VYUY fourcc_code('V', 'Y', 'U', 'Y')
#define DRM_FORMAT_AYUV fourcc_code('A', 'Y', 'U', 'V')
#define DRM_FORMAT_XYUV8888 fourcc_code('X', 'Y', 'U', 'V')
+#define DRM_FORMAT_VUY888 fourcc_code('V', 'U', '2', '4')
+#define DRM_FORMAT_VUY101010 fourcc_code('V', 'U', '3', '0')
+#define DRM_FORMAT_Y210 fourcc_code('Y', '2', '1', '0')
+#define DRM_FORMAT_Y212 fourcc_code('Y', '2', '1', '2')
+#define DRM_FORMAT_Y216 fourcc_code('Y', '2', '1', '6')
+#define DRM_FORMAT_Y410 fourcc_code('Y', '4', '1', '0')
+#define DRM_FORMAT_Y412 fourcc_code('Y', '4', '1', '2')
+#define DRM_FORMAT_Y416 fourcc_code('Y', '4', '1', '6')
+#define DRM_FORMAT_XVYU2101010 fourcc_code('X', 'V', '3', '0')
+#define DRM_FORMAT_XVYU12_16161616 fourcc_code('X', 'V', '3', '6')
+#define DRM_FORMAT_XVYU16161616 fourcc_code('X', 'V', '4', '8')
#define DRM_FORMAT_Y0L0 fourcc_code('Y', '0', 'L', '0')
#define DRM_FORMAT_X0L0 fourcc_code('X', '0', 'L', '0')
#define DRM_FORMAT_Y0L2 fourcc_code('Y', '0', 'L', '2')
#define DRM_FORMAT_X0L2 fourcc_code('X', '0', 'L', '2')
+#define DRM_FORMAT_YUV420_8BIT fourcc_code('Y', 'U', '0', '8')
+#define DRM_FORMAT_YUV420_10BIT fourcc_code('Y', 'U', '1', '0')
#define DRM_FORMAT_XRGB8888_A8 fourcc_code('X', 'R', 'A', '8')
#define DRM_FORMAT_XBGR8888_A8 fourcc_code('X', 'B', 'A', '8')
#define DRM_FORMAT_RGBX8888_A8 fourcc_code('R', 'X', 'A', '8')
@@ -94,6 +111,7 @@ extern "C" {
#define DRM_FORMAT_NV61 fourcc_code('N', 'V', '6', '1')
#define DRM_FORMAT_NV24 fourcc_code('N', 'V', '2', '4')
#define DRM_FORMAT_NV42 fourcc_code('N', 'V', '4', '2')
+#define DRM_FORMAT_P210 fourcc_code('P', '2', '1', '0')
#define DRM_FORMAT_P010 fourcc_code('P', '0', '1', '0')
#define DRM_FORMAT_P012 fourcc_code('P', '0', '1', '2')
#define DRM_FORMAT_P016 fourcc_code('P', '0', '1', '6')
diff --git a/libc/kernel/uapi/drm/drm_mode.h b/libc/kernel/uapi/drm/drm_mode.h
index 1944c9cd8..3f321d039 100644
--- a/libc/kernel/uapi/drm/drm_mode.h
+++ b/libc/kernel/uapi/drm/drm_mode.h
@@ -22,7 +22,6 @@
#ifdef __cplusplus
extern "C" {
#endif
-#define DRM_DISPLAY_INFO_LEN 32
#define DRM_CONNECTOR_NAME_LEN 32
#define DRM_DISPLAY_MODE_LEN 32
#define DRM_PROP_NAME_LEN 32
diff --git a/libc/kernel/uapi/drm/i915_drm.h b/libc/kernel/uapi/drm/i915_drm.h
index d48a581a6..d83a4c0d2 100644
--- a/libc/kernel/uapi/drm/i915_drm.h
+++ b/libc/kernel/uapi/drm/i915_drm.h
@@ -25,6 +25,12 @@ extern "C" {
#define I915_L3_PARITY_UEVENT "L3_PARITY_ERROR"
#define I915_ERROR_UEVENT "ERROR"
#define I915_RESET_UEVENT "RESET"
+struct i915_user_extension {
+ __u64 next_extension;
+ __u32 name;
+ __u32 flags;
+ __u32 rsvd[4];
+};
enum i915_mocs_table_index {
I915_MOCS_UNCACHED,
I915_MOCS_PTE,
@@ -37,6 +43,10 @@ enum drm_i915_gem_engine_class {
I915_ENGINE_CLASS_VIDEO_ENHANCE = 3,
I915_ENGINE_CLASS_INVALID = - 1
};
+struct i915_engine_class_instance {
+ __u16 engine_class;
+ __u16 engine_instance;
+};
enum drm_i915_pmu_engine_sample {
I915_SAMPLE_BUSY = 0,
I915_SAMPLE_WAIT = 1,
@@ -249,6 +259,7 @@ typedef struct _drm_i915_sarea {
#define DRM_IOCTL_I915_GET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GET_SPRITE_COLORKEY, struct drm_intel_sprite_colorkey)
#define DRM_IOCTL_I915_GEM_WAIT DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_WAIT, struct drm_i915_gem_wait)
#define DRM_IOCTL_I915_GEM_CONTEXT_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_CREATE, struct drm_i915_gem_context_create)
+#define DRM_IOCTL_I915_GEM_CONTEXT_CREATE_EXT DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_CREATE, struct drm_i915_gem_context_create_ext)
#define DRM_IOCTL_I915_GEM_CONTEXT_DESTROY DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_DESTROY, struct drm_i915_gem_context_destroy)
#define DRM_IOCTL_I915_REG_READ DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_REG_READ, struct drm_i915_reg_read)
#define DRM_IOCTL_I915_GET_RESET_STATS DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GET_RESET_STATS, struct drm_i915_reset_stats)
@@ -328,6 +339,7 @@ typedef struct drm_i915_irq_wait {
#define I915_SCHEDULER_CAP_ENABLED (1ul << 0)
#define I915_SCHEDULER_CAP_PRIORITY (1ul << 1)
#define I915_SCHEDULER_CAP_PREEMPTION (1ul << 2)
+#define I915_SCHEDULER_CAP_SEMAPHORES (1ul << 3)
#define I915_PARAM_HUC_STATUS 42
#define I915_PARAM_HAS_EXEC_ASYNC 43
#define I915_PARAM_HAS_EXEC_FENCE 44
@@ -499,7 +511,7 @@ struct drm_i915_gem_execbuffer2 {
__u32 DR4;
__u32 num_cliprects;
__u64 cliprects_ptr;
-#define I915_EXEC_RING_MASK (7 << 0)
+#define I915_EXEC_RING_MASK (0x3f)
#define I915_EXEC_DEFAULT (0 << 0)
#define I915_EXEC_RENDER (1 << 0)
#define I915_EXEC_BSD (2 << 0)
@@ -665,30 +677,12 @@ struct drm_i915_gem_context_create {
__u32 ctx_id;
__u32 pad;
};
-struct drm_i915_gem_context_destroy {
- __u32 ctx_id;
- __u32 pad;
-};
-struct drm_i915_reg_read {
- __u64 offset;
-#define I915_REG_READ_8B_WA (1ul << 0)
- __u64 val;
-};
-struct drm_i915_reset_stats {
+struct drm_i915_gem_context_create_ext {
__u32 ctx_id;
__u32 flags;
- __u32 reset_count;
- __u32 batch_active;
- __u32 batch_pending;
- __u32 pad;
-};
-struct drm_i915_gem_userptr {
- __u64 user_ptr;
- __u64 user_size;
- __u32 flags;
-#define I915_USERPTR_READ_ONLY 0x1
-#define I915_USERPTR_UNSYNCHRONIZED 0x80000000
- __u32 handle;
+#define I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS (1u << 0)
+#define I915_CONTEXT_CREATE_FLAGS_UNKNOWN (- (I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS << 1))
+ __u64 extensions;
};
struct drm_i915_gem_context_param {
__u32 ctx_id;
@@ -704,11 +698,11 @@ struct drm_i915_gem_context_param {
#define I915_CONTEXT_DEFAULT_PRIORITY 0
#define I915_CONTEXT_MIN_USER_PRIORITY - 1023
#define I915_CONTEXT_PARAM_SSEU 0x7
+#define I915_CONTEXT_PARAM_RECOVERABLE 0x8
__u64 value;
};
struct drm_i915_gem_context_param_sseu {
- __u16 engine_class;
- __u16 engine_instance;
+ struct i915_engine_class_instance engine;
__u32 flags;
__u64 slice_mask;
__u64 subslice_mask;
@@ -716,6 +710,41 @@ struct drm_i915_gem_context_param_sseu {
__u16 max_eus_per_subslice;
__u32 rsvd;
};
+struct drm_i915_gem_context_create_ext_setparam {
+#define I915_CONTEXT_CREATE_EXT_SETPARAM 0
+ struct i915_user_extension base;
+ struct drm_i915_gem_context_param param;
+};
+struct drm_i915_gem_context_destroy {
+ __u32 ctx_id;
+ __u32 pad;
+};
+struct drm_i915_gem_vm_control {
+ __u64 extensions;
+ __u32 flags;
+ __u32 vm_id;
+};
+struct drm_i915_reg_read {
+ __u64 offset;
+#define I915_REG_READ_8B_WA (1ul << 0)
+ __u64 val;
+};
+struct drm_i915_reset_stats {
+ __u32 ctx_id;
+ __u32 flags;
+ __u32 reset_count;
+ __u32 batch_active;
+ __u32 batch_pending;
+ __u32 pad;
+};
+struct drm_i915_gem_userptr {
+ __u64 user_ptr;
+ __u64 user_size;
+ __u32 flags;
+#define I915_USERPTR_READ_ONLY 0x1
+#define I915_USERPTR_UNSYNCHRONIZED 0x80000000
+ __u32 handle;
+};
enum drm_i915_oa_format {
I915_OA_FORMAT_A13 = 1,
I915_OA_FORMAT_A29,
diff --git a/libc/kernel/uapi/drm/lima_drm.h b/libc/kernel/uapi/drm/lima_drm.h
new file mode 100644
index 000000000..bb70cf79d
--- /dev/null
+++ b/libc/kernel/uapi/drm/lima_drm.h
@@ -0,0 +1,129 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** 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 __LIMA_DRM_H__
+#define __LIMA_DRM_H__
+#include "drm.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+enum drm_lima_param_gpu_id {
+ DRM_LIMA_PARAM_GPU_ID_UNKNOWN,
+ DRM_LIMA_PARAM_GPU_ID_MALI400,
+ DRM_LIMA_PARAM_GPU_ID_MALI450,
+};
+enum drm_lima_param {
+ DRM_LIMA_PARAM_GPU_ID,
+ DRM_LIMA_PARAM_NUM_PP,
+ DRM_LIMA_PARAM_GP_VERSION,
+ DRM_LIMA_PARAM_PP_VERSION,
+};
+struct drm_lima_get_param {
+ __u32 param;
+ __u32 pad;
+ __u64 value;
+};
+struct drm_lima_gem_create {
+ __u32 size;
+ __u32 flags;
+ __u32 handle;
+ __u32 pad;
+};
+struct drm_lima_gem_info {
+ __u32 handle;
+ __u32 va;
+ __u64 offset;
+};
+#define LIMA_SUBMIT_BO_READ 0x01
+#define LIMA_SUBMIT_BO_WRITE 0x02
+struct drm_lima_gem_submit_bo {
+ __u32 handle;
+ __u32 flags;
+};
+#define LIMA_GP_FRAME_REG_NUM 6
+struct drm_lima_gp_frame {
+ __u32 frame[LIMA_GP_FRAME_REG_NUM];
+};
+#define LIMA_PP_FRAME_REG_NUM 23
+#define LIMA_PP_WB_REG_NUM 12
+struct drm_lima_m400_pp_frame {
+ __u32 frame[LIMA_PP_FRAME_REG_NUM];
+ __u32 num_pp;
+ __u32 wb[3 * LIMA_PP_WB_REG_NUM];
+ __u32 plbu_array_address[4];
+ __u32 fragment_stack_address[4];
+};
+struct drm_lima_m450_pp_frame {
+ __u32 frame[LIMA_PP_FRAME_REG_NUM];
+ __u32 num_pp;
+ __u32 wb[3 * LIMA_PP_WB_REG_NUM];
+ __u32 use_dlbu;
+ __u32 _pad;
+ union {
+ __u32 plbu_array_address[8];
+ __u32 dlbu_regs[4];
+ };
+ __u32 fragment_stack_address[8];
+};
+#define LIMA_PIPE_GP 0x00
+#define LIMA_PIPE_PP 0x01
+#define LIMA_SUBMIT_FLAG_EXPLICIT_FENCE (1 << 0)
+struct drm_lima_gem_submit {
+ __u32 ctx;
+ __u32 pipe;
+ __u32 nr_bos;
+ __u32 frame_size;
+ __u64 bos;
+ __u64 frame;
+ __u32 flags;
+ __u32 out_sync;
+ __u32 in_sync[2];
+};
+#define LIMA_GEM_WAIT_READ 0x01
+#define LIMA_GEM_WAIT_WRITE 0x02
+struct drm_lima_gem_wait {
+ __u32 handle;
+ __u32 op;
+ __s64 timeout_ns;
+};
+struct drm_lima_ctx_create {
+ __u32 id;
+ __u32 _pad;
+};
+struct drm_lima_ctx_free {
+ __u32 id;
+ __u32 _pad;
+};
+#define DRM_LIMA_GET_PARAM 0x00
+#define DRM_LIMA_GEM_CREATE 0x01
+#define DRM_LIMA_GEM_INFO 0x02
+#define DRM_LIMA_GEM_SUBMIT 0x03
+#define DRM_LIMA_GEM_WAIT 0x04
+#define DRM_LIMA_CTX_CREATE 0x05
+#define DRM_LIMA_CTX_FREE 0x06
+#define DRM_IOCTL_LIMA_GET_PARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_LIMA_GET_PARAM, struct drm_lima_get_param)
+#define DRM_IOCTL_LIMA_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_LIMA_GEM_CREATE, struct drm_lima_gem_create)
+#define DRM_IOCTL_LIMA_GEM_INFO DRM_IOWR(DRM_COMMAND_BASE + DRM_LIMA_GEM_INFO, struct drm_lima_gem_info)
+#define DRM_IOCTL_LIMA_GEM_SUBMIT DRM_IOW(DRM_COMMAND_BASE + DRM_LIMA_GEM_SUBMIT, struct drm_lima_gem_submit)
+#define DRM_IOCTL_LIMA_GEM_WAIT DRM_IOW(DRM_COMMAND_BASE + DRM_LIMA_GEM_WAIT, struct drm_lima_gem_wait)
+#define DRM_IOCTL_LIMA_CTX_CREATE DRM_IOR(DRM_COMMAND_BASE + DRM_LIMA_CTX_CREATE, struct drm_lima_ctx_create)
+#define DRM_IOCTL_LIMA_CTX_FREE DRM_IOW(DRM_COMMAND_BASE + DRM_LIMA_CTX_FREE, struct drm_lima_ctx_free)
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/libc/kernel/uapi/drm/msm_drm.h b/libc/kernel/uapi/drm/msm_drm.h
index f6bee3e32..3c1b734b2 100644
--- a/libc/kernel/uapi/drm/msm_drm.h
+++ b/libc/kernel/uapi/drm/msm_drm.h
@@ -40,6 +40,8 @@ struct drm_msm_timespec {
#define MSM_PARAM_TIMESTAMP 0x05
#define MSM_PARAM_GMEM_BASE 0x06
#define MSM_PARAM_NR_RINGS 0x07
+#define MSM_PARAM_PP_PGTABLE 0x08
+#define MSM_PARAM_FAULTS 0x09
struct drm_msm_param {
__u32 pipe;
__u32 param;
@@ -143,6 +145,14 @@ struct drm_msm_submitqueue {
__u32 prio;
__u32 id;
};
+#define MSM_SUBMITQUEUE_PARAM_FAULTS 0
+struct drm_msm_submitqueue_query {
+ __u64 data;
+ __u32 id;
+ __u32 param;
+ __u32 len;
+ __u32 pad;
+};
#define DRM_MSM_GET_PARAM 0x00
#define DRM_MSM_GEM_NEW 0x02
#define DRM_MSM_GEM_INFO 0x03
@@ -153,6 +163,7 @@ struct drm_msm_submitqueue {
#define DRM_MSM_GEM_MADVISE 0x08
#define DRM_MSM_SUBMITQUEUE_NEW 0x0A
#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_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)
@@ -163,6 +174,7 @@ struct drm_msm_submitqueue {
#define DRM_IOCTL_MSM_GEM_MADVISE DRM_IOWR(DRM_COMMAND_BASE + DRM_MSM_GEM_MADVISE, struct drm_msm_gem_madvise)
#define DRM_IOCTL_MSM_SUBMITQUEUE_NEW DRM_IOWR(DRM_COMMAND_BASE + DRM_MSM_SUBMITQUEUE_NEW, struct drm_msm_submitqueue)
#define DRM_IOCTL_MSM_SUBMITQUEUE_CLOSE DRM_IOW(DRM_COMMAND_BASE + DRM_MSM_SUBMITQUEUE_CLOSE, __u32)
+#define DRM_IOCTL_MSM_SUBMITQUEUE_QUERY DRM_IOW(DRM_COMMAND_BASE + DRM_MSM_SUBMITQUEUE_QUERY, struct drm_msm_submitqueue_query)
#ifdef __cplusplus
}
#endif
diff --git a/libc/kernel/uapi/drm/panfrost_drm.h b/libc/kernel/uapi/drm/panfrost_drm.h
new file mode 100644
index 000000000..17f093ba4
--- /dev/null
+++ b/libc/kernel/uapi/drm/panfrost_drm.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** 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 _PANFROST_DRM_H_
+#define _PANFROST_DRM_H_
+#include "drm.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+#define DRM_PANFROST_SUBMIT 0x00
+#define DRM_PANFROST_WAIT_BO 0x01
+#define DRM_PANFROST_CREATE_BO 0x02
+#define DRM_PANFROST_MMAP_BO 0x03
+#define DRM_PANFROST_GET_PARAM 0x04
+#define DRM_PANFROST_GET_BO_OFFSET 0x05
+#define DRM_IOCTL_PANFROST_SUBMIT DRM_IOW(DRM_COMMAND_BASE + DRM_PANFROST_SUBMIT, struct drm_panfrost_submit)
+#define DRM_IOCTL_PANFROST_WAIT_BO DRM_IOW(DRM_COMMAND_BASE + DRM_PANFROST_WAIT_BO, struct drm_panfrost_wait_bo)
+#define DRM_IOCTL_PANFROST_CREATE_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_PANFROST_CREATE_BO, struct drm_panfrost_create_bo)
+#define DRM_IOCTL_PANFROST_MMAP_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_PANFROST_MMAP_BO, struct drm_panfrost_mmap_bo)
+#define DRM_IOCTL_PANFROST_GET_PARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_PANFROST_GET_PARAM, struct drm_panfrost_get_param)
+#define DRM_IOCTL_PANFROST_GET_BO_OFFSET DRM_IOWR(DRM_COMMAND_BASE + DRM_PANFROST_GET_BO_OFFSET, struct drm_panfrost_get_bo_offset)
+#define PANFROST_JD_REQ_FS (1 << 0)
+struct drm_panfrost_submit {
+ __u64 jc;
+ __u64 in_syncs;
+ __u32 in_sync_count;
+ __u32 out_sync;
+ __u64 bo_handles;
+ __u32 bo_handle_count;
+ __u32 requirements;
+};
+struct drm_panfrost_wait_bo {
+ __u32 handle;
+ __u32 pad;
+ __s64 timeout_ns;
+};
+struct drm_panfrost_create_bo {
+ __u32 size;
+ __u32 flags;
+ __u32 handle;
+ __u32 pad;
+ __u64 offset;
+};
+struct drm_panfrost_mmap_bo {
+ __u32 handle;
+ __u32 flags;
+ __u64 offset;
+};
+enum drm_panfrost_param {
+ DRM_PANFROST_PARAM_GPU_PROD_ID,
+};
+struct drm_panfrost_get_param {
+ __u32 param;
+ __u32 pad;
+ __u64 value;
+};
+struct drm_panfrost_get_bo_offset {
+ __u32 handle;
+ __u32 pad;
+ __u64 offset;
+};
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/libc/kernel/uapi/linux/aspeed-p2a-ctrl.h b/libc/kernel/uapi/linux/aspeed-p2a-ctrl.h
new file mode 100644
index 000000000..94e51326f
--- /dev/null
+++ b/libc/kernel/uapi/linux/aspeed-p2a-ctrl.h
@@ -0,0 +1,33 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _UAPI_LINUX_ASPEED_P2A_CTRL_H
+#define _UAPI_LINUX_ASPEED_P2A_CTRL_H
+#include <linux/ioctl.h>
+#include <linux/types.h>
+#define ASPEED_P2A_CTRL_READ_ONLY 0
+#define ASPEED_P2A_CTRL_READWRITE 1
+struct aspeed_p2a_ctrl_mapping {
+ __u64 addr;
+ __u32 length;
+ __u32 flags;
+};
+#define __ASPEED_P2A_CTRL_IOCTL_MAGIC 0xb3
+#define ASPEED_P2A_CTRL_IOCTL_SET_WINDOW _IOW(__ASPEED_P2A_CTRL_IOCTL_MAGIC, 0x00, struct aspeed_p2a_ctrl_mapping)
+#define ASPEED_P2A_CTRL_IOCTL_GET_MEMORY_CONFIG _IOWR(__ASPEED_P2A_CTRL_IOCTL_MAGIC, 0x01, struct aspeed_p2a_ctrl_mapping)
+#endif
diff --git a/libc/kernel/uapi/linux/audit.h b/libc/kernel/uapi/linux/audit.h
index 0698fc84c..509d734c8 100644
--- a/libc/kernel/uapi/linux/audit.h
+++ b/libc/kernel/uapi/linux/audit.h
@@ -79,6 +79,8 @@
#define AUDIT_REPLACE 1329
#define AUDIT_KERN_MODULE 1330
#define AUDIT_FANOTIFY 1331
+#define AUDIT_TIME_INJOFFSET 1332
+#define AUDIT_TIME_ADJNTPVAL 1333
#define AUDIT_AVC 1400
#define AUDIT_SELINUX_ERR 1401
#define AUDIT_AVC_PATH 1402
@@ -262,11 +264,19 @@ enum {
#define __AUDIT_ARCH_LE 0x40000000
#define AUDIT_ARCH_AARCH64 (EM_AARCH64 | __AUDIT_ARCH_64BIT | __AUDIT_ARCH_LE)
#define AUDIT_ARCH_ALPHA (EM_ALPHA | __AUDIT_ARCH_64BIT | __AUDIT_ARCH_LE)
+#define AUDIT_ARCH_ARCOMPACT (EM_ARCOMPACT | __AUDIT_ARCH_LE)
+#define AUDIT_ARCH_ARCOMPACTBE (EM_ARCOMPACT)
+#define AUDIT_ARCH_ARCV2 (EM_ARCV2 | __AUDIT_ARCH_LE)
+#define AUDIT_ARCH_ARCV2BE (EM_ARCV2)
#define AUDIT_ARCH_ARM (EM_ARM | __AUDIT_ARCH_LE)
#define AUDIT_ARCH_ARMEB (EM_ARM)
+#define AUDIT_ARCH_C6X (EM_TI_C6000 | __AUDIT_ARCH_LE)
+#define AUDIT_ARCH_C6XBE (EM_TI_C6000)
#define AUDIT_ARCH_CRIS (EM_CRIS | __AUDIT_ARCH_LE)
#define AUDIT_ARCH_CSKY (EM_CSKY | __AUDIT_ARCH_LE)
#define AUDIT_ARCH_FRV (EM_FRV)
+#define AUDIT_ARCH_H8300 (EM_H8_300)
+#define AUDIT_ARCH_HEXAGON (EM_HEXAGON)
#define AUDIT_ARCH_I386 (EM_386 | __AUDIT_ARCH_LE)
#define AUDIT_ARCH_IA64 (EM_IA_64 | __AUDIT_ARCH_64BIT | __AUDIT_ARCH_LE)
#define AUDIT_ARCH_M32R (EM_M32R)
@@ -278,6 +288,9 @@ enum {
#define AUDIT_ARCH_MIPS64N32 (EM_MIPS | __AUDIT_ARCH_64BIT | __AUDIT_ARCH_CONVENTION_MIPS64_N32)
#define AUDIT_ARCH_MIPSEL64 (EM_MIPS | __AUDIT_ARCH_64BIT | __AUDIT_ARCH_LE)
#define AUDIT_ARCH_MIPSEL64N32 (EM_MIPS | __AUDIT_ARCH_64BIT | __AUDIT_ARCH_LE | __AUDIT_ARCH_CONVENTION_MIPS64_N32)
+#define AUDIT_ARCH_NDS32 (EM_NDS32 | __AUDIT_ARCH_LE)
+#define AUDIT_ARCH_NDS32BE (EM_NDS32)
+#define AUDIT_ARCH_NIOS2 (EM_ALTERA_NIOS2 | __AUDIT_ARCH_LE)
#define AUDIT_ARCH_OPENRISC (EM_OPENRISC)
#define AUDIT_ARCH_PARISC (EM_PARISC)
#define AUDIT_ARCH_PARISC64 (EM_PARISC | __AUDIT_ARCH_64BIT)
@@ -297,6 +310,7 @@ enum {
#define AUDIT_ARCH_TILEGX (EM_TILEGX | __AUDIT_ARCH_64BIT | __AUDIT_ARCH_LE)
#define AUDIT_ARCH_TILEGX32 (EM_TILEGX | __AUDIT_ARCH_LE)
#define AUDIT_ARCH_TILEPRO (EM_TILEPRO | __AUDIT_ARCH_LE)
+#define AUDIT_ARCH_UNICORE (EM_UNICORE | __AUDIT_ARCH_LE)
#define AUDIT_ARCH_X86_64 (EM_X86_64 | __AUDIT_ARCH_64BIT | __AUDIT_ARCH_LE)
#define AUDIT_ARCH_XTENSA (EM_XTENSA)
#define AUDIT_PERM_EXEC 1
diff --git a/libc/kernel/uapi/linux/batman_adv.h b/libc/kernel/uapi/linux/batman_adv.h
index 9cad20a15..96b259b23 100644
--- a/libc/kernel/uapi/linux/batman_adv.h
+++ b/libc/kernel/uapi/linux/batman_adv.h
@@ -104,6 +104,7 @@ enum batadv_nl_attrs {
BATADV_ATTR_ORIG_INTERVAL,
BATADV_ATTR_ELP_INTERVAL,
BATADV_ATTR_THROUGHPUT_OVERRIDE,
+ BATADV_ATTR_MULTICAST_FANOUT,
__BATADV_ATTR_AFTER_LAST,
NUM_BATADV_ATTR = __BATADV_ATTR_AFTER_LAST,
BATADV_ATTR_MAX = __BATADV_ATTR_AFTER_LAST - 1
diff --git a/libc/kernel/uapi/linux/bpf.h b/libc/kernel/uapi/linux/bpf.h
index edae89389..3f0942167 100644
--- a/libc/kernel/uapi/linux/bpf.h
+++ b/libc/kernel/uapi/linux/bpf.h
@@ -93,6 +93,7 @@ enum bpf_cmd {
BPF_BTF_GET_FD_BY_ID,
BPF_TASK_FD_QUERY,
BPF_MAP_LOOKUP_AND_DELETE_ELEM,
+ BPF_MAP_FREEZE,
};
enum bpf_map_type {
BPF_MAP_TYPE_UNSPEC,
@@ -119,6 +120,7 @@ enum bpf_map_type {
BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE,
BPF_MAP_TYPE_QUEUE,
BPF_MAP_TYPE_STACK,
+ BPF_MAP_TYPE_SK_STORAGE,
};
enum bpf_prog_type {
BPF_PROG_TYPE_UNSPEC,
@@ -144,6 +146,8 @@ enum bpf_prog_type {
BPF_PROG_TYPE_LIRC_MODE2,
BPF_PROG_TYPE_SK_REUSEPORT,
BPF_PROG_TYPE_FLOW_DISSECTOR,
+ BPF_PROG_TYPE_CGROUP_SYSCTL,
+ BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE,
};
enum bpf_attach_type {
BPF_CGROUP_INET_INGRESS,
@@ -164,6 +168,9 @@ enum bpf_attach_type {
BPF_CGROUP_UDP6_SENDMSG,
BPF_LIRC_MODE2,
BPF_FLOW_DISSECTOR,
+ BPF_CGROUP_SYSCTL,
+ BPF_CGROUP_UDP4_RECVMSG,
+ BPF_CGROUP_UDP6_RECVMSG,
__MAX_BPF_ATTACH_TYPE
};
#define MAX_BPF_ATTACH_TYPE __MAX_BPF_ATTACH_TYPE
@@ -172,6 +179,7 @@ enum bpf_attach_type {
#define BPF_F_STRICT_ALIGNMENT (1U << 0)
#define BPF_F_ANY_ALIGNMENT (1U << 1)
#define BPF_PSEUDO_MAP_FD 1
+#define BPF_PSEUDO_MAP_VALUE 2
#define BPF_PSEUDO_CALL 1
#define BPF_ANY 0
#define BPF_NOEXIST 1
@@ -185,6 +193,8 @@ enum bpf_attach_type {
#define BPF_F_WRONLY (1U << 4)
#define BPF_F_STACK_BUILD_ID (1U << 5)
#define BPF_F_ZERO_SEED (1U << 6)
+#define BPF_F_RDONLY_PROG (1U << 7)
+#define BPF_F_WRONLY_PROG (1U << 8)
#define BPF_F_QUERY_EFFECTIVE (1U << 0)
enum bpf_stack_build_id_status {
BPF_STACK_BUILD_ID_EMPTY = 0,
@@ -265,6 +275,10 @@ union bpf_attr {
__aligned_u64 data_out;
__u32 repeat;
__u32 duration;
+ __u32 ctx_size_in;
+ __u32 ctx_size_out;
+ __aligned_u64 ctx_in;
+ __aligned_u64 ctx_out;
} test;
struct {
union {
@@ -312,7 +326,7 @@ union bpf_attr {
__u64 probe_addr;
} task_fd_query;
} __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),
+#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),
#define __BPF_ENUM_FN(x) BPF_FUNC_ ##x
enum bpf_func_id {
__BPF_FUNC_MAPPER(__BPF_ENUM_FN) __BPF_FUNC_MAX_ID,
@@ -338,8 +352,19 @@ enum bpf_func_id {
#define BPF_F_CURRENT_CPU BPF_F_INDEX_MASK
#define BPF_F_CTXLEN_MASK (0xfffffULL << 32)
#define BPF_F_CURRENT_NETNS (- 1L)
+#define BPF_F_ADJ_ROOM_FIXED_GSO (1ULL << 0)
+#define BPF_ADJ_ROOM_ENCAP_L2_MASK 0xff
+#define BPF_ADJ_ROOM_ENCAP_L2_SHIFT 56
+#define BPF_F_ADJ_ROOM_ENCAP_L3_IPV4 (1ULL << 1)
+#define BPF_F_ADJ_ROOM_ENCAP_L3_IPV6 (1ULL << 2)
+#define BPF_F_ADJ_ROOM_ENCAP_L4_GRE (1ULL << 3)
+#define BPF_F_ADJ_ROOM_ENCAP_L4_UDP (1ULL << 4)
+#define BPF_F_ADJ_ROOM_ENCAP_L2(len) (((__u64) len & BPF_ADJ_ROOM_ENCAP_L2_MASK) << BPF_ADJ_ROOM_ENCAP_L2_SHIFT)
+#define BPF_F_SYSCTL_BASE_NAME (1ULL << 0)
+#define BPF_SK_STORAGE_GET_F_CREATE (1ULL << 0)
enum bpf_adj_room_mode {
BPF_ADJ_ROOM_NET,
+ BPF_ADJ_ROOM_MAC,
};
enum bpf_hdr_start_off {
BPF_HDR_START_MAC,
@@ -523,6 +548,7 @@ struct bpf_prog_info {
char name[BPF_OBJ_NAME_LEN];
__u32 ifindex;
__u32 gpl_compatible : 1;
+ __u32 : 31;
__u64 netns_dev;
__u64 netns_ino;
__u32 nr_jited_ksyms;
@@ -670,8 +696,8 @@ struct bpf_cgroup_dev_ctx {
struct bpf_raw_tracepoint_args {
__u64 args[0];
};
-#define BPF_FIB_LOOKUP_DIRECT BIT(0)
-#define BPF_FIB_LOOKUP_OUTPUT BIT(1)
+#define BPF_FIB_LOOKUP_DIRECT (1U << 0)
+#define BPF_FIB_LOOKUP_OUTPUT (1U << 1)
enum {
BPF_FIB_LKUP_RET_SUCCESS,
BPF_FIB_LKUP_RET_BLACKHOLE,
@@ -753,4 +779,8 @@ struct bpf_line_info {
struct bpf_spin_lock {
__u32 val;
};
+struct bpf_sysctl {
+ __u32 write;
+ __u32 file_pos;
+};
#endif
diff --git a/libc/kernel/uapi/linux/btf.h b/libc/kernel/uapi/linux/btf.h
index 6e1363151..475e2eb71 100644
--- a/libc/kernel/uapi/linux/btf.h
+++ b/libc/kernel/uapi/linux/btf.h
@@ -59,10 +59,12 @@ struct btf_type {
#define BTF_KIND_RESTRICT 11
#define BTF_KIND_FUNC 12
#define BTF_KIND_FUNC_PROTO 13
-#define BTF_KIND_MAX 13
-#define NR_BTF_KINDS 14
+#define BTF_KIND_VAR 14
+#define BTF_KIND_DATASEC 15
+#define BTF_KIND_MAX BTF_KIND_DATASEC
+#define NR_BTF_KINDS (BTF_KIND_MAX + 1)
#define BTF_INT_ENCODING(VAL) (((VAL) & 0x0f000000) >> 24)
-#define BTF_INT_OFFSET(VAL) (((VAL & 0x00ff0000)) >> 16)
+#define BTF_INT_OFFSET(VAL) (((VAL) & 0x00ff0000) >> 16)
#define BTF_INT_BITS(VAL) ((VAL) & 0x000000ff)
#define BTF_INT_SIGNED (1 << 0)
#define BTF_INT_CHAR (1 << 1)
@@ -87,4 +89,16 @@ struct btf_param {
__u32 name_off;
__u32 type;
};
+enum {
+ BTF_VAR_STATIC = 0,
+ BTF_VAR_GLOBAL_ALLOCATED,
+};
+struct btf_var {
+ __u32 linkage;
+};
+struct btf_var_secinfo {
+ __u32 type;
+ __u32 offset;
+ __u32 size;
+};
#endif
diff --git a/libc/kernel/uapi/linux/elf-em.h b/libc/kernel/uapi/linux/elf-em.h
index 99835aeca..d1ed1f6ce 100644
--- a/libc/kernel/uapi/linux/elf-em.h
+++ b/libc/kernel/uapi/linux/elf-em.h
@@ -45,14 +45,19 @@
#define EM_M32R 88
#define EM_MN10300 89
#define EM_OPENRISC 92
+#define EM_ARCOMPACT 93
#define EM_XTENSA 94
#define EM_BLACKFIN 106
+#define EM_UNICORE 110
#define EM_ALTERA_NIOS2 113
#define EM_TI_C6000 140
+#define EM_HEXAGON 164
+#define EM_NDS32 167
#define EM_AARCH64 183
#define EM_TILEPRO 188
#define EM_MICROBLAZE 189
#define EM_TILEGX 191
+#define EM_ARCV2 195
#define EM_RISCV 243
#define EM_BPF 247
#define EM_CSKY 252
diff --git a/libc/kernel/uapi/linux/ethtool.h b/libc/kernel/uapi/linux/ethtool.h
index 642af99f3..67a7efde0 100644
--- a/libc/kernel/uapi/linux/ethtool.h
+++ b/libc/kernel/uapi/linux/ethtool.h
@@ -101,9 +101,12 @@ struct ethtool_tunable {
};
#define DOWNSHIFT_DEV_DEFAULT_COUNT 0xff
#define DOWNSHIFT_DEV_DISABLE 0
+#define ETHTOOL_PHY_FAST_LINK_DOWN_ON 0
+#define ETHTOOL_PHY_FAST_LINK_DOWN_OFF 0xff
enum phy_tunable_id {
ETHTOOL_PHY_ID_UNSPEC,
ETHTOOL_PHY_DOWNSHIFT,
+ ETHTOOL_PHY_FAST_LINK_DOWN,
__ETHTOOL_PHY_TUNABLE_COUNT,
};
struct ethtool_regs {
@@ -754,6 +757,8 @@ enum ethtool_link_mode_bit_indices {
#define ETH_MODULE_SFF_8636_LEN 256
#define ETH_MODULE_SFF_8436 0x4
#define ETH_MODULE_SFF_8436_LEN 256
+#define ETH_MODULE_SFF_8636_MAX_LEN 640
+#define ETH_MODULE_SFF_8436_MAX_LEN 640
enum ethtool_reset_flags {
ETH_RESET_MGMT = 1 << 0,
ETH_RESET_IRQ = 1 << 1,
diff --git a/libc/kernel/uapi/linux/fcntl.h b/libc/kernel/uapi/linux/fcntl.h
index 66f27b659..e2045c8cf 100644
--- a/libc/kernel/uapi/linux/fcntl.h
+++ b/libc/kernel/uapi/linux/fcntl.h
@@ -60,4 +60,5 @@
#define AT_STATX_SYNC_AS_STAT 0x0000
#define AT_STATX_FORCE_SYNC 0x2000
#define AT_STATX_DONT_SYNC 0x4000
+#define AT_RECURSIVE 0x8000
#endif
diff --git a/libc/kernel/uapi/linux/fou.h b/libc/kernel/uapi/linux/fou.h
index 7e59bd026..a16b8c672 100644
--- a/libc/kernel/uapi/linux/fou.h
+++ b/libc/kernel/uapi/linux/fou.h
@@ -27,6 +27,12 @@ enum {
FOU_ATTR_IPPROTO,
FOU_ATTR_TYPE,
FOU_ATTR_REMCSUM_NOPARTIAL,
+ FOU_ATTR_LOCAL_V4,
+ FOU_ATTR_LOCAL_V6,
+ FOU_ATTR_PEER_V4,
+ FOU_ATTR_PEER_V6,
+ FOU_ATTR_PEER_PORT,
+ FOU_ATTR_IFINDEX,
__FOU_ATTR_MAX,
};
#define FOU_ATTR_MAX (__FOU_ATTR_MAX - 1)
diff --git a/libc/kernel/uapi/linux/fs.h b/libc/kernel/uapi/linux/fs.h
index 84dc010ea..5edd66b78 100644
--- a/libc/kernel/uapi/linux/fs.h
+++ b/libc/kernel/uapi/linux/fs.h
@@ -219,6 +219,7 @@ struct fscrypt_key {
#define SYNC_FILE_RANGE_WAIT_BEFORE 1
#define SYNC_FILE_RANGE_WRITE 2
#define SYNC_FILE_RANGE_WAIT_AFTER 4
+#define SYNC_FILE_RANGE_WRITE_AND_WAIT (SYNC_FILE_RANGE_WRITE | SYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WAIT_AFTER)
typedef int __bitwise __kernel_rwf_t;
#define RWF_HIPRI ((__force __kernel_rwf_t) 0x00000001)
#define RWF_DSYNC ((__force __kernel_rwf_t) 0x00000002)
diff --git a/libc/kernel/uapi/linux/fuse.h b/libc/kernel/uapi/linux/fuse.h
index 4a76ae317..86b01f05a 100644
--- a/libc/kernel/uapi/linux/fuse.h
+++ b/libc/kernel/uapi/linux/fuse.h
@@ -20,7 +20,7 @@
#define _LINUX_FUSE_H
#include <stdint.h>
#define FUSE_KERNEL_VERSION 7
-#define FUSE_KERNEL_MINOR_VERSION 29
+#define FUSE_KERNEL_MINOR_VERSION 31
#define FUSE_ROOT_ID 1
struct fuse_attr {
uint64_t ino;
@@ -73,6 +73,7 @@ struct fuse_file_lock {
#define FOPEN_KEEP_CACHE (1 << 1)
#define FOPEN_NONSEEKABLE (1 << 2)
#define FOPEN_CACHE_DIR (1 << 3)
+#define FOPEN_STREAM (1 << 4)
#define FUSE_ASYNC_READ (1 << 0)
#define FUSE_POSIX_LOCKS (1 << 1)
#define FUSE_FILE_OPS (1 << 2)
@@ -98,6 +99,7 @@ struct fuse_file_lock {
#define FUSE_MAX_PAGES (1 << 22)
#define FUSE_CACHE_SYMLINKS (1 << 23)
#define FUSE_NO_OPENDIR_SUPPORT (1 << 24)
+#define FUSE_EXPLICIT_INVAL_DATA (1 << 25)
#define CUSE_UNRESTRICTED_IOCTL (1 << 0)
#define FUSE_RELEASE_FLUSH (1 << 0)
#define FUSE_RELEASE_FLOCK_UNLOCK (1 << 1)
@@ -105,14 +107,17 @@ struct fuse_file_lock {
#define FUSE_LK_FLOCK (1 << 0)
#define FUSE_WRITE_CACHE (1 << 0)
#define FUSE_WRITE_LOCKOWNER (1 << 1)
+#define FUSE_WRITE_KILL_PRIV (1 << 2)
#define FUSE_READ_LOCKOWNER (1 << 1)
#define FUSE_IOCTL_COMPAT (1 << 0)
#define FUSE_IOCTL_UNRESTRICTED (1 << 1)
#define FUSE_IOCTL_RETRY (1 << 2)
#define FUSE_IOCTL_32BIT (1 << 3)
#define FUSE_IOCTL_DIR (1 << 4)
+#define FUSE_IOCTL_COMPAT_X32 (1 << 5)
#define FUSE_IOCTL_MAX_IOV 256
#define FUSE_POLL_SCHEDULE_NOTIFY (1 << 0)
+#define FUSE_FSYNC_FDATASYNC (1 << 0)
enum fuse_opcode {
FUSE_LOOKUP = 1,
FUSE_FORGET = 2,
diff --git a/libc/kernel/uapi/linux/icmpv6.h b/libc/kernel/uapi/linux/icmpv6.h
index ef73a7c18..798a94599 100644
--- a/libc/kernel/uapi/linux/icmpv6.h
+++ b/libc/kernel/uapi/linux/icmpv6.h
@@ -77,6 +77,7 @@ struct icmp6hdr {
#define ICMPV6_PKT_TOOBIG 2
#define ICMPV6_TIME_EXCEED 3
#define ICMPV6_PARAMPROB 4
+#define ICMPV6_ERRMSG_MAX 127
#define ICMPV6_INFOMSG_MASK 0x80
#define ICMPV6_ECHO_REQUEST 128
#define ICMPV6_ECHO_REPLY 129
@@ -91,6 +92,7 @@ struct icmp6hdr {
#define ICMPV6_MOBILE_PREFIX_SOL 146
#define ICMPV6_MOBILE_PREFIX_ADV 147
#define ICMPV6_MRDISC_ADV 151
+#define ICMPV6_MSG_MAX 255
#define ICMPV6_NOROUTE 0
#define ICMPV6_ADM_PROHIBITED 1
#define ICMPV6_NOT_NEIGHBOUR 2
diff --git a/libc/kernel/uapi/linux/if_ether.h b/libc/kernel/uapi/linux/if_ether.h
index 4fb58f193..9e0b15c54 100644
--- a/libc/kernel/uapi/linux/if_ether.h
+++ b/libc/kernel/uapi/linux/if_ether.h
@@ -90,6 +90,7 @@
#define ETH_P_QINQ2 0x9200
#define ETH_P_QINQ3 0x9300
#define ETH_P_EDSA 0xDADA
+#define ETH_P_DSA_8021Q 0xDADB
#define ETH_P_IFE 0xED3E
#define ETH_P_AF_IUCV 0xFBFB
#define ETH_P_802_3_MIN 0x0600
diff --git a/libc/kernel/uapi/linux/if_tun.h b/libc/kernel/uapi/linux/if_tun.h
index cb2d2d234..d1a8f9ecf 100644
--- a/libc/kernel/uapi/linux/if_tun.h
+++ b/libc/kernel/uapi/linux/if_tun.h
@@ -52,6 +52,7 @@
#define TUNSETSTEERINGEBPF _IOR('T', 224, int)
#define TUNSETFILTEREBPF _IOR('T', 225, int)
#define TUNSETCARRIER _IOW('T', 226, int)
+#define TUNGETDEVNETNS _IO('T', 227)
#define IFF_TUN 0x0001
#define IFF_TAP 0x0002
#define IFF_NAPI 0x0010
diff --git a/libc/kernel/uapi/linux/if_vlan.h b/libc/kernel/uapi/linux/if_vlan.h
index 27403b639..8ca8900db 100644
--- a/libc/kernel/uapi/linux/if_vlan.h
+++ b/libc/kernel/uapi/linux/if_vlan.h
@@ -35,6 +35,7 @@ enum vlan_flags {
VLAN_FLAG_GVRP = 0x2,
VLAN_FLAG_LOOSE_BINDING = 0x4,
VLAN_FLAG_MVRP = 0x8,
+ VLAN_FLAG_BRIDGE_BINDING = 0x10,
};
enum vlan_name_types {
VLAN_NAME_TYPE_PLUS_VID,
diff --git a/libc/kernel/uapi/linux/input-event-codes.h b/libc/kernel/uapi/linux/input-event-codes.h
index 7bbb2340e..5d20c2481 100644
--- a/libc/kernel/uapi/linux/input-event-codes.h
+++ b/libc/kernel/uapi/linux/input-event-codes.h
@@ -543,6 +543,7 @@
#define KEY_SCREENSAVER 0x245
#define KEY_VOICECOMMAND 0x246
#define KEY_ASSISTANT 0x247
+#define KEY_KBD_LAYOUT_NEXT 0x248
#define KEY_BRIGHTNESS_MIN 0x250
#define KEY_BRIGHTNESS_MAX 0x251
#define KEY_KBDINPUTASSIST_PREV 0x260
diff --git a/libc/kernel/uapi/linux/io_uring.h b/libc/kernel/uapi/linux/io_uring.h
index fe2d0eb28..434b24bfa 100644
--- a/libc/kernel/uapi/linux/io_uring.h
+++ b/libc/kernel/uapi/linux/io_uring.h
@@ -32,6 +32,7 @@ struct io_uring_sqe {
__kernel_rwf_t rw_flags;
__u32 fsync_flags;
__u16 poll_events;
+ __u32 sync_range_flags;
};
__u64 user_data;
union {
@@ -40,6 +41,7 @@ struct io_uring_sqe {
};
};
#define IOSQE_FIXED_FILE (1U << 0)
+#define IOSQE_IO_DRAIN (1U << 1)
#define IORING_SETUP_IOPOLL (1U << 0)
#define IORING_SETUP_SQPOLL (1U << 1)
#define IORING_SETUP_SQ_AFF (1U << 2)
@@ -51,6 +53,7 @@ struct io_uring_sqe {
#define IORING_OP_WRITE_FIXED 5
#define IORING_OP_POLL_ADD 6
#define IORING_OP_POLL_REMOVE 7
+#define IORING_OP_SYNC_FILE_RANGE 8
#define IORING_FSYNC_DATASYNC (1U << 0)
struct io_uring_cqe {
__u64 user_data;
@@ -97,4 +100,6 @@ struct io_uring_params {
#define IORING_UNREGISTER_BUFFERS 1
#define IORING_REGISTER_FILES 2
#define IORING_UNREGISTER_FILES 3
+#define IORING_REGISTER_EVENTFD 4
+#define IORING_UNREGISTER_EVENTFD 5
#endif
diff --git a/libc/kernel/uapi/linux/ip_vs.h b/libc/kernel/uapi/linux/ip_vs.h
index d89598d25..0230aae7a 100644
--- a/libc/kernel/uapi/linux/ip_vs.h
+++ b/libc/kernel/uapi/linux/ip_vs.h
@@ -85,6 +85,11 @@
#define IP_VS_PENAME_MAXLEN 16
#define IP_VS_IFNAME_MAXLEN 16
#define IP_VS_PEDATA_MAXLEN 255
+enum {
+ IP_VS_CONN_F_TUNNEL_TYPE_IPIP = 0,
+ IP_VS_CONN_F_TUNNEL_TYPE_GUE,
+ IP_VS_CONN_F_TUNNEL_TYPE_MAX,
+};
struct ip_vs_service_user {
__u16 protocol;
__be32 addr;
@@ -236,6 +241,8 @@ enum {
IPVS_DEST_ATTR_STATS,
IPVS_DEST_ATTR_ADDR_FAMILY,
IPVS_DEST_ATTR_STATS64,
+ IPVS_DEST_ATTR_TUN_TYPE,
+ IPVS_DEST_ATTR_TUN_PORT,
__IPVS_DEST_ATTR_MAX,
};
#define IPVS_DEST_ATTR_MAX (__IPVS_DEST_ATTR_MAX - 1)
diff --git a/libc/kernel/uapi/linux/kfd_ioctl.h b/libc/kernel/uapi/linux/kfd_ioctl.h
index 5e2060617..400c4239d 100644
--- a/libc/kernel/uapi/linux/kfd_ioctl.h
+++ b/libc/kernel/uapi/linux/kfd_ioctl.h
@@ -148,6 +148,10 @@ struct kfd_ioctl_dbg_wave_control_args {
#define KFD_HW_EXCEPTION_PER_ENGINE_RESET 1
#define KFD_HW_EXCEPTION_GPU_HANG 0
#define KFD_HW_EXCEPTION_ECC 1
+#define KFD_MEM_ERR_NO_RAS 0
+#define KFD_MEM_ERR_SRAM_ECC 1
+#define KFD_MEM_ERR_POISON_CONSUMED 2
+#define KFD_MEM_ERR_GPU_HANG 3
struct kfd_ioctl_create_event_args {
__u64 event_page_offset;
__u32 event_trigger_data;
@@ -179,7 +183,7 @@ struct kfd_hsa_memory_exception_data {
struct kfd_memory_exception_failure failure;
__u64 va;
__u32 gpu_id;
- __u32 pad;
+ __u32 ErrorType;
};
struct kfd_hsa_hw_exception_data {
__u32 reset_type;
diff --git a/libc/kernel/uapi/linux/kvm.h b/libc/kernel/uapi/linux/kvm.h
index 8cfa34d76..374b0d15e 100644
--- a/libc/kernel/uapi/linux/kvm.h
+++ b/libc/kernel/uapi/linux/kvm.h
@@ -770,6 +770,11 @@ struct kvm_ppc_resize_hpt {
#define KVM_CAP_ARM_VM_IPA_SIZE 165
#define KVM_CAP_MANUAL_DIRTY_LOG_PROTECT 166
#define KVM_CAP_HYPERV_CPUID 167
+#define KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 168
+#define KVM_CAP_PPC_IRQ_XIVE 169
+#define KVM_CAP_ARM_SVE 170
+#define KVM_CAP_ARM_PTRAUTH_ADDRESS 171
+#define KVM_CAP_ARM_PTRAUTH_GENERIC 172
#ifdef KVM_CAP_IRQ_ROUTING
struct kvm_irq_routing_irqchip {
__u32 irqchip;
@@ -886,6 +891,7 @@ struct kvm_dirty_tlb {
#define KVM_REG_SIZE_U256 0x0050000000000000ULL
#define KVM_REG_SIZE_U512 0x0060000000000000ULL
#define KVM_REG_SIZE_U1024 0x0070000000000000ULL
+#define KVM_REG_SIZE_U2048 0x0080000000000000ULL
struct kvm_reg_list {
__u64 n;
__u64 reg[0];
@@ -940,6 +946,8 @@ enum kvm_device_type {
#define KVM_DEV_TYPE_ARM_VGIC_V3 KVM_DEV_TYPE_ARM_VGIC_V3
KVM_DEV_TYPE_ARM_VGIC_ITS,
#define KVM_DEV_TYPE_ARM_VGIC_ITS KVM_DEV_TYPE_ARM_VGIC_ITS
+ KVM_DEV_TYPE_XIVE,
+#define KVM_DEV_TYPE_XIVE KVM_DEV_TYPE_XIVE
KVM_DEV_TYPE_MAX,
};
struct kvm_vfio_spapr_tce {
@@ -1083,6 +1091,7 @@ struct kvm_enc_region {
#define KVM_SET_NESTED_STATE _IOW(KVMIO, 0xbf, struct kvm_nested_state)
#define KVM_CLEAR_DIRTY_LOG _IOWR(KVMIO, 0xc0, struct kvm_clear_dirty_log)
#define KVM_GET_SUPPORTED_HV_CPUID _IOWR(KVMIO, 0xc1, struct kvm_cpuid2)
+#define KVM_ARM_VCPU_FINALIZE _IOW(KVMIO, 0xc2, int)
enum sev_cmd_id {
KVM_SEV_INIT = 0,
KVM_SEV_ES_INIT,
diff --git a/libc/kernel/uapi/linux/lirc.h b/libc/kernel/uapi/linux/lirc.h
index 515d8ce90..20b08e9ed 100644
--- a/libc/kernel/uapi/linux/lirc.h
+++ b/libc/kernel/uapi/linux/lirc.h
@@ -130,5 +130,6 @@ enum rc_proto {
RC_PROTO_RCMM12 = 24,
RC_PROTO_RCMM24 = 25,
RC_PROTO_RCMM32 = 26,
+ RC_PROTO_XBOX_DVD = 27,
};
#endif
diff --git a/libc/kernel/uapi/linux/media-bus-format.h b/libc/kernel/uapi/linux/media-bus-format.h
index 7c701b1ca..1b1300215 100644
--- a/libc/kernel/uapi/linux/media-bus-format.h
+++ b/libc/kernel/uapi/linux/media-bus-format.h
@@ -34,6 +34,7 @@
#define MEDIA_BUS_FMT_RGB666_1X24_CPADHI 0x1015
#define MEDIA_BUS_FMT_RGB666_1X7X3_SPWG 0x1010
#define MEDIA_BUS_FMT_BGR888_1X24 0x1013
+#define MEDIA_BUS_FMT_BGR888_3X8 0x101b
#define MEDIA_BUS_FMT_GBR888_1X24 0x1014
#define MEDIA_BUS_FMT_RGB888_1X24 0x100a
#define MEDIA_BUS_FMT_RGB888_2X12_BE 0x100b
diff --git a/libc/kernel/uapi/linux/media.h b/libc/kernel/uapi/linux/media.h
index 4ba0ef669..68821e70c 100644
--- a/libc/kernel/uapi/linux/media.h
+++ b/libc/kernel/uapi/linux/media.h
@@ -141,6 +141,10 @@ struct media_links_enum {
#define MEDIA_INTF_T_V4L_SUBDEV (MEDIA_INTF_T_V4L_BASE + 3)
#define MEDIA_INTF_T_V4L_SWRADIO (MEDIA_INTF_T_V4L_BASE + 4)
#define MEDIA_INTF_T_V4L_TOUCH (MEDIA_INTF_T_V4L_BASE + 5)
+#define MEDIA_INTF_T_ALSA_BASE 0x00000300
+#define MEDIA_INTF_T_ALSA_PCM_CAPTURE (MEDIA_INTF_T_ALSA_BASE)
+#define MEDIA_INTF_T_ALSA_PCM_PLAYBACK (MEDIA_INTF_T_ALSA_BASE + 1)
+#define MEDIA_INTF_T_ALSA_CONTROL (MEDIA_INTF_T_ALSA_BASE + 2)
#define MEDIA_V2_ENTITY_HAS_FLAGS(media_version) ((media_version) >= ((4 << 16) | (19 << 8) | 0))
struct media_v2_entity {
__u32 id;
@@ -219,10 +223,6 @@ struct media_v2_topology {
#define MEDIA_ENT_T_V4L2_SUBDEV_DECODER MEDIA_ENT_F_ATV_DECODER
#define MEDIA_ENT_T_V4L2_SUBDEV_TUNER MEDIA_ENT_F_TUNER
#define MEDIA_ENT_F_DTV_DECODER MEDIA_ENT_F_DV_DECODER
-#define MEDIA_INTF_T_ALSA_BASE 0x00000300
-#define MEDIA_INTF_T_ALSA_PCM_CAPTURE (MEDIA_INTF_T_ALSA_BASE)
-#define MEDIA_INTF_T_ALSA_PCM_PLAYBACK (MEDIA_INTF_T_ALSA_BASE + 1)
-#define MEDIA_INTF_T_ALSA_CONTROL (MEDIA_INTF_T_ALSA_BASE + 2)
#define MEDIA_INTF_T_ALSA_COMPRESS (MEDIA_INTF_T_ALSA_BASE + 3)
#define MEDIA_INTF_T_ALSA_RAWMIDI (MEDIA_INTF_T_ALSA_BASE + 4)
#define MEDIA_INTF_T_ALSA_HWDEP (MEDIA_INTF_T_ALSA_BASE + 5)
diff --git a/libc/kernel/uapi/linux/mount.h b/libc/kernel/uapi/linux/mount.h
index 54a471968..10c53a506 100644
--- a/libc/kernel/uapi/linux/mount.h
+++ b/libc/kernel/uapi/linux/mount.h
@@ -52,4 +52,38 @@
#define MS_RMT_MASK (MS_RDONLY | MS_SYNCHRONOUS | MS_MANDLOCK | MS_I_VERSION | MS_LAZYTIME)
#define MS_MGC_VAL 0xC0ED0000
#define MS_MGC_MSK 0xffff0000
+#define OPEN_TREE_CLONE 1
+#define OPEN_TREE_CLOEXEC O_CLOEXEC
+#define MOVE_MOUNT_F_SYMLINKS 0x00000001
+#define MOVE_MOUNT_F_AUTOMOUNTS 0x00000002
+#define MOVE_MOUNT_F_EMPTY_PATH 0x00000004
+#define MOVE_MOUNT_T_SYMLINKS 0x00000010
+#define MOVE_MOUNT_T_AUTOMOUNTS 0x00000020
+#define MOVE_MOUNT_T_EMPTY_PATH 0x00000040
+#define MOVE_MOUNT__MASK 0x00000077
+#define FSOPEN_CLOEXEC 0x00000001
+#define FSPICK_CLOEXEC 0x00000001
+#define FSPICK_SYMLINK_NOFOLLOW 0x00000002
+#define FSPICK_NO_AUTOMOUNT 0x00000004
+#define FSPICK_EMPTY_PATH 0x00000008
+enum fsconfig_command {
+ FSCONFIG_SET_FLAG = 0,
+ FSCONFIG_SET_STRING = 1,
+ FSCONFIG_SET_BINARY = 2,
+ FSCONFIG_SET_PATH = 3,
+ FSCONFIG_SET_PATH_EMPTY = 4,
+ FSCONFIG_SET_FD = 5,
+ FSCONFIG_CMD_CREATE = 6,
+ FSCONFIG_CMD_RECONFIGURE = 7,
+};
+#define FSMOUNT_CLOEXEC 0x00000001
+#define MOUNT_ATTR_RDONLY 0x00000001
+#define MOUNT_ATTR_NOSUID 0x00000002
+#define MOUNT_ATTR_NODEV 0x00000004
+#define MOUNT_ATTR_NOEXEC 0x00000008
+#define MOUNT_ATTR__ATIME 0x00000070
+#define MOUNT_ATTR_RELATIME 0x00000000
+#define MOUNT_ATTR_NOATIME 0x00000010
+#define MOUNT_ATTR_STRICTATIME 0x00000020
+#define MOUNT_ATTR_NODIRATIME 0x00000080
#endif
diff --git a/libc/kernel/uapi/linux/netfilter/nf_tables.h b/libc/kernel/uapi/linux/netfilter/nf_tables.h
index 1043799a0..6869f58f8 100644
--- a/libc/kernel/uapi/linux/netfilter/nf_tables.h
+++ b/libc/kernel/uapi/linux/netfilter/nf_tables.h
@@ -496,7 +496,7 @@ enum nft_ct_keys {
NFT_CT_DST_IP,
NFT_CT_SRC_IP6,
NFT_CT_DST_IP6,
- NFT_CT_TIMEOUT,
+ NFT_CT_ID,
__NFT_CT_MAX
};
#define NFT_CT_MAX (__NFT_CT_MAX - 1)
@@ -574,7 +574,7 @@ enum nft_log_level {
NFT_LOGLEVEL_AUDIT,
__NFT_LOGLEVEL_MAX
};
-#define NFT_LOGLEVEL_MAX (__NFT_LOGLEVEL_MAX + 1)
+#define NFT_LOGLEVEL_MAX (__NFT_LOGLEVEL_MAX - 1)
enum nft_queue_attributes {
NFTA_QUEUE_UNSPEC,
NFTA_QUEUE_NUM,
@@ -786,9 +786,13 @@ enum nft_osf_attributes {
NFTA_OSF_UNSPEC,
NFTA_OSF_DREG,
NFTA_OSF_TTL,
+ NFTA_OSF_FLAGS,
__NFTA_OSF_MAX,
};
#define NFTA_OSF_MAX (__NFTA_OSF_MAX - 1)
+enum nft_osf_flags {
+ NFT_OSF_F_VERSION = (1 << 0),
+};
enum nft_devices_attributes {
NFTA_DEVICE_UNSPEC,
NFTA_DEVICE_NAME,
diff --git a/libc/kernel/uapi/linux/nfs_mount.h b/libc/kernel/uapi/linux/nfs_mount.h
index ddd318abd..5b0022238 100644
--- a/libc/kernel/uapi/linux/nfs_mount.h
+++ b/libc/kernel/uapi/linux/nfs_mount.h
@@ -62,10 +62,4 @@ struct nfs_mount_data {
#define NFS_MOUNT_NORDIRPLUS 0x4000
#define NFS_MOUNT_UNSHARED 0x8000
#define NFS_MOUNT_FLAGMASK 0xFFFF
-#define NFS_MOUNT_LOOKUP_CACHE_NONEG 0x10000
-#define NFS_MOUNT_LOOKUP_CACHE_NONE 0x20000
-#define NFS_MOUNT_NORESVPORT 0x40000
-#define NFS_MOUNT_LEGACY_INTERFACE 0x80000
-#define NFS_MOUNT_LOCAL_FLOCK 0x100000
-#define NFS_MOUNT_LOCAL_FCNTL 0x200000
#endif
diff --git a/libc/kernel/uapi/linux/nfsd/cld.h b/libc/kernel/uapi/linux/nfsd/cld.h
index 82651d13c..ed99e73bf 100644
--- a/libc/kernel/uapi/linux/nfsd/cld.h
+++ b/libc/kernel/uapi/linux/nfsd/cld.h
@@ -26,6 +26,7 @@ enum cld_command {
Cld_Remove,
Cld_Check,
Cld_GraceDone,
+ Cld_GraceStart,
};
struct cld_name {
__u16 cn_len;
diff --git a/libc/kernel/uapi/linux/nilfs2_ondisk.h b/libc/kernel/uapi/linux/nilfs2_ondisk.h
index e9995a11a..a05e7b732 100644
--- a/libc/kernel/uapi/linux/nilfs2_ondisk.h
+++ b/libc/kernel/uapi/linux/nilfs2_ondisk.h
@@ -20,6 +20,7 @@
#define _LINUX_NILFS2_ONDISK_H
#include <linux/types.h>
#include <linux/magic.h>
+#include <asm/byteorder.h>
#define NILFS_INODE_BMAP_SIZE 7
struct nilfs_inode {
__le64 i_blocks;
@@ -248,11 +249,11 @@ enum {
NILFS_CHECKPOINT_MINOR,
};
#define NILFS_CHECKPOINT_FNS(flag,name) static inline void nilfs_checkpoint_set_ ##name(struct nilfs_checkpoint * cp) \
-{ cp->cp_flags = cpu_to_le32(le32_to_cpu(cp->cp_flags) | (1UL << NILFS_CHECKPOINT_ ##flag)); \
+{ cp->cp_flags = __cpu_to_le32(__le32_to_cpu(cp->cp_flags) | (1UL << NILFS_CHECKPOINT_ ##flag)); \
} static inline void nilfs_checkpoint_clear_ ##name(struct nilfs_checkpoint * cp) \
-{ cp->cp_flags = cpu_to_le32(le32_to_cpu(cp->cp_flags) & ~(1UL << NILFS_CHECKPOINT_ ##flag)); \
+{ cp->cp_flags = __cpu_to_le32(__le32_to_cpu(cp->cp_flags) & ~(1UL << NILFS_CHECKPOINT_ ##flag)); \
} static inline int nilfs_checkpoint_ ##name(const struct nilfs_checkpoint * cp) \
-{ return ! ! (le32_to_cpu(cp->cp_flags) & (1UL << NILFS_CHECKPOINT_ ##flag)); \
+{ return ! ! (__le32_to_cpu(cp->cp_flags) & (1UL << NILFS_CHECKPOINT_ ##flag)); \
}
struct nilfs_cpfile_header {
__le64 ch_ncheckpoints;
@@ -272,11 +273,11 @@ enum {
NILFS_SEGMENT_USAGE_ERROR,
};
#define NILFS_SEGMENT_USAGE_FNS(flag,name) static inline void nilfs_segment_usage_set_ ##name(struct nilfs_segment_usage * su) \
-{ su->su_flags = cpu_to_le32(le32_to_cpu(su->su_flags) | (1UL << NILFS_SEGMENT_USAGE_ ##flag)); \
+{ su->su_flags = __cpu_to_le32(__le32_to_cpu(su->su_flags) | (1UL << NILFS_SEGMENT_USAGE_ ##flag)); \
} static inline void nilfs_segment_usage_clear_ ##name(struct nilfs_segment_usage * su) \
-{ su->su_flags = cpu_to_le32(le32_to_cpu(su->su_flags) & ~(1UL << NILFS_SEGMENT_USAGE_ ##flag)); \
+{ su->su_flags = __cpu_to_le32(__le32_to_cpu(su->su_flags) & ~(1UL << NILFS_SEGMENT_USAGE_ ##flag)); \
} static inline int nilfs_segment_usage_ ##name(const struct nilfs_segment_usage * su) \
-{ return ! ! (le32_to_cpu(su->su_flags) & (1UL << NILFS_SEGMENT_USAGE_ ##flag)); \
+{ return ! ! (__le32_to_cpu(su->su_flags) & (1UL << NILFS_SEGMENT_USAGE_ ##flag)); \
}
struct nilfs_sufile_header {
__le64 sh_ncleansegs;
diff --git a/libc/kernel/uapi/linux/nl80211.h b/libc/kernel/uapi/linux/nl80211.h
index a7f63096e..93b219690 100644
--- a/libc/kernel/uapi/linux/nl80211.h
+++ b/libc/kernel/uapi/linux/nl80211.h
@@ -168,6 +168,8 @@ enum nl80211_commands {
NL80211_CMD_PEER_MEASUREMENT_RESULT,
NL80211_CMD_PEER_MEASUREMENT_COMPLETE,
NL80211_CMD_NOTIFY_RADAR,
+ NL80211_CMD_UPDATE_OWE_INFO,
+ NL80211_CMD_PROBE_MESH_LINK,
__NL80211_CMD_AFTER_LAST,
NL80211_CMD_MAX = __NL80211_CMD_AFTER_LAST - 1
};
@@ -459,6 +461,8 @@ enum nl80211_attrs {
NL80211_ATTR_TIMEOUT,
NL80211_ATTR_PEER_MEASUREMENTS,
NL80211_ATTR_AIRTIME_WEIGHT,
+ NL80211_ATTR_STA_TX_POWER_SETTING,
+ NL80211_ATTR_STA_TX_POWER,
__NL80211_ATTR_AFTER_LAST,
NUM_NL80211_ATTR = __NL80211_ATTR_AFTER_LAST,
NL80211_ATTR_MAX = __NL80211_ATTR_AFTER_LAST - 1
@@ -491,7 +495,7 @@ enum nl80211_attrs {
#define NL80211_WIPHY_NAME_MAXLEN 64
#define NL80211_MAX_SUPP_RATES 32
#define NL80211_MAX_SUPP_HT_RATES 77
-#define NL80211_MAX_SUPP_REG_RULES 64
+#define NL80211_MAX_SUPP_REG_RULES 128
#define NL80211_TKIP_DATA_OFFSET_ENCR_KEY 0
#define NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY 16
#define NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY 24
@@ -631,6 +635,7 @@ enum nl80211_sta_info {
NL80211_STA_INFO_CONNECTED_TO_GATE,
NL80211_STA_INFO_TX_DURATION,
NL80211_STA_INFO_AIRTIME_WEIGHT,
+ NL80211_STA_INFO_AIRTIME_LINK_METRIC,
__NL80211_STA_INFO_AFTER_LAST,
NL80211_STA_INFO_MAX = __NL80211_STA_INFO_AFTER_LAST - 1
};
@@ -783,6 +788,7 @@ enum nl80211_sched_scan_match_attr {
NL80211_SCHED_SCAN_MATCH_ATTR_RELATIVE_RSSI,
NL80211_SCHED_SCAN_MATCH_ATTR_RSSI_ADJUST,
NL80211_SCHED_SCAN_MATCH_ATTR_BSSID,
+ NL80211_SCHED_SCAN_MATCH_PER_BAND_RSSI,
__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST,
NL80211_SCHED_SCAN_MATCH_ATTR_MAX = __NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST - 1
};
@@ -935,6 +941,11 @@ enum nl80211_channel_type {
NL80211_CHAN_HT40MINUS,
NL80211_CHAN_HT40PLUS
};
+enum nl80211_key_mode {
+ NL80211_KEY_RX_TX,
+ NL80211_KEY_NO_TX,
+ NL80211_KEY_SET_TX
+};
enum nl80211_chan_width {
NL80211_CHAN_WIDTH_20_NOHT,
NL80211_CHAN_WIDTH_20,
@@ -1023,6 +1034,7 @@ enum nl80211_key_attributes {
NL80211_KEY_DEFAULT_MGMT,
NL80211_KEY_TYPE,
NL80211_KEY_DEFAULT_TYPES,
+ NL80211_KEY_MODE,
__NL80211_KEY_AFTER_LAST,
NL80211_KEY_MAX = __NL80211_KEY_AFTER_LAST - 1
};
@@ -1311,6 +1323,9 @@ enum nl80211_ext_feature_index {
NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER,
NL80211_EXT_FEATURE_AIRTIME_FAIRNESS,
NL80211_EXT_FEATURE_AP_PMKSA_CACHING,
+ NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD,
+ NL80211_EXT_FEATURE_EXT_KEY_ID,
+ NL80211_EXT_FEATURE_STA_TX_PWR,
NUM_NL80211_EXT_FEATURES,
MAX_NL80211_EXT_FEATURES = NUM_NL80211_EXT_FEATURES - 1
};
diff --git a/libc/kernel/uapi/linux/openvswitch.h b/libc/kernel/uapi/linux/openvswitch.h
index 7e75ac6f6..2344ab19e 100644
--- a/libc/kernel/uapi/linux/openvswitch.h
+++ b/libc/kernel/uapi/linux/openvswitch.h
@@ -205,6 +205,7 @@ enum ovs_tunnel_key_attr {
OVS_TUNNEL_KEY_ATTR_IPV6_DST,
OVS_TUNNEL_KEY_ATTR_PAD,
OVS_TUNNEL_KEY_ATTR_ERSPAN_OPTS,
+ OVS_TUNNEL_KEY_ATTR_IPV4_INFO_BRIDGE,
__OVS_TUNNEL_KEY_ATTR_MAX
};
#define OVS_TUNNEL_KEY_ATTR_MAX (__OVS_TUNNEL_KEY_ATTR_MAX - 1)
@@ -384,6 +385,7 @@ enum ovs_ct_attr {
OVS_CT_ATTR_NAT,
OVS_CT_ATTR_FORCE_COMMIT,
OVS_CT_ATTR_EVENTMASK,
+ OVS_CT_ATTR_TIMEOUT,
__OVS_CT_ATTR_MAX
};
#define OVS_CT_ATTR_MAX (__OVS_CT_ATTR_MAX - 1)
@@ -404,6 +406,14 @@ enum ovs_nat_attr {
struct ovs_action_push_eth {
struct ovs_key_ethernet addresses;
};
+enum ovs_check_pkt_len_attr {
+ OVS_CHECK_PKT_LEN_ATTR_UNSPEC,
+ OVS_CHECK_PKT_LEN_ATTR_PKT_LEN,
+ OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_GREATER,
+ OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_LESS_EQUAL,
+ __OVS_CHECK_PKT_LEN_ATTR_MAX,
+};
+#define OVS_CHECK_PKT_LEN_ATTR_MAX (__OVS_CHECK_PKT_LEN_ATTR_MAX - 1)
enum ovs_action_attr {
OVS_ACTION_ATTR_UNSPEC,
OVS_ACTION_ATTR_OUTPUT,
@@ -426,6 +436,7 @@ enum ovs_action_attr {
OVS_ACTION_ATTR_POP_NSH,
OVS_ACTION_ATTR_METER,
OVS_ACTION_ATTR_CLONE,
+ OVS_ACTION_ATTR_CHECK_PKT_LEN,
__OVS_ACTION_ATTR_MAX,
};
#define OVS_ACTION_ATTR_MAX (__OVS_ACTION_ATTR_MAX - 1)
diff --git a/libc/kernel/uapi/linux/pci_regs.h b/libc/kernel/uapi/linux/pci_regs.h
index d75d200e9..4c8cc9583 100644
--- a/libc/kernel/uapi/linux/pci_regs.h
+++ b/libc/kernel/uapi/linux/pci_regs.h
@@ -275,7 +275,7 @@
#define PCI_MSIX_ENTRY_UPPER_ADDR 4
#define PCI_MSIX_ENTRY_DATA 8
#define PCI_MSIX_ENTRY_VECTOR_CTRL 12
-#define PCI_MSIX_ENTRY_CTRL_MASKBIT 1
+#define PCI_MSIX_ENTRY_CTRL_MASKBIT 0x00000001
#define PCI_CHSWP_CSR 2
#define PCI_CHSWP_DHA 0x01
#define PCI_CHSWP_EIM 0x02
@@ -299,6 +299,9 @@
#define PCI_EA_FIRST_ENT_BRIDGE 8
#define PCI_EA_ES 0x00000007
#define PCI_EA_BEI 0x000000f0
+#define PCI_EA_SEC_BUS_MASK 0xff
+#define PCI_EA_SUB_BUS_MASK 0xff00
+#define PCI_EA_SUB_BUS_SHIFT 8
#define PCI_EA_BEI_BAR0 0
#define PCI_EA_BEI_BAR5 5
#define PCI_EA_BEI_BRIDGE 6
@@ -746,12 +749,12 @@
#define PCI_ATS_MIN_STU 12
#define PCI_EXT_CAP_ATS_SIZEOF 8
#define PCI_PRI_CTRL 0x04
-#define PCI_PRI_CTRL_ENABLE 0x01
-#define PCI_PRI_CTRL_RESET 0x02
+#define PCI_PRI_CTRL_ENABLE 0x0001
+#define PCI_PRI_CTRL_RESET 0x0002
#define PCI_PRI_STATUS 0x06
-#define PCI_PRI_STATUS_RF 0x001
-#define PCI_PRI_STATUS_UPRGI 0x002
-#define PCI_PRI_STATUS_STOPPED 0x100
+#define PCI_PRI_STATUS_RF 0x0001
+#define PCI_PRI_STATUS_UPRGI 0x0002
+#define PCI_PRI_STATUS_STOPPED 0x0100
#define PCI_PRI_STATUS_PASID 0x8000
#define PCI_PRI_MAX_REQ 0x08
#define PCI_PRI_ALLOC_REQ 0x0c
@@ -765,16 +768,16 @@
#define PCI_PASID_CTRL_PRIV 0x04
#define PCI_EXT_CAP_PASID_SIZEOF 8
#define PCI_SRIOV_CAP 0x04
-#define PCI_SRIOV_CAP_VFM 0x01
+#define PCI_SRIOV_CAP_VFM 0x00000001
#define PCI_SRIOV_CAP_INTR(x) ((x) >> 21)
#define PCI_SRIOV_CTRL 0x08
-#define PCI_SRIOV_CTRL_VFE 0x01
-#define PCI_SRIOV_CTRL_VFM 0x02
-#define PCI_SRIOV_CTRL_INTR 0x04
-#define PCI_SRIOV_CTRL_MSE 0x08
-#define PCI_SRIOV_CTRL_ARI 0x10
+#define PCI_SRIOV_CTRL_VFE 0x0001
+#define PCI_SRIOV_CTRL_VFM 0x0002
+#define PCI_SRIOV_CTRL_INTR 0x0004
+#define PCI_SRIOV_CTRL_MSE 0x0008
+#define PCI_SRIOV_CTRL_ARI 0x0010
#define PCI_SRIOV_STATUS 0x0a
-#define PCI_SRIOV_STATUS_VFM 0x01
+#define PCI_SRIOV_STATUS_VFM 0x0001
#define PCI_SRIOV_INITIAL_VF 0x0c
#define PCI_SRIOV_TOTAL_VF 0x0e
#define PCI_SRIOV_NUM_VF 0x10
@@ -801,13 +804,13 @@
#define PCI_LTR_SCALE_SHIFT 10
#define PCI_EXT_CAP_LTR_SIZEOF 8
#define PCI_ACS_CAP 0x04
-#define PCI_ACS_SV 0x01
-#define PCI_ACS_TB 0x02
-#define PCI_ACS_RR 0x04
-#define PCI_ACS_CR 0x08
-#define PCI_ACS_UF 0x10
-#define PCI_ACS_EC 0x20
-#define PCI_ACS_DT 0x40
+#define PCI_ACS_SV 0x0001
+#define PCI_ACS_TB 0x0002
+#define PCI_ACS_RR 0x0004
+#define PCI_ACS_CR 0x0008
+#define PCI_ACS_UF 0x0010
+#define PCI_ACS_EC 0x0020
+#define PCI_ACS_DT 0x0040
#define PCI_ACS_EGRESS_BITS 0x05
#define PCI_ACS_CTRL 0x06
#define PCI_ACS_EGRESS_CTL_V 0x08
diff --git a/libc/kernel/uapi/linux/pkt_sched.h b/libc/kernel/uapi/linux/pkt_sched.h
index 6adc01307..2e1f24b7d 100644
--- a/libc/kernel/uapi/linux/pkt_sched.h
+++ b/libc/kernel/uapi/linux/pkt_sched.h
@@ -883,6 +883,9 @@ enum {
TCA_TAPRIO_ATTR_SCHED_SINGLE_ENTRY,
TCA_TAPRIO_ATTR_SCHED_CLOCKID,
TCA_TAPRIO_PAD,
+ TCA_TAPRIO_ATTR_ADMIN_SCHED,
+ TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME,
+ TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME_EXTENSION,
__TCA_TAPRIO_ATTR_MAX,
};
#define TCA_TAPRIO_ATTR_MAX (__TCA_TAPRIO_ATTR_MAX - 1)
diff --git a/libc/kernel/uapi/linux/psci.h b/libc/kernel/uapi/linux/psci.h
index 658552a6f..bc522e78f 100644
--- a/libc/kernel/uapi/linux/psci.h
+++ b/libc/kernel/uapi/linux/psci.h
@@ -40,7 +40,10 @@
#define PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU PSCI_0_2_FN64(7)
#define PSCI_1_0_FN_PSCI_FEATURES PSCI_0_2_FN(10)
#define PSCI_1_0_FN_SYSTEM_SUSPEND PSCI_0_2_FN(14)
+#define PSCI_1_0_FN_SET_SUSPEND_MODE PSCI_0_2_FN(15)
+#define PSCI_1_1_FN_SYSTEM_RESET2 PSCI_0_2_FN(18)
#define PSCI_1_0_FN64_SYSTEM_SUSPEND PSCI_0_2_FN64(14)
+#define PSCI_1_1_FN64_SYSTEM_RESET2 PSCI_0_2_FN64(18)
#define PSCI_0_2_POWER_STATE_ID_MASK 0xffff
#define PSCI_0_2_POWER_STATE_ID_SHIFT 0
#define PSCI_0_2_POWER_STATE_TYPE_SHIFT 16
@@ -65,6 +68,9 @@
#define PSCI_VERSION(maj,min) ((((maj) << PSCI_VERSION_MAJOR_SHIFT) & PSCI_VERSION_MAJOR_MASK) | ((min) & PSCI_VERSION_MINOR_MASK))
#define PSCI_1_0_FEATURES_CPU_SUSPEND_PF_SHIFT 1
#define PSCI_1_0_FEATURES_CPU_SUSPEND_PF_MASK (0x1 << PSCI_1_0_FEATURES_CPU_SUSPEND_PF_SHIFT)
+#define PSCI_1_0_OS_INITIATED BIT(0)
+#define PSCI_1_0_SUSPEND_MODE_PC 0
+#define PSCI_1_0_SUSPEND_MODE_OSI 1
#define PSCI_RET_SUCCESS 0
#define PSCI_RET_NOT_SUPPORTED - 1
#define PSCI_RET_INVALID_PARAMS - 2
diff --git a/libc/kernel/uapi/linux/psp-sev.h b/libc/kernel/uapi/linux/psp-sev.h
index 10582d48a..b3f88dc2f 100644
--- a/libc/kernel/uapi/linux/psp-sev.h
+++ b/libc/kernel/uapi/linux/psp-sev.h
@@ -28,6 +28,7 @@ enum {
SEV_PDH_CERT_EXPORT,
SEV_PEK_CERT_IMPORT,
SEV_GET_ID,
+ SEV_GET_ID2,
SEV_MAX,
};
typedef enum {
@@ -83,6 +84,10 @@ struct sev_user_data_get_id {
__u8 socket1[64];
__u8 socket2[64];
} __packed;
+struct sev_user_data_get_id2 {
+ __u64 address;
+ __u32 length;
+} __packed;
struct sev_issue_cmd {
__u32 cmd;
__u64 data;
diff --git a/libc/kernel/uapi/linux/sched.h b/libc/kernel/uapi/linux/sched.h
index 20d4956a7..046008391 100644
--- a/libc/kernel/uapi/linux/sched.h
+++ b/libc/kernel/uapi/linux/sched.h
@@ -23,6 +23,7 @@
#define CLONE_FS 0x00000200
#define CLONE_FILES 0x00000400
#define CLONE_SIGHAND 0x00000800
+#define CLONE_PIDFD 0x00001000
#define CLONE_PTRACE 0x00002000
#define CLONE_VFORK 0x00004000
#define CLONE_PARENT 0x00008000
diff --git a/libc/kernel/uapi/linux/serial_core.h b/libc/kernel/uapi/linux/serial_core.h
index 791f5d7f6..c5ce9fe02 100644
--- a/libc/kernel/uapi/linux/serial_core.h
+++ b/libc/kernel/uapi/linux/serial_core.h
@@ -136,4 +136,6 @@
#define PORT_MPS2UART 116
#define PORT_MTK_BTIF 117
#define PORT_RDA 118
+#define PORT_MLB_USIO 119
+#define PORT_SIFIVE_V0 120
#endif
diff --git a/libc/kernel/uapi/linux/snmp.h b/libc/kernel/uapi/linux/snmp.h
index 75dea5495..2a48541fc 100644
--- a/libc/kernel/uapi/linux/snmp.h
+++ b/libc/kernel/uapi/linux/snmp.h
@@ -250,6 +250,7 @@ enum {
LINUX_MIB_TCPACKCOMPRESSED,
LINUX_MIB_TCPZEROWINDOWDROP,
LINUX_MIB_TCPRCVQDROP,
+ LINUX_MIB_TCPWQUEUETOOBIG,
__LINUX_MIB_MAX
};
enum {
diff --git a/libc/kernel/uapi/linux/sockios.h b/libc/kernel/uapi/linux/sockios.h
index c68a5b137..2d13d9380 100644
--- a/libc/kernel/uapi/linux/sockios.h
+++ b/libc/kernel/uapi/linux/sockios.h
@@ -18,10 +18,20 @@
****************************************************************************/
#ifndef _LINUX_SOCKIOS_H
#define _LINUX_SOCKIOS_H
+#include <asm/bitsperlong.h>
#include <asm/sockios.h>
#define SIOCINQ FIONREAD
#define SIOCOUTQ TIOCOUTQ
#define SOCK_IOC_TYPE 0x89
+#define SIOCGSTAMP_NEW _IOR(SOCK_IOC_TYPE, 0x06, long long[2])
+#define SIOCGSTAMPNS_NEW _IOR(SOCK_IOC_TYPE, 0x07, long long[2])
+#if __BITS_PER_LONG == 64 || defined(__x86_64__) && defined(__ILP32__)
+#define SIOCGSTAMP SIOCGSTAMP_OLD
+#define SIOCGSTAMPNS SIOCGSTAMPNS_OLD
+#else
+#define SIOCGSTAMP ((sizeof(struct timeval)) == 8 ? SIOCGSTAMP_OLD : SIOCGSTAMP_NEW)
+#define SIOCGSTAMPNS ((sizeof(struct timespec)) == 8 ? SIOCGSTAMPNS_OLD : SIOCGSTAMPNS_NEW)
+#endif
#define SIOCADDRT 0x890B
#define SIOCDELRT 0x890C
#define SIOCRTMSG 0x890D
diff --git a/libc/kernel/uapi/linux/spi/spidev.h b/libc/kernel/uapi/linux/spi/spidev.h
index 2fe826445..343285b20 100644
--- a/libc/kernel/uapi/linux/spi/spidev.h
+++ b/libc/kernel/uapi/linux/spi/spidev.h
@@ -47,7 +47,8 @@ struct spi_ioc_transfer {
__u8 cs_change;
__u8 tx_nbits;
__u8 rx_nbits;
- __u16 pad;
+ __u8 word_delay_usecs;
+ __u8 pad;
};
#define SPI_MSGSIZE(N) ((((N) * (sizeof(struct spi_ioc_transfer))) < (1 << _IOC_SIZEBITS)) ? ((N) * (sizeof(struct spi_ioc_transfer))) : 0)
#define SPI_IOC_MESSAGE(N) _IOW(SPI_IOC_MAGIC, 0, char[SPI_MSGSIZE(N)])
diff --git a/libc/kernel/uapi/linux/switchtec_ioctl.h b/libc/kernel/uapi/linux/switchtec_ioctl.h
index 09cf9cdba..2143148e6 100644
--- a/libc/kernel/uapi/linux/switchtec_ioctl.h
+++ b/libc/kernel/uapi/linux/switchtec_ioctl.h
@@ -46,7 +46,7 @@ struct switchtec_ioctl_flash_part_info {
__u32 length;
__u32 active;
};
-struct switchtec_ioctl_event_summary {
+struct switchtec_ioctl_event_summary_legacy {
__u64 global;
__u64 part_bitmap;
__u32 local_part;
@@ -54,6 +54,14 @@ struct switchtec_ioctl_event_summary {
__u32 part[48];
__u32 pff[48];
};
+struct switchtec_ioctl_event_summary {
+ __u64 global;
+ __u64 part_bitmap;
+ __u32 local_part;
+ __u32 padding;
+ __u32 part[48];
+ __u32 pff[255];
+};
#define SWITCHTEC_IOCTL_EVENT_STACK_ERROR 0
#define SWITCHTEC_IOCTL_EVENT_PPU_ERROR 1
#define SWITCHTEC_IOCTL_EVENT_ISP_ERROR 2
@@ -114,6 +122,7 @@ struct switchtec_ioctl_pff_port {
#define SWITCHTEC_IOCTL_FLASH_INFO _IOR('W', 0x40, struct switchtec_ioctl_flash_info)
#define SWITCHTEC_IOCTL_FLASH_PART_INFO _IOWR('W', 0x41, struct switchtec_ioctl_flash_part_info)
#define SWITCHTEC_IOCTL_EVENT_SUMMARY _IOR('W', 0x42, struct switchtec_ioctl_event_summary)
+#define SWITCHTEC_IOCTL_EVENT_SUMMARY_LEGACY _IOR('W', 0x42, struct switchtec_ioctl_event_summary_legacy)
#define SWITCHTEC_IOCTL_EVENT_CTL _IOWR('W', 0x43, struct switchtec_ioctl_event_ctl)
#define SWITCHTEC_IOCTL_PFF_TO_PORT _IOWR('W', 0x44, struct switchtec_ioctl_pff_port)
#define SWITCHTEC_IOCTL_PORT_TO_PFF _IOWR('W', 0x45, struct switchtec_ioctl_pff_port)
diff --git a/libc/kernel/uapi/linux/tipc.h b/libc/kernel/uapi/linux/tipc.h
index 72bcad97d..b66b3400d 100644
--- a/libc/kernel/uapi/linux/tipc.h
+++ b/libc/kernel/uapi/linux/tipc.h
@@ -111,6 +111,7 @@ struct sockaddr_tipc {
#define TIPC_MCAST_REPLICAST 134
#define TIPC_GROUP_JOIN 135
#define TIPC_GROUP_LEAVE 136
+#define TIPC_SOCK_RECVQ_USED 137
#define TIPC_GROUP_LOOPBACK 0x1
#define TIPC_GROUP_MEMBER_EVTS 0x2
struct tipc_group_req {
diff --git a/libc/kernel/uapi/linux/tipc_netlink.h b/libc/kernel/uapi/linux/tipc_netlink.h
index 911bbdea1..372111819 100644
--- a/libc/kernel/uapi/linux/tipc_netlink.h
+++ b/libc/kernel/uapi/linux/tipc_netlink.h
@@ -212,6 +212,8 @@ enum {
TIPC_NLA_PROP_TOL,
TIPC_NLA_PROP_WIN,
TIPC_NLA_PROP_MTU,
+ TIPC_NLA_PROP_BROADCAST,
+ TIPC_NLA_PROP_BROADCAST_RATIO,
__TIPC_NLA_PROP_MAX,
TIPC_NLA_PROP_MAX = __TIPC_NLA_PROP_MAX - 1
};
diff --git a/libc/kernel/uapi/linux/tls.h b/libc/kernel/uapi/linux/tls.h
index 96bb3a56e..e18882634 100644
--- a/libc/kernel/uapi/linux/tls.h
+++ b/libc/kernel/uapi/linux/tls.h
@@ -42,6 +42,12 @@
#define TLS_CIPHER_AES_GCM_256_SALT_SIZE 4
#define TLS_CIPHER_AES_GCM_256_TAG_SIZE 16
#define TLS_CIPHER_AES_GCM_256_REC_SEQ_SIZE 8
+#define TLS_CIPHER_AES_CCM_128 53
+#define TLS_CIPHER_AES_CCM_128_IV_SIZE 8
+#define TLS_CIPHER_AES_CCM_128_KEY_SIZE 16
+#define TLS_CIPHER_AES_CCM_128_SALT_SIZE 4
+#define TLS_CIPHER_AES_CCM_128_TAG_SIZE 16
+#define TLS_CIPHER_AES_CCM_128_REC_SEQ_SIZE 8
#define TLS_SET_RECORD_TYPE 1
#define TLS_GET_RECORD_TYPE 2
struct tls_crypto_info {
@@ -62,4 +68,11 @@ struct tls12_crypto_info_aes_gcm_256 {
unsigned char salt[TLS_CIPHER_AES_GCM_256_SALT_SIZE];
unsigned char rec_seq[TLS_CIPHER_AES_GCM_256_REC_SEQ_SIZE];
};
+struct tls12_crypto_info_aes_ccm_128 {
+ struct tls_crypto_info info;
+ unsigned char iv[TLS_CIPHER_AES_CCM_128_IV_SIZE];
+ unsigned char key[TLS_CIPHER_AES_CCM_128_KEY_SIZE];
+ unsigned char salt[TLS_CIPHER_AES_CCM_128_SALT_SIZE];
+ unsigned char rec_seq[TLS_CIPHER_AES_CCM_128_REC_SEQ_SIZE];
+};
#endif
diff --git a/libc/kernel/uapi/linux/v4l2-controls.h b/libc/kernel/uapi/linux/v4l2-controls.h
index e8108dd10..7a133f538 100644
--- a/libc/kernel/uapi/linux/v4l2-controls.h
+++ b/libc/kernel/uapi/linux/v4l2-controls.h
@@ -310,6 +310,8 @@ enum v4l2_mpeg_video_multi_slice_mode {
#define V4L2_CID_MPEG_VIDEO_MV_H_SEARCH_RANGE (V4L2_CID_MPEG_BASE + 227)
#define V4L2_CID_MPEG_VIDEO_MV_V_SEARCH_RANGE (V4L2_CID_MPEG_BASE + 228)
#define V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME (V4L2_CID_MPEG_BASE + 229)
+#define V4L2_CID_FWHT_I_FRAME_QP (V4L2_CID_MPEG_BASE + 290)
+#define V4L2_CID_FWHT_P_FRAME_QP (V4L2_CID_MPEG_BASE + 291)
#define V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP (V4L2_CID_MPEG_BASE + 300)
#define V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP (V4L2_CID_MPEG_BASE + 301)
#define V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP (V4L2_CID_MPEG_BASE + 302)
@@ -441,6 +443,10 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type {
#define V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_QP (V4L2_CID_MPEG_BASE + 382)
#define V4L2_CID_MPEG_VIDEO_H264_CONSTRAINED_INTRA_PREDICTION (V4L2_CID_MPEG_BASE + 383)
#define V4L2_CID_MPEG_VIDEO_H264_CHROMA_QP_INDEX_OFFSET (V4L2_CID_MPEG_BASE + 384)
+#define V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MIN_QP (V4L2_CID_MPEG_BASE + 385)
+#define V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MAX_QP (V4L2_CID_MPEG_BASE + 386)
+#define V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MIN_QP (V4L2_CID_MPEG_BASE + 387)
+#define V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MAX_QP (V4L2_CID_MPEG_BASE + 388)
#define V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP (V4L2_CID_MPEG_BASE + 400)
#define V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP (V4L2_CID_MPEG_BASE + 401)
#define V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP (V4L2_CID_MPEG_BASE + 402)
diff --git a/libc/kernel/uapi/linux/version.h b/libc/kernel/uapi/linux/version.h
index 5905e81de..94bf4ba5e 100644
--- a/libc/kernel/uapi/linux/version.h
+++ b/libc/kernel/uapi/linux/version.h
@@ -16,5 +16,5 @@
***
****************************************************************************
****************************************************************************/
-#define LINUX_VERSION_CODE 327939
+#define LINUX_VERSION_CODE 328198
#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
diff --git a/libc/kernel/uapi/linux/vfio.h b/libc/kernel/uapi/linux/vfio.h
index b947abce2..62cd970ab 100644
--- a/libc/kernel/uapi/linux/vfio.h
+++ b/libc/kernel/uapi/linux/vfio.h
@@ -114,6 +114,8 @@ struct vfio_region_gfx_edid {
#define VFIO_DEVICE_GFX_LINK_STATE_UP 1
#define VFIO_DEVICE_GFX_LINK_STATE_DOWN 2
};
+#define VFIO_REGION_TYPE_CCW (2)
+#define VFIO_REGION_SUBTYPE_CCW_ASYNC_CMD (1)
#define VFIO_REGION_SUBTYPE_NVIDIA_NVLINK2_RAM (1)
#define VFIO_REGION_SUBTYPE_IBM_NVLINK2_ATSD (1)
#define VFIO_REGION_INFO_CAP_MSIX_MAPPABLE 3
diff --git a/libc/kernel/uapi/linux/vfio_ccw.h b/libc/kernel/uapi/linux/vfio_ccw.h
index 047862fd9..6ed6830e4 100644
--- a/libc/kernel/uapi/linux/vfio_ccw.h
+++ b/libc/kernel/uapi/linux/vfio_ccw.h
@@ -28,4 +28,10 @@ struct ccw_io_region {
__u8 irb_area[IRB_AREA_SIZE];
__u32 ret_code;
} __packed;
+#define VFIO_CCW_ASYNC_CMD_HSCH (1 << 0)
+#define VFIO_CCW_ASYNC_CMD_CSCH (1 << 1)
+struct ccw_cmd_region {
+ __u32 command;
+ __u32 ret_code;
+} __packed;
#endif
diff --git a/libc/kernel/uapi/linux/videodev2.h b/libc/kernel/uapi/linux/videodev2.h
index 3bd71381f..f77c6bda5 100644
--- a/libc/kernel/uapi/linux/videodev2.h
+++ b/libc/kernel/uapi/linux/videodev2.h
@@ -206,9 +206,21 @@ struct v4l2_pix_format {
#define V4L2_PIX_FMT_RGB444 v4l2_fourcc('R', '4', '4', '4')
#define V4L2_PIX_FMT_ARGB444 v4l2_fourcc('A', 'R', '1', '2')
#define V4L2_PIX_FMT_XRGB444 v4l2_fourcc('X', 'R', '1', '2')
+#define V4L2_PIX_FMT_RGBA444 v4l2_fourcc('R', 'A', '1', '2')
+#define V4L2_PIX_FMT_RGBX444 v4l2_fourcc('R', 'X', '1', '2')
+#define V4L2_PIX_FMT_ABGR444 v4l2_fourcc('A', 'B', '1', '2')
+#define V4L2_PIX_FMT_XBGR444 v4l2_fourcc('X', 'B', '1', '2')
+#define V4L2_PIX_FMT_BGRA444 v4l2_fourcc('G', 'A', '1', '2')
+#define V4L2_PIX_FMT_BGRX444 v4l2_fourcc('B', 'X', '1', '2')
#define V4L2_PIX_FMT_RGB555 v4l2_fourcc('R', 'G', 'B', 'O')
#define V4L2_PIX_FMT_ARGB555 v4l2_fourcc('A', 'R', '1', '5')
#define V4L2_PIX_FMT_XRGB555 v4l2_fourcc('X', 'R', '1', '5')
+#define V4L2_PIX_FMT_RGBA555 v4l2_fourcc('R', 'A', '1', '5')
+#define V4L2_PIX_FMT_RGBX555 v4l2_fourcc('R', 'X', '1', '5')
+#define V4L2_PIX_FMT_ABGR555 v4l2_fourcc('A', 'B', '1', '5')
+#define V4L2_PIX_FMT_XBGR555 v4l2_fourcc('X', 'B', '1', '5')
+#define V4L2_PIX_FMT_BGRA555 v4l2_fourcc('B', 'A', '1', '5')
+#define V4L2_PIX_FMT_BGRX555 v4l2_fourcc('B', 'X', '1', '5')
#define V4L2_PIX_FMT_RGB565 v4l2_fourcc('R', 'G', 'B', 'P')
#define V4L2_PIX_FMT_RGB555X v4l2_fourcc('R', 'G', 'B', 'Q')
#define V4L2_PIX_FMT_ARGB555X v4l2_fourcc_be('A', 'R', '1', '5')
@@ -220,7 +232,11 @@ struct v4l2_pix_format {
#define V4L2_PIX_FMT_BGR32 v4l2_fourcc('B', 'G', 'R', '4')
#define V4L2_PIX_FMT_ABGR32 v4l2_fourcc('A', 'R', '2', '4')
#define V4L2_PIX_FMT_XBGR32 v4l2_fourcc('X', 'R', '2', '4')
+#define V4L2_PIX_FMT_BGRA32 v4l2_fourcc('R', 'A', '2', '4')
+#define V4L2_PIX_FMT_BGRX32 v4l2_fourcc('R', 'X', '2', '4')
#define V4L2_PIX_FMT_RGB32 v4l2_fourcc('R', 'G', 'B', '4')
+#define V4L2_PIX_FMT_RGBA32 v4l2_fourcc('A', 'B', '2', '4')
+#define V4L2_PIX_FMT_RGBX32 v4l2_fourcc('X', 'B', '2', '4')
#define V4L2_PIX_FMT_ARGB32 v4l2_fourcc('B', 'A', '2', '4')
#define V4L2_PIX_FMT_XRGB32 v4l2_fourcc('B', 'X', '2', '4')
#define V4L2_PIX_FMT_GREY v4l2_fourcc('G', 'R', 'E', 'Y')
@@ -332,6 +348,7 @@ struct v4l2_pix_format {
#define V4L2_PIX_FMT_VP9 v4l2_fourcc('V', 'P', '9', '0')
#define V4L2_PIX_FMT_HEVC v4l2_fourcc('H', 'E', 'V', 'C')
#define V4L2_PIX_FMT_FWHT v4l2_fourcc('F', 'W', 'H', 'T')
+#define V4L2_PIX_FMT_FWHT_STATELESS v4l2_fourcc('S', 'F', 'W', 'H')
#define V4L2_PIX_FMT_CPIA1 v4l2_fourcc('C', 'P', 'I', 'A')
#define V4L2_PIX_FMT_WNVA v4l2_fourcc('W', 'N', 'V', 'A')
#define V4L2_PIX_FMT_SN9C10X v4l2_fourcc('S', '9', '1', '0')
diff --git a/libc/kernel/uapi/misc/habanalabs.h b/libc/kernel/uapi/misc/habanalabs.h
index c2e25de6d..1029a672d 100644
--- a/libc/kernel/uapi/misc/habanalabs.h
+++ b/libc/kernel/uapi/misc/habanalabs.h
@@ -39,10 +39,16 @@ enum goya_queue_id {
GOYA_QUEUE_ID_TPC7,
GOYA_QUEUE_ID_SIZE
};
+enum hl_device_status {
+ HL_DEVICE_STATUS_OPERATIONAL,
+ HL_DEVICE_STATUS_IN_RESET,
+ HL_DEVICE_STATUS_MALFUNCTION
+};
#define HL_INFO_HW_IP_INFO 0
#define HL_INFO_HW_EVENTS 1
#define HL_INFO_DRAM_USAGE 2
#define HL_INFO_HW_IDLE 3
+#define HL_INFO_DEVICE_STATUS 4
#define HL_INFO_VERSION_MAX_LEN 128
struct hl_info_hw_ip_info {
__u64 sram_base_address;
@@ -70,6 +76,10 @@ struct hl_info_hw_idle {
__u32 is_idle;
__u32 pad;
};
+struct hl_info_device_status {
+ __u32 status;
+ __u32 pad;
+};
struct hl_info_args {
__u64 return_pointer;
__u32 return_size;
@@ -183,11 +193,64 @@ union hl_mem_args {
struct hl_mem_in in;
struct hl_mem_out out;
};
+#define HL_DEBUG_MAX_AUX_VALUES 10
+struct hl_debug_params_etr {
+ __u64 buffer_address;
+ __u64 buffer_size;
+ __u32 sink_mode;
+ __u32 pad;
+};
+struct hl_debug_params_etf {
+ __u64 buffer_address;
+ __u64 buffer_size;
+ __u32 sink_mode;
+ __u32 pad;
+};
+struct hl_debug_params_stm {
+ __u64 he_mask;
+ __u64 sp_mask;
+ __u32 id;
+ __u32 frequency;
+};
+struct hl_debug_params_bmon {
+ __u64 start_addr0;
+ __u64 addr_mask0;
+ __u64 start_addr1;
+ __u64 addr_mask1;
+ __u32 bw_win;
+ __u32 win_capture;
+ __u32 id;
+ __u32 pad;
+};
+struct hl_debug_params_spmu {
+ __u64 event_types[HL_DEBUG_MAX_AUX_VALUES];
+ __u32 event_types_num;
+ __u32 pad;
+};
+#define HL_DEBUG_OP_ETR 0
+#define HL_DEBUG_OP_ETF 1
+#define HL_DEBUG_OP_STM 2
+#define HL_DEBUG_OP_FUNNEL 3
+#define HL_DEBUG_OP_BMON 4
+#define HL_DEBUG_OP_SPMU 5
+#define HL_DEBUG_OP_TIMESTAMP 6
+#define HL_DEBUG_OP_SET_MODE 7
+struct hl_debug_args {
+ __u64 input_ptr;
+ __u64 output_ptr;
+ __u32 input_size;
+ __u32 output_size;
+ __u32 op;
+ __u32 reg_idx;
+ __u32 enable;
+ __u32 ctx_id;
+};
#define HL_IOCTL_INFO _IOWR('H', 0x01, struct hl_info_args)
#define HL_IOCTL_CB _IOWR('H', 0x02, union hl_cb_args)
#define HL_IOCTL_CS _IOWR('H', 0x03, union hl_cs_args)
#define HL_IOCTL_WAIT_CS _IOWR('H', 0x04, union hl_wait_cs_args)
#define HL_IOCTL_MEMORY _IOWR('H', 0x05, union hl_mem_args)
+#define HL_IOCTL_DEBUG _IOWR('H', 0x06, struct hl_debug_args)
#define HL_COMMAND_START 0x01
-#define HL_COMMAND_END 0x06
+#define HL_COMMAND_END 0x07
#endif
diff --git a/libc/kernel/uapi/rdma/efa-abi.h b/libc/kernel/uapi/rdma/efa-abi.h
new file mode 100644
index 000000000..1445c9c2a
--- /dev/null
+++ b/libc/kernel/uapi/rdma/efa-abi.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** 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 EFA_ABI_USER_H
+#define EFA_ABI_USER_H
+#include <linux/types.h>
+#define EFA_UVERBS_ABI_VERSION 1
+enum efa_ibv_user_cmds_supp_udata {
+ EFA_USER_CMDS_SUPP_UDATA_QUERY_DEVICE = 1 << 0,
+ EFA_USER_CMDS_SUPP_UDATA_CREATE_AH = 1 << 1,
+};
+struct efa_ibv_alloc_ucontext_resp {
+ __u32 comp_mask;
+ __u32 cmds_supp_udata_mask;
+ __u16 sub_cqs_per_cq;
+ __u16 inline_buf_size;
+ __u32 max_llq_size;
+};
+struct efa_ibv_alloc_pd_resp {
+ __u32 comp_mask;
+ __u16 pdn;
+ __u8 reserved_30[2];
+};
+struct efa_ibv_create_cq {
+ __u32 comp_mask;
+ __u32 cq_entry_size;
+ __u16 num_sub_cqs;
+ __u8 reserved_50[6];
+};
+struct efa_ibv_create_cq_resp {
+ __u32 comp_mask;
+ __u8 reserved_20[4];
+ __aligned_u64 q_mmap_key;
+ __aligned_u64 q_mmap_size;
+ __u16 cq_idx;
+ __u8 reserved_d0[6];
+};
+enum {
+ EFA_QP_DRIVER_TYPE_SRD = 0,
+};
+struct efa_ibv_create_qp {
+ __u32 comp_mask;
+ __u32 rq_ring_size;
+ __u32 sq_ring_size;
+ __u32 driver_qp_type;
+};
+struct efa_ibv_create_qp_resp {
+ __u32 comp_mask;
+ __u32 rq_db_offset;
+ __u32 sq_db_offset;
+ __u32 llq_desc_offset;
+ __aligned_u64 rq_mmap_key;
+ __aligned_u64 rq_mmap_size;
+ __aligned_u64 rq_db_mmap_key;
+ __aligned_u64 sq_db_mmap_key;
+ __aligned_u64 llq_desc_mmap_key;
+ __u16 send_sub_cq_idx;
+ __u16 recv_sub_cq_idx;
+ __u8 reserved_1e0[4];
+};
+struct efa_ibv_create_ah_resp {
+ __u32 comp_mask;
+ __u16 efa_address_handle;
+ __u8 reserved_30[2];
+};
+struct efa_ibv_ex_query_device_resp {
+ __u32 comp_mask;
+ __u32 max_sq_wr;
+ __u32 max_rq_wr;
+ __u16 max_sq_sge;
+ __u16 max_rq_sge;
+};
+#endif
diff --git a/libc/kernel/uapi/rdma/mlx5-abi.h b/libc/kernel/uapi/rdma/mlx5-abi.h
index f1ab1474e..e01b6d377 100644
--- a/libc/kernel/uapi/rdma/mlx5-abi.h
+++ b/libc/kernel/uapi/rdma/mlx5-abi.h
@@ -263,6 +263,7 @@ enum mlx5_ib_create_qp_resp_mask {
MLX5_IB_CREATE_QP_RESP_MASK_TISN = 1UL << 1,
MLX5_IB_CREATE_QP_RESP_MASK_RQN = 1UL << 2,
MLX5_IB_CREATE_QP_RESP_MASK_SQN = 1UL << 3,
+ MLX5_IB_CREATE_QP_RESP_MASK_TIR_ICM_ADDR = 1UL << 4,
};
struct mlx5_ib_create_qp_resp {
__u32 bfreg_index;
@@ -273,6 +274,7 @@ struct mlx5_ib_create_qp_resp {
__u32 rqn;
__u32 sqn;
__u32 reserved1;
+ __u64 tir_icm_addr;
};
struct mlx5_ib_alloc_mw {
__u32 comp_mask;
diff --git a/libc/kernel/uapi/rdma/mlx5_user_ioctl_cmds.h b/libc/kernel/uapi/rdma/mlx5_user_ioctl_cmds.h
index 88b84c29c..66bd6663f 100644
--- a/libc/kernel/uapi/rdma/mlx5_user_ioctl_cmds.h
+++ b/libc/kernel/uapi/rdma/mlx5_user_ioctl_cmds.h
@@ -26,6 +26,7 @@ enum mlx5_ib_create_flow_action_attrs {
enum mlx5_ib_alloc_dm_attrs {
MLX5_IB_ATTR_ALLOC_DM_RESP_START_OFFSET = (1U << UVERBS_ID_NS_SHIFT),
MLX5_IB_ATTR_ALLOC_DM_RESP_PAGE_INDEX,
+ MLX5_IB_ATTR_ALLOC_DM_REQ_TYPE,
};
enum mlx5_ib_devx_methods {
MLX5_IB_METHOD_DEVX_OTHER = (1U << UVERBS_ID_NS_SHIFT),
@@ -109,6 +110,7 @@ enum mlx5_ib_flow_matcher_create_attrs {
MLX5_IB_ATTR_FLOW_MATCHER_FLOW_TYPE,
MLX5_IB_ATTR_FLOW_MATCHER_MATCH_CRITERIA,
MLX5_IB_ATTR_FLOW_MATCHER_FLOW_FLAGS,
+ MLX5_IB_ATTR_FLOW_MATCHER_FT_TYPE,
};
enum mlx5_ib_flow_matcher_destroy_attrs {
MLX5_IB_ATTR_FLOW_MATCHER_DESTROY_HANDLE = (1U << UVERBS_ID_NS_SHIFT),
diff --git a/libc/kernel/uapi/rdma/mlx5_user_ioctl_verbs.h b/libc/kernel/uapi/rdma/mlx5_user_ioctl_verbs.h
index e83b9e2dd..a75368d49 100644
--- a/libc/kernel/uapi/rdma/mlx5_user_ioctl_verbs.h
+++ b/libc/kernel/uapi/rdma/mlx5_user_ioctl_verbs.h
@@ -25,6 +25,7 @@ enum mlx5_ib_uapi_flow_action_flags {
enum mlx5_ib_uapi_flow_table_type {
MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_RX = 0x0,
MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_TX = 0x1,
+ MLX5_IB_UAPI_FLOW_TABLE_TYPE_FDB = 0x2,
};
enum mlx5_ib_uapi_flow_action_packet_reformat_type {
MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TUNNEL_TO_L2 = 0x0,
@@ -36,4 +37,9 @@ struct mlx5_ib_uapi_devx_async_cmd_hdr {
__aligned_u64 wr_id;
__u8 out_data[];
};
+enum mlx5_ib_uapi_dm_type {
+ MLX5_IB_UAPI_DM_TYPE_MEMIC,
+ MLX5_IB_UAPI_DM_TYPE_STEERING_SW_ICM,
+ MLX5_IB_UAPI_DM_TYPE_HEADER_MODIFY_SW_ICM,
+};
#endif
diff --git a/libc/kernel/uapi/rdma/rdma_netlink.h b/libc/kernel/uapi/rdma/rdma_netlink.h
index 7730edfc7..bbb18227d 100644
--- a/libc/kernel/uapi/rdma/rdma_netlink.h
+++ b/libc/kernel/uapi/rdma/rdma_netlink.h
@@ -51,16 +51,6 @@ enum {
RDMA_NL_IWPM_HELLO,
RDMA_NL_IWPM_NUM_OPS
};
-struct rdma_cm_id_stats {
- __u32 qp_num;
- __u32 bound_dev_if;
- __u32 port_space;
- __s32 pid;
- __u8 cm_state;
- __u8 node_type;
- __u8 port_num;
- __u8 qp_type;
-};
enum {
IWPM_NLA_REG_PID_UNSPEC = 0,
IWPM_NLA_REG_PID_SEQ,
@@ -193,6 +183,8 @@ enum rdma_nldev_command {
RDMA_NLDEV_CMD_NEWLINK,
RDMA_NLDEV_CMD_DELLINK,
RDMA_NLDEV_CMD_PORT_GET,
+ RDMA_NLDEV_CMD_SYS_GET,
+ RDMA_NLDEV_CMD_SYS_SET,
RDMA_NLDEV_CMD_RES_GET = 9,
RDMA_NLDEV_CMD_RES_QP_GET,
RDMA_NLDEV_CMD_RES_CM_ID_GET,
@@ -276,6 +268,9 @@ enum rdma_nldev_attr {
RDMA_NLDEV_ATTR_RES_CM_IDN,
RDMA_NLDEV_ATTR_RES_CTXN,
RDMA_NLDEV_ATTR_LINK_TYPE,
+ RDMA_NLDEV_SYS_ATTR_NETNS_MODE,
+ RDMA_NLDEV_ATTR_DEV_PROTOCOL,
+ RDMA_NLDEV_NET_NS_FD,
RDMA_NLDEV_ATTR_MAX
};
#endif
diff --git a/libc/kernel/uapi/rdma/rdma_user_ioctl_cmds.h b/libc/kernel/uapi/rdma/rdma_user_ioctl_cmds.h
index 7cd6cd0c1..2692e3ae5 100644
--- a/libc/kernel/uapi/rdma/rdma_user_ioctl_cmds.h
+++ b/libc/kernel/uapi/rdma/rdma_user_ioctl_cmds.h
@@ -70,5 +70,6 @@ enum rdma_driver_id {
RDMA_DRIVER_RXE,
RDMA_DRIVER_HFI1,
RDMA_DRIVER_QIB,
+ RDMA_DRIVER_EFA,
};
#endif
diff --git a/libc/kernel/uapi/scsi/fc/fc_els.h b/libc/kernel/uapi/scsi/fc/fc_els.h
index 7e9409ad0..1cabaddfa 100644
--- a/libc/kernel/uapi/scsi/fc/fc_els.h
+++ b/libc/kernel/uapi/scsi/fc/fc_els.h
@@ -40,6 +40,7 @@ enum fc_els_cmd {
ELS_RRQ = 0x12,
ELS_REC = 0x13,
ELS_SRR = 0x14,
+ ELS_FPIN = 0x16,
ELS_PRLI = 0x20,
ELS_PRLO = 0x21,
ELS_SCN = 0x22,
@@ -81,7 +82,7 @@ enum fc_els_cmd {
ELS_LKA = 0x80,
ELS_AUTH_ELS = 0x90,
};
-#define FC_ELS_CMDS_INIT {[ELS_LS_RJT] = "LS_RJT",[ELS_LS_ACC] = "LS_ACC",[ELS_PLOGI] = "PLOGI",[ELS_FLOGI] = "FLOGI",[ELS_LOGO] = "LOGO",[ELS_ABTX] = "ABTX",[ELS_RCS] = "RCS",[ELS_RES] = "RES",[ELS_RSS] = "RSS",[ELS_RSI] = "RSI",[ELS_ESTS] = "ESTS",[ELS_ESTC] = "ESTC",[ELS_ADVC] = "ADVC",[ELS_RTV] = "RTV",[ELS_RLS] = "RLS",[ELS_ECHO] = "ECHO",[ELS_TEST] = "TEST",[ELS_RRQ] = "RRQ",[ELS_REC] = "REC",[ELS_SRR] = "SRR",[ELS_PRLI] = "PRLI",[ELS_PRLO] = "PRLO",[ELS_SCN] = "SCN",[ELS_TPLS] = "TPLS",[ELS_TPRLO] = "TPRLO",[ELS_LCLM] = "LCLM",[ELS_GAID] = "GAID",[ELS_FACT] = "FACT",[ELS_FDACDT] = "FDACDT",[ELS_NACT] = "NACT",[ELS_NDACT] = "NDACT",[ELS_QOSR] = "QOSR",[ELS_RVCS] = "RVCS",[ELS_PDISC] = "PDISC",[ELS_FDISC] = "FDISC",[ELS_ADISC] = "ADISC",[ELS_RNC] = "RNC",[ELS_FARP_REQ] = "FARP_REQ",[ELS_FARP_REPL] = "FARP_REPL",[ELS_RPS] = "RPS",[ELS_RPL] = "RPL",[ELS_RPBC] = "RPBC",[ELS_FAN] = "FAN",[ELS_RSCN] = "RSCN",[ELS_SCR] = "SCR",[ELS_RNFT] = "RNFT",[ELS_CSR] = "CSR",[ELS_CSU] = "CSU",[ELS_LINIT] = "LINIT",[ELS_LSTS] = "LSTS",[ELS_RNID] = "RNID",[ELS_RLIR] = "RLIR",[ELS_LIRR] = "LIRR",[ELS_SRL] = "SRL",[ELS_SBRP] = "SBRP",[ELS_RPSC] = "RPSC",[ELS_QSA] = "QSA",[ELS_EVFP] = "EVFP",[ELS_LKA] = "LKA",[ELS_AUTH_ELS] = "AUTH_ELS", \
+#define FC_ELS_CMDS_INIT {[ELS_LS_RJT] = "LS_RJT",[ELS_LS_ACC] = "LS_ACC",[ELS_PLOGI] = "PLOGI",[ELS_FLOGI] = "FLOGI",[ELS_LOGO] = "LOGO",[ELS_ABTX] = "ABTX",[ELS_RCS] = "RCS",[ELS_RES] = "RES",[ELS_RSS] = "RSS",[ELS_RSI] = "RSI",[ELS_ESTS] = "ESTS",[ELS_ESTC] = "ESTC",[ELS_ADVC] = "ADVC",[ELS_RTV] = "RTV",[ELS_RLS] = "RLS",[ELS_ECHO] = "ECHO",[ELS_TEST] = "TEST",[ELS_RRQ] = "RRQ",[ELS_REC] = "REC",[ELS_SRR] = "SRR",[ELS_FPIN] = "FPIN",[ELS_PRLI] = "PRLI",[ELS_PRLO] = "PRLO",[ELS_SCN] = "SCN",[ELS_TPLS] = "TPLS",[ELS_TPRLO] = "TPRLO",[ELS_LCLM] = "LCLM",[ELS_GAID] = "GAID",[ELS_FACT] = "FACT",[ELS_FDACDT] = "FDACDT",[ELS_NACT] = "NACT",[ELS_NDACT] = "NDACT",[ELS_QOSR] = "QOSR",[ELS_RVCS] = "RVCS",[ELS_PDISC] = "PDISC",[ELS_FDISC] = "FDISC",[ELS_ADISC] = "ADISC",[ELS_RNC] = "RNC",[ELS_FARP_REQ] = "FARP_REQ",[ELS_FARP_REPL] = "FARP_REPL",[ELS_RPS] = "RPS",[ELS_RPL] = "RPL",[ELS_RPBC] = "RPBC",[ELS_FAN] = "FAN",[ELS_RSCN] = "RSCN",[ELS_SCR] = "SCR",[ELS_RNFT] = "RNFT",[ELS_CSR] = "CSR",[ELS_CSU] = "CSU",[ELS_LINIT] = "LINIT",[ELS_LSTS] = "LSTS",[ELS_RNID] = "RNID",[ELS_RLIR] = "RLIR",[ELS_LIRR] = "LIRR",[ELS_SRL] = "SRL",[ELS_SBRP] = "SBRP",[ELS_RPSC] = "RPSC",[ELS_QSA] = "QSA",[ELS_EVFP] = "EVFP",[ELS_LKA] = "LKA",[ELS_AUTH_ELS] = "AUTH_ELS", \
}
struct fc_els_ls_acc {
__u8 la_cmd;
@@ -542,4 +543,20 @@ enum fc_els_clid_ic {
ELS_CLID_IC_LOOP_TO = 7,
ELS_CLID_IC_LIP = 8,
};
+enum fc_fn_dtag {
+ ELS_FN_DTAG_LNK_INTEGRITY = 0x00020001,
+ ELS_FN_DTAG_PEER_CONGEST = 0x00020003,
+ ELS_FN_DTAG_CONGESTION = 0x00020004,
+};
+struct fc_fn_desc {
+ __be32 fn_desc_tag;
+ __be32 fn_desc_value_len;
+ __u8 fn_desc_value[0];
+};
+struct fc_els_fpin {
+ __u8 fpin_cmd;
+ __u8 fpin_zero[3];
+ __be32 fpin_desc_cnt;
+ struct fc_fn_desc fpin_desc[0];
+};
#endif
diff --git a/libc/kernel/uapi/sound/sof/abi.h b/libc/kernel/uapi/sound/sof/abi.h
new file mode 100644
index 000000000..2111f5c37
--- /dev/null
+++ b/libc/kernel/uapi/sound/sof/abi.h
@@ -0,0 +1,37 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** 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 __INCLUDE_UAPI_SOUND_SOF_ABI_H__
+#define __INCLUDE_UAPI_SOUND_SOF_ABI_H__
+#define SOF_ABI_MAJOR 3
+#define SOF_ABI_MINOR 6
+#define SOF_ABI_PATCH 0
+#define SOF_ABI_MAJOR_SHIFT 24
+#define SOF_ABI_MAJOR_MASK 0xff
+#define SOF_ABI_MINOR_SHIFT 12
+#define SOF_ABI_MINOR_MASK 0xfff
+#define SOF_ABI_PATCH_SHIFT 0
+#define SOF_ABI_PATCH_MASK 0xfff
+#define SOF_ABI_VER(major,minor,patch) (((major) << SOF_ABI_MAJOR_SHIFT) | ((minor) << SOF_ABI_MINOR_SHIFT) | ((patch) << SOF_ABI_PATCH_SHIFT))
+#define SOF_ABI_VERSION_MAJOR(version) (((version) >> SOF_ABI_MAJOR_SHIFT) & SOF_ABI_MAJOR_MASK)
+#define SOF_ABI_VERSION_MINOR(version) (((version) >> SOF_ABI_MINOR_SHIFT) & SOF_ABI_MINOR_MASK)
+#define SOF_ABI_VERSION_PATCH(version) (((version) >> SOF_ABI_PATCH_SHIFT) & SOF_ABI_PATCH_MASK)
+#define SOF_ABI_VERSION_INCOMPATIBLE(sof_ver,client_ver) (SOF_ABI_VERSION_MAJOR((sof_ver)) != SOF_ABI_VERSION_MAJOR((client_ver)))
+#define SOF_ABI_VERSION SOF_ABI_VER(SOF_ABI_MAJOR, SOF_ABI_MINOR, SOF_ABI_PATCH)
+#define SOF_ABI_MAGIC 0x00464F53
+#endif
diff --git a/libc/kernel/uapi/sound/sof/eq.h b/libc/kernel/uapi/sound/sof/eq.h
new file mode 100644
index 000000000..c45ba3554
--- /dev/null
+++ b/libc/kernel/uapi/sound/sof/eq.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** 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 __INCLUDE_UAPI_SOUND_SOF_USER_EQ_H__
+#define __INCLUDE_UAPI_SOUND_SOF_USER_EQ_H__
+#define SOF_EQ_FIR_IDX_SWITCH 0
+#define SOF_EQ_FIR_MAX_SIZE 4096
+#define SOF_EQ_FIR_MAX_LENGTH 192
+#define SOF_EQ_FIR_MAX_RESPONSES 8
+struct sof_eq_fir_config {
+ uint32_t size;
+ uint16_t channels_in_config;
+ uint16_t number_of_responses;
+ uint32_t reserved[4];
+ int16_t data[];
+} __packed;
+struct sof_eq_fir_coef_data {
+ int16_t length;
+ int16_t out_shift;
+ uint32_t reserved[4];
+ int16_t coef[];
+} __packed;
+#define SOF_EQ_FIR_COEF_NHEADER (sizeof(struct sof_eq_fir_coef_data) / sizeof(int16_t))
+#define SOF_EQ_IIR_IDX_SWITCH 0
+#define SOF_EQ_IIR_MAX_SIZE 1024
+#define SOF_EQ_IIR_MAX_RESPONSES 8
+struct sof_eq_iir_config {
+ uint32_t size;
+ uint32_t channels_in_config;
+ uint32_t number_of_responses;
+ uint32_t reserved[4];
+ int32_t data[];
+} __packed;
+struct sof_eq_iir_header_df2t {
+ uint32_t num_sections;
+ uint32_t num_sections_in_series;
+ uint32_t reserved[4];
+ int32_t biquads[];
+} __packed;
+struct sof_eq_iir_biquad_df2t {
+ int32_t a2;
+ int32_t a1;
+ int32_t b2;
+ int32_t b1;
+ int32_t b0;
+ int32_t output_shift;
+ int32_t output_gain;
+} __packed;
+#define SOF_EQ_IIR_DF2T_BIQUADS_MAX 11
+#define SOF_EQ_IIR_NHEADER_DF2T (sizeof(struct sof_eq_iir_header_df2t) / sizeof(int32_t))
+#define SOF_EQ_IIR_NBIQUAD_DF2T (sizeof(struct sof_eq_iir_biquad_df2t) / sizeof(int32_t))
+#endif
diff --git a/libc/kernel/uapi/sound/sof/fw.h b/libc/kernel/uapi/sound/sof/fw.h
new file mode 100644
index 000000000..72bb31c21
--- /dev/null
+++ b/libc/kernel/uapi/sound/sof/fw.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** 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 __INCLUDE_UAPI_SOF_FW_H__
+#define __INCLUDE_UAPI_SOF_FW_H__
+#define SND_SOF_FW_SIG_SIZE 4
+#define SND_SOF_FW_ABI 1
+#define SND_SOF_FW_SIG "Reef"
+enum snd_sof_fw_blk_type {
+ SOF_FW_BLK_TYPE_INVALID = - 1,
+ SOF_FW_BLK_TYPE_START = 0,
+ SOF_FW_BLK_TYPE_RSRVD0 = SOF_FW_BLK_TYPE_START,
+ SOF_FW_BLK_TYPE_IRAM = 1,
+ SOF_FW_BLK_TYPE_DRAM = 2,
+ SOF_FW_BLK_TYPE_SRAM = 3,
+ SOF_FW_BLK_TYPE_ROM = 4,
+ SOF_FW_BLK_TYPE_IMR = 5,
+ SOF_FW_BLK_TYPE_RSRVD6 = 6,
+ SOF_FW_BLK_TYPE_RSRVD7 = 7,
+ SOF_FW_BLK_TYPE_RSRVD8 = 8,
+ SOF_FW_BLK_TYPE_RSRVD9 = 9,
+ SOF_FW_BLK_TYPE_RSRVD10 = 10,
+ SOF_FW_BLK_TYPE_RSRVD11 = 11,
+ SOF_FW_BLK_TYPE_RSRVD12 = 12,
+ SOF_FW_BLK_TYPE_RSRVD13 = 13,
+ SOF_FW_BLK_TYPE_RSRVD14 = 14,
+ SOF_FW_BLK_TYPE_NUM
+};
+struct snd_sof_blk_hdr {
+ enum snd_sof_fw_blk_type type;
+ uint32_t size;
+ uint32_t offset;
+} __packed;
+enum snd_sof_fw_mod_type {
+ SOF_FW_BASE = 0,
+ SOF_FW_MODULE = 1,
+};
+struct snd_sof_mod_hdr {
+ enum snd_sof_fw_mod_type type;
+ uint32_t size;
+ uint32_t num_blocks;
+} __packed;
+struct snd_sof_fw_header {
+ unsigned char sig[SND_SOF_FW_SIG_SIZE];
+ uint32_t file_size;
+ uint32_t num_modules;
+ uint32_t abi;
+} __packed;
+#endif
diff --git a/libc/kernel/uapi/sound/sof/header.h b/libc/kernel/uapi/sound/sof/header.h
new file mode 100644
index 000000000..cf90e9bcc
--- /dev/null
+++ b/libc/kernel/uapi/sound/sof/header.h
@@ -0,0 +1,29 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** 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 __INCLUDE_UAPI_SOUND_SOF_USER_HEADER_H__
+#define __INCLUDE_UAPI_SOUND_SOF_USER_HEADER_H__
+struct sof_abi_hdr {
+ uint32_t magic;
+ uint32_t type;
+ uint32_t size;
+ uint32_t abi;
+ uint32_t reserved[4];
+ uint32_t data[0];
+} __packed;
+#endif
diff --git a/libc/kernel/uapi/sound/sof/manifest.h b/libc/kernel/uapi/sound/sof/manifest.h
new file mode 100644
index 000000000..b8bd3e5dd
--- /dev/null
+++ b/libc/kernel/uapi/sound/sof/manifest.h
@@ -0,0 +1,128 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** 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 __INCLUDE_UAPI_SOUND_SOF_USER_MANIFEST_H__
+#define __INCLUDE_UAPI_SOUND_SOF_USER_MANIFEST_H__
+#define SOF_MAN_ELF_TEXT_OFFSET 0x2000
+#define SOF_MAN_EXT_HEADER_MAGIC 0x31454124
+#define SOF_MAN_MOD_TYPE_BUILTIN 0
+#define SOF_MAN_MOD_TYPE_MODULE 1
+struct sof_man_module_type {
+ uint32_t load_type : 4;
+ uint32_t auto_start : 1;
+ uint32_t domain_ll : 1;
+ uint32_t domain_dp : 1;
+ uint32_t rsvd_ : 25;
+};
+#define SOF_MAN_SEGMENT_TEXT 0
+#define SOF_MAN_SEGMENT_RODATA 1
+#define SOF_MAN_SEGMENT_DATA 1
+#define SOF_MAN_SEGMENT_BSS 2
+#define SOF_MAN_SEGMENT_EMPTY 15
+union sof_man_segment_flags {
+ uint32_t ul;
+ struct {
+ uint32_t contents : 1;
+ uint32_t alloc : 1;
+ uint32_t load : 1;
+ uint32_t readonly : 1;
+ uint32_t code : 1;
+ uint32_t data : 1;
+ uint32_t _rsvd0 : 2;
+ uint32_t type : 4;
+ uint32_t _rsvd1 : 4;
+ uint32_t length : 16;
+ } r;
+} __packed;
+struct sof_man_segment_desc {
+ union sof_man_segment_flags flags;
+ uint32_t v_base_addr;
+ uint32_t file_offset;
+} __packed;
+#define SOF_MAN_MOD_ID_LEN 4
+#define SOF_MAN_MOD_NAME_LEN 8
+#define SOF_MAN_MOD_SHA256_LEN 32
+#define SOF_MAN_MOD_ID { '$', 'A', 'M', 'E' }
+struct sof_man_module {
+ uint8_t struct_id[SOF_MAN_MOD_ID_LEN];
+ uint8_t name[SOF_MAN_MOD_NAME_LEN];
+ uint8_t uuid[16];
+ struct sof_man_module_type type;
+ uint8_t hash[SOF_MAN_MOD_SHA256_LEN];
+ uint32_t entry_point;
+ uint16_t cfg_offset;
+ uint16_t cfg_count;
+ uint32_t affinity_mask;
+ uint16_t instance_max_count;
+ uint16_t instance_bss_size;
+ struct sof_man_segment_desc segment[3];
+} __packed;
+struct sof_man_mod_config {
+ uint32_t par[4];
+ uint32_t is_pages;
+ uint32_t cps;
+ uint32_t ibs;
+ uint32_t obs;
+ uint32_t module_flags;
+ uint32_t cpc;
+ uint32_t obls;
+} __packed;
+#define SOF_MAN_FW_HDR_FW_NAME_LEN 8
+#define SOF_MAN_FW_HDR_ID { '$', 'A', 'M', '1' }
+#define SOF_MAN_FW_HDR_NAME "ADSPFW"
+#define SOF_MAN_FW_HDR_FLAGS 0x0
+#define SOF_MAN_FW_HDR_FEATURES 0xff
+struct sof_man_fw_header {
+ uint8_t header_id[4];
+ uint32_t header_len;
+ uint8_t name[SOF_MAN_FW_HDR_FW_NAME_LEN];
+ uint32_t preload_page_count;
+ uint32_t fw_image_flags;
+ uint32_t feature_mask;
+ uint16_t major_version;
+ uint16_t minor_version;
+ uint16_t hotfix_version;
+ uint16_t build_version;
+ uint32_t num_module_entries;
+ uint32_t hw_buf_base_addr;
+ uint32_t hw_buf_length;
+ uint32_t load_offset;
+} __packed;
+struct sof_man_fw_desc {
+ struct sof_man_fw_header header;
+} __packed;
+struct sof_man_component_desc {
+ uint32_t reserved[2];
+ uint32_t version;
+ uint8_t hash[SOF_MAN_MOD_SHA256_LEN];
+ uint32_t base_offset;
+ uint32_t limit_offset;
+ uint32_t attributes[4];
+} __packed;
+struct sof_man_adsp_meta_file_ext {
+ uint32_t ext_type;
+ uint32_t ext_len;
+ uint32_t imr_type;
+ uint8_t reserved[16];
+ struct sof_man_component_desc comp_desc[1];
+} __packed;
+struct sof_man_module_manifest {
+ struct sof_man_module module;
+ uint32_t text_size;
+} __packed;
+#endif
diff --git a/libc/kernel/uapi/sound/sof/tokens.h b/libc/kernel/uapi/sound/sof/tokens.h
new file mode 100644
index 000000000..748c5fecb
--- /dev/null
+++ b/libc/kernel/uapi/sound/sof/tokens.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** 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 __INCLUDE_UAPI_SOF_TOPOLOGY_H__
+#define __INCLUDE_UAPI_SOF_TOPOLOGY_H__
+#define SOF_TPLG_KCTL_VOL_ID 256
+#define SOF_TPLG_KCTL_ENUM_ID 257
+#define SOF_TPLG_KCTL_BYTES_ID 258
+#define SOF_TPLG_KCTL_SWITCH_ID 259
+#define SOF_TKN_BUF_SIZE 100
+#define SOF_TKN_BUF_CAPS 101
+#define SOF_TKN_DAI_TYPE 154
+#define SOF_TKN_DAI_INDEX 155
+#define SOF_TKN_DAI_DIRECTION 156
+#define SOF_TKN_SCHED_PERIOD 200
+#define SOF_TKN_SCHED_PRIORITY 201
+#define SOF_TKN_SCHED_MIPS 202
+#define SOF_TKN_SCHED_CORE 203
+#define SOF_TKN_SCHED_FRAMES 204
+#define SOF_TKN_SCHED_TIME_DOMAIN 205
+#define SOF_TKN_VOLUME_RAMP_STEP_TYPE 250
+#define SOF_TKN_VOLUME_RAMP_STEP_MS 251
+#define SOF_TKN_SRC_RATE_IN 300
+#define SOF_TKN_SRC_RATE_OUT 301
+#define SOF_TKN_PCM_DMAC_CONFIG 353
+#define SOF_TKN_COMP_PERIOD_SINK_COUNT 400
+#define SOF_TKN_COMP_PERIOD_SOURCE_COUNT 401
+#define SOF_TKN_COMP_FORMAT 402
+#define SOF_TKN_INTEL_SSP_CLKS_CONTROL 500
+#define SOF_TKN_INTEL_SSP_MCLK_ID 501
+#define SOF_TKN_INTEL_SSP_SAMPLE_BITS 502
+#define SOF_TKN_INTEL_SSP_FRAME_PULSE_WIDTH 503
+#define SOF_TKN_INTEL_SSP_QUIRKS 504
+#define SOF_TKN_INTEL_SSP_TDM_PADDING_PER_SLOT 505
+#define SOF_TKN_INTEL_DMIC_DRIVER_VERSION 600
+#define SOF_TKN_INTEL_DMIC_CLK_MIN 601
+#define SOF_TKN_INTEL_DMIC_CLK_MAX 602
+#define SOF_TKN_INTEL_DMIC_DUTY_MIN 603
+#define SOF_TKN_INTEL_DMIC_DUTY_MAX 604
+#define SOF_TKN_INTEL_DMIC_NUM_PDM_ACTIVE 605
+#define SOF_TKN_INTEL_DMIC_SAMPLE_RATE 608
+#define SOF_TKN_INTEL_DMIC_FIFO_WORD_LENGTH 609
+#define SOF_TKN_INTEL_DMIC_PDM_CTRL_ID 700
+#define SOF_TKN_INTEL_DMIC_PDM_MIC_A_Enable 701
+#define SOF_TKN_INTEL_DMIC_PDM_MIC_B_Enable 702
+#define SOF_TKN_INTEL_DMIC_PDM_POLARITY_A 703
+#define SOF_TKN_INTEL_DMIC_PDM_POLARITY_B 704
+#define SOF_TKN_INTEL_DMIC_PDM_CLK_EDGE 705
+#define SOF_TKN_INTEL_DMIC_PDM_SKEW 706
+#define SOF_TKN_TONE_SAMPLE_RATE 800
+#define SOF_TKN_PROCESS_TYPE 900
+#define SOF_TKN_EFFECT_TYPE SOF_TKN_PROCESS_TYPE
+#endif
diff --git a/libc/kernel/uapi/sound/sof/tone.h b/libc/kernel/uapi/sound/sof/tone.h
new file mode 100644
index 000000000..a4b745ef7
--- /dev/null
+++ b/libc/kernel/uapi/sound/sof/tone.h
@@ -0,0 +1,29 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** 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 __INCLUDE_UAPI_SOUND_SOF_USER_TONE_H__
+#define __INCLUDE_UAPI_SOUND_SOF_USER_TONE_H__
+#define SOF_TONE_IDX_FREQUENCY 0
+#define SOF_TONE_IDX_AMPLITUDE 1
+#define SOF_TONE_IDX_FREQ_MULT 2
+#define SOF_TONE_IDX_AMPL_MULT 3
+#define SOF_TONE_IDX_LENGTH 4
+#define SOF_TONE_IDX_PERIOD 5
+#define SOF_TONE_IDX_REPEATS 6
+#define SOF_TONE_IDX_LIN_RAMP_STEP 7
+#endif
diff --git a/libc/kernel/uapi/sound/sof/trace.h b/libc/kernel/uapi/sound/sof/trace.h
new file mode 100644
index 000000000..a5eed43e0
--- /dev/null
+++ b/libc/kernel/uapi/sound/sof/trace.h
@@ -0,0 +1,45 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** 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 __INCLUDE_UAPI_SOUND_SOF_USER_TRACE_H__
+#define __INCLUDE_UAPI_SOUND_SOF_USER_TRACE_H__
+struct system_time {
+ uint32_t val_l;
+ uint32_t val_u;
+} __packed;
+#define LOG_ENABLE 1
+#define LOG_DISABLE 0
+#define LOG_LEVEL_CRITICAL 1
+#define LOG_LEVEL_VERBOSE 2
+struct log_buffer_layout {
+ uint32_t read_ptr;
+ uint32_t write_ptr;
+ uint32_t buffer[0];
+} __packed;
+struct log_buffer_status {
+ uint32_t core_id;
+} __packed;
+#define TRACE_ID_LENGTH 12
+struct log_entry_header {
+ uint32_t id_0 : TRACE_ID_LENGTH;
+ uint32_t id_1 : TRACE_ID_LENGTH;
+ uint32_t core_id : 8;
+ uint64_t timestamp;
+ uint32_t log_entry_address;
+} __packed;
+#endif
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
index b36ee4c5d..9b39bb842 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -690,7 +690,7 @@ LIBC {
ns_name_ntol; # arm64 x86_64 mips64 introduced=22
ns_name_ntop; # arm64 x86_64 mips64 introduced=22
ns_name_pack; # arm64 x86_64 mips64 introduced=22
- ns_name_pton; # arm64 x86_64 mips64 introduced=23
+ ns_name_pton; # arm64 x86_64 mips64 introduced=22
ns_name_rollback; # arm64 x86_64 mips64 introduced=22
ns_name_skip; # arm64 x86_64 mips64 introduced=22
ns_name_uncompress; # arm64 x86_64 mips64 introduced=22
@@ -1482,6 +1482,10 @@ LIBC_Q { # introduced=Q
LIBC_R { # introduced=R
global:
+ __mempcpy_chk;
+ __open64_2;
+ __openat64_2;
+ __tls_get_addr; # arm64
call_once;
cnd_broadcast;
cnd_destroy;
@@ -1489,12 +1493,20 @@ LIBC_R { # introduced=R
cnd_signal;
cnd_timedwait;
cnd_wait;
+ memfd_create;
+ mlock2;
mtx_destroy;
mtx_init;
mtx_lock;
mtx_timedlock;
mtx_trylock;
mtx_unlock;
+ pthread_cond_clockwait;
+ pthread_mutex_clocklock;
+ pthread_rwlock_clockrdlock;
+ pthread_rwlock_clockwrlock;
+ renameat2;
+ sem_clockwait;
thrd_create;
thrd_current;
thrd_detach;
diff --git a/libc/malloc_debug/Android.bp b/libc/malloc_debug/Android.bp
index aae16f14d..d6b85319e 100644
--- a/libc/malloc_debug/Android.bp
+++ b/libc/malloc_debug/Android.bp
@@ -16,7 +16,6 @@ cc_library_static {
whole_static_libs: [
"libbase",
"libasync_safe",
- "libdemangle",
],
include_dirs: ["bionic/libc"],
@@ -66,7 +65,6 @@ cc_library {
static_libs: [
"libasync_safe",
"libbase",
- "libdemangle",
"libc_malloc_debug_backtrace",
],
@@ -122,7 +120,6 @@ cc_test {
static_libs: [
"libc_malloc_debug",
- "libdemangle",
"libtinyxml2",
],
diff --git a/libc/malloc_debug/PointerData.cpp b/libc/malloc_debug/PointerData.cpp
index 8cc1a2891..b5219a172 100644
--- a/libc/malloc_debug/PointerData.cpp
+++ b/libc/malloc_debug/PointerData.cpp
@@ -43,7 +43,6 @@
#include <android-base/stringprintf.h>
#include <android-base/thread_annotations.h>
-#include <demangle.h>
#include <private/bionic_macros.h>
#include "Config.h"
@@ -54,6 +53,8 @@
#include "malloc_debug.h"
#include "UnwindBacktrace.h"
+extern "C" char* __cxa_demangle(const char*, char*, size_t*, int*);
+
std::atomic_uint8_t PointerData::backtrace_enabled_;
std::atomic_bool PointerData::backtrace_dump_;
@@ -599,7 +600,16 @@ void PointerData::DumpLiveToFile(FILE* fp) {
if (frame.function_name.empty()) {
fprintf(fp, " \"\" 0}");
} else {
- fprintf(fp, " \"%s\" %" PRIx64 "}", demangle(frame.function_name.c_str()).c_str(), frame.function_offset);
+ char* demangled_name = __cxa_demangle(frame.function_name.c_str(), nullptr, nullptr,
+ nullptr);
+ const char* name;
+ if (demangled_name != nullptr) {
+ name = demangled_name;
+ } else {
+ name = frame.function_name.c_str();
+ }
+ fprintf(fp, " \"%s\" %" PRIx64 "}", name, frame.function_offset);
+ free(demangled_name);
}
}
fprintf(fp, "\n");
diff --git a/libc/malloc_debug/UnwindBacktrace.cpp b/libc/malloc_debug/UnwindBacktrace.cpp
index ddafc731f..92fb3fa96 100644
--- a/libc/malloc_debug/UnwindBacktrace.cpp
+++ b/libc/malloc_debug/UnwindBacktrace.cpp
@@ -36,7 +36,6 @@
#include <vector>
#include <android-base/stringprintf.h>
-#include <demangle.h>
#include <unwindstack/LocalUnwinder.h>
#include <unwindstack/MapInfo.h>
@@ -49,6 +48,8 @@
#define PAD_PTR "08" PRIx64
#endif
+extern "C" char* __cxa_demangle(const char*, char*, size_t*, int*);
+
static pthread_once_t g_setup_once = PTHREAD_ONCE_INIT;
static unwindstack::LocalUnwinder* g_unwinder;
@@ -100,7 +101,14 @@ void UnwindLog(const std::vector<unwindstack::LocalFrameData>& frame_info) {
}
if (!info->function_name.empty()) {
- line += " (" + demangle(info->function_name.c_str());
+ line += " (";
+ char* demangled_name = __cxa_demangle(info->function_name.c_str(), nullptr, nullptr, nullptr);
+ if (demangled_name != nullptr) {
+ line += demangled_name;
+ free(demangled_name);
+ } else {
+ line += info->function_name;
+ }
if (info->function_offset != 0) {
line += "+" + std::to_string(info->function_offset);
}
diff --git a/libc/malloc_debug/backtrace.cpp b/libc/malloc_debug/backtrace.cpp
index 0e3a53f92..ab5c50523 100644
--- a/libc/malloc_debug/backtrace.cpp
+++ b/libc/malloc_debug/backtrace.cpp
@@ -36,8 +36,6 @@
#include <unistd.h>
#include <unwind.h>
-#include <demangle.h>
-
#include "MapData.h"
#include "backtrace.h"
#include "debug_log.h"
@@ -164,10 +162,18 @@ std::string backtrace_string(const uintptr_t* frames, size_t frame_count) {
char buf[1024];
if (symbol != nullptr) {
+ char* demangled_name = __cxa_demangle(symbol, nullptr, nullptr, nullptr);
+ const char* name;
+ if (demangled_name != nullptr) {
+ name = demangled_name;
+ } else {
+ name = symbol;
+ }
async_safe_format_buffer(buf, sizeof(buf),
" #%02zd pc %" PAD_PTR " %s%s (%s+%" PRIuPTR ")\n",
- frame_num, rel_pc, soname, offset_buf, demangle(symbol).c_str(),
+ frame_num, rel_pc, soname, offset_buf, name,
frames[frame_num] - offset);
+ free(demangled_name);
} else {
async_safe_format_buffer(buf, sizeof(buf), " #%02zd pc %" PAD_PTR " %s%s\n",
frame_num, rel_pc, soname, offset_buf);
diff --git a/libc/private/NetdClientDispatch.h b/libc/private/NetdClientDispatch.h
index 20e7f25b7..7ebbe0c02 100644
--- a/libc/private/NetdClientDispatch.h
+++ b/libc/private/NetdClientDispatch.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef PRIVATE_NETD_CLIENT_DISPATCH_H
-#define PRIVATE_NETD_CLIENT_DISPATCH_H
+#pragma once
#include <sys/cdefs.h>
#include <sys/socket.h>
@@ -25,6 +24,9 @@ __BEGIN_DECLS
struct NetdClientDispatch {
int (*accept4)(int, struct sockaddr*, socklen_t*, int);
int (*connect)(int, const struct sockaddr*, socklen_t);
+ int (*sendmmsg)(int, const struct mmsghdr*, unsigned int, int);
+ ssize_t (*sendmsg)(int, const struct msghdr*, unsigned int);
+ int (*sendto)(int, const void*, size_t, int, const struct sockaddr*, socklen_t);
int (*socket)(int, int, int);
unsigned (*netIdForResolv)(unsigned);
int (*dnsOpenProxy)();
@@ -33,5 +35,3 @@ struct NetdClientDispatch {
extern __LIBC_HIDDEN__ struct NetdClientDispatch __netdClientDispatch;
__END_DECLS
-
-#endif // PRIVATE_NETD_CLIENT_DISPATCH_H
diff --git a/libc/private/WriteProtected.h b/libc/private/WriteProtected.h
index 69a68229b..26c239ca1 100644
--- a/libc/private/WriteProtected.h
+++ b/libc/private/WriteProtected.h
@@ -46,6 +46,16 @@ class WriteProtected {
WriteProtectedContents<T> contents;
+ int set_protection(int prot) {
+ auto addr = &contents;
+#if __has_feature(hwaddress_sanitizer)
+ // The mprotect system call does not currently untag pointers, so do it
+ // ourselves.
+ addr = untag_address(addr);
+#endif
+ return mprotect(reinterpret_cast<void*>(addr), PAGE_SIZE, prot);
+ }
+
public:
WriteProtected() = default;
BIONIC_DISALLOW_COPY_AND_ASSIGN(WriteProtected);
@@ -55,7 +65,7 @@ class WriteProtected {
// multiple times by accident.
memset(&contents, 0, sizeof(contents));
- if (mprotect(&contents, PAGE_SIZE, PROT_READ)) {
+ if (set_protection(PROT_READ)) {
async_safe_fatal("failed to make WriteProtected nonwritable in initialize");
}
}
@@ -70,12 +80,12 @@ class WriteProtected {
template <typename Mutator>
void mutate(Mutator mutator) {
- if (mprotect(&contents, PAGE_SIZE, PROT_READ | PROT_WRITE) != 0) {
+ if (set_protection(PROT_READ | PROT_WRITE) != 0) {
async_safe_fatal("failed to make WriteProtected writable in mutate: %s",
strerror(errno));
}
mutator(&contents.value);
- if (mprotect(&contents, PAGE_SIZE, PROT_READ) != 0) {
+ if (set_protection(PROT_READ) != 0) {
async_safe_fatal("failed to make WriteProtected nonwritable in mutate: %s",
strerror(errno));
}
diff --git a/libc/private/bionic_globals.h b/libc/private/bionic_globals.h
index d73079e33..ef735bab0 100644
--- a/libc/private/bionic_globals.h
+++ b/libc/private/bionic_globals.h
@@ -88,6 +88,10 @@ struct libc_shared_globals {
TlsModules tls_modules;
BionicAllocator tls_allocator;
+ // Values passed from the HWASan runtime (via libc.so) to the loader.
+ void (*load_hook)(ElfW(Addr) base, const ElfW(Phdr)* phdr, ElfW(Half) phnum) = nullptr;
+ void (*unload_hook)(ElfW(Addr) base, const ElfW(Phdr)* phdr, ElfW(Half) phnum) = nullptr;
+
// Values passed from the linker to libc.so.
const char* init_progname = nullptr;
char** init_environ = nullptr;
diff --git a/libc/private/bionic_macros.h b/libc/private/bionic_macros.h
index 4800e3af9..13934e5f6 100644
--- a/libc/private/bionic_macros.h
+++ b/libc/private/bionic_macros.h
@@ -87,3 +87,12 @@ char (&ArraySizeHelper(T (&array)[N]))[N]; // NOLINT(readability/casting)
#else
#define __BIONIC_FALLTHROUGH
#endif
+
+template <typename T>
+static inline T* untag_address(T* p) {
+#if defined(__aarch64__)
+ return reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(p) & ((1ULL << 56) - 1));
+#else
+ return p;
+#endif
+}
diff --git a/libc/private/sigrtmin.h b/libc/private/sigrtmin.h
index d78d98058..5de1a32ae 100644
--- a/libc/private/sigrtmin.h
+++ b/libc/private/sigrtmin.h
@@ -39,13 +39,14 @@
// 33 (__SIGRTMIN + 1) libbacktrace
// 34 (__SIGRTMIN + 2) libcore
// 35 (__SIGRTMIN + 3) debuggerd -b
-// 36 (__SIGRTMIN + 4) heapprofd
+// 36 (__SIGRTMIN + 4) heapprofd native dumps
// 37 (__SIGRTMIN + 5) coverage (libprofile-extras)
+// 38 (__SIGRTMIN + 6) heapprofd ART managed heap dumps
//
// If you change this, also change __ndk_legacy___libc_current_sigrtmin
// in <android/legacy_signal_inlines.h> to match.
-#define __SIGRT_RESERVED 6
+#define __SIGRT_RESERVED 7
static inline __always_inline sigset64_t filter_reserved_signals(sigset64_t sigset, int how) {
int (*block)(sigset64_t*, int);
int (*unblock)(sigset64_t*, int);
@@ -72,5 +73,6 @@ static inline __always_inline sigset64_t filter_reserved_signals(sigset64_t sigs
unblock(&sigset, __SIGRTMIN + 3);
unblock(&sigset, __SIGRTMIN + 4);
unblock(&sigset, __SIGRTMIN + 5);
+ unblock(&sigset, __SIGRTMIN + 6);
return sigset;
}
diff --git a/libc/stdio/stdio.cpp b/libc/stdio/stdio.cpp
index 91c7689f8..a0b421923 100644
--- a/libc/stdio/stdio.cpp
+++ b/libc/stdio/stdio.cpp
@@ -57,8 +57,6 @@
#include "private/ErrnoRestorer.h"
#include "private/thread_private.h"
-extern "C" int ___close(int fd);
-
#define ALIGNBYTES (sizeof(uintptr_t) - 1)
#define ALIGN(p) (((uintptr_t)(p) + ALIGNBYTES) &~ ALIGNBYTES)
diff --git a/libc/symbol_ordering b/libc/symbol_ordering
deleted file mode 100644
index c04692bca..000000000
--- a/libc/symbol_ordering
+++ /dev/null
@@ -1,210 +0,0 @@
-# This file is generated by sorting symbols in the .bss section in libc.so by
-# their sizes and taking out symbols that are unique to a target. By sorting
-# symbols by size, we usually have less dirty pages at runtime, because small
-# symbols are grouped together.
-
-ctl_initialized
-gGlobalsMutating
-global_hashtable_initialized
-gmtcheck.gmt_is_set
-had_conf_error
-je_background_thread_enabled_state
-je_log_init_done
-je_opt_abort
-je_opt_abort_conf
-je_opt_background_thread
-je_opt_junk_alloc
-je_opt_junk_free
-je_opt_stats_print
-je_opt_utrace
-je_opt_xmalloc
-je_opt_zero
-je_tsd_booted
-malloc_disabled_tcache
-malloc_slow_flags
-mmap_flags
-os_overcommits
-restartloop
-_ZL24gHeapprofdInitInProgress
-_ZL27gHeapprofdInitHookInstalled
-_ZL23gZygoteChildProfileable
-_ZZ17__find_icu_symbolPKcE9found_icu
-ru_a
-ru_b
-ru_counter
-ru_g
-ru_msb
-ru_seed
-ru_seed2
-ru_x
-_ZZ12bindresvportE4port
-a0
-__atexit
-atexit_mutex
-b0
-ctl_arenas
-ctl_stats
-__cxa_finalize.call_depth
-daylight
-dirty_decay_ms_default.0
-environ
-error_message_count
-error_one_per_line
-error_print_progname
-__free_hook
-g_atexit_lock
-gGlobalsMutateLock
-global_hashtable
-gmtptr
-handlers
-je_background_thread_info
-je_hooks_arena_new_hook
-je_init_system_thp_mode
-je_malloc_conf
-je_malloc_disable.once_control
-je_malloc_message
-je_narenas_auto
-je_ncpus
-je_nhbins
-je_opt_dirty_decay_ms
-je_opt_metadata_thp
-je_opt_muzzy_decay_ms
-je_opt_narenas
-je_opt_thp
-je_tcache_bin_info
-je_tcache_maxclass
-je_tcaches
-je_tsd_tsd
-lastenv
-lcl_is_set
-lclptr
-locallock
-malloc_disabled_lock
-__malloc_hook
-malloc_initializer
-mbrlen.mbs
-mbtowc.mbs
-__memalign_hook
-muzzy_decay_ms_default.0
-narenas_total
-ncleanups
-optarg
-optreset
-os_page
-p5s
-__progname
-random_mutex
-__realloc_hook
-_res_cache_list_lock
-_res_cache_once
-_res_key
-__res_randomid.__libc_mutex_random
-rs
-_rs_forkdetect._rs_pid
-_rs_forked
-rsx
-ru_pid
-ru_prf
-ru_reseed
-__stack_chk_guard
-stack_nelms
-strtok.last
-suboptarg
-__system_property_area__
-tcaches_avail
-tcaches_past
-timezone
-tmpnam.tmpcount
-ut
-wctomb.mbs
-_ZL11g_arc4_lock
-_ZL13g_locale_once
-_ZL13g_thread_list
-_ZL14syslog_log_tag
-_ZL16gHeapprofdHandle
-_ZL17g_libicuuc_handle
-_ZL18netdClientInitOnce
-_ZL30g_propservice_protocol_version
-_ZN9prop_area13pa_data_size_E
-_ZN9prop_area8pa_size_E
-_ZZ10mbsnrtowcsE15__private_state
-_ZZ10wcsnrtombsE15__private_state
-_ZZ13error_at_lineE9last_file
-_ZZ13error_at_lineE9last_line
-_ZZ14__icu_charTypejE10u_charType
-_ZZ23__bionic_get_shell_pathE7sh_path
-_ZZ23__icu_hasBinaryPropertyj9UPropertyPFiiEE19u_hasBinaryProperty
-_ZZ25__icu_getIntPropertyValuej9UPropertyE21u_getIntPropertyValue
-_ZZ7mbrtowcE15__private_state
-_ZZ7wcrtombE15__private_state
-_ZZ8c16rtombE15__private_state
-_ZZ8c32rtombE15__private_state
-_ZZ8iswcntrlE10u_charType
-_ZZ8iswdigitE9u_isdigit
-_ZZ8iswpunctE9u_ispunct
-_ZZ8mbrtoc16E15__private_state
-_ZZ8mbrtoc32E15__private_state
-_ZZ8towlowerE9u_tolower
-_ZZ8towupperE9u_toupper
-ether_aton.addr
-seed48.sseed
-__dtoa_locks
-_ZGVZ14__icu_charTypejE10u_charType
-_ZGVZ14tzset_unlockedE20persist_sys_timezone
-_ZGVZ17__find_icu_symbolPKcE9found_icu
-_ZGVZ23__bionic_get_shell_pathE7sh_path
-_ZGVZ23__icu_hasBinaryPropertyj9UPropertyPFiiEE19u_hasBinaryProperty
-_ZGVZ25__icu_getIntPropertyValuej9UPropertyE21u_getIntPropertyValue
-_ZGVZ8iswcntrlE10u_charType
-_ZGVZ8iswdigitE9u_isdigit
-_ZGVZ8iswpunctE9u_ispunct
-_ZGVZ8towlowerE9u_tolower
-_ZGVZ8towupperE9u_toupper
-_ZL10gAllocated
-_ZL11gAllocLimit
-_ZL13g_atfork_list
-_ZL6g_lock
-_ZL6g_tags
-je_opt_stats_print_opts
-nuls
-precsize_ntoa.retbuf
-__p_secstodate.output
-ether_ntoa.buf
-inet_ntoa.b
-__p_class.classbuf
-__p_type.typebuf
-__sym_ntop.unname
-__sym_ntos.unname
-_ZL10gFunctions
-_ZL12vendor_group
-_ZL13vendor_passwd
-freelist
-__p_option.nbuf
-__p_time.nbuf
-_ZL18g_thread_list_lock
-tm
-_ZL8g_locale
-ctl_mtx
-init_lock
-je_arenas_lock
-je_background_thread_lock
-tcaches_mtx
-je_tsd_init_head
-buf_asctime
-__loc_ntoa.tmpbuf
-utmp
-_ZZ14tzset_unlockedE20persist_sys_timezone
-arena_binind_div_info
-__hexdig_D2A
-lcl_TZname
-inet_nsap_ntoa_tmpbuf
-_ZL7key_map
-_ZL17system_properties
-private_mem
-_res_cache_list
-__libc_globals
-tmpnam.buf
-je_extents_rtree
-_nres
-je_arenas
-je_extent_mutex_pool
diff --git a/libc/tools/gensyscalls.py b/libc/tools/gensyscalls.py
index b307486d5..0f3f1dc15 100755
--- a/libc/tools/gensyscalls.py
+++ b/libc/tools/gensyscalls.py
@@ -265,8 +265,7 @@ def add_footer(pointer_length, stub, syscall):
stub += "\nALIAS_SYMBOL(%s, %s)\n" % (alias, syscall["func"])
# Use hidden visibility on LP64 for any functions beginning with underscores.
- # Force hidden visibility for any functions which begin with 3 underscores
- if (pointer_length == 64 and syscall["func"].startswith("__")) or syscall["func"].startswith("___"):
+ if pointer_length == 64 and syscall["func"].startswith("__"):
stub += '.hidden ' + syscall["func"] + '\n'
return stub
diff --git a/libc/tzcode/bionic.cpp b/libc/tzcode/bionic.cpp
index 1742d7941..6d84303a4 100644
--- a/libc/tzcode/bionic.cpp
+++ b/libc/tzcode/bionic.cpp
@@ -199,37 +199,36 @@ static int __bionic_open_tzdata_path(const char* path,
int __bionic_open_tzdata(const char* olson_id, int32_t* entry_length) {
int fd;
-#if defined(__ANDROID__)
- // On Android devices, try the four hard-coded locations in order.
- //
+ // 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.
+ // 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.
+ // 2: The time zone data module which contains the main copy. This is the
+ // common case.
+ // 3: 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 >= 0) return fd;
- // 2: The time zone data module which may contain newer data on
- // devices that support module updates.
fd = __bionic_open_tzdata_path("/apex/com.android.tzdata/etc/tz/tzdata",
olson_id, entry_length);
if (fd >= 0) return fd;
- // 3: The runtime module, which should exist even on devices that
- // do not support APEX file updates.
- fd = __bionic_open_tzdata_path("/apex/com.android.runtime/etc/tz/tzdata",
- olson_id, entry_length);
- if (fd >= 0) return fd;
-
- // 4: The ultimate fallback: the non-updatable copy in /system.
fd = __bionic_open_tzdata_path("/system/usr/share/zoneinfo/tzdata",
olson_id, entry_length);
if (fd >= 0) return fd;
#else
- // On the host, we don't expect those locations to exist, and we're not
- // worried about security so we trust $ANDROID_DATA, $ANDROID_RUNTIME_ROOT,
- // $ANDROID_TZDATA_ROOT, and $ANDROID_ROOT to point us in the right direction.
+ // 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.
+
char* path = make_path("ANDROID_DATA", "/misc/zoneinfo/current/tzdata");
fd = __bionic_open_tzdata_path(path, olson_id, entry_length);
free(path);
@@ -240,11 +239,6 @@ int __bionic_open_tzdata(const char* olson_id, int32_t* entry_length) {
free(path);
if (fd >= 0) return fd;
- path = make_path("ANDROID_RUNTIME_ROOT", "/etc/tz/tzdata");
- fd = __bionic_open_tzdata_path(path, olson_id, entry_length);
- free(path);
- if (fd >= 0) return fd;
-
path = make_path("ANDROID_ROOT", "/usr/share/zoneinfo/tzdata");
fd = __bionic_open_tzdata_path(path, olson_id, entry_length);
free(path);
diff --git a/libc/versioner-dependencies/common/clang-builtins b/libc/versioner-dependencies/common/clang-builtins
index 7bd481c94..148dd2b63 120000
--- a/libc/versioner-dependencies/common/clang-builtins
+++ b/libc/versioner-dependencies/common/clang-builtins
@@ -1 +1 @@
-../../../../external/clang/lib/Headers/ \ No newline at end of file
+../../../../prebuilts/clang-tools/linux-x86/clang-headers \ No newline at end of file
diff --git a/libdl/libdl_cfi.cpp b/libdl/libdl_cfi.cpp
index 1dd5b21cd..3b68fc7d3 100644
--- a/libdl/libdl_cfi.cpp
+++ b/libdl/libdl_cfi.cpp
@@ -44,7 +44,8 @@ extern "C" size_t __cfi_shadow_size() {
}
static uint16_t shadow_load(void* p) {
- uintptr_t addr = reinterpret_cast<uintptr_t>(p);
+ // Untag the pointer to move it into the address space covered by the shadow.
+ uintptr_t addr = reinterpret_cast<uintptr_t>(untag_address(p));
uintptr_t ofs = CFIShadow::MemToShadowOffset(addr);
if (ofs > CFIShadow::kShadowSize) return CFIShadow::kInvalidShadow;
return *reinterpret_cast<uint16_t*>(shadow_base_storage.v + ofs);
diff --git a/libm/Android.bp b/libm/Android.bp
index 48b9a5f06..59466e490 100644
--- a/libm/Android.bp
+++ b/libm/Android.bp
@@ -324,8 +324,16 @@ cc_library {
x86: {
srcs: [
"i387/fenv.c",
+ "x86/ceil.S",
+ "x86/ceilf.S",
+ "x86/floor.S",
+ "x86/floorf.S",
+ "x86/rint.S",
+ "x86/rintf.S",
"x86/sqrt.S",
"x86/sqrtf.S",
+ "x86/trunc.S",
+ "x86/truncf.S",
"x86/e_acos.S",
"x86/e_asin.S",
"x86/e_atan2.S",
@@ -359,37 +367,23 @@ cc_library {
"upstream-freebsd/lib/msun/src/e_sqrtf.c",
"upstream-freebsd/lib/msun/src/s_atan.c",
"upstream-freebsd/lib/msun/src/s_cbrt.c",
+ "upstream-freebsd/lib/msun/src/s_ceil.c",
+ "upstream-freebsd/lib/msun/src/s_ceilf.c",
"upstream-freebsd/lib/msun/src/s_cos.c",
"upstream-freebsd/lib/msun/src/s_expm1.c",
+ "upstream-freebsd/lib/msun/src/s_floor.c",
+ "upstream-freebsd/lib/msun/src/s_floorf.c",
"upstream-freebsd/lib/msun/src/s_log1p.c",
"upstream-freebsd/lib/msun/src/s_lrint.c",
"upstream-freebsd/lib/msun/src/s_lrintf.c",
+ "upstream-freebsd/lib/msun/src/s_rint.c",
+ "upstream-freebsd/lib/msun/src/s_rintf.c",
"upstream-freebsd/lib/msun/src/s_sin.c",
"upstream-freebsd/lib/msun/src/s_tan.c",
"upstream-freebsd/lib/msun/src/s_tanh.c",
+ "upstream-freebsd/lib/msun/src/s_trunc.c",
+ "upstream-freebsd/lib/msun/src/s_truncf.c",
],
- sse4_1: {
- srcs: [
- "x86/ceil.S",
- "x86/ceilf.S",
- "x86/floor.S",
- "x86/floorf.S",
- "x86/rint.S",
- "x86/rintf.S",
- "x86/trunc.S",
- "x86/truncf.S",
- ],
- exclude_srcs: [
- "upstream-freebsd/lib/msun/src/s_ceil.c",
- "upstream-freebsd/lib/msun/src/s_ceilf.c",
- "upstream-freebsd/lib/msun/src/s_floor.c",
- "upstream-freebsd/lib/msun/src/s_floorf.c",
- "upstream-freebsd/lib/msun/src/s_rint.c",
- "upstream-freebsd/lib/msun/src/s_rintf.c",
- "upstream-freebsd/lib/msun/src/s_trunc.c",
- "upstream-freebsd/lib/msun/src/s_truncf.c",
- ],
- },
local_include_dirs: ["i387"],
pack_relocations: false,
ldflags: ["-Wl,--hash-style=both"],
@@ -399,8 +393,16 @@ cc_library {
x86_64: {
srcs: [
"amd64/fenv.c",
+ "x86_64/ceil.S",
+ "x86_64/ceilf.S",
+ "x86_64/floor.S",
+ "x86_64/floorf.S",
+ "x86_64/rint.S",
+ "x86_64/rintf.S",
"x86_64/sqrt.S",
"x86_64/sqrtf.S",
+ "x86_64/trunc.S",
+ "x86_64/truncf.S",
"x86_64/e_acos.S",
"x86_64/e_asin.S",
"x86_64/e_atan2.S",
@@ -431,39 +433,25 @@ cc_library {
"upstream-freebsd/lib/msun/src/e_sqrtf.c",
"upstream-freebsd/lib/msun/src/s_atan.c",
"upstream-freebsd/lib/msun/src/s_cbrt.c",
+ "upstream-freebsd/lib/msun/src/s_ceil.c",
+ "upstream-freebsd/lib/msun/src/s_ceilf.c",
"upstream-freebsd/lib/msun/src/s_cos.c",
"upstream-freebsd/lib/msun/src/s_expm1.c",
+ "upstream-freebsd/lib/msun/src/s_floor.c",
+ "upstream-freebsd/lib/msun/src/s_floorf.c",
"upstream-freebsd/lib/msun/src/s_log1p.c",
"upstream-freebsd/lib/msun/src/s_llrint.c",
"upstream-freebsd/lib/msun/src/s_llrintf.c",
"upstream-freebsd/lib/msun/src/s_lrint.c",
"upstream-freebsd/lib/msun/src/s_lrintf.c",
+ "upstream-freebsd/lib/msun/src/s_rint.c",
+ "upstream-freebsd/lib/msun/src/s_rintf.c",
"upstream-freebsd/lib/msun/src/s_sin.c",
"upstream-freebsd/lib/msun/src/s_tan.c",
"upstream-freebsd/lib/msun/src/s_tanh.c",
+ "upstream-freebsd/lib/msun/src/s_trunc.c",
+ "upstream-freebsd/lib/msun/src/s_truncf.c",
],
- sse4_1: {
- srcs: [
- "x86_64/ceil.S",
- "x86_64/ceilf.S",
- "x86_64/floor.S",
- "x86_64/floorf.S",
- "x86_64/rint.S",
- "x86_64/rintf.S",
- "x86_64/trunc.S",
- "x86_64/truncf.S",
- ],
- exclude_srcs: [
- "upstream-freebsd/lib/msun/src/s_ceil.c",
- "upstream-freebsd/lib/msun/src/s_ceilf.c",
- "upstream-freebsd/lib/msun/src/s_floor.c",
- "upstream-freebsd/lib/msun/src/s_floorf.c",
- "upstream-freebsd/lib/msun/src/s_rint.c",
- "upstream-freebsd/lib/msun/src/s_rintf.c",
- "upstream-freebsd/lib/msun/src/s_trunc.c",
- "upstream-freebsd/lib/msun/src/s_truncf.c",
- ],
- },
version_script: ":libm.x86_64.map",
},
},
@@ -503,7 +491,7 @@ cc_library {
native_coverage: bionic_coverage,
sanitize: {
address: false,
- coverage: false,
+ fuzzer: false,
integer_overflow: false,
},
stl: "none",
diff --git a/linker/Android.bp b/linker/Android.bp
index 5e7a921a4..bdb7c178a 100644
--- a/linker/Android.bp
+++ b/linker/Android.bp
@@ -177,11 +177,6 @@ cc_defaults {
"-Wextra",
"-Wunused",
"-Werror",
-
- // Define _USING_LIBCXX so <stdatomic.h> defers to the <atomic> header. When a Soong module
- // uses the platform libc++, Soong automatically passes this macro, but the dynamic linker
- // links against libc++ manually.
- "-D_USING_LIBCXX",
],
// TODO: split out the asflags.
diff --git a/linker/dlfcn.cpp b/linker/dlfcn.cpp
index 5a47272c1..18301e0e2 100644
--- a/linker/dlfcn.cpp
+++ b/linker/dlfcn.cpp
@@ -308,11 +308,11 @@ static uint8_t __libdl_info_buf[sizeof(soinfo)] __attribute__((aligned(8)));
static soinfo* __libdl_info = nullptr;
// This is used by the dynamic linker. Every process gets these symbols for free.
-soinfo* get_libdl_info(const char* linker_path, const soinfo& linker_si) {
+soinfo* get_libdl_info(const soinfo& linker_si) {
CHECK((linker_si.flags_ & FLAG_GNU_HASH) != 0);
if (__libdl_info == nullptr) {
- __libdl_info = new (__libdl_info_buf) soinfo(&g_default_namespace, linker_path, nullptr, 0, 0);
+ __libdl_info = new (__libdl_info_buf) soinfo(&g_default_namespace, nullptr, nullptr, 0, 0);
__libdl_info->flags_ |= (FLAG_LINKED | FLAG_GNU_HASH);
__libdl_info->strtab_ = linker_si.strtab_;
__libdl_info->symtab_ = linker_si.symtab_;
diff --git a/linker/ld.config.format.md b/linker/ld.config.format.md
index faf5cc8a6..f9fbcde3f 100644
--- a/linker/ld.config.format.md
+++ b/linker/ld.config.format.md
@@ -25,7 +25,7 @@ configuration using set of properties described in example below.
## Example
```
-# The following line maps section to a dir. Binraies ran from this location will use namespaces
+# The following line maps section to a dir. Binaries ran from this location will use namespaces
# configuration specified in [example_section] below
dir.example_section=/system/bin/example
@@ -38,7 +38,7 @@ dir.example_section=/system/bin/example
# default value is false
enable.target.sdk.version = true
-# This property can be used to declare additional namespaces.Note that there is always the default
+# This property can be used to declare additional namespaces. Note that there is always the default
# namespace. The default namespace is the namespace for the main executable. This list is
# comma-separated.
additional.namespaces = ns1
@@ -65,7 +65,7 @@ namespace.default.asan.permitted.paths = /data/${LIB}
# This declares linked namespaces - comma separated list.
namespace.default.links = ns1
-# For every link define list of shared libraries. This is list of the libraries accessilbe from
+# For every link define list of shared libraries. This is list of the libraries accessible from
# default namespace but loaded in the linked namespace.
namespace.default.link.ns1.shared_libs = libexternal.so:libother.so
diff --git a/linker/ldd b/linker/ldd
index 3a0aff91a..6bc49b4b1 100644
--- a/linker/ldd
+++ b/linker/ldd
@@ -10,7 +10,8 @@ function error() {
[ $# -eq 1 ] || error "usage: ldd FILE"
-case `file -L "$1"` in
+what=$(file -L "$1")
+case "$what" in
*32-bit*)
linker --list "$1"
;;
@@ -18,6 +19,6 @@ case `file -L "$1"` in
linker64 --list "$1"
;;
*)
- error "$1: not an ELF file"
+ error "$what"
;;
esac
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 32dce3805..d581dd8ce 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -76,6 +76,7 @@
static std::unordered_map<void*, size_t> g_dso_handle_counters;
+static bool g_anonymous_namespace_set = false;
static android_namespace_t* g_anonymous_namespace = &g_default_namespace;
static std::unordered_map<std::string, android_namespace_t*> g_exported_namespaces;
@@ -90,6 +91,8 @@ static const char* const kLdConfigArchFilePath = "/system/etc/ld.config." ABI_ST
static const char* const kLdConfigFilePath = "/system/etc/ld.config.txt";
static const char* const kLdConfigVndkLiteFilePath = "/system/etc/ld.config.vndk_lite.txt";
+static const char* const kLdGeneratedConfigFilePath = "/dev/linkerconfig/ld.config.txt";
+
#if defined(__LP64__)
static const char* const kSystemLibDir = "/system/lib64";
static const char* const kOdmLibDir = "/odm/lib64";
@@ -270,8 +273,6 @@ static bool translateSystemPathToApexPath(const char* name, std::string* out_nam
static std::vector<std::string> g_ld_preload_names;
-static bool g_anonymous_namespace_initialized;
-
#if STATS
struct linker_stats_t {
int count[kRelocMax];
@@ -282,6 +283,16 @@ static linker_stats_t linker_stats;
void count_relocation(RelocationKind kind) {
++linker_stats.count[kind];
}
+
+void print_linker_stats() {
+ PRINT("RELO STATS: %s: %d abs, %d rel, %d copy, %d symbol (%d cached)",
+ g_argv[0],
+ linker_stats.count[kRelocAbsolute],
+ linker_stats.count[kRelocRelative],
+ linker_stats.count[kRelocCopy],
+ linker_stats.count[kRelocSymbol],
+ linker_stats.count[kRelocSymbolCached]);
+}
#else
void count_relocation(RelocationKind) {
}
@@ -393,16 +404,23 @@ static void parse_LD_LIBRARY_PATH(const char* path) {
}
static bool realpath_fd(int fd, std::string* realpath) {
- std::vector<char> buf(PATH_MAX), proc_self_fd(PATH_MAX);
- async_safe_format_buffer(&proc_self_fd[0], proc_self_fd.size(), "/proc/self/fd/%d", fd);
- if (readlink(&proc_self_fd[0], &buf[0], buf.size()) == -1) {
+ // proc_self_fd needs to be large enough to hold "/proc/self/fd/" plus an
+ // integer, plus the NULL terminator.
+ char proc_self_fd[32];
+ // We want to statically allocate this large buffer so that we don't grow
+ // the stack by too much.
+ static char buf[PATH_MAX];
+
+ async_safe_format_buffer(proc_self_fd, sizeof(proc_self_fd), "/proc/self/fd/%d", fd);
+ auto length = readlink(proc_self_fd, buf, sizeof(buf));
+ if (length == -1) {
if (!is_first_stage_init()) {
- PRINT("readlink(\"%s\") failed: %s [fd=%d]", &proc_self_fd[0], strerror(errno), fd);
+ PRINT("readlink(\"%s\") failed: %s [fd=%d]", proc_self_fd, strerror(errno), fd);
}
return false;
}
- *realpath = &buf[0];
+ realpath->assign(buf, length);
return true;
}
@@ -934,7 +952,9 @@ static const ElfW(Sym)* dlsym_linear_lookup(android_namespace_t* ns,
}
soinfo* find_containing_library(const void* p) {
- ElfW(Addr) address = reinterpret_cast<ElfW(Addr)>(p);
+ // Addresses within a library may be tagged if they point to globals. Untag
+ // them so that the bounds check succeeds.
+ ElfW(Addr) address = reinterpret_cast<ElfW(Addr)>(untag_address(p));
for (soinfo* si = solist_get_head(); si != nullptr; si = si->next) {
if (address < si->base || address - si->base >= si->size) {
continue;
@@ -1215,12 +1235,14 @@ static bool find_loaded_library_by_inode(android_namespace_t* ns,
off64_t file_offset,
bool search_linked_namespaces,
soinfo** candidate) {
+ if (file_stat.st_dev == 0 || file_stat.st_ino == 0) {
+ *candidate = nullptr;
+ return false;
+ }
auto predicate = [&](soinfo* si) {
- return si->get_st_dev() != 0 &&
- si->get_st_ino() != 0 &&
+ return si->get_st_ino() == file_stat.st_ino &&
si->get_st_dev() == file_stat.st_dev &&
- si->get_st_ino() == file_stat.st_ino &&
si->get_file_offset() == file_offset;
};
@@ -1882,6 +1904,9 @@ bool find_libraries(android_namespace_t* ns,
// flag is set.
link_extinfo = extinfo;
}
+ if (__libc_shared_globals()->load_hook) {
+ __libc_shared_globals()->load_hook(si->load_bias, si->phdr, si->phnum);
+ }
if (!si->link_image(global_group, local_group, link_extinfo, &relro_fd_offset) ||
!get_cfi_shadow()->AfterLoad(si, solist_get_head())) {
return false;
@@ -2020,6 +2045,9 @@ static void soinfo_unload_impl(soinfo* root) {
si);
notify_gdb_of_unload(si);
unregister_soinfo_tls(si);
+ if (__libc_shared_globals()->unload_hook) {
+ __libc_shared_globals()->unload_hook(si->load_bias, si->phdr, si->phnum);
+ }
get_cfi_shadow()->BeforeUnload(si);
soinfo_free(si);
}
@@ -2452,14 +2480,29 @@ int do_dlclose(void* handle) {
return 0;
}
-bool init_anonymous_namespace(const char* shared_lib_sonames, const char* library_search_path) {
- if (g_anonymous_namespace_initialized) {
- DL_ERR("anonymous namespace has already been initialized.");
- return false;
+// Make ns as the anonymous namespace that is a namespace used when
+// we fail to determine the caller address (e.g., call from mono-jited code)
+// Since there can be multiple anonymous namespace in a process, subsequent
+// call to this function causes an error.
+static bool set_anonymous_namespace(android_namespace_t* ns) {
+ if (!g_anonymous_namespace_set && ns != nullptr) {
+ CHECK(ns->is_also_used_as_anonymous());
+ g_anonymous_namespace = ns;
+ g_anonymous_namespace_set = true;
+ return true;
}
+ return false;
+}
+// TODO(b/130388701) remove this. Currently, this is used only for testing
+// where we don't have classloader namespace.
+bool init_anonymous_namespace(const char* shared_lib_sonames, const char* library_search_path) {
ProtectedDataGuard guard;
+ // Test-only feature: we need to change the anonymous namespace multiple times
+ // while the test is running.
+ g_anonymous_namespace_set = false;
+
// create anonymous namespace
// When the caller is nullptr - create_namespace will take global group
// from the anonymous namespace, which is fine because anonymous namespace
@@ -2469,21 +2512,18 @@ bool init_anonymous_namespace(const char* shared_lib_sonames, const char* librar
"(anonymous)",
nullptr,
library_search_path,
- ANDROID_NAMESPACE_TYPE_ISOLATED,
+ ANDROID_NAMESPACE_TYPE_ISOLATED |
+ ANDROID_NAMESPACE_TYPE_ALSO_USED_AS_ANONYMOUS,
nullptr,
&g_default_namespace);
- if (anon_ns == nullptr) {
- return false;
- }
+ CHECK(anon_ns != nullptr);
if (!link_namespaces(anon_ns, &g_default_namespace, shared_lib_sonames)) {
+ // TODO: delete anon_ns
return false;
}
- g_anonymous_namespace = anon_ns;
- g_anonymous_namespace_initialized = true;
-
return true;
}
@@ -2523,6 +2563,7 @@ android_namespace_t* create_namespace(const void* caller_addr,
ns->set_name(name);
ns->set_isolated((type & ANDROID_NAMESPACE_TYPE_ISOLATED) != 0);
ns->set_greylist_enabled((type & ANDROID_NAMESPACE_TYPE_GREYLIST_ENABLED) != 0);
+ ns->set_also_used_as_anonymous((type & ANDROID_NAMESPACE_TYPE_ALSO_USED_AS_ANONYMOUS) != 0);
if ((type & ANDROID_NAMESPACE_TYPE_SHARED) != 0) {
// append parent namespace paths.
@@ -2554,6 +2595,16 @@ android_namespace_t* create_namespace(const void* caller_addr,
ns->set_default_library_paths(std::move(default_library_paths));
ns->set_permitted_paths(std::move(permitted_paths));
+ if (ns->is_also_used_as_anonymous() && !set_anonymous_namespace(ns)) {
+ DL_ERR("failed to set namespace: [name=\"%s\", ld_library_path=\"%s\", default_library_paths=\"%s\""
+ " permitted_paths=\"%s\"] as the anonymous namespace",
+ ns->get_name(),
+ android::base::Join(ns->get_ld_library_paths(), ':').c_str(),
+ android::base::Join(ns->get_default_library_paths(), ':').c_str(),
+ android::base::Join(ns->get_permitted_paths(), ':').c_str());
+ return nullptr;
+ }
+
return ns;
}
@@ -2874,6 +2925,17 @@ bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& r
const size_t tls_tp_base = __libc_shared_globals()->static_tls_layout.offset_thread_pointer();
std::vector<std::pair<TlsDescriptor*, size_t>> deferred_tlsdesc_relocs;
+ struct {
+ // Cache key
+ ElfW(Word) sym;
+
+ // Cache value
+ const ElfW(Sym)* s;
+ soinfo* lsi;
+ } symbol_lookup_cache;
+
+ symbol_lookup_cache.sym = 0;
+
for (size_t idx = 0; rel_iterator.has_next(); ++idx) {
const auto rel = rel_iterator.next();
if (rel == nullptr) {
@@ -2917,14 +2979,25 @@ bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& r
return false;
} else {
sym_name = get_string(symtab_[sym].st_name);
- const version_info* vi = nullptr;
- if (!lookup_version_info(version_tracker, sym, sym_name, &vi)) {
- return false;
- }
+ if (sym == symbol_lookup_cache.sym) {
+ s = symbol_lookup_cache.s;
+ lsi = symbol_lookup_cache.lsi;
+ count_relocation(kRelocSymbolCached);
+ } else {
+ const version_info* vi = nullptr;
- if (!soinfo_do_lookup(this, sym_name, vi, &lsi, global_group, local_group, &s)) {
- return false;
+ if (!lookup_version_info(version_tracker, sym, sym_name, &vi)) {
+ return false;
+ }
+
+ if (!soinfo_do_lookup(this, sym_name, vi, &lsi, global_group, local_group, &s)) {
+ return false;
+ }
+
+ symbol_lookup_cache.sym = sym;
+ symbol_lookup_cache.s = s;
+ symbol_lookup_cache.lsi = lsi;
}
if (s == nullptr) {
@@ -3121,10 +3194,6 @@ bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& r
*reinterpret_cast<ElfW(Addr)*>(reloc) = tpoff;
}
break;
-
-#if !defined(__aarch64__)
- // Omit support for DTPMOD/DTPREL on arm64, at least until
- // http://b/123385182 is fixed. arm64 uses TLSDESC instead.
case R_GENERIC_TLS_DTPMOD:
count_relocation(kRelocRelative);
MARK(rel->r_offset);
@@ -3149,7 +3218,6 @@ bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& r
reinterpret_cast<void*>(sym_addr + addend), sym_name);
*reinterpret_cast<ElfW(Addr)*>(reloc) = sym_addr + addend;
break;
-#endif // !defined(__aarch64__)
#if defined(__aarch64__)
// Bionic currently only implements TLSDESC for arm64. This implementation should work with
@@ -4073,10 +4141,10 @@ static std::vector<android_namespace_t*> init_default_namespace_no_config(bool i
return namespaces;
}
-// return /apex/<name>/etc/ld.config.txt from /apex/<name>/bin/<exec>
+// return /apex/<name>/etc/ld.config.txt from /apex/<name>/bin/*
static std::string get_ld_config_file_apex_path(const char* executable_path) {
std::vector<std::string> paths = android::base::Split(executable_path, "/");
- if (paths.size() == 5 && paths[1] == "apex" && paths[3] == "bin") {
+ if (paths.size() >= 5 && paths[1] == "apex" && paths[3] == "bin") {
return std::string("/apex/") + paths[2] + "/etc/ld.config.txt";
}
return "";
@@ -4106,6 +4174,13 @@ static std::string get_ld_config_file_path(const char* executable_path) {
}
#endif
+ // Use generated linker config if flag is set
+ // TODO(b/138920271) Do not check property once it is confirmed as stable
+ if (android::base::GetBoolProperty("sys.linker.use_generated_config", false) &&
+ file_exists(kLdGeneratedConfigFilePath)) {
+ return kLdGeneratedConfigFilePath;
+ }
+
std::string path = get_ld_config_file_apex_path(executable_path);
if (!path.empty()) {
if (file_exists(path.c_str())) {
diff --git a/linker/linker.h b/linker/linker.h
index 4c89cebcd..89390b384 100644
--- a/linker/linker.h
+++ b/linker/linker.h
@@ -94,12 +94,15 @@ enum RelocationKind {
kRelocRelative,
kRelocCopy,
kRelocSymbol,
+ kRelocSymbolCached,
kRelocMax
};
void count_relocation(RelocationKind kind);
-soinfo* get_libdl_info(const char* linker_path, const soinfo& linker_si);
+void print_linker_stats();
+
+soinfo* get_libdl_info(const soinfo& linker_si);
soinfo* find_containing_library(const void* p);
@@ -162,6 +165,13 @@ enum {
*/
ANDROID_NAMESPACE_TYPE_GREYLIST_ENABLED = 0x08000000,
+ /* This flag instructs linker to use this namespace as the anonymous
+ * namespace. There can be only one anonymous namespace in a process. If there
+ * already an anonymous namespace in the process, using this flag when
+ * creating a new namespace causes an error
+ */
+ ANDROID_NAMESPACE_TYPE_ALSO_USED_AS_ANONYMOUS = 0x10000000,
+
ANDROID_NAMESPACE_TYPE_SHARED_ISOLATED = ANDROID_NAMESPACE_TYPE_SHARED |
ANDROID_NAMESPACE_TYPE_ISOLATED,
};
diff --git a/linker/linker_main.cpp b/linker/linker_main.cpp
index f5760231a..fd1592d33 100644
--- a/linker/linker_main.cpp
+++ b/linker/linker_main.cpp
@@ -63,6 +63,8 @@ static ElfW(Addr) get_elf_exec_load_bias(const ElfW(Ehdr)* elf);
static void get_elf_base_from_phdr(const ElfW(Phdr)* phdr_table, size_t phdr_count,
ElfW(Addr)* base, ElfW(Addr)* load_bias);
+static void set_bss_vma_name(soinfo* si);
+
// These should be preserved static to avoid emitting
// RELATIVE relocations for the part of the code running
// before linker links itself.
@@ -176,11 +178,12 @@ static void add_vdso() {
}
// Initializes an soinfo's link_map_head field using other fields from the
-// soinfo (phdr, phnum, load_bias).
-static void init_link_map_head(soinfo& info, const char* linker_path) {
+// soinfo (phdr, phnum, load_bias). The soinfo's realpath must not change after
+// this function is called.
+static void init_link_map_head(soinfo& info) {
auto& map = info.link_map_head;
map.l_addr = info.load_bias;
- map.l_name = const_cast<char*>(linker_path);
+ map.l_name = const_cast<char*>(info.get_realpath());
phdr_table_get_dynamic_section(info.phdr, info.phnum, info.load_bias, &map.l_ld, nullptr);
}
@@ -232,9 +235,9 @@ static ExecutableInfo get_executable_info() {
}
#if defined(__LP64__)
-static char kLinkerPath[] = "/system/bin/linker64";
+static char kFallbackLinkerPath[] = "/system/bin/linker64";
#else
-static char kLinkerPath[] = "/system/bin/linker";
+static char kFallbackLinkerPath[] = "/system/bin/linker";
#endif
__printflike(1, 2)
@@ -350,15 +353,11 @@ static ElfW(Addr) linker_main(KernelArgumentBlock& args, const char* exe_to_load
const ExecutableInfo exe_info = exe_to_load ? load_executable(exe_to_load) :
get_executable_info();
- // Assign to a static variable for the sake of the debug map, which needs
- // a C-style string to last until the program exits.
- static std::string exe_path = exe_info.path;
-
- INFO("[ Linking executable \"%s\" ]", exe_path.c_str());
+ INFO("[ Linking executable \"%s\" ]", exe_info.path.c_str());
// Initialize the main exe's soinfo.
soinfo* si = soinfo_alloc(&g_default_namespace,
- exe_path.c_str(), &exe_info.file_stat,
+ exe_info.path.c_str(), &exe_info.file_stat,
0, RTLD_GLOBAL);
somain = si;
si->phdr = exe_info.phdr;
@@ -367,7 +366,27 @@ static ElfW(Addr) linker_main(KernelArgumentBlock& args, const char* exe_to_load
si->size = phdr_table_get_load_size(si->phdr, si->phnum);
si->dynamic = nullptr;
si->set_main_executable();
- init_link_map_head(*si, exe_path.c_str());
+ init_link_map_head(*si);
+
+ set_bss_vma_name(si);
+
+ // Use the executable's PT_INTERP string as the solinker filename in the
+ // dynamic linker's module list. gdb reads both PT_INTERP and the module list,
+ // and if the paths for the linker are different, gdb will report that the
+ // PT_INTERP linker path was unloaded once the module list is initialized.
+ // There are three situations to handle:
+ // - the APEX linker (/system/bin/linker[64] -> /apex/.../linker[64])
+ // - the ASAN linker (/system/bin/linker_asan[64] -> /apex/.../linker[64])
+ // - the bootstrap linker (/system/bin/bootstrap/linker[64])
+ const char *interp = phdr_table_get_interpreter_name(somain->phdr, somain->phnum,
+ somain->load_bias);
+ if (interp == nullptr) {
+ // This case can happen if the linker attempts to execute itself
+ // (e.g. "linker64 /system/bin/linker64").
+ interp = kFallbackLinkerPath;
+ }
+ solinker->set_realpath(interp);
+ init_link_map_head(*solinker);
// Register the main executable and the linker upfront to have
// gdb aware of them before loading the rest of the dependency
@@ -405,7 +424,7 @@ static ElfW(Addr) linker_main(KernelArgumentBlock& args, const char* exe_to_load
parse_LD_LIBRARY_PATH(ldpath_env);
parse_LD_PRELOAD(ldpreload_env);
- std::vector<android_namespace_t*> namespaces = init_default_namespaces(exe_path.c_str());
+ std::vector<android_namespace_t*> namespaces = init_default_namespaces(exe_info.path.c_str());
if (!si->prelink_image()) __linker_cannot_link(g_argv[0]);
@@ -475,11 +494,7 @@ static ElfW(Addr) linker_main(KernelArgumentBlock& args, const char* exe_to_load
static_cast<long long>(t0.tv_usec))));
#endif
#if STATS
- PRINT("RELO STATS: %s: %d abs, %d rel, %d copy, %d symbol", g_argv[0],
- linker_stats.count[kRelocAbsolute],
- linker_stats.count[kRelocRelative],
- linker_stats.count[kRelocCopy],
- linker_stats.count[kRelocSymbol]);
+ print_linker_stats();
#endif
#if COUNT_PAGES
{
@@ -559,6 +574,31 @@ static void get_elf_base_from_phdr(const ElfW(Phdr)* phdr_table, size_t phdr_cou
async_safe_fatal("Could not find a PHDR: broken executable?");
}
+/*
+ * Set anonymous VMA name for .bss section. For DSOs loaded by the linker, this
+ * is done by ElfReader. This function is here for DSOs loaded by the kernel,
+ * namely the linker itself and the main executable.
+ */
+static void set_bss_vma_name(soinfo* si) {
+ for (size_t i = 0; i < si->phnum; ++i) {
+ auto phdr = &si->phdr[i];
+
+ if (phdr->p_type != PT_LOAD) {
+ continue;
+ }
+
+ ElfW(Addr) seg_start = phdr->p_vaddr + si->load_bias;
+ ElfW(Addr) seg_page_end = PAGE_END(seg_start + phdr->p_memsz);
+ ElfW(Addr) seg_file_end = PAGE_END(seg_start + phdr->p_filesz);
+
+ if (seg_page_end > seg_file_end) {
+ prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME,
+ reinterpret_cast<void*>(seg_file_end), seg_page_end - seg_file_end,
+ ".bss");
+ }
+ }
+}
+
// Detect an attempt to run the linker on itself. e.g.:
// /system/bin/linker64 /system/bin/linker64
// Use priority-1 to run this constructor before other constructors.
@@ -649,6 +689,9 @@ __linker_init_post_relocation(KernelArgumentBlock& args, soinfo& tmp_linker_so)
// couldn't make system calls on x86 at that point, but we can now...
if (!tmp_linker_so.protect_relro()) __linker_cannot_link(args.argv[0]);
+ // And we can set VMA name for the bss section now
+ set_bss_vma_name(&tmp_linker_so);
+
// Initialize the linker's static libc's globals
__libc_init_globals();
@@ -695,9 +738,8 @@ __linker_init_post_relocation(KernelArgumentBlock& args, soinfo& tmp_linker_so)
// Initialize static variables. Note that in order to
// get correct libdl_info we need to call constructors
// before get_libdl_info().
- sonext = solist = solinker = get_libdl_info(kLinkerPath, tmp_linker_so);
+ sonext = solist = solinker = get_libdl_info(tmp_linker_so);
g_default_namespace.add_soinfo(solinker);
- init_link_map_head(*solinker, kLinkerPath);
ElfW(Addr) start_address = linker_main(args, exe_to_load);
diff --git a/linker/linker_namespaces.h b/linker/linker_namespaces.h
index 215ad05c3..9561bb444 100644
--- a/linker/linker_namespaces.h
+++ b/linker/linker_namespaces.h
@@ -72,7 +72,10 @@ struct android_namespace_link_t {
struct android_namespace_t {
public:
- android_namespace_t() : is_isolated_(false), is_greylist_enabled_(false) {}
+ android_namespace_t() :
+ is_isolated_(false),
+ is_greylist_enabled_(false),
+ is_also_used_as_anonymous_(false) {}
const char* get_name() const { return name_.c_str(); }
void set_name(const char* name) { name_ = name; }
@@ -83,6 +86,9 @@ struct android_namespace_t {
bool is_greylist_enabled() const { return is_greylist_enabled_; }
void set_greylist_enabled(bool enabled) { is_greylist_enabled_ = enabled; }
+ bool is_also_used_as_anonymous() const { return is_also_used_as_anonymous_; }
+ void set_also_used_as_anonymous(bool yes) { is_also_used_as_anonymous_ = yes; }
+
const std::vector<std::string>& get_ld_library_paths() const {
return ld_library_paths_;
}
@@ -164,6 +170,7 @@ struct android_namespace_t {
std::string name_;
bool is_isolated_;
bool is_greylist_enabled_;
+ bool is_also_used_as_anonymous_;
std::vector<std::string> ld_library_paths_;
std::vector<std::string> default_library_paths_;
std::vector<std::string> permitted_paths_;
diff --git a/linker/linker_relocs.h b/linker/linker_relocs.h
index 68191f911..1da5ebe34 100644
--- a/linker/linker_relocs.h
+++ b/linker/linker_relocs.h
@@ -38,9 +38,9 @@
#define R_GENERIC_GLOB_DAT R_AARCH64_GLOB_DAT
#define R_GENERIC_RELATIVE R_AARCH64_RELATIVE
#define R_GENERIC_IRELATIVE R_AARCH64_IRELATIVE
-#define R_GENERIC_TLS_DTPMOD R_AARCH64_TLS_DTPMOD64
-#define R_GENERIC_TLS_DTPREL R_AARCH64_TLS_DTPREL64
-#define R_GENERIC_TLS_TPREL R_AARCH64_TLS_TPREL64
+#define R_GENERIC_TLS_DTPMOD R_AARCH64_TLS_DTPMOD
+#define R_GENERIC_TLS_DTPREL R_AARCH64_TLS_DTPREL
+#define R_GENERIC_TLS_TPREL R_AARCH64_TLS_TPREL
#define R_GENERIC_TLSDESC R_AARCH64_TLSDESC
#elif defined (__arm__)
diff --git a/linker/linker_sdk_versions.cpp b/linker/linker_sdk_versions.cpp
index b06f3e63f..29c0f4af2 100644
--- a/linker/linker_sdk_versions.cpp
+++ b/linker/linker_sdk_versions.cpp
@@ -26,10 +26,13 @@
* SUCH DAMAGE.
*/
-#include "linker.h"
-#include <android/api-level.h>
#include <atomic>
+#include <android/api-level.h>
+#include <android/fdsan.h>
+
+#include "linker.h"
+
static std::atomic<int> g_target_sdk_version(__ANDROID_API__);
void set_application_target_sdk_version(int target) {
@@ -38,6 +41,10 @@ void set_application_target_sdk_version(int target) {
target = __ANDROID_API__;
}
g_target_sdk_version = target;
+
+ if (target < 30) {
+ android_fdsan_set_error_level_from_property(ANDROID_FDSAN_ERROR_LEVEL_WARN_ONCE);
+ }
}
int get_application_target_sdk_version() {
diff --git a/linker/linker_soinfo.cpp b/linker/linker_soinfo.cpp
index 5f40528e9..d4b25414e 100644
--- a/linker/linker_soinfo.cpp
+++ b/linker/linker_soinfo.cpp
@@ -550,6 +550,16 @@ void soinfo::set_nodelete() {
rtld_flags_ |= RTLD_NODELETE;
}
+void soinfo::set_realpath(const char* path) {
+#if defined(__work_around_b_24465209__)
+ if (has_min_version(2)) {
+ realpath_ = path;
+ }
+#else
+ realpath_ = path;
+#endif
+}
+
const char* soinfo::get_realpath() const {
#if defined(__work_around_b_24465209__)
if (has_min_version(2)) {
diff --git a/linker/linker_soinfo.h b/linker/linker_soinfo.h
index 80c51af9a..27032c2da 100644
--- a/linker/linker_soinfo.h
+++ b/linker/linker_soinfo.h
@@ -278,6 +278,7 @@ struct soinfo {
void set_soname(const char* soname);
const char* get_soname() const;
+ void set_realpath(const char* path);
const char* get_realpath() const;
const ElfW(Versym)* get_versym(size_t n) const;
ElfW(Addr) get_verneed_ptr() const;
@@ -372,7 +373,7 @@ struct soinfo {
android_namespace_list_t secondary_namespaces_;
uintptr_t handle_;
- friend soinfo* get_libdl_info(const char* linker_path, const soinfo& linker_si);
+ friend soinfo* get_libdl_info(const soinfo& linker_si);
// version >= 4
ElfW(Relr)* relr_;
diff --git a/tests/Android.bp b/tests/Android.bp
index db02d751a..aac419c23 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -241,6 +241,15 @@ cc_test_library {
cflags: [
"-fno-emulated-tls",
],
+ // With fuzzer builds, compiler instrumentation generates a reference to the
+ // __sancov_lowest_stack variable, which (for now) is defined by the fuzzer
+ // library as an emutls symbol. The -fno-emulated-tls flag above configures
+ // the compiler to reference an ordinary ELF TLS __sancov_lowest_stack
+ // symbol instead, which isn't defined. Disable the fuzzer for this test
+ // until the platform is switched to ELF TLS.
+ sanitize: {
+ fuzzer: false,
+ },
}
cc_test_library {
@@ -262,6 +271,15 @@ cc_test_library {
cflags: [
"-fno-emulated-tls",
],
+ // With fuzzer builds, compiler instrumentation generates a reference to the
+ // __sancov_lowest_stack variable, which (for now) is defined by the fuzzer
+ // library as an emutls symbol. The -fno-emulated-tls flag above configures
+ // the compiler to reference an ordinary ELF TLS __sancov_lowest_stack
+ // symbol instead, which isn't defined. Disable the fuzzer for this test
+ // until the platform is switched to ELF TLS.
+ sanitize: {
+ fuzzer: false,
+ },
}
// -----------------------------------------------------------------------------
@@ -269,6 +287,18 @@ cc_test_library {
// -----------------------------------------------------------------------------
cc_defaults {
+ name: "bionic_clang_fortify_tests_w_flags",
+ cflags: [
+ "-Wno-builtin-memcpy-chk-size",
+ "-Wno-format-security",
+ "-Wno-format-zero-length",
+ "-Wno-memset-transposed-args",
+ "-Wno-strlcpy-strlcat-size",
+ "-Wno-strncat-size",
+ ],
+}
+
+cc_defaults {
name: "bionic_fortify_tests_defaults",
cflags: [
"-U_FORTIFY_SOURCE",
@@ -287,6 +317,9 @@ cc_defaults {
// unused.
cc_test_library {
name: "fortify_disabled_for_asan",
+ defaults: [
+ "bionic_clang_fortify_tests_w_flags",
+ ],
cflags: [
"-Werror",
"-D_FORTIFY_SOURCE=2",
@@ -294,11 +327,10 @@ cc_test_library {
// enabled. Since the intent is just to build this, we can get away with
// passing this flag on its own.
"-fsanitize=address",
- "-Wno-memset-transposed-args",
],
// Ignore that we don't have ASAN symbols linked in.
allow_undefined_symbols: true,
- srcs: ["fortify_filecheck_diagnostics_test.cpp"],
+ srcs: ["clang_fortify_tests.cpp"],
}
// Ensure we don't use FORTIFY'ed functions with the static analyzer/clang-tidy:
@@ -307,13 +339,15 @@ cc_test_library {
// enabled. The library that results from building this is meant to be unused.
cc_test_library {
name: "fortify_disabled_for_tidy",
+ defaults: [
+ "bionic_clang_fortify_tests_w_flags",
+ ],
cflags: [
"-Werror",
"-D_FORTIFY_SOURCE=2",
"-D__clang_analyzer__",
- "-Wno-memset-transposed-args",
],
- srcs: ["fortify_filecheck_diagnostics_test.cpp"],
+ srcs: ["clang_fortify_tests.cpp"],
}
cc_test_library {
@@ -346,6 +380,53 @@ cc_test_library {
},
}
+cc_defaults {
+ name: "bionic_new_fortify_tests_defaults",
+ defaults: [
+ "bionic_clang_fortify_tests_w_flags",
+ ],
+ cflags: [
+ "-U_FORTIFY_SOURCE",
+ ],
+ srcs: ["clang_fortify_tests.cpp"],
+ target: {
+ host: {
+ clang_cflags: ["-D__clang__"],
+ },
+ },
+}
+
+cc_test_library {
+ name: "libfortify1-new-tests-clang",
+ defaults: [
+ "bionic_new_fortify_tests_defaults",
+ "bionic_tests_defaults",
+ ],
+ cflags: [
+ "-D_FORTIFY_SOURCE=1",
+ "-DTEST_NAME=Fortify1_clang_new",
+ ],
+ shared: {
+ enabled: false,
+ },
+}
+
+cc_test_library {
+ name: "libfortify2-new-tests-clang",
+ defaults: [
+ "bionic_new_fortify_tests_defaults",
+ "bionic_tests_defaults",
+ ],
+ cflags: [
+ "-D_FORTIFY_SOURCE=2",
+ "-DTEST_NAME=Fortify2_clang_new",
+ ],
+ shared: {
+ enabled: false,
+ },
+}
+
+
// -----------------------------------------------------------------------------
// Library of all tests (excluding the dynamic linker tests).
// -----------------------------------------------------------------------------
@@ -356,7 +437,9 @@ cc_test_library {
"libBionicStandardTests",
"libBionicElfTlsTests",
"libfortify1-tests-clang",
+ "libfortify1-new-tests-clang",
"libfortify2-tests-clang",
+ "libfortify2-new-tests-clang",
],
shared: {
enabled: false,
@@ -477,7 +560,6 @@ cc_defaults {
android: {
shared_libs: [
"ld-android",
- "libandroidicu",
"libdl",
"libdl_android",
"libdl_preempt_test_1",
diff --git a/tests/Android.mk b/tests/Android.mk
index 848d2917e..b5571e3f6 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -59,23 +59,11 @@ ifeq ($(HOST_OS)-$(HOST_ARCH),$(filter $(HOST_OS)-$(HOST_ARCH),linux-x86 linux-x
# Compile time tests.
# -----------------------------------------------------------------------------
-# Some of these are intentionally using = instead of := since we need access to
-# some variables not initialtized until we're in the build system.
-
-include $(CLEAR_VARS)
-LOCAL_ADDITIONAL_DEPENDENCIES := \
- $(LOCAL_PATH)/Android.mk \
- $(LOCAL_PATH)/touch-obj-on-success
-
-LOCAL_CXX := $(LOCAL_PATH)/touch-obj-on-success \
- $(LLVM_PREBUILTS_PATH)/clang++ \
-
-LOCAL_CLANG := true
-LOCAL_MODULE := bionic-compile-time-tests-clang++
-LOCAL_CPPFLAGS := -Wall -Wno-error
-LOCAL_CPPFLAGS += -fno-color-diagnostics -ferror-limit=10000 -Xclang -verify
-LOCAL_SRC_FILES := fortify_filecheck_diagnostics_test.cpp
-include $(BUILD_STATIC_LIBRARY)
+FORTIFY_LEVEL := 1
+include $(LOCAL_PATH)/make_fortify_compile_test.mk
+
+FORTIFY_LEVEL := 2
+include $(LOCAL_PATH)/make_fortify_compile_test.mk
endif # linux-x86
diff --git a/tests/clang_fortify_tests.cpp b/tests/clang_fortify_tests.cpp
new file mode 100644
index 000000000..1b6b898d5
--- /dev/null
+++ b/tests/clang_fortify_tests.cpp
@@ -0,0 +1,607 @@
+/*
+ * 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.
+ */
+
+#ifndef __clang__
+#error "Non-clang isn't supported"
+#endif
+
+// Clang compile-time and run-time tests for Bionic's FORTIFY.
+//
+// This file is compiled in two configurations ways to give us a sane set of tests for clang's
+// FORTIFY implementation.
+//
+// One configuration uses clang's diagnostic consumer
+// (https://clang.llvm.org/doxygen/classclang_1_1VerifyDiagnosticConsumer.html#details)
+// to check diagnostics (e.g. the expected-* comments everywhere).
+//
+// Please note that this test does things like leaking memory. That's WAI.
+
+// Silence all "from 'diagnose_if'" `note`s from anywhere, including headers; they're uninteresting
+// for this test case, and their line numbers may change over time.
+// expected-note@* 0+{{from 'diagnose_if'}}
+//
+// Similarly, there are a few overload tricks we have to emit errors. Ignore any notes from those.
+// expected-note@* 0+{{candidate function}}
+
+#ifndef _FORTIFY_SOURCE
+#error "_FORTIFY_SOURCE must be defined"
+#endif
+
+#include <sys/cdefs.h>
+
+// This is a test specifically of bionic's FORTIFY machinery. Other stdlibs need not apply.
+#ifndef __BIONIC__
+// expected-no-diagnostics
+#else
+
+// As alluded to above, we're going to be doing some obviously very broken things in this file.
+// FORTIFY helpfully flags a lot of it at compile-time, but we want it to *actually* crash, too. So
+// let's wipe out any build-time errors.
+#ifndef COMPILATION_TESTS
+#undef __clang_error_if
+#define __clang_error_if(...)
+#undef __clang_warning_if
+#define __clang_warning_if(...)
+
+// SOMETIMES_CONST allows clang to emit eager diagnostics when we're doing compilation tests, but
+// blocks them otherwise. This is needed for diagnostics emitted with __enable_if.
+#define SOMETIMES_CONST volatile
+#else
+#define SOMETIMES_CONST const
+#endif
+
+#include <err.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <poll.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <wchar.h>
+
+#ifndef COMPILATION_TESTS
+#include <gtest/gtest.h>
+#include "BionicDeathTest.h"
+
+#define CONCAT2(x, y) x##y
+#define CONCAT(x, y) CONCAT2(x, y)
+#define FORTIFY_TEST_NAME CONCAT(clang_fortify_test_, _FORTIFY_SOURCE)
+
+namespace {
+struct FORTIFY_TEST_NAME : BionicDeathTest {
+ protected:
+ void SetUp() override {
+ stdin_saved = dup(STDIN_FILENO);
+ if (stdin_saved < 0) err(1, "failed to dup stdin");
+
+ int devnull = open("/dev/null", O_RDONLY);
+ if (devnull < 0) err(1, "failed to open /dev/null");
+
+ if (!dup2(devnull, STDIN_FILENO)) err(1, "failed to overwrite stdin");
+ static_cast<void>(close(devnull));
+
+ BionicDeathTest::SetUp();
+ }
+
+ void TearDown() override {
+ if (stdin_saved == -1) return;
+ if (!dup2(stdin_saved, STDIN_FILENO)) warn("failed to restore stdin");
+
+ static_cast<void>(close(stdin_saved));
+
+ BionicDeathTest::TearDown();
+ }
+
+ private:
+ int stdin_saved = -1;
+};
+} // namespace
+
+template <typename Fn>
+__attribute__((noreturn)) static void ExitAfter(Fn&& f) {
+ f();
+ // No need to tear things down; our parent process should handle that.
+ _exit(0);
+}
+
+// In any case (including failing tests), we always want to die after this.
+#define DIE_WITH(expr, cond, regex) EXPECT_EXIT(ExitAfter([&] { (expr); }), cond, regex)
+
+// EXPECT_NO_DEATH forks so that the test remains alive on a bug, and so that the environment
+// doesn't get modified on no bug. (Environment modification is especially tricky to deal with given
+// the *_STRUCT variants below.)
+#define EXPECT_NO_DEATH(expr) DIE_WITH(expr, testing::ExitedWithCode(0), "")
+#define EXPECT_FORTIFY_DEATH(expr) DIE_WITH(expr, testing::KilledBySignal(SIGABRT), "FORTIFY")
+// Expecting death, but only if we're doing a "strict" struct-checking mode.
+#if _FORTIFY_SOURCE > 1
+#define EXPECT_FORTIFY_DEATH_STRUCT EXPECT_FORTIFY_DEATH
+#else
+#define EXPECT_FORTIFY_DEATH_STRUCT EXPECT_NO_DEATH
+#endif
+
+#define FORTIFY_TEST(test_name) TEST(FORTIFY_TEST_NAME, test_name)
+
+#else // defined(COMPILATION_TESTS)
+
+#define EXPECT_NO_DEATH(expr) expr
+#define EXPECT_FORTIFY_DEATH(expr) expr
+#define EXPECT_FORTIFY_DEATH_STRUCT EXPECT_FORTIFY_DEATH
+#define FORTIFY_TEST(test_name) void test_name()
+#endif
+
+const static int kBogusFD = -1;
+
+FORTIFY_TEST(string) {
+ char small_buffer[8] = {};
+
+ {
+ char large_buffer[sizeof(small_buffer) + 1] = {};
+ // expected-error@+1{{size bigger than buffer}}
+ EXPECT_FORTIFY_DEATH(memcpy(small_buffer, large_buffer, sizeof(large_buffer)));
+ // expected-error@+1{{size bigger than buffer}}
+ EXPECT_FORTIFY_DEATH(memmove(small_buffer, large_buffer, sizeof(large_buffer)));
+ // expected-error@+1{{size bigger than buffer}}
+ EXPECT_FORTIFY_DEATH(mempcpy(small_buffer, large_buffer, sizeof(large_buffer)));
+ // expected-error@+1{{size bigger than buffer}}
+ EXPECT_FORTIFY_DEATH(memset(small_buffer, 0, sizeof(large_buffer)));
+ // expected-warning@+1{{arguments got flipped?}}
+ EXPECT_NO_DEATH(memset(small_buffer, sizeof(small_buffer), 0));
+ // expected-error@+1{{size bigger than buffer}}
+ EXPECT_FORTIFY_DEATH(bcopy(large_buffer, small_buffer, sizeof(large_buffer)));
+ // expected-error@+1{{size bigger than buffer}}
+ EXPECT_FORTIFY_DEATH(bzero(small_buffer, sizeof(large_buffer)));
+ }
+
+ {
+ const char large_string[] = "Hello!!!";
+ static_assert(sizeof(large_string) > sizeof(small_buffer), "");
+
+ // expected-error@+1{{string bigger than buffer}}
+ EXPECT_FORTIFY_DEATH(strcpy(small_buffer, large_string));
+ // expected-error@+1{{string bigger than buffer}}
+ EXPECT_FORTIFY_DEATH(stpcpy(small_buffer, large_string));
+ // expected-error@+1{{size bigger than buffer}}
+ EXPECT_FORTIFY_DEATH(strncpy(small_buffer, large_string, sizeof(large_string)));
+ // expected-error@+1{{size bigger than buffer}}
+ EXPECT_FORTIFY_DEATH(stpncpy(small_buffer, large_string, sizeof(large_string)));
+ // expected-error@+1{{string bigger than buffer}}
+ EXPECT_FORTIFY_DEATH(strcat(small_buffer, large_string));
+ // expected-error@+1{{size bigger than buffer}}
+ EXPECT_FORTIFY_DEATH(strncat(small_buffer, large_string, sizeof(large_string)));
+ // expected-error@+1{{size bigger than buffer}}
+ EXPECT_FORTIFY_DEATH(strlcpy(small_buffer, large_string, sizeof(large_string)));
+ // expected-error@+1{{size bigger than buffer}}
+ EXPECT_FORTIFY_DEATH(strlcat(small_buffer, large_string, sizeof(large_string)));
+ }
+
+ {
+ struct {
+ char tiny_buffer[4];
+ char tiny_buffer2[4];
+ } split = {};
+
+ EXPECT_NO_DEATH(memcpy(split.tiny_buffer, &split, sizeof(split)));
+ EXPECT_NO_DEATH(memcpy(split.tiny_buffer, &split, sizeof(split)));
+ EXPECT_NO_DEATH(memmove(split.tiny_buffer, &split, sizeof(split)));
+ EXPECT_NO_DEATH(mempcpy(split.tiny_buffer, &split, sizeof(split)));
+ EXPECT_NO_DEATH(memset(split.tiny_buffer, 0, sizeof(split)));
+
+ EXPECT_NO_DEATH(bcopy(&split, split.tiny_buffer, sizeof(split)));
+ EXPECT_NO_DEATH(bzero(split.tiny_buffer, sizeof(split)));
+
+ const char small_string[] = "Hi!!";
+ static_assert(sizeof(small_string) > sizeof(split.tiny_buffer), "");
+
+#if _FORTIFY_SOURCE > 1
+ // expected-error@+2{{string bigger than buffer}}
+#endif
+ EXPECT_FORTIFY_DEATH_STRUCT(strcpy(split.tiny_buffer, small_string));
+
+#if _FORTIFY_SOURCE > 1
+ // expected-error@+2{{string bigger than buffer}}
+#endif
+ EXPECT_FORTIFY_DEATH_STRUCT(stpcpy(split.tiny_buffer, small_string));
+
+#if _FORTIFY_SOURCE > 1
+ // expected-error@+2{{size bigger than buffer}}
+#endif
+ EXPECT_FORTIFY_DEATH_STRUCT(strncpy(split.tiny_buffer, small_string, sizeof(small_string)));
+
+#if _FORTIFY_SOURCE > 1
+ // expected-error@+2{{size bigger than buffer}}
+#endif
+ EXPECT_FORTIFY_DEATH_STRUCT(stpncpy(split.tiny_buffer, small_string, sizeof(small_string)));
+
+#if _FORTIFY_SOURCE > 1
+ // expected-error@+2{{string bigger than buffer}}
+#endif
+ EXPECT_FORTIFY_DEATH_STRUCT(strcat(split.tiny_buffer, small_string));
+
+#if _FORTIFY_SOURCE > 1
+ // expected-error@+2{{size bigger than buffer}}
+#endif
+ EXPECT_FORTIFY_DEATH_STRUCT(strncat(split.tiny_buffer, small_string, sizeof(small_string)));
+
+#if _FORTIFY_SOURCE > 1
+ // expected-error@+2{{size bigger than buffer}}
+#endif
+ EXPECT_FORTIFY_DEATH_STRUCT(strlcat(split.tiny_buffer, small_string, sizeof(small_string)));
+
+#if _FORTIFY_SOURCE > 1
+ // expected-error@+2{{size bigger than buffer}}
+#endif
+ EXPECT_FORTIFY_DEATH_STRUCT(strlcpy(split.tiny_buffer, small_string, sizeof(small_string)));
+ }
+}
+
+FORTIFY_TEST(fcntl) {
+ const char target[] = "/dev/null";
+ int dirfd = 0;
+
+ // These all emit hard errors without diagnose_if, so running them is a bit
+ // more involved.
+#ifdef COMPILATION_TESTS
+ // expected-error@+1{{too many arguments}}
+ open("/", 0, 0, 0);
+ // expected-error@+1{{too many arguments}}
+ open64("/", 0, 0, 0);
+ // expected-error@+1{{too many arguments}}
+ openat(0, "/", 0, 0, 0);
+ // expected-error@+1{{too many arguments}}
+ openat64(0, "/", 0, 0, 0);
+#endif
+
+ // expected-error@+1{{missing mode}}
+ EXPECT_FORTIFY_DEATH(open(target, O_CREAT));
+ // expected-error@+1{{missing mode}}
+ EXPECT_FORTIFY_DEATH(open(target, O_TMPFILE));
+ // expected-error@+1{{missing mode}}
+ EXPECT_FORTIFY_DEATH(open64(target, O_CREAT));
+ // expected-error@+1{{missing mode}}
+ EXPECT_FORTIFY_DEATH(open64(target, O_TMPFILE));
+ // expected-error@+1{{missing mode}}
+ EXPECT_FORTIFY_DEATH(openat(dirfd, target, O_CREAT));
+ // expected-error@+1{{missing mode}}
+ EXPECT_FORTIFY_DEATH(openat(dirfd, target, O_TMPFILE));
+ // expected-error@+1{{missing mode}}
+ EXPECT_FORTIFY_DEATH(openat64(dirfd, target, O_CREAT));
+ // expected-error@+1{{missing mode}}
+ EXPECT_FORTIFY_DEATH(openat64(dirfd, target, O_TMPFILE));
+
+ // expected-warning@+1{{superfluous mode bits}}
+ EXPECT_NO_DEATH(open(target, O_RDONLY, 0777));
+ // expected-warning@+1{{superfluous mode bits}}
+ EXPECT_NO_DEATH(open64(target, O_RDONLY, 0777));
+ // expected-warning@+1{{superfluous mode bits}}
+ EXPECT_NO_DEATH(openat(dirfd, target, O_RDONLY, 0777));
+ // expected-warning@+1{{superfluous mode bits}}
+ EXPECT_NO_DEATH(openat64(dirfd, target, O_RDONLY, 0777));
+}
+
+// Since these emit hard errors, it's sort of hard to run them...
+#ifdef COMPILATION_TESTS
+namespace compilation_tests {
+template <typename T>
+static T declval() {
+ __builtin_unreachable();
+}
+
+static void testFormatStrings() {
+ const auto unsigned_value = declval<unsigned long long>();
+ const auto* unknown_string = declval<const char*>();
+ const auto va = *declval<va_list*>();
+
+ {
+ auto some_fd = declval<int>();
+ // expected-warning@+1{{format specifies type 'int'}}
+ dprintf(some_fd, "%d", unsigned_value);
+ // expected-warning@+1{{format string is not a string literal}}
+ dprintf(some_fd, unknown_string, unsigned_value);
+ // expected-warning@+1{{format string is not a string literal}}
+ vdprintf(1, unknown_string, va);
+ }
+
+ {
+ auto* retval = declval<char*>();
+#if 0
+ // expected-error@+2{{ignoring return value}}
+#endif
+ // expected-warning@+1{{format specifies type 'int'}}
+ asprintf(&retval, "%d", unsigned_value);
+#if 0
+ // expected-error@+2{{ignoring return value}}
+#endif
+ // expected-warning@+1{{format string is not a string literal}}
+ asprintf(&retval, unknown_string, unsigned_value);
+#if 0
+ // expected-error@+2{{ignoring return value}}
+#endif
+ // expected-warning@+1{{format string is not a string literal}}
+ vasprintf(&retval, unknown_string, va);
+ }
+
+ // expected-warning@+1{{format specifies type 'int'}}
+ syslog(0, "%d", unsigned_value);
+ // expected-warning@+1{{format string is not a string literal}}
+ syslog(0, unknown_string, unsigned_value);
+ // expected-warning@+1{{format string is not a string literal}}
+ vsyslog(0, unknown_string, va);
+
+ {
+ auto* file = declval<FILE*>();
+ // expected-warning@+1{{format specifies type 'int'}}
+ fprintf(file, "%d", unsigned_value);
+ // expected-warning@+1{{format string is not a string literal}}
+ fprintf(file, unknown_string, unsigned_value);
+ // expected-warning@+1{{format string is not a string literal}}
+ vfprintf(file, unknown_string, va);
+ }
+
+ // expected-warning@+1{{format specifies type 'int'}}
+ printf("%d", unsigned_value);
+ // expected-warning@+1{{format string is not a string literal}}
+ printf(unknown_string, unsigned_value);
+ // expected-warning@+1{{format string is not a string literal}}
+ vprintf(unknown_string, va);
+
+ {
+ char buf[128];
+ // expected-warning@+1{{format specifies type 'int'}}
+ sprintf(buf, "%d", unsigned_value);
+ // expected-warning@+1{{format string is not a string literal}}
+ sprintf(buf, unknown_string, unsigned_value);
+ // expected-warning@+1{{format string is not a string literal}}
+ sprintf(buf, unknown_string, va);
+
+ // expected-warning@+1{{format specifies type 'int'}}
+ snprintf(buf, sizeof(buf), "%d", unsigned_value);
+ // expected-warning@+1{{format string is not a string literal}}
+ snprintf(buf, sizeof(buf), unknown_string, unsigned_value);
+ // expected-warning@+1{{format string is not a string literal}}
+ vsnprintf(buf, sizeof(buf), unknown_string, va);
+ }
+
+ // FIXME: below are general format string cases where clang should probably try to warn.
+ {
+ char buf[4];
+ sprintf(buf, "%s", "1234");
+ sprintf(buf, "1%s4", "23");
+ sprintf(buf, "%d", 1234);
+
+ // Similar thoughts for strncpy, etc.
+ }
+}
+
+static void testStdlib() {
+ char path_buffer[PATH_MAX - 1];
+ // expected-warning@+2{{ignoring return value of function}}
+ // expected-error@+1{{must be NULL or a pointer to a buffer with >= PATH_MAX bytes}}
+ realpath("/", path_buffer);
+ // expected-warning@+1{{ignoring return value of function}}
+ realpath("/", nullptr);
+
+ // expected-warning@+2{{ignoring return value of function}}
+ // expected-error@+1{{flipped arguments?}}
+ realpath(nullptr, path_buffer);
+
+ // expected-warning@+2{{ignoring return value of function}}
+ // expected-error@+1{{flipped arguments?}}
+ realpath(nullptr, nullptr);
+}
+} // namespace compilation_tests
+#endif
+
+FORTIFY_TEST(poll) {
+ int pipe_fds[2];
+ if (pipe(pipe_fds)) err(1, "pipe failed");
+
+ // after this, pipe_fds[0] should always report RDHUP
+ if (close(pipe_fds[1])) err(1, "close failed");
+
+ struct pollfd poll_fd = { pipe_fds[0], POLLRDHUP, 0 };
+ {
+ struct pollfd few_fds[] = { poll_fd, poll_fd };
+ // expected-error@+1{{fd_count is larger than the given buffer}}
+ EXPECT_FORTIFY_DEATH(poll(few_fds, 3, 0));
+ // expected-error@+1{{fd_count is larger than the given buffer}}
+ EXPECT_FORTIFY_DEATH(ppoll(few_fds, 3, 0, 0));
+ // expected-error@+1{{fd_count is larger than the given buffer}}
+ EXPECT_FORTIFY_DEATH(ppoll64(few_fds, 3, 0, nullptr));
+ }
+
+ {
+ struct {
+ struct pollfd few[2];
+ struct pollfd extra[1];
+ } fds = { { poll_fd, poll_fd }, { poll_fd } };
+ static_assert(sizeof(fds) >= sizeof(struct pollfd) * 3, "");
+
+#if _FORTIFY_SOURCE > 1
+ // expected-error@+2{{fd_count is larger than the given buffer}}
+#endif
+ EXPECT_FORTIFY_DEATH_STRUCT(poll(fds.few, 3, 0));
+
+ struct timespec timeout = {};
+#if _FORTIFY_SOURCE > 1
+ // expected-error@+2{{fd_count is larger than the given buffer}}
+#endif
+ EXPECT_FORTIFY_DEATH_STRUCT(ppoll(fds.few, 3, &timeout, 0));
+
+#if _FORTIFY_SOURCE > 1
+ // expected-error@+2{{fd_count is larger than the given buffer}}
+#endif
+ EXPECT_FORTIFY_DEATH_STRUCT(ppoll64(fds.few, 3, 0, nullptr));
+ }
+}
+
+FORTIFY_TEST(socket) {
+ {
+ char small_buffer[8];
+ // expected-error@+1{{size bigger than buffer}}
+ EXPECT_FORTIFY_DEATH(recv(kBogusFD, small_buffer, sizeof(small_buffer) + 1, 0));
+ // expected-error@+1{{size bigger than buffer}}
+ EXPECT_FORTIFY_DEATH(recvfrom(kBogusFD, small_buffer, sizeof(small_buffer) + 1, 0, 0, 0));
+
+ // expected-error@+1{{size bigger than buffer}}
+ EXPECT_FORTIFY_DEATH(send(kBogusFD, small_buffer, sizeof(small_buffer) + 1, 0));
+ // expected-error@+1{{size bigger than buffer}}
+ EXPECT_FORTIFY_DEATH(sendto(kBogusFD, small_buffer, sizeof(small_buffer) + 1, 0, 0, 0));
+ }
+
+ {
+ struct {
+ char tiny_buffer[4];
+ char tiny_buffer2;
+ } split = {};
+
+ EXPECT_NO_DEATH(recv(kBogusFD, split.tiny_buffer, sizeof(split), 0));
+ EXPECT_NO_DEATH(recvfrom(kBogusFD, split.tiny_buffer, sizeof(split), 0, 0, 0));
+ }
+}
+
+FORTIFY_TEST(sys_stat) {
+ // expected-error@+1{{'umask' called with invalid mode}}
+ EXPECT_FORTIFY_DEATH(umask(01777));
+}
+
+FORTIFY_TEST(stdio) {
+ char small_buffer[8] = {};
+ {
+ // expected-error@+1{{size is larger than the destination buffer}}
+ EXPECT_FORTIFY_DEATH(snprintf(small_buffer, sizeof(small_buffer) + 1, ""));
+
+ va_list va;
+ // expected-error@+2{{size is larger than the destination buffer}}
+ // expected-warning@+1{{format string is empty}}
+ EXPECT_FORTIFY_DEATH(vsnprintf(small_buffer, sizeof(small_buffer) + 1, "", va));
+
+ const char *SOMETIMES_CONST format_string = "aaaaaaaaa";
+
+ // expected-error@+1{{format string will always overflow}}
+ EXPECT_FORTIFY_DEATH(sprintf(small_buffer, format_string));
+ }
+
+ // expected-error@+1{{size should not be negative}}
+ EXPECT_FORTIFY_DEATH(fgets(small_buffer, -1, stdin));
+ // expected-error@+1{{size is larger than the destination buffer}}
+ EXPECT_FORTIFY_DEATH(fgets(small_buffer, sizeof(small_buffer) + 1, stdin));
+
+ // expected-error@+1{{size * count overflows}}
+ EXPECT_NO_DEATH(fread(small_buffer, 2, (size_t)-1, stdin));
+ // expected-error@+1{{size * count is too large for the given buffer}}
+ EXPECT_FORTIFY_DEATH(fread(small_buffer, 1, sizeof(small_buffer) + 1, stdin));
+
+ // expected-error@+1{{size * count overflows}}
+ EXPECT_NO_DEATH(fwrite(small_buffer, 2, (size_t)-1, stdout));
+ // expected-error@+1{{size * count is too large for the given buffer}}
+ EXPECT_FORTIFY_DEATH(fwrite(small_buffer, 1, sizeof(small_buffer) + 1, stdout));
+}
+
+FORTIFY_TEST(unistd) {
+ char small_buffer[8];
+
+ // Return value warnings are (sort of) a part of FORTIFY, so we don't ignore them.
+#if 0
+ // expected-error@+2{{ignoring return value of function}}
+#endif
+ // expected-error@+1{{bytes overflows the given object}}
+ EXPECT_FORTIFY_DEATH(read(kBogusFD, small_buffer, sizeof(small_buffer) + 1));
+#if 0
+ // expected-error@+2{{ignoring return value of function}}
+#endif
+ // expected-error@+1{{bytes overflows the given object}}
+ EXPECT_FORTIFY_DEATH(pread(kBogusFD, small_buffer, sizeof(small_buffer) + 1, 0));
+#if 0
+ // expected-error@+2{{ignoring return value of function}}
+#endif
+ // expected-error@+1{{bytes overflows the given object}}
+ EXPECT_FORTIFY_DEATH(pread64(kBogusFD, small_buffer, sizeof(small_buffer) + 1, 0));
+#if 0
+ // expected-error@+2{{ignoring return value of function}}
+#endif
+ // expected-error@+1{{bytes overflows the given object}}
+ EXPECT_FORTIFY_DEATH(write(kBogusFD, small_buffer, sizeof(small_buffer) + 1));
+#if 0
+ // expected-error@+2{{ignoring return value of function}}
+#endif
+ // expected-error@+1{{bytes overflows the given object}}
+ EXPECT_FORTIFY_DEATH(pwrite(kBogusFD, small_buffer, sizeof(small_buffer) + 1, 0));
+#if 0
+ // expected-error@+2{{ignoring return value of function}}
+#endif
+ // expected-error@+1{{bytes overflows the given object}}
+ EXPECT_FORTIFY_DEATH(pwrite64(kBogusFD, small_buffer, sizeof(small_buffer) + 1, 0));
+#if 0
+ // expected-error@+2{{ignoring return value of function}}
+#endif
+ // expected-error@+1{{bytes overflows the given object}}
+ EXPECT_FORTIFY_DEATH(readlink("/", small_buffer, sizeof(small_buffer) + 1));
+#if 0
+ // expected-error@+2{{ignoring return value of function}}
+#endif
+ // expected-error@+1{{bytes overflows the given object}}
+ EXPECT_FORTIFY_DEATH(getcwd(small_buffer, sizeof(small_buffer) + 1));
+
+ // getcwd allocates and returns a buffer if you pass null to getcwd
+ EXPECT_NO_DEATH(getcwd(nullptr, 0));
+ EXPECT_NO_DEATH(getcwd(nullptr, 4096));
+
+ struct {
+ char tiny_buffer[4];
+ char tiny_buffer2[4];
+ } split;
+
+ EXPECT_NO_DEATH(read(kBogusFD, split.tiny_buffer, sizeof(split)));
+ EXPECT_NO_DEATH(pread(kBogusFD, split.tiny_buffer, sizeof(split), 0));
+ EXPECT_NO_DEATH(pread64(kBogusFD, split.tiny_buffer, sizeof(split), 0));
+ EXPECT_NO_DEATH(write(kBogusFD, split.tiny_buffer, sizeof(split)));
+ EXPECT_NO_DEATH(pwrite(kBogusFD, split.tiny_buffer, sizeof(split), 0));
+ EXPECT_NO_DEATH(pwrite64(kBogusFD, split.tiny_buffer, sizeof(split), 0));
+
+#if _FORTIFY_SOURCE > 1
+ // expected-error@+2{{bytes overflows the given object}}
+#endif
+ EXPECT_FORTIFY_DEATH_STRUCT(readlink("/", split.tiny_buffer, sizeof(split)));
+#if _FORTIFY_SOURCE > 1
+ // expected-error@+2{{bytes overflows the given object}}
+#endif
+ EXPECT_FORTIFY_DEATH_STRUCT(getcwd(split.tiny_buffer, sizeof(split)));
+
+ {
+ char* volatile unknown = small_buffer;
+ const size_t count = static_cast<size_t>(SSIZE_MAX) + 1;
+ // expected-error@+1{{'count' must be <= SSIZE_MAX}}
+ EXPECT_FORTIFY_DEATH(read(kBogusFD, unknown, count));
+ // expected-error@+1{{'count' must be <= SSIZE_MAX}}
+ EXPECT_FORTIFY_DEATH(pread(kBogusFD, unknown, count, 0));
+ // expected-error@+1{{'count' must be <= SSIZE_MAX}}
+ EXPECT_FORTIFY_DEATH(pread64(kBogusFD, unknown, count, 0));
+ // expected-error@+1{{'count' must be <= SSIZE_MAX}}
+ EXPECT_FORTIFY_DEATH(write(kBogusFD, unknown, count));
+ // expected-error@+1{{'count' must be <= SSIZE_MAX}}
+ EXPECT_FORTIFY_DEATH(pwrite(kBogusFD, unknown, count, 0));
+ // expected-error@+1{{'count' must be <= SSIZE_MAX}}
+ EXPECT_FORTIFY_DEATH(pwrite64(kBogusFD, unknown, count, 0));
+ }
+}
+
+#endif // defined(__BIONIC__)
diff --git a/tests/dlext_test.cpp b/tests/dlext_test.cpp
index 67ebf37df..e7274f704 100644
--- a/tests/dlext_test.cpp
+++ b/tests/dlext_test.cpp
@@ -29,9 +29,7 @@
#include <android-base/file.h>
#include <android-base/strings.h>
-#include <linux/memfd.h>
#include <sys/mman.h>
-#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/vfs.h>
#include <sys/wait.h>
@@ -363,8 +361,10 @@ TEST_F(DlExtTest, ReservedRecursive) {
uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle_, "dlopen_testlib_taxicab_number"));
ASSERT_DL_NOTNULL(taxicab_number);
- EXPECT_GE(reinterpret_cast<void*>(taxicab_number), start);
- EXPECT_LT(reinterpret_cast<void*>(taxicab_number), reinterpret_cast<char*>(start) + kLibSize);
+ // Untag the pointer so that it can be compared with start, which will be untagged.
+ void* addr = reinterpret_cast<void*>(untag_address(taxicab_number));
+ EXPECT_GE(addr, start);
+ EXPECT_LT(addr, reinterpret_cast<char*>(start) + kLibSize);
EXPECT_EQ(1729U, *taxicab_number);
}
@@ -942,7 +942,7 @@ TEST(dlext, dlopen_ext_use_memfd) {
const std::string lib_path = GetTestlibRoot() + "/libtest_simple.so";
// create memfd
- int memfd = syscall(__NR_memfd_create, "foobar", MFD_CLOEXEC);
+ int memfd = memfd_create("foobar", MFD_CLOEXEC);
if (memfd == -1 && errno == ENOSYS) {
return;
}
diff --git a/tests/fortify_filecheck_diagnostics_test.cpp b/tests/fortify_filecheck_diagnostics_test.cpp
deleted file mode 100644
index ac9853c7f..000000000
--- a/tests/fortify_filecheck_diagnostics_test.cpp
+++ /dev/null
@@ -1,323 +0,0 @@
-/*
- * Copyright (C) 2014 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.
- */
-
-/*
- * Silence all notes about enable_if-related 'candidates'; they're nice to know
- * about for users, but this test doesn't care.
- */
-// expected-note@* 0+{{candidate function}}
-
-/* Similarly, ignore all "from 'diagnose_if'"s. */
-// expected-note@* 0+{{from 'diagnose_if'}}
-
-
-#undef _FORTIFY_SOURCE
-#define _FORTIFY_SOURCE 2
-#include <fcntl.h>
-#include <netinet/in.h>
-#include <poll.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <time.h>
-#include <unistd.h>
-
-#if !defined(__BIONIC__)
-# error "This only works with Bionic."
-#endif
-
-void test_sprintf() {
- char buf[4];
-
- // NOLINTNEXTLINE(whitespace/line_length)
- // expected-error@+1{{call to unavailable function 'sprintf': format string will always overflow destination buffer}}
- sprintf(buf, "foobar"); // NOLINT(runtime/printf)
-
- // TODO: clang should emit a warning, but doesn't
- sprintf(buf, "%s", "foobar"); // NOLINT(runtime/printf)
-}
-
-void test_snprintf() {
- char buf[4];
-
- // NOLINTNEXTLINE(whitespace/line_length)
- // expected-error@+1{{call to unavailable function 'snprintf': format string will always overflow destination buffer}}
- snprintf(buf, 5, "foobar"); // NOLINT(runtime/printf)
-
- // TODO: clang should emit a warning, but doesn't
- snprintf(buf, 5, "%s", "foobar"); // NOLINT(runtime/printf)
-
- // TODO: clang should emit a warning, but doesn't
- snprintf(buf, 5, " %s ", "foobar"); // NOLINT(runtime/printf)
-
- // TODO: clang should emit a warning, but doesn't
- snprintf(buf, 5, "%d", 100000); // NOLINT(runtime/printf)
-}
-
-void test_memcpy() {
- char buf[4];
-
- // expected-error@+1{{'memcpy' called with size bigger than buffer}}
- memcpy(buf, "foobar", sizeof("foobar") + 100);
-}
-
-void test_memmove() {
- char buf[4];
-
- // expected-error@+1{{'memmove' called with size bigger than buffer}}
- memmove(buf, "foobar", sizeof("foobar"));
-}
-
-void test_memset() {
- char buf[4];
-
- // expected-error@+1{{'memset' called with size bigger than buffer}}
- memset(buf, 0, 6);
-}
-
-void test_strcpy() {
- char buf[4];
-
- // expected-error@+1{{'strcpy' called with string bigger than buffer}}
- strcpy(buf, "foobar"); // NOLINT(runtime/printf)
-
- // expected-error@+1{{'strcpy' called with string bigger than buffer}}
- strcpy(buf, "quux");
-}
-
-void test_stpcpy() {
- char buf[4];
-
- // expected-error@+1{{'stpcpy' called with string bigger than buffer}}
- stpcpy(buf, "foobar");
-
- // expected-error@+1{{'stpcpy' called with string bigger than buffer}}
- stpcpy(buf, "quux");
-}
-
-void test_strncpy() {
- char buf[4];
-
- // TODO: clang should emit a warning, but doesn't
- strncpy(buf, "foobar", sizeof("foobar"));
-}
-
-void test_strcat() {
- char buf[4] = "";
-
- // TODO: clang should emit a warning, but doesn't
- strcat(buf, "foobar"); // NOLINT(runtime/printf)
-}
-
-void test_strncat() {
- char buf[4] = "";
-
- // TODO: clang should emit a warning, but doesn't
- strncat(buf, "foobar", sizeof("foobar"));
-}
-
-void test_vsprintf(const char* fmt, ...) {
- va_list va;
- char buf[4];
- va_start(va, fmt);
-
- // clang should emit a warning, but doesn't
- vsprintf(buf, "foobar", va);
- va_end(va);
-}
-
-void test_vsnprintf(const char* fmt, ...) {
- va_list va;
- char buf[4];
- va_start(va, fmt);
-
- // clang should emit a warning, but doesn't
- vsnprintf(buf, 5, "foobar", va); // NOLINT(runtime/printf)
-
- va_end(va);
-}
-
-void test_fgets() {
- char buf[4];
-
- // expected-error@+1{{in call to 'fgets', size should not be negative}}
- fgets(buf, -1, stdin);
-
- // expected-error@+1{{in call to 'fgets', size is larger than the destination buffer}}
- fgets(buf, 6, stdin);
-}
-
-void test_recvfrom() {
- char buf[4];
- sockaddr_in addr;
-
- // expected-error@+1{{'recvfrom' called with size bigger than buffer}}
- recvfrom(0, buf, 6, 0, reinterpret_cast<sockaddr*>(&addr), nullptr);
-}
-
-void test_recv() {
- char buf[4] = {0};
-
- // expected-error@+1{{'recv' called with size bigger than buffer}}
- recv(0, buf, 6, 0);
-}
-
-void test_umask() {
- // expected-error@+1{{'umask' called with invalid mode}}
- umask(01777);
-}
-
-void test_read() {
- char buf[4];
- // expected-error@+1{{in call to 'read', 'count' bytes overflows the given object}}
- read(0, buf, 6);
-}
-
-void test_open() {
- // expected-error@+1{{'open' called with O_CREAT or O_TMPFILE, but missing mode}}
- open("/dev/null", O_CREAT);
-
- // expected-error@+1{{'open' called with O_CREAT or O_TMPFILE, but missing mode}}
- open("/dev/null", O_TMPFILE);
-
- // expected-error@+1{{call to unavailable function 'open': too many arguments}}
- open("/dev/null", O_CREAT, 0, 0);
-
- // expected-error@+1{{call to unavailable function 'open': too many arguments}}
- open("/dev/null", O_TMPFILE, 0, 0);
-
- // expected-warning@+1{{'open' has superfluous mode bits; missing O_CREAT?}}
- open("/dev/null", O_RDONLY, 0644);
-
- // expected-warning@+1{{'open' has superfluous mode bits; missing O_CREAT?}}
- open("/dev/null", O_DIRECTORY, 0644);
-}
-
-void test_poll() {
- pollfd fds[1];
- // expected-error@+1{{in call to 'poll', fd_count is larger than the given buffer}}
- poll(fds, 2, 0);
-}
-
-void test_ppoll() {
- pollfd fds[1];
- timespec timeout;
- // expected-error@+1{{in call to 'ppoll', fd_count is larger than the given buffer}}
- ppoll(fds, 2, &timeout, nullptr);
-}
-
-void test_ppoll64() {
- pollfd fds[1];
- timespec timeout;
- // NOLINTNEXTLINE(whitespace/line_length)
- // expected-error@+1{{in call to 'ppoll64', fd_count is larger than the given buffer}}
- ppoll64(fds, 2, &timeout, nullptr);
-}
-
-void test_fread_overflow() {
- char buf[4];
- // expected-error@+1{{in call to 'fread', size * count overflows}}
- fread(buf, 2, (size_t)-1, stdin);
-}
-
-void test_fread_too_big() {
- char buf[4];
- // NOLINTNEXTLINE(whitespace/line_length)
- // expected-error@+1{{in call to 'fread', size * count is too large for the given buffer}}
- fread(buf, 1, 5, stdin);
-}
-
-void test_fwrite_overflow() {
- char buf[4] = {0};
- // expected-error@+1{{in call to 'fwrite', size * count overflows}}
- fwrite(buf, 2, (size_t)-1, stdout);
-}
-
-void test_fwrite_too_big() {
- char buf[4] = {0};
- // NOLINTNEXTLINE(whitespace/line_length)
- // expected-error@+1{{in call to 'fwrite', size * count is too large for the given buffer}}
- fwrite(buf, 1, 5, stdout);
-}
-
-void test_getcwd() {
- char buf[4];
- // expected-error@+1{{in call to 'getcwd', 'size' bytes overflows the given object}}
- getcwd(buf, 5);
-}
-
-void test_pwrite64_size() {
- char buf[4] = {0};
- // expected-error@+1{{in call to 'pwrite64', 'count' bytes overflows the given object}}
- pwrite64(STDOUT_FILENO, buf, 5, 0);
-}
-
-void test_pwrite64_too_big_malloc() {
- void *buf = calloc(atoi("5"), 1);
- // expected-error@+1{{in call to 'pwrite64', 'count' must be <= SSIZE_MAX}}
- pwrite64(STDOUT_FILENO, buf, SIZE_MAX, 0);
-}
-
-void test_pwrite64_too_big() {
- char buf[4] = {0};
- // expected-error@+1{{in call to 'pwrite64', 'count' must be <= SSIZE_MAX}}
- pwrite64(STDOUT_FILENO, buf, SIZE_MAX, 0);
-}
-
-void test_write_size() {
- char buf[4] = {0};
- // expected-error@+1{{in call to 'write', 'count' bytes overflows the given object}}
- write(STDOUT_FILENO, buf, 5);
-}
-
-void test_memset_args_flipped() {
- char from[4] = {0};
- // NOLINTNEXTLINE(whitespace/line_length)
- // expected-warning@+1{{'memset' will set 0 bytes; maybe the arguments got flipped?}}
- memset(from, sizeof(from), 0);
-}
-
-void test_sendto() {
- char buf[4] = {0};
- sockaddr_in addr;
-
- // expected-error@+1{{'sendto' called with size bigger than buffer}}
- sendto(0, buf, 6, 0, reinterpret_cast<sockaddr*>(&addr), sizeof(sockaddr_in));
-}
-
-void test_send() {
- char buf[4] = {0};
-
- // expected-error@+1{{'send' called with size bigger than buffer}}
- send(0, buf, 6, 0);
-}
-
-void test_realpath() {
- char buf[4] = {0};
- // NOLINTNEXTLINE(whitespace/line_length)
- // expected-error@+1{{'realpath' output parameter must be NULL or a pointer to a buffer with >= PATH_MAX bytes}}
- realpath(".", buf);
-
- // This is fine.
- realpath(".", nullptr);
-
- char bigbuf[PATH_MAX];
- // expected-error@+1{{'realpath': NULL path is never correct; flipped arguments?}}
- realpath(nullptr, bigbuf);
-}
diff --git a/tests/fortify_test.cpp b/tests/fortify_test.cpp
index 489b7018d..9a4b781fc 100644
--- a/tests/fortify_test.cpp
+++ b/tests/fortify_test.cpp
@@ -926,6 +926,24 @@ TEST(TEST_NAME, strcat_chk_max_int_size) {
ASSERT_EQ('\0', buf[9]);
}
+TEST(TEST_NAME, mempcpy_chk) {
+ const char input_str[] = "abcdefg";
+ size_t input_str_size = strlen(input_str) + 1;
+
+ char buf1[10] = {};
+ char buf2[10] = {};
+
+ __builtin_mempcpy(buf1, input_str, input_str_size);
+ __builtin___mempcpy_chk(buf2, input_str, input_str_size, __bos0(buf2));
+
+ ASSERT_EQ(memcmp(buf1, buf2, sizeof(buf2)), 0);
+
+ void *builtin_ptr = __builtin_mempcpy(buf1, input_str, input_str_size);
+ void *fortify_ptr = __builtin___mempcpy_chk(buf1, input_str, input_str_size, __bos0(buf2));
+
+ ASSERT_EQ(builtin_ptr, fortify_ptr);
+}
+
extern "C" char* __stpcpy_chk(char*, const char*, size_t);
TEST(TEST_NAME, stpcpy_chk_max_int_size) {
diff --git a/tests/grp_pwd_test.cpp b/tests/grp_pwd_test.cpp
index ebc357c4b..6b49e298e 100644
--- a/tests/grp_pwd_test.cpp
+++ b/tests/grp_pwd_test.cpp
@@ -46,6 +46,8 @@ using android::base::ReadFileToString;
using android::base::Split;
using android::base::StartsWith;
+using namespace std::literals;
+
enum uid_type_t {
TYPE_APP,
TYPE_SYSTEM,
@@ -73,11 +75,7 @@ static void check_passwd(const passwd* pwd, const char* username, uid_t uid, uid
EXPECT_STREQ("/", pwd->pw_dir);
}
- if (uid_type == TYPE_VENDOR) {
- EXPECT_STREQ("/vendor/bin/sh", pwd->pw_shell);
- } else {
- EXPECT_STREQ("/system/bin/sh", pwd->pw_shell);
- }
+ EXPECT_STREQ("/bin/sh", pwd->pw_shell);
}
static void check_getpwuid(const char* username, uid_t uid, uid_type_t uid_type,
@@ -130,12 +128,41 @@ static void check_getpwnam_r(const char* username, uid_t uid, uid_type_t uid_typ
static void check_get_passwd(const char* username, uid_t uid, uid_type_t uid_type,
bool check_username = true) {
+ SCOPED_TRACE("username '"s + username + "'");
check_getpwuid(username, uid, uid_type, check_username);
check_getpwnam(username, uid, uid_type, check_username);
check_getpwuid_r(username, uid, uid_type, check_username);
check_getpwnam_r(username, uid, uid_type, check_username);
}
+static void expect_no_passwd_id(uid_t uid) {
+ SCOPED_TRACE("uid '" + std::to_string(uid) + "'");
+ errno = 0;
+ passwd* passwd = nullptr;
+ passwd = getpwuid(uid);
+ EXPECT_EQ(nullptr, passwd) << "name = '" << passwd->pw_name << "'";
+ EXPECT_EQ(ENOENT, errno);
+
+ struct passwd passwd_storage;
+ char buf[512];
+ EXPECT_EQ(ENOENT, getpwuid_r(uid, &passwd_storage, buf, sizeof(buf), &passwd));
+ EXPECT_EQ(nullptr, passwd) << "name = '" << passwd->pw_name << "'";
+}
+
+static void expect_no_passwd_name(const char* username) {
+ SCOPED_TRACE("username '"s + username + "'");
+ errno = 0;
+ passwd* passwd = nullptr;
+ passwd = getpwnam(username);
+ EXPECT_EQ(nullptr, passwd) << "name = '" << passwd->pw_name << "'";
+ EXPECT_EQ(ENOENT, errno);
+
+ struct passwd passwd_storage;
+ char buf[512];
+ EXPECT_EQ(ENOENT, getpwnam_r(username, &passwd_storage, buf, sizeof(buf), &passwd));
+ EXPECT_EQ(nullptr, passwd) << "name = '" << passwd->pw_name << "'";
+}
+
#else // !defined(__BIONIC__)
static void check_get_passwd(const char* /* username */, uid_t /* uid */, uid_type_t /* uid_type */,
@@ -147,75 +174,124 @@ static void check_get_passwd(const char* /* username */, uid_t /* uid */, uid_ty
GTEST_SKIP() << "bionic-only test";
}
+static void expect_no_passwd_id(uid_t /* uid */) {
+ GTEST_SKIP() << "bionic-only test";
+}
+
+static void expect_no_passwd_name(const char* /* username */) {
+ GTEST_SKIP() << "bionic-only test";
+}
+
#endif
-TEST(pwd, getpwnam_system_id_root) {
+TEST(pwd, getpwnam_platform_ids) {
check_get_passwd("root", 0, TYPE_SYSTEM);
-}
+ check_get_passwd("daemon", 1, TYPE_SYSTEM);
+ check_get_passwd("bin", 2, TYPE_SYSTEM);
-TEST(pwd, getpwnam_system_id_system) {
check_get_passwd("system", 1000, TYPE_SYSTEM);
-}
-
-TEST(pwd, getpwnam_app_id_radio) {
check_get_passwd("radio", 1001, TYPE_SYSTEM);
-}
-TEST(pwd, getpwnam_oem_id_5000) {
- check_get_passwd("oem_5000", 5000, TYPE_VENDOR, false);
-}
+ check_get_passwd("shell", 2000, TYPE_SYSTEM);
-TEST(pwd, getpwnam_oem_id_5999) {
- check_get_passwd("oem_5999", 5999, TYPE_VENDOR, false);
+ check_get_passwd("nobody", 9999, TYPE_SYSTEM);
}
-TEST(pwd, getpwnam_oem_id_2900) {
+TEST(pwd, getpwnam_oem_ids) {
check_get_passwd("oem_2900", 2900, TYPE_VENDOR, false);
-}
-
-TEST(pwd, getpwnam_oem_id_2999) {
+ check_get_passwd("oem_2945", 2945, TYPE_VENDOR, false);
check_get_passwd("oem_2999", 2999, TYPE_VENDOR, false);
+ check_get_passwd("oem_5000", 5000, TYPE_VENDOR, false);
+ check_get_passwd("oem_5454", 5454, TYPE_VENDOR, false);
+ check_get_passwd("oem_5999", 5999, TYPE_VENDOR, false);
}
-TEST(pwd, getpwnam_app_id_nobody) {
- check_get_passwd("nobody", 9999, TYPE_SYSTEM);
-}
+TEST(pwd, getpwnam_non_exist) {
+ expect_no_passwd_id(999); // End of the system reserved range, unallocated.
+ expect_no_passwd_id(1999); // End of the system reserved range, unallocated.
+ expect_no_passwd_id(2899); // End of the system reserved range, unallocated.
-TEST(pwd, getpwnam_app_id_u0_a0) {
- check_get_passwd("u0_a0", 10000, TYPE_APP);
-}
+ // These ranges are for GIDs only.
+ expect_no_passwd_id(20000);
+ expect_no_passwd_id(30000);
+ expect_no_passwd_id(40000);
+ expect_no_passwd_id(50000);
-TEST(pwd, getpwnam_app_id_u0_a1234) {
- check_get_passwd("u0_a1234", 11234, TYPE_APP);
+ // These should not be parsed as users, only as groups.
+ expect_no_passwd_name("u0_a9999_cache");
+ expect_no_passwd_name("u0_a9999_ext");
+ expect_no_passwd_name("u0_a9999_ext_cache");
+ expect_no_passwd_name("all_a9999");
}
-// Test the difference between uid and shared gid.
-TEST(pwd, getpwnam_app_id_u0_a49999) {
- check_get_passwd("u0_a49999", 59999, TYPE_APP);
-}
+TEST(pwd, getpwnam_u0_app_ids) {
+ check_get_passwd("u0_a0", 10000, TYPE_APP);
+ check_get_passwd("u0_a1234", 11234, TYPE_APP);
+ check_get_passwd("u0_a9999", 19999, TYPE_APP);
-TEST(pwd, getpwnam_app_id_u0_i1) {
check_get_passwd("u0_i1", 90001, TYPE_APP);
+ check_get_passwd("u0_i4545", 94545, TYPE_APP);
+ check_get_passwd("u0_i9999", 99999, TYPE_APP);
}
-TEST(pwd, getpwnam_app_id_u1_root) {
- check_get_passwd("u1_root", 100000, TYPE_SYSTEM);
+TEST(pwd, getpwnam_app_id_u1_ids) {
+ check_get_passwd("u1_system", 101000, TYPE_SYSTEM);
+ check_get_passwd("u1_radio", 101001, TYPE_SYSTEM);
+
+ check_get_passwd("u1_a0", 110000, TYPE_APP);
+ check_get_passwd("u1_a1234", 111234, TYPE_APP);
+ check_get_passwd("u1_a9999", 119999, TYPE_APP);
+
+ check_get_passwd("u1_i1", 190001, TYPE_APP);
+ check_get_passwd("u1_i4545", 194545, TYPE_APP);
+ check_get_passwd("u1_i9999", 199999, TYPE_APP);
}
-TEST(pwd, getpwnam_app_id_u1_radio) {
- check_get_passwd("u1_radio", 101001, TYPE_SYSTEM);
+TEST(pwd, getpwnam_app_id_u31_ids) {
+ check_get_passwd("u31_system", 3101000, TYPE_SYSTEM);
+ check_get_passwd("u31_radio", 3101001, TYPE_SYSTEM);
+
+ check_get_passwd("u31_a0", 3110000, TYPE_APP);
+ check_get_passwd("u31_a1234", 3111234, TYPE_APP);
+ check_get_passwd("u31_a9999", 3119999, TYPE_APP);
+
+ check_get_passwd("u31_i1", 3190001, TYPE_APP);
+ check_get_passwd("u31_i4545", 3194545, TYPE_APP);
+ check_get_passwd("u31_i9999", 3199999, TYPE_APP);
}
-TEST(pwd, getpwnam_app_id_u1_a0) {
- check_get_passwd("u1_a0", 110000, TYPE_APP);
+TEST(pwd, getpwnam_app_id_not_allowed_platform) {
+ expect_no_passwd_name("u1_root");
+ expect_no_passwd_name("u1_debuggerd");
+
+ expect_no_passwd_name("u31_root");
+ expect_no_passwd_name("u31_debuggerd");
}
-TEST(pwd, getpwnam_app_id_u1_a40000) {
- check_get_passwd("u1_a40000", 150000, TYPE_APP);
+TEST(pwd, getpwuid_app_id_u1_non_exist) {
+ expect_no_passwd_id(100000); // There is no 'root' for secondary users.
+ expect_no_passwd_id(101999); // End of the system reserved range, unallocated.
+ expect_no_passwd_id(102900); // The OEM ranges were never allocated to secondary users.
+ expect_no_passwd_id(105000); // The OEM ranges were never allocated to secondary users.
+
+ // These ranges are for GIDs only.
+ expect_no_passwd_id(120000);
+ expect_no_passwd_id(130000);
+ expect_no_passwd_id(140000);
+ expect_no_passwd_id(150000);
}
-TEST(pwd, getpwnam_app_id_u1_i0) {
- check_get_passwd("u1_i0", 190000, TYPE_APP);
+TEST(pwd, getpwuid_app_id_u31_non_exist) {
+ expect_no_passwd_id(3100000); // There is no 'root' for secondary users.
+ expect_no_passwd_id(3101999); // End of the system reserved range, unallocated.
+ expect_no_passwd_id(3102900); // The OEM ranges were never allocated to secondary users.
+ expect_no_passwd_id(3105000); // The OEM ranges were never allocated to secondary users.
+
+ // These ranges are for GIDs only.
+ expect_no_passwd_id(3120000);
+ expect_no_passwd_id(3130000);
+ expect_no_passwd_id(3140000);
+ expect_no_passwd_id(3150000);
}
TEST(pwd, getpwnam_r_alignment) {
@@ -302,7 +378,7 @@ TEST(pwd, getpwnam_r_large_enough_suggested_buffer_size) {
#if defined(__BIONIC__)
template <typename T>
-static void expect_ids(const T& ids) {
+static void expect_ids(T ids, bool is_group) {
std::set<typename T::key_type> expected_ids;
// Ensure that all android_ids are iterated through.
for (size_t n = 0; n < android_id_count; ++n) {
@@ -321,10 +397,12 @@ static void expect_ids(const T& ids) {
expect_range(AID_OEM_RESERVED_START, AID_OEM_RESERVED_END);
expect_range(AID_OEM_RESERVED_2_START, AID_OEM_RESERVED_2_END);
expect_range(AID_APP_START, AID_APP_END);
- expect_range(AID_CACHE_GID_START, AID_CACHE_GID_END);
- expect_range(AID_EXT_GID_START, AID_EXT_GID_END);
- expect_range(AID_EXT_CACHE_GID_START, AID_EXT_CACHE_GID_END);
- expect_range(AID_SHARED_GID_START, AID_SHARED_GID_END);
+ if (is_group) {
+ expect_range(AID_CACHE_GID_START, AID_CACHE_GID_END);
+ expect_range(AID_EXT_GID_START, AID_EXT_GID_END);
+ expect_range(AID_EXT_CACHE_GID_START, AID_EXT_CACHE_GID_END);
+ expect_range(AID_SHARED_GID_START, AID_SHARED_GID_END);
+ }
expect_range(AID_ISOLATED_START, AID_ISOLATED_END);
// TODO(73062966): We still don't have a good way to create vendor AIDs in the system or other
@@ -333,6 +411,14 @@ static void expect_ids(const T& ids) {
return;
}
+ auto allow_range = [&ids](uid_t start, uid_t end) {
+ for (size_t n = start; n <= end; ++n) {
+ ids.erase(n);
+ }
+ };
+
+ allow_range(AID_SYSTEM_RESERVED_START, AID_SYSTEM_EXT_RESERVED_END);
+
// Ensure that no other ids were returned.
auto return_differences = [&ids, &expected_ids] {
std::vector<typename T::key_type> missing_from_ids;
@@ -388,7 +474,7 @@ TEST(pwd, getpwent_iterate) {
}
endpwent();
- expect_ids(uids);
+ expect_ids(uids, false);
#else
GTEST_SKIP() << "bionic-only test";
#endif
@@ -453,12 +539,41 @@ static void check_getgrnam_r(const char* group_name, gid_t gid, bool check_group
}
static void check_get_group(const char* group_name, gid_t gid, bool check_groupname = true) {
+ SCOPED_TRACE("groupname '"s + group_name + "'");
check_getgrgid(group_name, gid, check_groupname);
check_getgrnam(group_name, gid, check_groupname);
check_getgrgid_r(group_name, gid, check_groupname);
check_getgrnam_r(group_name, gid, check_groupname);
}
+static void expect_no_group_id(gid_t gid) {
+ SCOPED_TRACE("gid '" + std::to_string(gid) + "'");
+ errno = 0;
+ group* group = nullptr;
+ group = getgrgid(gid);
+ EXPECT_EQ(nullptr, group) << "name = '" << group->gr_name << "'";
+ EXPECT_EQ(ENOENT, errno);
+
+ struct group group_storage;
+ char buf[512];
+ EXPECT_EQ(ENOENT, getgrgid_r(gid, &group_storage, buf, sizeof(buf), &group));
+ EXPECT_EQ(nullptr, group) << "name = '" << group->gr_name << "'";
+}
+
+static void expect_no_group_name(const char* groupname) {
+ SCOPED_TRACE("groupname '"s + groupname + "'");
+ errno = 0;
+ group* group = nullptr;
+ group = getgrnam(groupname);
+ EXPECT_EQ(nullptr, group) << "name = '" << group->gr_name << "'";
+ EXPECT_EQ(ENOENT, errno);
+
+ struct group group_storage;
+ char buf[512];
+ EXPECT_EQ(ENOENT, getgrnam_r(groupname, &group_storage, buf, sizeof(buf), &group));
+ EXPECT_EQ(nullptr, group) << "name = '" << group->gr_name << "'";
+}
+
#else // !defined(__BIONIC__)
static void check_get_group(const char*, gid_t, bool) {
@@ -469,95 +584,144 @@ static void check_get_group(const char*, gid_t) {
GTEST_SKIP() << "bionic-only test";
}
+static void expect_no_group_id(gid_t /* gid */) {
+ GTEST_SKIP() << "bionic-only test";
+}
+
+static void expect_no_group_name(const char* /* groupname */) {
+ GTEST_SKIP() << "bionic-only test";
+}
+
#endif
-TEST(grp, getgrnam_system_id_root) {
+TEST(grp, getgrnam_platform_ids) {
check_get_group("root", 0);
-}
+ check_get_group("daemon", 1);
+ check_get_group("bin", 2);
-TEST(grp, getgrnam_system_id_system) {
check_get_group("system", 1000);
-}
-
-TEST(grp, getgrnam_app_id_radio) {
check_get_group("radio", 1001);
-}
-TEST(grp, getgrnam_oem_id_5000) {
- check_get_group("oem_5000", 5000, false);
-}
+ check_get_group("shell", 2000);
-TEST(grp, getgrnam_oem_id_5999) {
- check_get_group("oem_5999", 5999, false);
+ check_get_group("nobody", 9999);
}
-TEST(grp, getgrnam_oem_id_2900) {
+TEST(grp, getgrnam_oem_ids) {
check_get_group("oem_2900", 2900, false);
-}
-
-TEST(grp, getgrnam_oem_id_2999) {
+ check_get_group("oem_2945", 2945, false);
check_get_group("oem_2999", 2999, false);
+ check_get_group("oem_5000", 5000, false);
+ check_get_group("oem_5454", 5454, false);
+ check_get_group("oem_5999", 5999, false);
}
-TEST(grp, getgrnam_app_id_nobody) {
- check_get_group("nobody", 9999);
+TEST(grp, getgrnam_non_exist) {
+ expect_no_passwd_id(999); // End of the system reserved range, unallocated.
+ expect_no_passwd_id(1999); // End of the system reserved range, unallocated.
+ expect_no_passwd_id(2899); // End of the system reserved range, unallocated.
}
-TEST(grp, getgrnam_app_id_u0_a0) {
+TEST(grp, getgrnam_u0_app_ids) {
check_get_group("u0_a0", 10000);
-}
-
-TEST(grp, getgrnam_app_id_u0_a1234) {
check_get_group("u0_a1234", 11234);
-}
-
-TEST(grp, getgrnam_app_id_u0_a9999) {
check_get_group("u0_a9999", 19999);
-}
-TEST(getgrnam, app_id_u0_a0_cache) {
check_get_group("u0_a0_cache", 20000);
-}
-
-TEST(getgrnam, app_id_u0_a1234_cache) {
check_get_group("u0_a1234_cache", 21234);
-}
-
-TEST(getgrnam, app_id_u0_a9999_cache) {
check_get_group("u0_a9999_cache", 29999);
-}
-TEST(getgrnam, app_id_u10_a1234_cache) {
- check_get_group("u10_a1234_cache", 1021234);
-}
+ check_get_group("u0_a0_ext", 30000);
+ check_get_group("u0_a4545_ext", 34545);
+ check_get_group("u0_a9999_ext", 39999);
+
+ check_get_group("u0_a0_ext_cache", 40000);
+ check_get_group("u0_a4545_ext_cache", 44545);
+ check_get_group("u0_a9999_ext_cache", 49999);
-// Test the difference between uid and shared gid.
-TEST(grp, getgrnam_app_id_all_a9999) {
+ check_get_group("all_a0", 50000);
+ check_get_group("all_a4545", 54545);
check_get_group("all_a9999", 59999);
-}
-TEST(grp, getgrnam_app_id_u0_i1) {
check_get_group("u0_i1", 90001);
}
-TEST(grp, getgrnam_app_id_u1_root) {
- check_get_group("u1_root", 100000);
+TEST(grp, getgrnam_u1_app_ids) {
+ check_get_group("u1_system", 101000);
+ check_get_group("u1_radio", 101001);
+
+ check_get_group("u1_a0", 110000);
+ check_get_group("u1_a1234", 111234);
+ check_get_group("u1_a9999", 119999);
+
+ check_get_group("u1_a0_cache", 120000);
+ check_get_group("u1_a1234_cache", 121234);
+ check_get_group("u1_a9999_cache", 129999);
+
+ check_get_group("u1_a0_ext", 130000);
+ check_get_group("u1_a4545_ext", 134545);
+ check_get_group("u1_a9999_ext", 139999);
+
+ check_get_group("u1_a0_ext_cache", 140000);
+ check_get_group("u1_a4545_ext_cache", 144545);
+ check_get_group("u1_a9999_ext_cache", 149999);
+
+ check_get_group("u1_i1", 190001);
}
-TEST(grp, getgrnam_app_id_u1_radio) {
- check_get_group("u1_radio", 101001);
+TEST(grp, getgrnam_u31_app_ids) {
+ check_get_group("u31_system", 3101000);
+ check_get_group("u31_radio", 3101001);
+
+ check_get_group("u31_a0", 3110000);
+ check_get_group("u31_a1234", 3111234);
+ check_get_group("u31_a9999", 3119999);
+
+ check_get_group("u31_a0_cache", 3120000);
+ check_get_group("u31_a1234_cache", 3121234);
+ check_get_group("u31_a9999_cache", 3129999);
+
+ check_get_group("u31_a0_cache", 3120000);
+ check_get_group("u31_a1234_cache", 3121234);
+ check_get_group("u31_a9999_cache", 3129999);
+
+ check_get_group("u31_a0_ext", 3130000);
+ check_get_group("u31_a4545_ext", 3134545);
+ check_get_group("u31_a9999_ext", 3139999);
+
+ check_get_group("u31_a0_ext_cache", 3140000);
+ check_get_group("u31_a4545_ext_cache", 3144545);
+ check_get_group("u31_a9999_ext_cache", 3149999);
+
+ check_get_group("u31_i1", 3190001);
}
-TEST(grp, getgrnam_app_id_u1_a0) {
- check_get_group("u1_a0", 110000);
+TEST(grp, getpgram_app_id_not_allowed_platform) {
+ expect_no_group_name("u1_root");
+ expect_no_group_name("u1_debuggerd");
+
+ expect_no_group_name("u31_root");
+ expect_no_group_name("u31_debuggerd");
}
-TEST(grp, getgrnam_app_id_u1_a40000) {
- check_get_group("u1_a40000", 150000);
+TEST(grp, getgrgid_app_id_u1_non_exist) {
+ expect_no_group_id(100000); // There is no 'root' for secondary users.
+ expect_no_group_id(101999); // End of the system reserved range, unallocated.
+ expect_no_group_id(102900); // The OEM ranges were never allocated to secondary users.
+ expect_no_group_id(105000); // The OEM ranges were never allocated to secondary users.
+
+ // The shared range is shared among users, and therefore doesn't exist for secondary users.
+ expect_no_group_id(150000);
}
-TEST(grp, getgrnam_app_id_u1_i0) {
- check_get_group("u1_i0", 190000);
+TEST(grp, getgrgid_app_id_u31_non_exist) {
+ expect_no_group_id(3100000); // There is no 'root' for secondary users.
+ expect_no_group_id(3101999); // End of the system reserved range, unallocated.
+ expect_no_group_id(3102900); // The OEM ranges were never allocated to secondary users.
+ expect_no_group_id(3105000); // The OEM ranges were never allocated to secondary users.
+
+ // The shared range is shared among users, and therefore doesn't exist for secondary users.
+ expect_no_group_id(3150000);
}
TEST(grp, getgrnam_r_alignment) {
@@ -660,7 +824,7 @@ TEST(grp, getgrent_iterate) {
}
endgrent();
- expect_ids(gids);
+ expect_ids(gids, true);
#else
GTEST_SKIP() << "bionic-only test";
#endif
diff --git a/tests/leak_test.cpp b/tests/leak_test.cpp
index 600520959..3cc1a0a91 100644
--- a/tests/leak_test.cpp
+++ b/tests/leak_test.cpp
@@ -17,6 +17,7 @@
#include <err.h>
#include <inttypes.h>
#include <pthread.h>
+#include <sched.h>
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
@@ -30,26 +31,28 @@
#include <vector>
#include <android-base/macros.h>
+#include <android-base/threads.h>
#include "utils.h"
using namespace std::chrono_literals;
-static void WaitUntilAllExited(pid_t* pids, size_t pid_count) {
+static void WaitUntilAllThreadsExited(pid_t* tids, size_t tid_count) {
// Wait until all children have exited.
bool alive = true;
while (alive) {
alive = false;
- for (size_t i = 0; i < pid_count; ++i) {
- if (pids[i] != 0) {
- if (kill(pids[i], 0) == 0) {
+ for (size_t i = 0; i < tid_count; ++i) {
+ if (tids[i] != 0) {
+ if (tgkill(getpid(), tids[i], 0) == 0) {
alive = true;
} else {
EXPECT_EQ(errno, ESRCH);
- pids[i] = 0; // Skip in next loop.
+ tids[i] = 0; // Skip in next loop.
}
}
}
+ sched_yield();
}
}
@@ -155,7 +158,7 @@ TEST(pthread_leak, detach) {
pthread_barrier_wait(&barrier);
ASSERT_EQ(pthread_barrier_destroy(&barrier), 0);
- WaitUntilAllExited(tids, arraysize(tids));
+ WaitUntilAllThreadsExited(tids, threads_count);
// A native bridge implementation might need a warm up pass to reach a steady state.
// http://b/37920774.
diff --git a/tests/libs/Android.bp b/tests/libs/Android.bp
index 422cd75c0..98d4f25e7 100644
--- a/tests/libs/Android.bp
+++ b/tests/libs/Android.bp
@@ -29,7 +29,7 @@ cc_defaults {
gtest: false,
sanitize: {
address: false,
- coverage: false,
+ fuzzer: false,
},
stl: "libc++_static",
target: {
diff --git a/tests/libs/segment_gap_outer.lds b/tests/libs/segment_gap_outer.lds
index f326aab26..c2961b2c6 100644
--- a/tests/libs/segment_gap_outer.lds
+++ b/tests/libs/segment_gap_outer.lds
@@ -22,6 +22,6 @@ SECTIONS {
# Place end_of_gap at the end of the gap.
. = 0x1000000;
.bss.end_of_gap : {
- *(.bss.end_of_gap);
+ *(.bss.*end_of_gap*);
}
}
diff --git a/tests/make_fortify_compile_test.mk b/tests/make_fortify_compile_test.mk
new file mode 100644
index 000000000..8270f29d7
--- /dev/null
+++ b/tests/make_fortify_compile_test.mk
@@ -0,0 +1,20 @@
+include $(CLEAR_VARS)
+
+LOCAL_ADDITIONAL_DEPENDENCIES := \
+ $(LOCAL_PATH)/Android.mk \
+ $(LOCAL_PATH)/touch-obj-on-success
+
+LOCAL_CXX := $(LOCAL_PATH)/touch-obj-on-success \
+ $(LLVM_PREBUILTS_PATH)/clang++ \
+
+LOCAL_CLANG := true
+LOCAL_MODULE := bionic-compile-time-tests$(FORTIFY_LEVEL)-clang++
+LOCAL_CPPFLAGS := -Wall -Wno-error
+LOCAL_CPPFLAGS += -fno-color-diagnostics -ferror-limit=10000 -Xclang -verify
+LOCAL_CPPFLAGS += -DCOMPILATION_TESTS=1 -Wformat-nonliteral
+LOCAL_CPPFLAGS += -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=$(FORTIFY_LEVEL)
+LOCAL_SRC_FILES := clang_fortify_tests.cpp
+
+include $(BUILD_STATIC_LIBRARY)
+
+FORTIFY_LEVEL :=
diff --git a/tests/malloc_test.cpp b/tests/malloc_test.cpp
index 983592f0a..edcc179ed 100644
--- a/tests/malloc_test.cpp
+++ b/tests/malloc_test.cpp
@@ -312,32 +312,48 @@ TEST(malloc, realloc_overflow) {
#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
extern "C" void* pvalloc(size_t);
extern "C" void* valloc(size_t);
+#endif
TEST(malloc, pvalloc_std) {
+#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
size_t pagesize = sysconf(_SC_PAGESIZE);
void* ptr = pvalloc(100);
ASSERT_TRUE(ptr != nullptr);
ASSERT_TRUE((reinterpret_cast<uintptr_t>(ptr) & (pagesize-1)) == 0);
ASSERT_LE(pagesize, malloc_usable_size(ptr));
free(ptr);
+#else
+ GTEST_SKIP() << "pvalloc not supported.";
+#endif
}
TEST(malloc, pvalloc_overflow) {
+#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
ASSERT_EQ(nullptr, pvalloc(SIZE_MAX));
+#else
+ GTEST_SKIP() << "pvalloc not supported.";
+#endif
}
TEST(malloc, valloc_std) {
+#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
size_t pagesize = sysconf(_SC_PAGESIZE);
- void* ptr = pvalloc(100);
+ void* ptr = valloc(100);
ASSERT_TRUE(ptr != nullptr);
ASSERT_TRUE((reinterpret_cast<uintptr_t>(ptr) & (pagesize-1)) == 0);
free(ptr);
+#else
+ GTEST_SKIP() << "valloc not supported.";
+#endif
}
TEST(malloc, valloc_overflow) {
+#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
ASSERT_EQ(nullptr, valloc(SIZE_MAX));
-}
+#else
+ GTEST_SKIP() << "valloc not supported.";
#endif
+}
TEST(malloc, malloc_info) {
#ifdef __BIONIC__
diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp
index 0bf8e294b..d8257381c 100644
--- a/tests/pthread_test.cpp
+++ b/tests/pthread_test.cpp
@@ -990,6 +990,25 @@ TEST(pthread, pthread_rwlock_reader_wakeup_writer_timedwait_monotonic_np) {
#endif // __BIONIC__
}
+TEST(pthread, pthread_rwlock_reader_wakeup_writer_clockwait) {
+#if defined(__BIONIC__)
+ timespec ts;
+ ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, &ts));
+ ts.tv_sec += 1;
+ test_pthread_rwlock_reader_wakeup_writer([&](pthread_rwlock_t* lock) {
+ return pthread_rwlock_clockwrlock(lock, CLOCK_MONOTONIC, &ts);
+ });
+
+ ASSERT_EQ(0, clock_gettime(CLOCK_REALTIME, &ts));
+ ts.tv_sec += 1;
+ test_pthread_rwlock_reader_wakeup_writer([&](pthread_rwlock_t* lock) {
+ return pthread_rwlock_clockwrlock(lock, CLOCK_REALTIME, &ts);
+ });
+#else // __BIONIC__
+ GTEST_SKIP() << "pthread_rwlock_clockwrlock not available";
+#endif // __BIONIC__
+}
+
static void test_pthread_rwlock_writer_wakeup_reader(std::function<int (pthread_rwlock_t*)> lock_function) {
RwlockWakeupHelperArg wakeup_arg;
ASSERT_EQ(0, pthread_rwlock_init(&wakeup_arg.lock, nullptr));
@@ -1038,6 +1057,25 @@ TEST(pthread, pthread_rwlock_writer_wakeup_reader_timedwait_monotonic_np) {
#endif // __BIONIC__
}
+TEST(pthread, pthread_rwlock_writer_wakeup_reader_clockwait) {
+#if defined(__BIONIC__)
+ timespec ts;
+ ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, &ts));
+ ts.tv_sec += 1;
+ test_pthread_rwlock_writer_wakeup_reader([&](pthread_rwlock_t* lock) {
+ return pthread_rwlock_clockrdlock(lock, CLOCK_MONOTONIC, &ts);
+ });
+
+ ASSERT_EQ(0, clock_gettime(CLOCK_REALTIME, &ts));
+ ts.tv_sec += 1;
+ test_pthread_rwlock_writer_wakeup_reader([&](pthread_rwlock_t* lock) {
+ return pthread_rwlock_clockrdlock(lock, CLOCK_REALTIME, &ts);
+ });
+#else // __BIONIC__
+ GTEST_SKIP() << "pthread_rwlock_clockrdlock not available";
+#endif // __BIONIC__
+}
+
static void pthread_rwlock_wakeup_timeout_helper(RwlockWakeupHelperArg* arg) {
arg->tid = gettid();
ASSERT_EQ(RwlockWakeupHelperArg::LOCK_INITIALIZED, arg->progress);
@@ -1098,6 +1136,38 @@ TEST(pthread, pthread_rwlock_timedrdlock_monotonic_np_timeout) {
#endif // __BIONIC__
}
+TEST(pthread, pthread_rwlock_clockrdlock_monotonic_timeout) {
+#if defined(__BIONIC__)
+ pthread_rwlock_timedrdlock_timeout_helper(
+ CLOCK_MONOTONIC, [](pthread_rwlock_t* __rwlock, const timespec* __timeout) {
+ return pthread_rwlock_clockrdlock(__rwlock, CLOCK_MONOTONIC, __timeout);
+ });
+#else // __BIONIC__
+ GTEST_SKIP() << "pthread_rwlock_clockrdlock not available";
+#endif // __BIONIC__
+}
+
+TEST(pthread, pthread_rwlock_clockrdlock_realtime_timeout) {
+#if defined(__BIONIC__)
+ pthread_rwlock_timedrdlock_timeout_helper(
+ CLOCK_REALTIME, [](pthread_rwlock_t* __rwlock, const timespec* __timeout) {
+ return pthread_rwlock_clockrdlock(__rwlock, CLOCK_REALTIME, __timeout);
+ });
+#else // __BIONIC__
+ GTEST_SKIP() << "pthread_rwlock_clockrdlock not available";
+#endif // __BIONIC__
+}
+
+TEST(pthread, pthread_rwlock_clockrdlock_invalid) {
+#if defined(__BIONIC__)
+ pthread_rwlock_t lock = PTHREAD_RWLOCK_INITIALIZER;
+ timespec ts;
+ EXPECT_EQ(EINVAL, pthread_rwlock_clockrdlock(&lock, CLOCK_PROCESS_CPUTIME_ID, &ts));
+#else // __BIONIC__
+ GTEST_SKIP() << "pthread_rwlock_clockrdlock not available";
+#endif // __BIONIC__
+}
+
static void pthread_rwlock_timedwrlock_timeout_helper(
clockid_t clock, int (*lock_function)(pthread_rwlock_t* __rwlock, const timespec* __timeout)) {
RwlockWakeupHelperArg wakeup_arg;
@@ -1134,6 +1204,38 @@ TEST(pthread, pthread_rwlock_timedwrlock_monotonic_np_timeout) {
#endif // __BIONIC__
}
+TEST(pthread, pthread_rwlock_clockwrlock_monotonic_timeout) {
+#if defined(__BIONIC__)
+ pthread_rwlock_timedwrlock_timeout_helper(
+ CLOCK_MONOTONIC, [](pthread_rwlock_t* __rwlock, const timespec* __timeout) {
+ return pthread_rwlock_clockwrlock(__rwlock, CLOCK_MONOTONIC, __timeout);
+ });
+#else // __BIONIC__
+ GTEST_SKIP() << "pthread_rwlock_clockwrlock not available";
+#endif // __BIONIC__
+}
+
+TEST(pthread, pthread_rwlock_clockwrlock_realtime_timeout) {
+#if defined(__BIONIC__)
+ pthread_rwlock_timedwrlock_timeout_helper(
+ CLOCK_REALTIME, [](pthread_rwlock_t* __rwlock, const timespec* __timeout) {
+ return pthread_rwlock_clockwrlock(__rwlock, CLOCK_REALTIME, __timeout);
+ });
+#else // __BIONIC__
+ GTEST_SKIP() << "pthread_rwlock_clockwrlock not available";
+#endif // __BIONIC__
+}
+
+TEST(pthread, pthread_rwlock_clockwrlock_invalid) {
+#if defined(__BIONIC__)
+ pthread_rwlock_t lock = PTHREAD_RWLOCK_INITIALIZER;
+ timespec ts;
+ EXPECT_EQ(EINVAL, pthread_rwlock_clockwrlock(&lock, CLOCK_PROCESS_CPUTIME_ID, &ts));
+#else // __BIONIC__
+ GTEST_SKIP() << "pthread_rwlock_clockrwlock not available";
+#endif // __BIONIC__
+}
+
class RwlockKindTestHelper {
private:
struct ThreadArg {
@@ -1392,16 +1494,43 @@ class pthread_CondWakeupTest : public ::testing::Test {
ASSERT_EQ(0, pthread_condattr_destroy(&attr));
}
- void StartWaitingThread(std::function<int (pthread_cond_t* cond, pthread_mutex_t* mutex)> wait_function) {
+ void StartWaitingThread(
+ std::function<int(pthread_cond_t* cond, pthread_mutex_t* mutex)> wait_function) {
progress = INITIALIZED;
this->wait_function = wait_function;
- ASSERT_EQ(0, pthread_create(&thread, nullptr, reinterpret_cast<void* (*)(void*)>(WaitThreadFn), this));
+ ASSERT_EQ(0, pthread_create(&thread, nullptr, reinterpret_cast<void* (*)(void*)>(WaitThreadFn),
+ this));
while (progress != WAITING) {
usleep(5000);
}
usleep(5000);
}
+ void RunTimedTest(
+ clockid_t clock,
+ std::function<int(pthread_cond_t* cond, pthread_mutex_t* mutex, const timespec* timeout)>
+ wait_function) {
+ timespec ts;
+ ASSERT_EQ(0, clock_gettime(clock, &ts));
+ ts.tv_sec += 1;
+
+ StartWaitingThread([&wait_function, &ts](pthread_cond_t* cond, pthread_mutex_t* mutex) {
+ return wait_function(cond, mutex, &ts);
+ });
+
+ progress = SIGNALED;
+ ASSERT_EQ(0, pthread_cond_signal(&cond));
+ }
+
+ void RunTimedTest(clockid_t clock, std::function<int(pthread_cond_t* cond, pthread_mutex_t* mutex,
+ clockid_t clock, const timespec* timeout)>
+ wait_function) {
+ RunTimedTest(clock, [clock, &wait_function](pthread_cond_t* cond, pthread_mutex_t* mutex,
+ const timespec* timeout) {
+ return wait_function(cond, mutex, clock, timeout);
+ });
+ }
+
void TearDown() override {
ASSERT_EQ(0, pthread_join(thread, nullptr));
ASSERT_EQ(FINISHED, progress);
@@ -1442,52 +1571,80 @@ TEST_F(pthread_CondWakeupTest, broadcast_wait) {
TEST_F(pthread_CondWakeupTest, signal_timedwait_CLOCK_REALTIME) {
InitCond(CLOCK_REALTIME);
- timespec ts;
- ASSERT_EQ(0, clock_gettime(CLOCK_REALTIME, &ts));
- ts.tv_sec += 1;
- StartWaitingThread([&](pthread_cond_t* cond, pthread_mutex_t* mutex) {
- return pthread_cond_timedwait(cond, mutex, &ts);
- });
- progress = SIGNALED;
- ASSERT_EQ(0, pthread_cond_signal(&cond));
+ RunTimedTest(CLOCK_REALTIME, pthread_cond_timedwait);
}
TEST_F(pthread_CondWakeupTest, signal_timedwait_CLOCK_MONOTONIC) {
InitCond(CLOCK_MONOTONIC);
- timespec ts;
- ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, &ts));
- ts.tv_sec += 1;
- StartWaitingThread([&](pthread_cond_t* cond, pthread_mutex_t* mutex) {
- return pthread_cond_timedwait(cond, mutex, &ts);
- });
- progress = SIGNALED;
- ASSERT_EQ(0, pthread_cond_signal(&cond));
+ RunTimedTest(CLOCK_MONOTONIC, pthread_cond_timedwait);
}
TEST_F(pthread_CondWakeupTest, signal_timedwait_CLOCK_MONOTONIC_np) {
#if defined(__BIONIC__)
InitCond(CLOCK_REALTIME);
- timespec ts;
- ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, &ts));
- ts.tv_sec += 1;
- StartWaitingThread([&](pthread_cond_t* cond, pthread_mutex_t* mutex) {
- return pthread_cond_timedwait_monotonic_np(cond, mutex, &ts);
- });
- progress = SIGNALED;
- ASSERT_EQ(0, pthread_cond_signal(&cond));
+ RunTimedTest(CLOCK_MONOTONIC, pthread_cond_timedwait_monotonic_np);
#else // __BIONIC__
GTEST_SKIP() << "pthread_cond_timedwait_monotonic_np not available";
#endif // __BIONIC__
}
-static void pthread_cond_timedwait_timeout_helper(clockid_t clock,
+TEST_F(pthread_CondWakeupTest, signal_clockwait_monotonic_monotonic) {
+#if defined(__BIONIC__)
+ InitCond(CLOCK_MONOTONIC);
+ RunTimedTest(CLOCK_MONOTONIC, pthread_cond_clockwait);
+#else // __BIONIC__
+ GTEST_SKIP() << "pthread_cond_clockwait not available";
+#endif // __BIONIC__
+}
+
+TEST_F(pthread_CondWakeupTest, signal_clockwait_monotonic_realtime) {
+#if defined(__BIONIC__)
+ InitCond(CLOCK_MONOTONIC);
+ RunTimedTest(CLOCK_REALTIME, pthread_cond_clockwait);
+#else // __BIONIC__
+ GTEST_SKIP() << "pthread_cond_clockwait not available";
+#endif // __BIONIC__
+}
+
+TEST_F(pthread_CondWakeupTest, signal_clockwait_realtime_monotonic) {
+#if defined(__BIONIC__)
+ InitCond(CLOCK_REALTIME);
+ RunTimedTest(CLOCK_MONOTONIC, pthread_cond_clockwait);
+#else // __BIONIC__
+ GTEST_SKIP() << "pthread_cond_clockwait not available";
+#endif // __BIONIC__
+}
+
+TEST_F(pthread_CondWakeupTest, signal_clockwait_realtime_realtime) {
+#if defined(__BIONIC__)
+ InitCond(CLOCK_REALTIME);
+ RunTimedTest(CLOCK_REALTIME, pthread_cond_clockwait);
+#else // __BIONIC__
+ GTEST_SKIP() << "pthread_cond_clockwait not available";
+#endif // __BIONIC__
+}
+
+static void pthread_cond_timedwait_timeout_helper(bool init_monotonic, clockid_t clock,
int (*wait_function)(pthread_cond_t* __cond,
pthread_mutex_t* __mutex,
const timespec* __timeout)) {
pthread_mutex_t mutex;
ASSERT_EQ(0, pthread_mutex_init(&mutex, nullptr));
pthread_cond_t cond;
- ASSERT_EQ(0, pthread_cond_init(&cond, nullptr));
+
+ if (init_monotonic) {
+ pthread_condattr_t attr;
+ pthread_condattr_init(&attr);
+
+ ASSERT_EQ(0, pthread_condattr_setclock(&attr, CLOCK_MONOTONIC));
+ clockid_t clock;
+ ASSERT_EQ(0, pthread_condattr_getclock(&attr, &clock));
+ ASSERT_EQ(CLOCK_MONOTONIC, clock);
+
+ ASSERT_EQ(0, pthread_cond_init(&cond, &attr));
+ } else {
+ ASSERT_EQ(0, pthread_cond_init(&cond, nullptr));
+ }
ASSERT_EQ(0, pthread_mutex_lock(&mutex));
timespec ts;
@@ -1504,17 +1661,57 @@ static void pthread_cond_timedwait_timeout_helper(clockid_t clock,
}
TEST(pthread, pthread_cond_timedwait_timeout) {
- pthread_cond_timedwait_timeout_helper(CLOCK_REALTIME, pthread_cond_timedwait);
+ pthread_cond_timedwait_timeout_helper(false, CLOCK_REALTIME, pthread_cond_timedwait);
}
TEST(pthread, pthread_cond_timedwait_monotonic_np_timeout) {
#if defined(__BIONIC__)
- pthread_cond_timedwait_timeout_helper(CLOCK_MONOTONIC, pthread_cond_timedwait_monotonic_np);
+ pthread_cond_timedwait_timeout_helper(false, CLOCK_MONOTONIC, pthread_cond_timedwait_monotonic_np);
+ pthread_cond_timedwait_timeout_helper(true, CLOCK_MONOTONIC, pthread_cond_timedwait_monotonic_np);
#else // __BIONIC__
GTEST_SKIP() << "pthread_cond_timedwait_monotonic_np not available";
#endif // __BIONIC__
}
+TEST(pthread, pthread_cond_clockwait_timeout) {
+#if defined(__BIONIC__)
+ pthread_cond_timedwait_timeout_helper(
+ false, CLOCK_MONOTONIC,
+ [](pthread_cond_t* __cond, pthread_mutex_t* __mutex, const timespec* __timeout) {
+ return pthread_cond_clockwait(__cond, __mutex, CLOCK_MONOTONIC, __timeout);
+ });
+ pthread_cond_timedwait_timeout_helper(
+ true, CLOCK_MONOTONIC,
+ [](pthread_cond_t* __cond, pthread_mutex_t* __mutex, const timespec* __timeout) {
+ return pthread_cond_clockwait(__cond, __mutex, CLOCK_MONOTONIC, __timeout);
+ });
+ pthread_cond_timedwait_timeout_helper(
+ false, CLOCK_REALTIME,
+ [](pthread_cond_t* __cond, pthread_mutex_t* __mutex, const timespec* __timeout) {
+ return pthread_cond_clockwait(__cond, __mutex, CLOCK_REALTIME, __timeout);
+ });
+ pthread_cond_timedwait_timeout_helper(
+ true, CLOCK_REALTIME,
+ [](pthread_cond_t* __cond, pthread_mutex_t* __mutex, const timespec* __timeout) {
+ return pthread_cond_clockwait(__cond, __mutex, CLOCK_REALTIME, __timeout);
+ });
+#else // __BIONIC__
+ GTEST_SKIP() << "pthread_cond_clockwait not available";
+#endif // __BIONIC__
+}
+
+TEST(pthread, pthread_cond_clockwait_invalid) {
+#if defined(__BIONIC__)
+ pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+ pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+ timespec ts;
+ EXPECT_EQ(EINVAL, pthread_cond_clockwait(&cond, &mutex, CLOCK_PROCESS_CPUTIME_ID, &ts));
+
+#else // __BIONIC__
+ GTEST_SKIP() << "pthread_cond_clockwait not available";
+#endif // __BIONIC__
+}
+
TEST(pthread, pthread_attr_getstack__main_thread) {
// This test is only meaningful for the main thread, so make sure we're running on it!
ASSERT_EQ(getpid(), syscall(__NR_gettid));
@@ -2180,6 +2377,21 @@ TEST(pthread, pthread_mutex_timedlock_monotonic_np) {
#endif // __BIONIC__
}
+TEST(pthread, pthread_mutex_clocklock) {
+#if defined(__BIONIC__)
+ pthread_mutex_timedlock_helper(
+ CLOCK_MONOTONIC, [](pthread_mutex_t* __mutex, const timespec* __timeout) {
+ return pthread_mutex_clocklock(__mutex, CLOCK_MONOTONIC, __timeout);
+ });
+ pthread_mutex_timedlock_helper(
+ CLOCK_REALTIME, [](pthread_mutex_t* __mutex, const timespec* __timeout) {
+ return pthread_mutex_clocklock(__mutex, CLOCK_REALTIME, __timeout);
+ });
+#else // __BIONIC__
+ GTEST_SKIP() << "pthread_mutex_clocklock not available";
+#endif // __BIONIC__
+}
+
static void pthread_mutex_timedlock_pi_helper(clockid_t clock,
int (*lock_function)(pthread_mutex_t* __mutex,
const timespec* __timeout)) {
@@ -2231,6 +2443,31 @@ TEST(pthread, pthread_mutex_timedlock_monotonic_np_pi) {
#endif // __BIONIC__
}
+TEST(pthread, pthread_mutex_clocklock_pi) {
+#if defined(__BIONIC__)
+ pthread_mutex_timedlock_pi_helper(
+ CLOCK_MONOTONIC, [](pthread_mutex_t* __mutex, const timespec* __timeout) {
+ return pthread_mutex_clocklock(__mutex, CLOCK_MONOTONIC, __timeout);
+ });
+ pthread_mutex_timedlock_pi_helper(
+ CLOCK_REALTIME, [](pthread_mutex_t* __mutex, const timespec* __timeout) {
+ return pthread_mutex_clocklock(__mutex, CLOCK_REALTIME, __timeout);
+ });
+#else // __BIONIC__
+ GTEST_SKIP() << "pthread_mutex_clocklock not available";
+#endif // __BIONIC__
+}
+
+TEST(pthread, pthread_mutex_clocklock_invalid) {
+#if defined(__BIONIC__)
+ pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+ timespec ts;
+ EXPECT_EQ(EINVAL, pthread_mutex_clocklock(&mutex, CLOCK_PROCESS_CPUTIME_ID, &ts));
+#else // __BIONIC__
+ GTEST_SKIP() << "pthread_mutex_clocklock not available";
+#endif // __BIONIC__
+}
+
TEST(pthread, pthread_mutex_using_destroyed_mutex) {
#if defined(__BIONIC__)
pthread_mutex_t m;
@@ -2247,6 +2484,13 @@ TEST(pthread, pthread_mutex_using_destroyed_mutex) {
"pthread_mutex_timedlock called on a destroyed mutex");
ASSERT_EXIT(pthread_mutex_timedlock_monotonic_np(&m, &ts), ::testing::KilledBySignal(SIGABRT),
"pthread_mutex_timedlock_monotonic_np called on a destroyed mutex");
+ ASSERT_EXIT(pthread_mutex_clocklock(&m, CLOCK_MONOTONIC, &ts), ::testing::KilledBySignal(SIGABRT),
+ "pthread_mutex_clocklock called on a destroyed mutex");
+ ASSERT_EXIT(pthread_mutex_clocklock(&m, CLOCK_REALTIME, &ts), ::testing::KilledBySignal(SIGABRT),
+ "pthread_mutex_clocklock called on a destroyed mutex");
+ ASSERT_EXIT(pthread_mutex_clocklock(&m, CLOCK_PROCESS_CPUTIME_ID, &ts),
+ ::testing::KilledBySignal(SIGABRT),
+ "pthread_mutex_clocklock called on a destroyed mutex");
ASSERT_EXIT(pthread_mutex_destroy(&m), ::testing::KilledBySignal(SIGABRT),
"pthread_mutex_destroy called on a destroyed mutex");
#else
diff --git a/tests/semaphore_test.cpp b/tests/semaphore_test.cpp
index 7addf6dda..5a23b96bf 100644
--- a/tests/semaphore_test.cpp
+++ b/tests/semaphore_test.cpp
@@ -145,6 +145,19 @@ TEST(semaphore, sem_timedwait_monotonic_np) {
#endif // __BIONIC__
}
+TEST(semaphore, sem_clockwait) {
+#if defined(__BIONIC__)
+ sem_timedwait_helper(CLOCK_MONOTONIC, [](sem_t* __sem, const timespec* __ts) {
+ return sem_clockwait(__sem, CLOCK_MONOTONIC, __ts);
+ });
+ sem_timedwait_helper(CLOCK_REALTIME, [](sem_t* __sem, const timespec* __ts) {
+ return sem_clockwait(__sem, CLOCK_REALTIME, __ts);
+ });
+#else // __BIONIC__
+ GTEST_SKIP() << "sem_clockwait is only supported on bionic";
+#endif // __BIONIC__
+}
+
TEST(semaphore_DeathTest, sem_timedwait_null_timeout) {
sem_t s;
ASSERT_EQ(0, sem_init(&s, 0, 0));
diff --git a/tests/stdatomic_test.cpp b/tests/stdatomic_test.cpp
index d122d2f39..a9665d18e 100644
--- a/tests/stdatomic_test.cpp
+++ b/tests/stdatomic_test.cpp
@@ -15,9 +15,14 @@
*/
#include <gtest/gtest.h>
-// Fool stdatomic.h into not using <atomic>.
-#undef _USING_LIBCXX
+
+#if defined(__ANDROID__)
+#include <bits/stdatomic.h>
+#else
+#undef _USING_LIBCXX //TODO(b/137876753): Remove this
#include <stdatomic.h>
+#endif
+
#include <pthread.h>
#include <stdint.h>
diff --git a/tests/stdio_test.cpp b/tests/stdio_test.cpp
index 01b4dbab7..a0cda1be0 100644
--- a/tests/stdio_test.cpp
+++ b/tests/stdio_test.cpp
@@ -19,7 +19,6 @@
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
-#include <linux/fs.h>
#include <math.h>
#include <stdio.h>
#include <sys/types.h>
@@ -34,10 +33,18 @@
#include <vector>
#include <android-base/file.h>
+#include <android-base/unique_fd.h>
#include "BionicDeathTest.h"
#include "utils.h"
+// This #include is actually a test too. We have to duplicate the
+// definitions of the RENAME_ constants because <linux/fs.h> also contains
+// pollution such as BLOCK_SIZE which conflicts with lots of user code.
+// Important to check that we have matching definitions.
+// There's no _MAX to test that we have all the constants, sadly.
+#include <linux/fs.h>
+
#if defined(NOFORTIFY)
#define STDIO_TEST stdio_nofortify
#define STDIO_DEATHTEST stdio_nofortify_DeathTest
@@ -2610,3 +2617,77 @@ TEST(STDIO_TEST, SEEK_macros) {
// So we'll notice if Linux grows another constant in <linux/fs.h>...
ASSERT_EQ(SEEK_MAX, SEEK_HOLE);
}
+
+TEST(STDIO_TEST, rename) {
+ TemporaryDir td;
+ std::string old_path = td.path + "/old"s;
+ std::string new_path = td.path + "/new"s;
+
+ // Create the file, check it exists.
+ ASSERT_EQ(0, close(creat(old_path.c_str(), 0666)));
+ struct stat sb;
+ ASSERT_EQ(0, stat(old_path.c_str(), &sb));
+ ASSERT_EQ(-1, stat(new_path.c_str(), &sb));
+
+ // Rename and check it moved.
+ ASSERT_EQ(0, rename(old_path.c_str(), new_path.c_str()));
+ ASSERT_EQ(-1, stat(old_path.c_str(), &sb));
+ ASSERT_EQ(0, stat(new_path.c_str(), &sb));
+}
+
+TEST(STDIO_TEST, renameat) {
+ TemporaryDir td;
+ android::base::unique_fd dirfd{open(td.path, O_PATH)};
+ std::string old_path = td.path + "/old"s;
+ std::string new_path = td.path + "/new"s;
+
+ // Create the file, check it exists.
+ ASSERT_EQ(0, close(creat(old_path.c_str(), 0666)));
+ struct stat sb;
+ ASSERT_EQ(0, stat(old_path.c_str(), &sb));
+ ASSERT_EQ(-1, stat(new_path.c_str(), &sb));
+
+ // Rename and check it moved.
+ ASSERT_EQ(0, renameat(dirfd, "old", dirfd, "new"));
+ ASSERT_EQ(-1, stat(old_path.c_str(), &sb));
+ ASSERT_EQ(0, stat(new_path.c_str(), &sb));
+}
+
+TEST(STDIO_TEST, renameat2) {
+#if defined(__GLIBC__)
+ GTEST_SKIP() << "glibc doesn't have renameat2 until 2.28";
+#else
+ TemporaryDir td;
+ android::base::unique_fd dirfd{open(td.path, O_PATH)};
+ std::string old_path = td.path + "/old"s;
+ std::string new_path = td.path + "/new"s;
+
+ // Create the file, check it exists.
+ ASSERT_EQ(0, close(creat(old_path.c_str(), 0666)));
+ struct stat sb;
+ ASSERT_EQ(0, stat(old_path.c_str(), &sb));
+ ASSERT_EQ(-1, stat(new_path.c_str(), &sb));
+
+ // Rename and check it moved.
+ ASSERT_EQ(0, renameat2(dirfd, "old", dirfd, "new", 0));
+ ASSERT_EQ(-1, stat(old_path.c_str(), &sb));
+ ASSERT_EQ(0, stat(new_path.c_str(), &sb));
+
+ // After this, both "old" and "new" exist.
+ ASSERT_EQ(0, close(creat(old_path.c_str(), 0666)));
+
+ // Rename and check it moved.
+ ASSERT_EQ(-1, renameat2(dirfd, "old", dirfd, "new", RENAME_NOREPLACE));
+ ASSERT_EQ(EEXIST, errno);
+#endif
+}
+
+TEST(STDIO_TEST, renameat2_flags) {
+#if defined(__GLIBC__)
+ GTEST_SKIP() << "glibc doesn't have renameat2 until 2.28";
+#else
+ ASSERT_NE(0, RENAME_EXCHANGE);
+ ASSERT_NE(0, RENAME_NOREPLACE);
+ ASSERT_NE(0, RENAME_WHITEOUT);
+#endif
+}
diff --git a/tests/sys_mman_test.cpp b/tests/sys_mman_test.cpp
index 0b981981c..e403ea5b5 100644
--- a/tests/sys_mman_test.cpp
+++ b/tests/sys_mman_test.cpp
@@ -230,7 +230,10 @@ TEST(sys_mman, mmap_PTRDIFF_MAX) {
TEST(sys_mman, mremap_PTRDIFF_MAX) {
void* map = mmap(nullptr, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
ASSERT_NE(MAP_FAILED, map);
+
ASSERT_EQ(MAP_FAILED, mremap(map, PAGE_SIZE, kHuge, MREMAP_MAYMOVE));
+
+ ASSERT_EQ(0, munmap(map, PAGE_SIZE));
}
TEST(sys_mman, mmap_bug_27265969) {
@@ -239,3 +242,61 @@ TEST(sys_mman, mmap_bug_27265969) {
// Some kernels had bugs that would cause segfaults here...
__builtin___clear_cache(base, base + (PAGE_SIZE * 2));
}
+
+TEST(sys_mman, mlock) {
+ void* map = mmap(nullptr, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ ASSERT_NE(MAP_FAILED, map);
+
+ // Not really anything we can assert about this.
+ mlock(map, PAGE_SIZE);
+
+ ASSERT_EQ(0, munmap(map, PAGE_SIZE));
+}
+
+TEST(sys_mman, mlock2) {
+#if defined(__GLIBC__)
+ GTEST_SKIP() << "needs glibc 2.27";
+#else
+ void* map = mmap(nullptr, PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ ASSERT_NE(MAP_FAILED, map);
+
+ // Not really anything we can assert about this.
+ mlock2(map, PAGE_SIZE, MLOCK_ONFAULT);
+
+ ASSERT_EQ(0, munmap(map, PAGE_SIZE));
+#endif
+}
+
+TEST(sys_mman, memfd_create) {
+#if defined(__GLIBC__)
+ GTEST_SKIP() << "needs glibc 2.27";
+#else
+ // Is the MFD_CLOEXEC flag obeyed?
+ errno = 0;
+ int fd = memfd_create("doesn't matter", 0);
+ if (fd == -1) {
+ ASSERT_EQ(ENOSYS, errno);
+ GTEST_SKIP() << "no memfd_create available";
+ }
+ int f = fcntl(fd, F_GETFD);
+ ASSERT_NE(-1, f);
+ ASSERT_FALSE(f & FD_CLOEXEC);
+ close(fd);
+
+ errno = 0;
+ fd = memfd_create("doesn't matter", MFD_CLOEXEC);
+ f = fcntl(fd, F_GETFD);
+ ASSERT_NE(-1, f);
+ ASSERT_TRUE(f & FD_CLOEXEC);
+
+ // Can we read and write?
+ std::string expected("hello, world!");
+ ASSERT_TRUE(android::base::WriteStringToFd(expected, fd));
+ ASSERT_EQ(0, lseek(fd, 0, SEEK_SET));
+ std::string actual;
+ ASSERT_TRUE(android::base::ReadFdToString(fd, &actual));
+ ASSERT_EQ(expected, actual);
+
+ close(fd);
+#endif
+}
diff --git a/tests/time_test.cpp b/tests/time_test.cpp
index c890358fa..4e1724211 100644
--- a/tests/time_test.cpp
+++ b/tests/time_test.cpp
@@ -748,11 +748,11 @@ TEST(time, clock_getres_unknown) {
}
TEST(time, clock) {
- // clock(3) is hard to test, but a 1s sleep should cost less than 1ms.
+ // clock(3) is hard to test, but a 1s sleep should cost less than 5ms.
clock_t t0 = clock();
sleep(1);
clock_t t1 = clock();
- ASSERT_LT(t1 - t0, CLOCKS_PER_SEC / 1000);
+ ASSERT_LT(t1 - t0, 5 * (CLOCKS_PER_SEC / 1000));
}
static pid_t GetInvalidPid() {
diff --git a/tests/touch-obj-on-success b/tests/touch-obj-on-success
index df08a4968..d8a71ba24 100755
--- a/tests/touch-obj-on-success
+++ b/tests/touch-obj-on-success
@@ -4,5 +4,8 @@
# from that command line and touches it.
"$@"
-obj="$(echo "$@" | grep -oP '\S+\.o\b')"
-touch "${obj}"
+for arg in "$@"; do
+ if [[ "$arg" == *.o ]]; then
+ touch "$arg"
+ fi
+done