diff options
author | Edward Liaw <edliaw@google.com> | 2023-10-09 20:23:13 +0000 |
---|---|---|
committer | Edward Liaw <edliaw@google.com> | 2023-10-12 22:07:50 +0000 |
commit | 984fbcd5cb4de0bee50378b26d86da8d810e2f49 (patch) | |
tree | ef2edb14efd15dd53311644d25caaa893f549a02 | |
parent | 236e58f2f3f5099cbf4e10138f9ac7ca0c79c81c (diff) | |
download | linux-kselftest-984fbcd5cb4de0bee50378b26d86da8d810e2f49.tar.gz |
kselftest: Apply android/patches to 6.1 merge
Bug: 303675116
Test: atest vts_linux_kselftest_x86_64
Test: atest vts_linux_kselftest_arm_64
Change-Id: Ic95543014df0bfd50b45572c582e22f4ae24f5d4
Signed-off-by: Edward Liaw <edliaw@google.com>
-rw-r--r-- | tools/testing/selftests/capabilities/test_execve.c | 2 | ||||
-rw-r--r-- | tools/testing/selftests/exec/execveat.c | 2 | ||||
-rwxr-xr-x | tools/testing/selftests/exec/execveat.sh | 33 | ||||
-rw-r--r-- | tools/testing/selftests/filesystems/binderfs/binderfs_test.c | 10 | ||||
-rwxr-xr-x | tools/testing/selftests/futex/functional/run.sh | 78 | ||||
-rw-r--r-- | tools/testing/selftests/kcmp/kcmp_test.c | 2 | ||||
-rw-r--r-- | tools/testing/selftests/kvm/aarch64/pvm_wipe_mem.c | 174 | ||||
-rw-r--r-- | tools/testing/selftests/net/psock_tpacket.c | 32 | ||||
-rw-r--r-- | tools/testing/selftests/rtc/rtctest.c | 2 | ||||
-rw-r--r-- | tools/testing/selftests/seccomp/seccomp_bpf.c | 141 | ||||
-rw-r--r-- | tools/testing/selftests/timers/valid-adjtimex.c | 3 | ||||
-rw-r--r-- | tools/testing/selftests/vDSO/parse_vdso.c | 7 | ||||
-rwxr-xr-x | tools/testing/selftests/vm/run_vmtests.sh | 298 | ||||
-rw-r--r-- | tools/testing/selftests/vm/userfaultfd.c | 86 | ||||
-rw-r--r-- | tools/testing/selftests/x86/test_FISTTP.c | 18 |
15 files changed, 693 insertions, 195 deletions
diff --git a/tools/testing/selftests/capabilities/test_execve.c b/tools/testing/selftests/capabilities/test_execve.c index df0ef02b4036..08667a0159c7 100644 --- a/tools/testing/selftests/capabilities/test_execve.c +++ b/tools/testing/selftests/capabilities/test_execve.c @@ -91,7 +91,7 @@ static bool create_and_enter_ns(uid_t inner_uid) uid_t outer_uid; gid_t outer_gid; int i; - bool have_outer_privilege; + bool have_outer_privilege = false; outer_uid = getuid(); outer_gid = getgid(); diff --git a/tools/testing/selftests/exec/execveat.c b/tools/testing/selftests/exec/execveat.c index 67bf7254a48f..ecc974e75a9b 100644 --- a/tools/testing/selftests/exec/execveat.c +++ b/tools/testing/selftests/exec/execveat.c @@ -379,7 +379,7 @@ static int run_tests(void) static void prerequisites(void) { int fd; - const char *script = "#!/bin/sh\nexit $*\n"; + const char *script = "#!/system/bin/sh\nexit $*\n"; /* Create ephemeral copies of files */ exe_cp("execveat", "execveat.ephemeral"); diff --git a/tools/testing/selftests/exec/execveat.sh b/tools/testing/selftests/exec/execveat.sh new file mode 100755 index 000000000000..dc049eaef690 --- /dev/null +++ b/tools/testing/selftests/exec/execveat.sh @@ -0,0 +1,33 @@ +#!/system/bin/sh + +# +# Copyright (C) 2017 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# These are normally created as part of the kselftest build but for VTS +# it is probably easier to use a wrapper script that creates them +# at runtime, on target, as part of the test. + +DIR=$(dirname "$0") +cd $DIR && \ +mkdir -p subdir && \ +echo '#!/system/bin/sh' > script && \ +echo 'exit $*' >> script && \ +chmod +x script && \ +touch Makefile && \ +ln -s -f execveat execveat.symlink && \ +cp execveat execveat.denatured && \ +chmod -x execveat.denatured && \ +./execveat diff --git a/tools/testing/selftests/filesystems/binderfs/binderfs_test.c b/tools/testing/selftests/filesystems/binderfs/binderfs_test.c index 5f362c0fd890..047b228fcb91 100644 --- a/tools/testing/selftests/filesystems/binderfs/binderfs_test.c +++ b/tools/testing/selftests/filesystems/binderfs/binderfs_test.c @@ -291,6 +291,11 @@ static int write_id_mapping(enum idmap_type type, pid_t pid, const char *buf, return 0; } +static bool has_userns() +{ + return (access("/proc/self/ns/user", F_OK) == 0); +} + static void change_userns(struct __test_metadata *_metadata, int syncfds[2]) { int ret; @@ -378,6 +383,9 @@ static void *binder_version_thread(void *data) */ TEST(binderfs_stress) { + if (!has_userns()) + SKIP(return, "%s: user namespace not supported\n", __func__); + int fds[1000]; int syncfds[2]; pid_t pid; @@ -502,6 +510,8 @@ TEST(binderfs_test_privileged) TEST(binderfs_test_unprivileged) { + if (!has_userns()) + SKIP(return, "%s: user namespace not supported\n", __func__); int ret; int syncfds[2]; pid_t pid; diff --git a/tools/testing/selftests/futex/functional/run.sh b/tools/testing/selftests/futex/functional/run.sh index 5ccd599da6c3..f7bd16078707 100755 --- a/tools/testing/selftests/futex/functional/run.sh +++ b/tools/testing/selftests/futex/functional/run.sh @@ -18,6 +18,16 @@ # ############################################################################### +run_test() +{ + $@ + ret=$? + if [ $ret -ne 0 ] && [ $ret -ne 4 ]; then # KSFT_SKIP=4 + echo "Failed with $ret" + rc=1 + fi +} + # Test for a color capable console if [ -z "$USE_COLOR" ]; then tput setf 7 || tput setaf 7 @@ -34,51 +44,57 @@ fi echo # requeue pi testing # without timeouts -./futex_requeue_pi $COLOR -./futex_requeue_pi $COLOR -b -./futex_requeue_pi $COLOR -b -l -./futex_requeue_pi $COLOR -b -o -./futex_requeue_pi $COLOR -l -./futex_requeue_pi $COLOR -o +run_test ./futex_requeue_pi $COLOR +run_test ./futex_requeue_pi $COLOR -b +run_test ./futex_requeue_pi $COLOR -b -l +run_test ./futex_requeue_pi $COLOR -b -o +run_test ./futex_requeue_pi $COLOR -l +run_test ./futex_requeue_pi $COLOR -o # with timeouts -./futex_requeue_pi $COLOR -b -l -t 5000 -./futex_requeue_pi $COLOR -l -t 5000 -./futex_requeue_pi $COLOR -b -l -t 500000 -./futex_requeue_pi $COLOR -l -t 500000 -./futex_requeue_pi $COLOR -b -t 5000 -./futex_requeue_pi $COLOR -t 5000 -./futex_requeue_pi $COLOR -b -t 500000 -./futex_requeue_pi $COLOR -t 500000 -./futex_requeue_pi $COLOR -b -o -t 5000 -./futex_requeue_pi $COLOR -l -t 5000 -./futex_requeue_pi $COLOR -b -o -t 500000 -./futex_requeue_pi $COLOR -l -t 500000 +run_test ./futex_requeue_pi $COLOR -b -l -t 5000 +run_test ./futex_requeue_pi $COLOR -l -t 5000 +run_test ./futex_requeue_pi $COLOR -b -l -t 500000 +run_test ./futex_requeue_pi $COLOR -l -t 500000 +run_test ./futex_requeue_pi $COLOR -b -t 5000 +run_test ./futex_requeue_pi $COLOR -t 5000 +run_test ./futex_requeue_pi $COLOR -b -t 500000 +run_test ./futex_requeue_pi $COLOR -t 500000 +run_test ./futex_requeue_pi $COLOR -b -o -t 5000 +run_test ./futex_requeue_pi $COLOR -l -t 5000 +run_test ./futex_requeue_pi $COLOR -b -o -t 500000 +run_test ./futex_requeue_pi $COLOR -l -t 500000 # with long timeout -./futex_requeue_pi $COLOR -b -l -t 2000000000 -./futex_requeue_pi $COLOR -l -t 2000000000 +run_test ./futex_requeue_pi $COLOR -b -l -t 2000000000 +run_test ./futex_requeue_pi $COLOR -l -t 2000000000 echo -./futex_requeue_pi_mismatched_ops $COLOR +run_test ./futex_requeue_pi_mismatched_ops $COLOR echo -./futex_requeue_pi_signal_restart $COLOR +run_test ./futex_requeue_pi_signal_restart $COLOR echo -./futex_wait_timeout $COLOR +run_test ./futex_wait_timeout $COLOR echo -./futex_wait_wouldblock $COLOR +run_test ./futex_wait_wouldblock $COLOR echo -./futex_wait_uninitialized_heap $COLOR -./futex_wait_private_mapped_file $COLOR +run_test ./futex_wait_uninitialized_heap $COLOR +run_test ./futex_wait_private_mapped_file $COLOR -echo -./futex_wait $COLOR +# b/234151152 +# Disable because system v shared memory not available +#echo +#run_test ./futex_wait $COLOR echo -./futex_requeue $COLOR +run_test ./futex_requeue $COLOR -echo -./futex_waitv $COLOR +# b/234151152 +# Disable because system v shared memory not available +#echo +#run_test ./futex_waitv $COLOR + +exit $rc diff --git a/tools/testing/selftests/kcmp/kcmp_test.c b/tools/testing/selftests/kcmp/kcmp_test.c index 25110c7c0b3e..d7a8e321bb16 100644 --- a/tools/testing/selftests/kcmp/kcmp_test.c +++ b/tools/testing/selftests/kcmp/kcmp_test.c @@ -91,7 +91,7 @@ int main(int argc, char **argv) ksft_print_header(); ksft_set_plan(3); - fd2 = open(kpath, O_RDWR, 0644); + fd2 = open(kpath, O_RDWR); if (fd2 < 0) { perror("Can't open file"); ksft_exit_fail(); diff --git a/tools/testing/selftests/kvm/aarch64/pvm_wipe_mem.c b/tools/testing/selftests/kvm/aarch64/pvm_wipe_mem.c new file mode 100644 index 000000000000..4af8ca3c4bad --- /dev/null +++ b/tools/testing/selftests/kvm/aarch64/pvm_wipe_mem.c @@ -0,0 +1,174 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Test checking that memory of protected guests is wiped after teardown. + * + * Copyright (C) 2022, Google LLC. + */ + +#define _GNU_SOURCE + +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <linux/kvm.h> +#include <sys/ioctl.h> +#include <sys/mman.h> + +#include "kselftest.h" + +#define KVM_VM_TYPE_ARM_PROTECTED (1UL << 31) + +#define REG_X(number) (0x6030000000100000ULL + (number) * 2UL) +#define REG_PC 0x6030000000100040ULL + +static void set_one_reg(int vcpufd, uint64_t reg_id, uint64_t val) +{ + uint64_t reg_data; + struct kvm_one_reg reg; + int ret; + + reg.addr = (__u64) ®_data; + reg_data = val; + reg.id = reg_id; + + ret = ioctl(vcpufd, KVM_SET_ONE_REG, ®); + if (ret < 0) + ksft_exit_fail_msg("Failed to set reg: %d\n", ret); +} + +static int get_kvm(void) +{ + size_t run_size; + int kvm, ret; + + kvm = open("/dev/kvm", O_RDWR | O_CLOEXEC); + if (kvm < 0) + ksft_exit_skip("KVM not supported\n"); + + ret = ioctl(kvm, KVM_GET_API_VERSION, NULL); + if (ret != 12) + ksft_exit_fail_msg("KVM_GET_API_VERSION %d, expected 12", ret); + + run_size = ioctl(kvm, KVM_GET_VCPU_MMAP_SIZE, NULL); + if (run_size < sizeof(struct kvm_run)) + ksft_exit_fail_msg("KVM_GET_VCPU_MMAP_SIZE unexpectedly small\n"); + + return kvm; +} + +static int create_protected_vm(int kvm) +{ + int vmfd = ioctl(kvm, KVM_CREATE_VM, KVM_VM_TYPE_ARM_PROTECTED); + + if (vmfd < 0) + ksft_exit_skip("Protected guests not supported: %d\n", vmfd); + + return vmfd; +} + +static int create_vcpu(int vmfd, struct kvm_run **run) +{ + struct kvm_vcpu_init vcpu_init; + int vcpufd, ret; + + ret = ioctl(vmfd, KVM_ARM_PREFERRED_TARGET, &vcpu_init); + if (ret) + ksft_exit_fail_msg("Failed to set kvm_vcpu_init %d\n", ret); + + vcpufd = ioctl(vmfd, KVM_CREATE_VCPU, (unsigned long)0); + if (vcpufd < 0) + ksft_exit_fail_msg("Failed to create VCPU: %d\n", vcpufd); + + *run = mmap(NULL, sizeof(**run), PROT_READ | PROT_WRITE, MAP_SHARED, vcpufd, 0); + if (!run) + ksft_exit_fail_msg("Failed to mmap vcpu_run struct\n"); + + ret = ioctl(vcpufd, KVM_ARM_VCPU_INIT, &vcpu_init); + if (ret) + ksft_exit_fail_msg("Failed to initialize VCPU %d\n", ret); + + return vcpufd; +} + +static void teardown(int kvm, int vmfd, int vcpufd, struct kvm_run *run) +{ + int ret = munmap(run, sizeof(*run)); + + if (ret) + ksft_exit_fail_msg("Failed to unmap vCPU run: %d\n", ret); + + ret = close(vcpufd); + if (ret) + ksft_exit_fail_msg("Failed to destroy VCPU: %d\n", ret); + + ret = close(vmfd); + if (ret) + ksft_exit_fail_msg("Failed to destroy VM: %d\n", ret); + + ret = close(kvm); + if (ret) + ksft_exit_fail_msg("Failed to close KVM fd: %d\n", ret); +} + +int main(void) +{ + struct kvm_userspace_memory_region region; + long page_size = sysconf(_SC_PAGESIZE); + int ret, kvm, vmfd, vcpufd; + uint32_t guest_code[2]; + struct kvm_run *run; + uint8_t *guest_mem; + size_t run_size; + + kvm = get_kvm(); + vmfd = create_protected_vm(kvm); + vcpufd = create_vcpu(vmfd, &run); + + /* Create a one-page memslot for the guest */ + guest_mem = mmap(NULL, page_size, PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_ANONYMOUS, -1, 0); + if (guest_mem == MAP_FAILED) + ksft_exit_fail_msg("Failed to mmap guest memory\n"); + region = (struct kvm_userspace_memory_region) { + .slot = 0, + .guest_phys_addr = 1UL << 30, + .memory_size = page_size, + .userspace_addr = (uint64_t)guest_mem, + }; + + /* Copy some code in guest memory. */ + guest_code[0] = 0xf9400001; /* 1: ldr x1, [x0] */ + guest_code[1] = 0x17ffffff; /* b 1b */ + memcpy(guest_mem, guest_code, sizeof(guest_code)); + ret = ioctl(vmfd, KVM_SET_USER_MEMORY_REGION, ®ion); + if (ret) + ksft_exit_fail_msg("Failed to set memory region: %d\n", ret); + + /* + * Get the VCPU to run one instruction, to be sure the page containing + * the code has been faulted in. + */ + set_one_reg(vcpufd, REG_PC, region.guest_phys_addr); + set_one_reg(vcpufd, REG_X(0), region.guest_phys_addr + region.memory_size); + ret = ioctl(vcpufd, KVM_RUN, NULL); + if (ret) + ksft_exit_fail_msg("Failed to run vcpu: %d\n", ret); + if (run->exit_reason != KVM_EXIT_MMIO) + ksft_exit_fail_msg("Unexpected KVM exit reason: %u\n", run->exit_reason); + + /* + * Tear the guest down, and check that the donated memory has been + * wiped by the hypervisor. + */ + teardown(kvm, vmfd, vcpufd, run); + if (!memcmp(guest_mem, guest_code, sizeof(guest_code))) + ksft_exit_fail_msg("Protected guest memory has not been poisoned\n"); + + ksft_exit_pass(); +} diff --git a/tools/testing/selftests/net/psock_tpacket.c b/tools/testing/selftests/net/psock_tpacket.c index 404a2ce759ab..9696c9e484d5 100644 --- a/tools/testing/selftests/net/psock_tpacket.c +++ b/tools/testing/selftests/net/psock_tpacket.c @@ -28,12 +28,15 @@ #include <sys/stat.h> #include <sys/socket.h> #include <sys/mman.h> +#include <sys/utsname.h> #include <linux/if_packet.h> #include <linux/filter.h> #include <ctype.h> #include <fcntl.h> #include <unistd.h> +#ifndef __ANDROID__ #include <bits/wordsize.h> +#endif #include <net/ethernet.h> #include <netinet/ip.h> #include <arpa/inet.h> @@ -363,6 +366,7 @@ static inline void *get_next_frame(struct ring *ring, int n) return f0 + (n * ring->req3.tp_frame_size); default: bug_on(1); + return NULL; } } @@ -829,9 +833,34 @@ static int test_tpacket(int version, int type) return 0; } +void get_kernel_version(int *version, int *patchlevel) +{ + int ret, sublevel; + struct utsname utsname; + + ret = uname(&utsname); + if (ret) { + perror("uname"); + exit(1); + } + + ret = sscanf(utsname.release, "%d.%d.%d", version, patchlevel, + &sublevel); + if (ret < 0) { + perror("sscanf"); + exit(1); + } else if (ret != 3) { + printf("Malformed kernel version %s\n", &utsname.release); + exit(1); + } +} + int main(void) { int ret = 0; + int version, patchlevel; + + get_kernel_version(&version, &patchlevel); ret |= test_tpacket(TPACKET_V1, PACKET_RX_RING); ret |= test_tpacket(TPACKET_V1, PACKET_TX_RING); @@ -840,7 +869,8 @@ int main(void) ret |= test_tpacket(TPACKET_V2, PACKET_TX_RING); ret |= test_tpacket(TPACKET_V3, PACKET_RX_RING); - ret |= test_tpacket(TPACKET_V3, PACKET_TX_RING); + if (version > 4 || (version == 4 && patchlevel >= 11)) + ret |= test_tpacket(TPACKET_V3, PACKET_TX_RING); if (ret) return 1; diff --git a/tools/testing/selftests/rtc/rtctest.c b/tools/testing/selftests/rtc/rtctest.c index 2b9d929a24ed..0d2674b43cad 100644 --- a/tools/testing/selftests/rtc/rtctest.c +++ b/tools/testing/selftests/rtc/rtctest.c @@ -115,6 +115,7 @@ TEST_F_TIMEOUT(rtc, date_read_loop, READ_LOOP_DURATION_SEC + 2) { TH_LOG("Performed %ld RTC time reads.", iter_count); } +#ifndef __ANDROID__ // b/31578457 TEST_F_TIMEOUT(rtc, uie_read, NUM_UIE + 2) { int i, rc, irq = 0; unsigned long data; @@ -378,6 +379,7 @@ TEST_F_TIMEOUT(rtc, alarm_wkalm_set_minute, 65) { new = timegm((struct tm *)&tm); ASSERT_EQ(new, secs); } +#endif static void __attribute__((constructor)) __constructor_order_last(void) diff --git a/tools/testing/selftests/seccomp/seccomp_bpf.c b/tools/testing/selftests/seccomp/seccomp_bpf.c index 4ae6c8991307..110ca8bf8e2b 100644 --- a/tools/testing/selftests/seccomp/seccomp_bpf.c +++ b/tools/testing/selftests/seccomp/seccomp_bpf.c @@ -13,12 +13,14 @@ * we need to use the kernel's siginfo.h file and trick glibc * into accepting it. */ +#if defined(__GLIBC_PREREQ) #if !__GLIBC_PREREQ(2, 26) # include <asm/siginfo.h> # define __have_siginfo_t 1 # define __have_sigval_t 1 # define __have_sigevent_t 1 #endif +#endif #include <errno.h> #include <linux/filter.h> @@ -855,6 +857,14 @@ void kill_thread_or_group(struct __test_metadata *_metadata, exit(42); } +/* + * b/147676645 + * SECCOMP_FILTER_FLAG_TSYNC_ESRCH not compatible < 5.7 + * SECCOMP_FILTER_FLAG_NEW_LISTENER not compatible < 5.0 + * SECCOMP_FILTER_FLAG_SPEC_ALLOW not compatible < 4.17 + * SECCOMP_FILTER_FLAG_LOG not compatible < 4.14 + */ +#ifndef __ANDROID__ TEST(KILL_thread) { int status; @@ -873,6 +883,7 @@ TEST(KILL_thread) ASSERT_TRUE(WIFEXITED(status)); ASSERT_EQ(42, WEXITSTATUS(status)); } +#endif TEST(KILL_process) { @@ -2047,8 +2058,15 @@ void tracer_ptrace(struct __test_metadata *_metadata, pid_t tracee, /* Make sure we got an appropriate message. */ ret = ptrace(PTRACE_GETEVENTMSG, tracee, NULL, &msg); EXPECT_EQ(0, ret); - EXPECT_EQ(entry ? PTRACE_EVENTMSG_SYSCALL_ENTRY - : PTRACE_EVENTMSG_SYSCALL_EXIT, msg); + + /* + * TODO: b/33027081 + * PTRACE_EVENTMSG_SYSCALL_ENTRY and PTRACE_EVENTMSG_SYSCALL_EXIT not + * compatible < 5.3 (see 201766a) + * + * EXPECT_EQ(entry ? PTRACE_EVENTMSG_SYSCALL_ENTRY + * : PTRACE_EVENTMSG_SYSCALL_EXIT, msg); + */ /* * Some architectures only support setting return values during @@ -2374,6 +2392,14 @@ TEST(seccomp_syscall_mode_lock) } /* + * b/147676645 + * SECCOMP_FILTER_FLAG_TSYNC_ESRCH not compatible < 5.7 + * SECCOMP_FILTER_FLAG_NEW_LISTENER not compatible < 5.0 + * SECCOMP_FILTER_FLAG_SPEC_ALLOW not compatible < 4.17 + * SECCOMP_FILTER_FLAG_LOG not compatible < 4.14 + */ +#ifndef __ANDROID__ +/* * Test detection of known and unknown filter flags. Userspace needs to be able * to check if a filter flag is supported by the current kernel and a good way * of doing that is by attempting to enter filter mode, with the flag bit in @@ -2463,6 +2489,7 @@ TEST(detect_seccomp_filter_flags) flag); } } +#endif TEST(TSYNC_first) { @@ -2844,6 +2871,11 @@ TEST_F(TSYNC, two_siblings_with_one_divergence) EXPECT_EQ(SIBLING_EXIT_UNKILLED, (long)status); } +/* + * b/147676645 + * SECCOMP_FILTER_FLAG_TSYNC_ESRCH not compatible < 5.7 + */ +#ifndef __ANDROID__ TEST_F(TSYNC, two_siblings_with_one_divergence_no_tid_in_err) { long ret, flags; @@ -2892,6 +2924,7 @@ TEST_F(TSYNC, two_siblings_with_one_divergence_no_tid_in_err) PTHREAD_JOIN(self->sibling[1].tid, &status); EXPECT_EQ(SIBLING_EXIT_UNKILLED, (long)status); } +#endif TEST_F(TSYNC, two_siblings_not_under_filter) { @@ -3021,6 +3054,7 @@ TEST(syscall_restart) }; #if defined(__arm__) struct utsname utsbuf; + int arm_version; #endif ASSERT_EQ(0, pipe(pipefd)); @@ -3136,12 +3170,12 @@ TEST(syscall_restart) ret = get_syscall(_metadata, child_pid); #if defined(__arm__) /* - * FIXME: * - native ARM registers do NOT expose true syscall. * - compat ARM registers on ARM64 DO expose true syscall. */ ASSERT_EQ(0, uname(&utsbuf)); - if (strncmp(utsbuf.machine, "arm", 3) == 0) { + if (sscanf(utsbuf.machine, "armv%d", &arm_version) == 1 && + arm_version < 8) { EXPECT_EQ(__NR_nanosleep, ret); } else #endif @@ -3252,6 +3286,11 @@ TEST(get_action_avail) EXPECT_EQ(errno, EOPNOTSUPP); } +/* + * b/147676645 + * PTRACE_SECCOMP_GET_METADATA not compatible < 4.16 + */ +#ifndef __ANDROID__ TEST(get_metadata) { pid_t pid; @@ -3320,6 +3359,7 @@ TEST(get_metadata) skip: ASSERT_EQ(0, kill(pid, SIGKILL)); } +#endif static int user_notif_syscall(int nr, unsigned int flags) { @@ -3340,6 +3380,12 @@ static int user_notif_syscall(int nr, unsigned int flags) } #define USER_NOTIF_MAGIC INT_MAX + +/* + * b/147676645 + * SECCOMP_FILTER_FLAG_NEW_LISTENER not compatible < 5.0 + */ +#ifndef __ANDROID__ TEST(user_notification_basic) { pid_t pid; @@ -3445,7 +3491,13 @@ TEST(user_notification_basic) EXPECT_EQ(true, WIFEXITED(status)); EXPECT_EQ(0, WEXITSTATUS(status)); } +#endif +/* + * b/147676645 + * SECCOMP_FILTER_FLAG_NEW_LISTENER not compatible < 5.0 + */ +#ifndef __ANDROID__ TEST(user_notification_with_tsync) { int ret; @@ -3468,7 +3520,13 @@ TEST(user_notification_with_tsync) close(ret); ASSERT_LE(0, ret); } +#endif +/* + * b/147676645 + * SECCOMP_FILTER_FLAG_NEW_LISTENER not compatible < 5.0 + */ +#ifndef __ANDROID__ TEST(user_notification_kill_in_middle) { pid_t pid; @@ -3511,6 +3569,7 @@ TEST(user_notification_kill_in_middle) EXPECT_EQ(ret, -1); EXPECT_EQ(errno, ENOENT); } +#endif static int handled = -1; @@ -3520,6 +3579,11 @@ static void signal_handler(int signal) perror("write from signal"); } +/* + * b/147676645 + * SECCOMP_FILTER_FLAG_NEW_LISTENER not compatible < 5.0 + */ +#ifndef __ANDROID__ TEST(user_notification_signal) { pid_t pid; @@ -3594,7 +3658,13 @@ TEST(user_notification_signal) EXPECT_EQ(true, WIFEXITED(status)); EXPECT_EQ(0, WEXITSTATUS(status)); } +#endif +/* + * b/147676645 + * SECCOMP_FILTER_FLAG_NEW_LISTENER not compatible < 5.0 + */ +#ifndef __ANDROID__ TEST(user_notification_closed_listener) { pid_t pid; @@ -3627,8 +3697,16 @@ TEST(user_notification_closed_listener) EXPECT_EQ(true, WIFEXITED(status)); EXPECT_EQ(0, WEXITSTATUS(status)); } +#endif /* + * b/147676645 + * SECCOMP_FILTER_FLAG_NEW_LISTENER not compatible < 5.0 + * unshare(CLONE_NEWUSER) returns EINVAL with Android + * unshare(CLONE_NEWPID) returns EINVAL with Android + */ +#ifndef __ANDROID__ +/* * Check that a pid in a child namespace still shows up as valid in ours. */ TEST(user_notification_child_pid_ns) @@ -3667,8 +3745,15 @@ TEST(user_notification_child_pid_ns) EXPECT_EQ(0, WEXITSTATUS(status)); close(listener); } +#endif /* + * b/147676645 + * SECCOMP_FILTER_FLAG_NEW_LISTENER not compatible < 5.0 + * unshare(CLONE_NEWPID) returns EINVAL with Android + */ +#ifndef __ANDROID__ +/* * Check that a pid in a sibling (i.e. unrelated) namespace shows up as 0, i.e. * invalid. */ @@ -3741,7 +3826,14 @@ TEST(user_notification_sibling_pid_ns) EXPECT_EQ(true, WIFEXITED(status)); EXPECT_EQ(0, WEXITSTATUS(status)); } +#endif +/* + * b/147676645 + * SECCOMP_FILTER_FLAG_NEW_LISTENER not compatible < 5.0 + * unshare(CLONE_NEWUSER) returns EINVAL with Android + */ +#ifndef __ANDROID__ TEST(user_notification_fault_recv) { pid_t pid; @@ -3782,7 +3874,13 @@ TEST(user_notification_fault_recv) EXPECT_EQ(true, WIFEXITED(status)); EXPECT_EQ(0, WEXITSTATUS(status)); } +#endif +/* + * b/147676645 + * SECCOMP_GET_NOTIF_SIZES not compatible < 5.0 + */ +#ifndef __ANDROID__ TEST(seccomp_get_notif_sizes) { struct seccomp_notif_sizes sizes; @@ -3791,7 +3889,13 @@ TEST(seccomp_get_notif_sizes) EXPECT_EQ(sizes.seccomp_notif, sizeof(struct seccomp_notif)); EXPECT_EQ(sizes.seccomp_notif_resp, sizeof(struct seccomp_notif_resp)); } +#endif +/* + * b/147676645 + * SECCOMP_FILTER_FLAG_NEW_LISTENER not compatible < 5.0 + */ +#ifndef __ANDROID__ TEST(user_notification_continue) { pid_t pid; @@ -3877,7 +3981,13 @@ skip: } } } +#endif +/* + * b/147676645 + * SECCOMP_FILTER_FLAG_NEW_LISTENER not compatible < 5.0 + */ +#ifndef __ANDROID__ TEST(user_notification_filter_empty) { pid_t pid; @@ -3926,7 +4036,13 @@ TEST(user_notification_filter_empty) EXPECT_GT(poll(&pollfd, 1, 2000), 0); EXPECT_GT((pollfd.revents & POLLHUP) ?: 0, 0); } +#endif +/* + * b/147676645 + * SECCOMP_FILTER_FLAG_NEW_LISTENER not compatible < 5.0 + */ +#ifndef __ANDROID__ static void *do_thread(void *data) { return NULL; @@ -4012,7 +4128,15 @@ TEST(user_notification_filter_empty_threaded) EXPECT_GT(poll(&pollfd, 1, 2000), 0); EXPECT_GT((pollfd.revents & POLLHUP) ?: 0, 0); } +#endif +/* + * b/147676645 + * SECCOMP_ADDED_FLAG_SEND not compatible < 5.14 + * SECCOMP_IOCTL_NOTIF_ADDFD not comptible < 5.9 + * SECCOMP_FILTER_FLAG_NEW_LISTENER not compatible < 5.0 + */ +#ifndef __ANDROID__ TEST(user_notification_addfd) { pid_t pid; @@ -4170,7 +4294,15 @@ TEST(user_notification_addfd) close(memfd); } +#endif +/* + * b/147676645 + * SECCOMP_ADDED_FLAG_SEND not compatible < 5.14 + * SECCOMP_IOCTL_NOTIF_ADDFD not comptible < 5.9 + * SECCOMP_FILTER_FLAG_NEW_LISTENER not compatible < 5.0 + */ +#ifndef __ANDROID__ TEST(user_notification_addfd_rlimit) { pid_t pid; @@ -4240,6 +4372,7 @@ TEST(user_notification_addfd_rlimit) close(memfd); } +#endif /* Make sure PTRACE_O_SUSPEND_SECCOMP requires CAP_SYS_ADMIN. */ FIXTURE(O_SUSPEND_SECCOMP) { diff --git a/tools/testing/selftests/timers/valid-adjtimex.c b/tools/testing/selftests/timers/valid-adjtimex.c index 48b9a803235a..ecac8fadd939 100644 --- a/tools/testing/selftests/timers/valid-adjtimex.c +++ b/tools/testing/selftests/timers/valid-adjtimex.c @@ -39,12 +39,13 @@ #define ADJ_SETOFFSET 0x0100 +#ifndef __ANDROID__ #include <sys/syscall.h> int clock_adjtime(clockid_t id, struct timex *tx) { return syscall(__NR_clock_adjtime, id, tx); } - +#endif /* clear NTP time_status & time_state */ int clear_time_state(void) diff --git a/tools/testing/selftests/vDSO/parse_vdso.c b/tools/testing/selftests/vDSO/parse_vdso.c index 413f75620a35..945d4e63296a 100644 --- a/tools/testing/selftests/vDSO/parse_vdso.c +++ b/tools/testing/selftests/vDSO/parse_vdso.c @@ -56,13 +56,16 @@ static struct vdso_info } vdso_info; /* Straight from the ELF specification. */ -static unsigned long elf_hash(const unsigned char *name) +static unsigned long elf_hash(const char *s_name) { unsigned long h = 0, g; + const unsigned char *name = (const unsigned char *)s_name; + while (*name) { h = (h << 4) + *name++; - if (g = h & 0xf0000000) + g = h & 0xf0000000; + if (g) h ^= g >> 24; h &= ~g; } diff --git a/tools/testing/selftests/vm/run_vmtests.sh b/tools/testing/selftests/vm/run_vmtests.sh index e780e76c26b8..b936dfe44822 100755 --- a/tools/testing/selftests/vm/run_vmtests.sh +++ b/tools/testing/selftests/vm/run_vmtests.sh @@ -8,62 +8,62 @@ ksft_skip=4 mnt=./huge exitcode=0 -#get huge pagesize and freepages from /proc/meminfo -while read -r name size unit; do - if [ "$name" = "HugePages_Free:" ]; then - freepgs="$size" - fi - if [ "$name" = "Hugepagesize:" ]; then - hpgsize_KB="$size" - fi -done < /proc/meminfo - -# Simple hugetlbfs tests have a hardcoded minimum requirement of -# huge pages totaling 256MB (262144KB) in size. The userfaultfd -# hugetlb test requires a minimum of 2 * nr_cpus huge pages. Take -# both of these requirements into account and attempt to increase -# number of huge pages available. -nr_cpus=$(nproc) -hpgsize_MB=$((hpgsize_KB / 1024)) -half_ufd_size_MB=$((((nr_cpus * hpgsize_MB + 127) / 128) * 128)) -needmem_KB=$((half_ufd_size_MB * 2 * 1024)) - -#set proper nr_hugepages -if [ -n "$freepgs" ] && [ -n "$hpgsize_KB" ]; then - nr_hugepgs=$(cat /proc/sys/vm/nr_hugepages) - needpgs=$((needmem_KB / hpgsize_KB)) - tries=2 - while [ "$tries" -gt 0 ] && [ "$freepgs" -lt "$needpgs" ]; do - lackpgs=$((needpgs - freepgs)) - echo 3 > /proc/sys/vm/drop_caches - if ! echo $((lackpgs + nr_hugepgs)) > /proc/sys/vm/nr_hugepages; then - echo "Please run this test as root" - exit $ksft_skip - fi - while read -r name size unit; do - if [ "$name" = "HugePages_Free:" ]; then - freepgs=$size - fi - done < /proc/meminfo - tries=$((tries - 1)) - done - if [ "$freepgs" -lt "$needpgs" ]; then - printf "Not enough huge pages available (%d < %d)\n" \ - "$freepgs" "$needpgs" - exit 1 - fi -else - echo "no hugetlbfs support in kernel?" - exit 1 -fi - -#filter 64bit architectures -ARCH64STR="arm64 ia64 mips64 parisc64 ppc64 ppc64le riscv64 s390x sh64 sparc64 x86_64" -if [ -z "$ARCH" ]; then - ARCH=$(uname -m 2>/dev/null | sed -e 's/aarch64.*/arm64/') -fi -VADDR64=0 -echo "$ARCH64STR" | grep "$ARCH" && VADDR64=1 +##get huge pagesize and freepages from /proc/meminfo +#while read -r name size unit; do +# if [ "$name" = "HugePages_Free:" ]; then +# freepgs="$size" +# fi +# if [ "$name" = "Hugepagesize:" ]; then +# hpgsize_KB="$size" +# fi +#done < /proc/meminfo +# +## Simple hugetlbfs tests have a hardcoded minimum requirement of +## huge pages totaling 256MB (262144KB) in size. The userfaultfd +## hugetlb test requires a minimum of 2 * nr_cpus huge pages. Take +## both of these requirements into account and attempt to increase +## number of huge pages available. +#nr_cpus=$(nproc) +#hpgsize_MB=$((hpgsize_KB / 1024)) +#half_ufd_size_MB=$((((nr_cpus * hpgsize_MB + 127) / 128) * 128)) +#needmem_KB=$((half_ufd_size_MB * 2 * 1024)) +# +##set proper nr_hugepages +#if [ -n "$freepgs" ] && [ -n "$hpgsize_KB" ]; then +# nr_hugepgs=$(cat /proc/sys/vm/nr_hugepages) +# needpgs=$((needmem_KB / hpgsize_KB)) +# tries=2 +# while [ "$tries" -gt 0 ] && [ "$freepgs" -lt "$needpgs" ]; do +# lackpgs=$((needpgs - freepgs)) +# echo 3 > /proc/sys/vm/drop_caches +# if ! echo $((lackpgs + nr_hugepgs)) > /proc/sys/vm/nr_hugepages; then +# echo "Please run this test as root" +# exit $ksft_skip +# fi +# while read -r name size unit; do +# if [ "$name" = "HugePages_Free:" ]; then +# freepgs=$size +# fi +# done < /proc/meminfo +# tries=$((tries - 1)) +# done +# if [ "$freepgs" -lt "$needpgs" ]; then +# printf "Not enough huge pages available (%d < %d)\n" \ +# "$freepgs" "$needpgs" +# exit 1 +# fi +#else +# echo "no hugetlbfs support in kernel?" +# exit 1 +#fi +# +##filter 64bit architectures +#ARCH64STR="arm64 ia64 mips64 parisc64 ppc64 ppc64le riscv64 s390x sh64 sparc64 x86_64" +#if [ -z "$ARCH" ]; then +# ARCH=$(uname -m 2>/dev/null | sed -e 's/aarch64.*/arm64/') +#fi +#VADDR64=0 +#echo "$ARCH64STR" | grep "$ARCH" && VADDR64=1 # Usage: run_test [test binary] [arbitrary test arguments...] run_test() { @@ -84,63 +84,63 @@ run_test() { fi } -mkdir "$mnt" -mount -t hugetlbfs none "$mnt" - -run_test ./hugepage-mmap - -shmmax=$(cat /proc/sys/kernel/shmmax) -shmall=$(cat /proc/sys/kernel/shmall) -echo 268435456 > /proc/sys/kernel/shmmax -echo 4194304 > /proc/sys/kernel/shmall -run_test ./hugepage-shm -echo "$shmmax" > /proc/sys/kernel/shmmax -echo "$shmall" > /proc/sys/kernel/shmall - -run_test ./map_hugetlb - -run_test ./hugepage-mremap "$mnt"/huge_mremap -rm -f "$mnt"/huge_mremap - -run_test ./hugepage-vmemmap - -run_test ./hugetlb-madvise "$mnt"/madvise-test -rm -f "$mnt"/madvise-test - -echo "NOTE: The above hugetlb tests provide minimal coverage. Use" -echo " https://github.com/libhugetlbfs/libhugetlbfs.git for" -echo " hugetlb regression testing." - -run_test ./map_fixed_noreplace - -# get_user_pages_fast() benchmark -run_test ./gup_test -u -# pin_user_pages_fast() benchmark -run_test ./gup_test -a -# Dump pages 0, 19, and 4096, using pin_user_pages: -run_test ./gup_test -ct -F 0x1 0 19 0x1000 - -uffd_mods=("" ":dev") -for mod in "${uffd_mods[@]}"; do - run_test ./userfaultfd anon${mod} 20 16 - # Hugetlb tests require source and destination huge pages. Pass in half - # the size ($half_ufd_size_MB), which is used for *each*. - run_test ./userfaultfd hugetlb${mod} "$half_ufd_size_MB" 32 - run_test ./userfaultfd hugetlb_shared${mod} "$half_ufd_size_MB" 32 "$mnt"/uffd-test - rm -f "$mnt"/uffd-test - run_test ./userfaultfd shmem${mod} 20 16 -done - -#cleanup -umount "$mnt" -rm -rf "$mnt" -echo "$nr_hugepgs" > /proc/sys/vm/nr_hugepages - -run_test ./compaction_test +#mkdir "$mnt" +#mount -t hugetlbfs none "$mnt" +# +#run_test ./hugepage-mmap +# +#shmmax=$(cat /proc/sys/kernel/shmmax) +#shmall=$(cat /proc/sys/kernel/shmall) +#echo 268435456 > /proc/sys/kernel/shmmax +#echo 4194304 > /proc/sys/kernel/shmall +#run_test ./hugepage-shm +#echo "$shmmax" > /proc/sys/kernel/shmmax +#echo "$shmall" > /proc/sys/kernel/shmall +# +#run_test ./map_hugetlb +# +#run_test ./hugepage-mremap "$mnt"/huge_mremap +#rm -f "$mnt"/huge_mremap +# +#run_test ./hugepage-vmemmap +# +#run_test ./hugetlb-madvise "$mnt"/madvise-test +#rm -f "$mnt"/madvise-test +# +#echo "NOTE: The above hugetlb tests provide minimal coverage. Use" +#echo " https://github.com/libhugetlbfs/libhugetlbfs.git for" +#echo " hugetlb regression testing." +# +#run_test ./map_fixed_noreplace +# +## get_user_pages_fast() benchmark +#run_test ./gup_test -u +## pin_user_pages_fast() benchmark +#run_test ./gup_test -a +## Dump pages 0, 19, and 4096, using pin_user_pages: +#run_test ./gup_test -ct -F 0x1 0 19 0x1000 +# +#uffd_mods=("" ":dev") +#for mod in "${uffd_mods[@]}"; do +# run_test ./userfaultfd anon${mod} 20 16 +# # Hugetlb tests require source and destination huge pages. Pass in half +# # the size ($half_ufd_size_MB), which is used for *each*. +# run_test ./userfaultfd hugetlb${mod} "$half_ufd_size_MB" 32 +# run_test ./userfaultfd hugetlb_shared${mod} "$half_ufd_size_MB" 32 "$mnt"/uffd-test +# rm -f "$mnt"/uffd-test +# run_test ./userfaultfd shmem${mod} 20 16 +#done +# +##cleanup +#umount "$mnt" +#rm -rf "$mnt" +#echo "$nr_hugepgs" > /proc/sys/vm/nr_hugepages +# +#run_test ./compaction_test run_test sudo -u nobody ./on-fault-limit -run_test ./map_populate +#run_test ./map_populate run_test ./mlock-random-test @@ -152,49 +152,49 @@ run_test ./mremap_test run_test ./thuge-gen -if [ $VADDR64 -ne 0 ]; then - run_test ./virtual_address_range - - # virtual address 128TB switch test - run_test ./va_128TBswitch.sh -fi # VADDR64 +#if [ $VADDR64 -ne 0 ]; then +# run_test ./virtual_address_range +# +# # virtual address 128TB switch test +# run_test ./va_128TBswitch.sh +#fi # VADDR64 # vmalloc stability smoke test -run_test ./test_vmalloc.sh smoke +#run_test ./test_vmalloc.sh smoke run_test ./mremap_dontunmap -run_test ./test_hmm.sh smoke - -# MADV_POPULATE_READ and MADV_POPULATE_WRITE tests -run_test ./madv_populate - -run_test ./memfd_secret - -# KSM MADV_MERGEABLE test with 10 identical pages -run_test ./ksm_tests -M -p 10 -# KSM unmerge test -run_test ./ksm_tests -U -# KSM test with 10 zero pages and use_zero_pages = 0 -run_test ./ksm_tests -Z -p 10 -z 0 -# KSM test with 10 zero pages and use_zero_pages = 1 -run_test ./ksm_tests -Z -p 10 -z 1 -# KSM test with 2 NUMA nodes and merge_across_nodes = 1 -run_test ./ksm_tests -N -m 1 -# KSM test with 2 NUMA nodes and merge_across_nodes = 0 -run_test ./ksm_tests -N -m 0 - -# protection_keys tests -if [ -x ./protection_keys_32 ] -then - run_test ./protection_keys_32 -fi - -if [ -x ./protection_keys_64 ] -then - run_test ./protection_keys_64 -fi - -run_test ./soft-dirty +#run_test ./test_hmm.sh smoke + +## MADV_POPULATE_READ and MADV_POPULATE_WRITE tests +#run_test ./madv_populate +# +#run_test ./memfd_secret + +## KSM MADV_MERGEABLE test with 10 identical pages +#run_test ./ksm_tests -M -p 10 +## KSM unmerge test +#run_test ./ksm_tests -U +## KSM test with 10 zero pages and use_zero_pages = 0 +#run_test ./ksm_tests -Z -p 10 -z 0 +## KSM test with 10 zero pages and use_zero_pages = 1 +#run_test ./ksm_tests -Z -p 10 -z 1 +## KSM test with 2 NUMA nodes and merge_across_nodes = 1 +#run_test ./ksm_tests -N -m 1 +## KSM test with 2 NUMA nodes and merge_across_nodes = 0 +#run_test ./ksm_tests -N -m 0 + +## protection_keys tests +#if [ -x ./protection_keys_32 ] +#then +# run_test ./protection_keys_32 +#fi +# +#if [ -x ./protection_keys_64 ] +#then +# run_test ./protection_keys_64 +#fi +# +#run_test ./soft-dirty exit $exitcode diff --git a/tools/testing/selftests/vm/userfaultfd.c b/tools/testing/selftests/vm/userfaultfd.c index 297f250c1d95..02cc35b65a7a 100644 --- a/tools/testing/selftests/vm/userfaultfd.c +++ b/tools/testing/selftests/vm/userfaultfd.c @@ -100,9 +100,11 @@ static int huge_fd; static unsigned long long *count_verify; static int uffd = -1; static int uffd_flags, finished, *pipefd; +static volatile bool ready_for_fork; static char *area_src, *area_src_alias, *area_dst, *area_dst_alias, *area_remap; static char *zeropage; pthread_attr_t attr; +pthread_key_t long_jmp_key; static bool test_collapse; /* Userfaultfd test statistics */ @@ -821,6 +823,9 @@ static void *uffd_poll_thread(void *arg) pollfd[1].fd = pipefd[cpu*2]; pollfd[1].events = POLLIN; + // Notify the main thread that it can now fork. + ready_for_fork = true; + for (;;) { ret = poll(pollfd, 2, -1); if (ret <= 0) { @@ -868,15 +873,27 @@ static void *uffd_poll_thread(void *arg) pthread_mutex_t uffd_read_mutex = PTHREAD_MUTEX_INITIALIZER; +static void sigusr1_handler(int signum, siginfo_t *siginfo, void *ptr) +{ + jmp_buf *env; + env = pthread_getspecific(long_jmp_key); + longjmp(*env, 1); +} + static void *uffd_read_thread(void *arg) { struct uffd_stats *stats = (struct uffd_stats *)arg; struct uffd_msg msg; + jmp_buf env; + int setjmp_ret; - pthread_mutex_unlock(&uffd_read_mutex); - /* from here cancellation is ok */ + pthread_setspecific(long_jmp_key, &env); - for (;;) { + pthread_mutex_unlock(&uffd_read_mutex); + // One first return setjmp return 0. On second (fake) return from + // longjmp() it returns the provided value, which will be 1 in our case. + setjmp_ret = setjmp(env); + while (!setjmp_ret) { if (uffd_read_msg(uffd, &msg)) continue; uffd_handle_page_fault(&msg, stats); @@ -974,7 +991,7 @@ static int stress(struct uffd_stats *uffd_stats) (void *)&uffd_stats[cpu])) return 1; } else { - if (pthread_cancel(uffd_threads[cpu])) + if (pthread_kill(uffd_threads[cpu], SIGUSR1)) return 1; if (pthread_join(uffd_threads[cpu], NULL)) return 1; @@ -1208,6 +1225,10 @@ static int userfaultfd_events_test(void) char c; struct uffd_stats stats = { 0 }; + // All the syscalls below up to pthread_create will ensure that this + // write is completed before, the uffd_thread sets it to true. + ready_for_fork = false; + printf("testing events (fork, remap, remove): "); fflush(stdout); @@ -1231,6 +1252,11 @@ static int userfaultfd_events_test(void) if (pthread_create(&uffd_mon, &attr, uffd_poll_thread, &stats)) err("uffd_poll_thread create"); + // Wait for the poll_thread to start executing before forking. This is + // required to avoid a deadlock, which can happen if poll_thread doesn't + // start getting executed by the time fork is invoked. + while (!ready_for_fork); + pid = fork(); if (pid < 0) err("fork"); @@ -1261,6 +1287,10 @@ static int userfaultfd_sig_test(void) char c; struct uffd_stats stats = { 0 }; + // All the syscalls below up to pthread_create will ensure that this + // write is completed before, the uffd_thread sets it to true. + ready_for_fork = false; + printf("testing signal delivery: "); fflush(stdout); @@ -1288,6 +1318,11 @@ static int userfaultfd_sig_test(void) if (pthread_create(&uffd_mon, &attr, uffd_poll_thread, &stats)) err("uffd_poll_thread create"); + // Wait for the poll_thread to start executing before forking. This is + // required to avoid a deadlock, which can happen if poll_thread doesn't + // start getting executed by the time fork is invoked. + while (!ready_for_fork); + pid = fork(); if (pid < 0) err("fork"); @@ -1409,6 +1444,11 @@ static int userfaultfd_minor_test(void) #define PM_SWAP BIT_ULL(62) #define PM_PRESENT BIT_ULL(63) +/* + * b/232026677 + * pagemap not compatible with < 5.14 + */ +#ifndef __ANDROID__ static int pagemap_open(void) { int fd = open("/proc/self/pagemap", O_RDONLY); @@ -1534,12 +1574,14 @@ static void userfaultfd_pagemap_test(unsigned int test_pgsize) close(pagemap_fd); printf("done\n"); } +#endif static int userfaultfd_stress(void) { void *area; unsigned long nr; struct uffdio_register uffdio_register; + struct sigaction act; struct uffd_stats uffd_stats[nr_cpus]; uffd_test_ctx_init(0); @@ -1554,6 +1596,17 @@ static int userfaultfd_stress(void) pthread_attr_init(&attr); pthread_attr_setstacksize(&attr, 16*1024*1024); + // For handling thread termination of read thread in the absence of + // pthread_cancel(). + pthread_key_create(&long_jmp_key, NULL); + memset(&act, 0, sizeof(act)); + act.sa_sigaction = sigusr1_handler; + act.sa_flags = SA_SIGINFO; + if (sigaction(SIGUSR1, &act, 0)) { + perror("sigaction"); + return 1; + } + while (bounces--) { printf("bounces: %d, mode:", bounces); if (bounces & BOUNCE_RANDOM) @@ -1655,6 +1708,11 @@ static int userfaultfd_stress(void) uffd_stats_report(uffd_stats, nr_cpus); } +/* + * b/232026677 + * pagemap not compatible with < 5.14 + */ +#ifndef __ANDROID__ if (test_type == TEST_ANON) { /* * shmem/hugetlb won't be able to run since they have different @@ -1669,6 +1727,9 @@ static int userfaultfd_stress(void) */ userfaultfd_pagemap_test(page_size * 512); } +#endif + + pthread_key_delete(long_jmp_key); return userfaultfd_zeropage_test() || userfaultfd_sig_test() || userfaultfd_events_test() || userfaultfd_minor_test(); @@ -1723,7 +1784,24 @@ static void set_test_type(const char *type) static void parse_test_type_arg(const char *raw_type) { char *buf = strdup(raw_type); + /* b/234150821 + * UFFD_FEATURE_PAGEFAULT_FLAG_WP unsupported in kernel <5.7 + */ +#ifdef __ANDROID__ + uint64_t features = ( + UFFD_FEATURE_EVENT_FORK | \ + UFFD_FEATURE_EVENT_REMAP | \ + UFFD_FEATURE_EVENT_REMOVE | \ + UFFD_FEATURE_EVENT_UNMAP | \ + UFFD_FEATURE_MISSING_HUGETLBFS | \ + UFFD_FEATURE_MISSING_SHMEM | \ + UFFD_FEATURE_SIGBUS | \ + UFFD_FEATURE_THREAD_ID | \ + UFFD_FEATURE_MINOR_HUGETLBFS | \ + UFFD_FEATURE_MINOR_SHMEM); +#else uint64_t features = UFFD_API_FEATURES; +#endif while (buf) { const char *token = strsep(&buf, ":"); diff --git a/tools/testing/selftests/x86/test_FISTTP.c b/tools/testing/selftests/x86/test_FISTTP.c index 09789c0ce3e9..c920a57ddb06 100644 --- a/tools/testing/selftests/x86/test_FISTTP.c +++ b/tools/testing/selftests/x86/test_FISTTP.c @@ -25,7 +25,11 @@ int test(void) feclearexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW); asm volatile ("\n" " fld1""\n" +#ifdef __clang__ + " fisttps res16""\n" +#else " fisttp res16""\n" +#endif " fld1""\n" " fisttpl res32""\n" " fld1""\n" @@ -45,7 +49,11 @@ int test(void) feclearexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW); asm volatile ("\n" " fldpi""\n" +#ifdef __clang__ + " fisttps res16""\n" +#else " fisttp res16""\n" +#endif " fldpi""\n" " fisttpl res32""\n" " fldpi""\n" @@ -66,7 +74,13 @@ int test(void) asm volatile ("\n" " fldpi""\n" " fchs""\n" +#ifdef __clang__ + " fisttps res16""\n" +#else + // clang will complain: ambiguous instructions require an explicit suffix + // (could be 'fisttps', or 'fisttpl') " fisttp res16""\n" +#endif " fldpi""\n" " fchs""\n" " fisttpl res32""\n" @@ -88,7 +102,11 @@ int test(void) feclearexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW); asm volatile ("\n" " fldln2""\n" +#ifdef __clang__ + " fisttps res16""\n" +#else " fisttp res16""\n" +#endif " fldln2""\n" " fisttpl res32""\n" " fldln2""\n" |