162306a36Sopenharmony_ci#if defined __amd64__ || defined __i386__ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) 2022 Alexey Dobriyan <adobriyan@gmail.com> 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Permission to use, copy, modify, and distribute this software for any 662306a36Sopenharmony_ci * purpose with or without fee is hereby granted, provided that the above 762306a36Sopenharmony_ci * copyright notice and this permission notice appear in all copies. 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 1062306a36Sopenharmony_ci * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1162306a36Sopenharmony_ci * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1262306a36Sopenharmony_ci * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1362306a36Sopenharmony_ci * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1462306a36Sopenharmony_ci * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1562306a36Sopenharmony_ci * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1662306a36Sopenharmony_ci */ 1762306a36Sopenharmony_ci/* 1862306a36Sopenharmony_ci * Create a process without mappings by unmapping everything at once and 1962306a36Sopenharmony_ci * holding it with ptrace(2). See what happens to 2062306a36Sopenharmony_ci * 2162306a36Sopenharmony_ci * /proc/${pid}/maps 2262306a36Sopenharmony_ci * /proc/${pid}/numa_maps 2362306a36Sopenharmony_ci * /proc/${pid}/smaps 2462306a36Sopenharmony_ci * /proc/${pid}/smaps_rollup 2562306a36Sopenharmony_ci */ 2662306a36Sopenharmony_ci#undef NDEBUG 2762306a36Sopenharmony_ci#include <assert.h> 2862306a36Sopenharmony_ci#include <errno.h> 2962306a36Sopenharmony_ci#include <stdint.h> 3062306a36Sopenharmony_ci#include <stdio.h> 3162306a36Sopenharmony_ci#include <stdlib.h> 3262306a36Sopenharmony_ci#include <string.h> 3362306a36Sopenharmony_ci#include <fcntl.h> 3462306a36Sopenharmony_ci#include <sys/mman.h> 3562306a36Sopenharmony_ci#include <sys/ptrace.h> 3662306a36Sopenharmony_ci#include <sys/resource.h> 3762306a36Sopenharmony_ci#include <sys/types.h> 3862306a36Sopenharmony_ci#include <sys/wait.h> 3962306a36Sopenharmony_ci#include <unistd.h> 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci#ifdef __amd64__ 4262306a36Sopenharmony_ci#define TEST_VSYSCALL 4362306a36Sopenharmony_ci#endif 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci/* 4662306a36Sopenharmony_ci * 0: vsyscall VMA doesn't exist vsyscall=none 4762306a36Sopenharmony_ci * 1: vsyscall VMA is --xp vsyscall=xonly 4862306a36Sopenharmony_ci * 2: vsyscall VMA is r-xp vsyscall=emulate 4962306a36Sopenharmony_ci */ 5062306a36Sopenharmony_cistatic volatile int g_vsyscall; 5162306a36Sopenharmony_cistatic const char *g_proc_pid_maps_vsyscall; 5262306a36Sopenharmony_cistatic const char *g_proc_pid_smaps_vsyscall; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_cistatic const char proc_pid_maps_vsyscall_0[] = ""; 5562306a36Sopenharmony_cistatic const char proc_pid_maps_vsyscall_1[] = 5662306a36Sopenharmony_ci"ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsyscall]\n"; 5762306a36Sopenharmony_cistatic const char proc_pid_maps_vsyscall_2[] = 5862306a36Sopenharmony_ci"ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]\n"; 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_cistatic const char proc_pid_smaps_vsyscall_0[] = ""; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_cistatic const char proc_pid_smaps_vsyscall_1[] = 6362306a36Sopenharmony_ci"ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]\n" 6462306a36Sopenharmony_ci"Size: 4 kB\n" 6562306a36Sopenharmony_ci"KernelPageSize: 4 kB\n" 6662306a36Sopenharmony_ci"MMUPageSize: 4 kB\n" 6762306a36Sopenharmony_ci"Rss: 0 kB\n" 6862306a36Sopenharmony_ci"Pss: 0 kB\n" 6962306a36Sopenharmony_ci"Pss_Dirty: 0 kB\n" 7062306a36Sopenharmony_ci"Shared_Clean: 0 kB\n" 7162306a36Sopenharmony_ci"Shared_Dirty: 0 kB\n" 7262306a36Sopenharmony_ci"Private_Clean: 0 kB\n" 7362306a36Sopenharmony_ci"Private_Dirty: 0 kB\n" 7462306a36Sopenharmony_ci"Referenced: 0 kB\n" 7562306a36Sopenharmony_ci"Anonymous: 0 kB\n" 7662306a36Sopenharmony_ci"LazyFree: 0 kB\n" 7762306a36Sopenharmony_ci"AnonHugePages: 0 kB\n" 7862306a36Sopenharmony_ci"ShmemPmdMapped: 0 kB\n" 7962306a36Sopenharmony_ci"FilePmdMapped: 0 kB\n" 8062306a36Sopenharmony_ci"Shared_Hugetlb: 0 kB\n" 8162306a36Sopenharmony_ci"Private_Hugetlb: 0 kB\n" 8262306a36Sopenharmony_ci"Swap: 0 kB\n" 8362306a36Sopenharmony_ci"SwapPss: 0 kB\n" 8462306a36Sopenharmony_ci"Locked: 0 kB\n" 8562306a36Sopenharmony_ci"THPeligible: 0\n" 8662306a36Sopenharmony_ci/* 8762306a36Sopenharmony_ci * "ProtectionKey:" field is conditional. It is possible to check it as well, 8862306a36Sopenharmony_ci * but I don't have such machine. 8962306a36Sopenharmony_ci */ 9062306a36Sopenharmony_ci; 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_cistatic const char proc_pid_smaps_vsyscall_2[] = 9362306a36Sopenharmony_ci"ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsyscall]\n" 9462306a36Sopenharmony_ci"Size: 4 kB\n" 9562306a36Sopenharmony_ci"KernelPageSize: 4 kB\n" 9662306a36Sopenharmony_ci"MMUPageSize: 4 kB\n" 9762306a36Sopenharmony_ci"Rss: 0 kB\n" 9862306a36Sopenharmony_ci"Pss: 0 kB\n" 9962306a36Sopenharmony_ci"Pss_Dirty: 0 kB\n" 10062306a36Sopenharmony_ci"Shared_Clean: 0 kB\n" 10162306a36Sopenharmony_ci"Shared_Dirty: 0 kB\n" 10262306a36Sopenharmony_ci"Private_Clean: 0 kB\n" 10362306a36Sopenharmony_ci"Private_Dirty: 0 kB\n" 10462306a36Sopenharmony_ci"Referenced: 0 kB\n" 10562306a36Sopenharmony_ci"Anonymous: 0 kB\n" 10662306a36Sopenharmony_ci"LazyFree: 0 kB\n" 10762306a36Sopenharmony_ci"AnonHugePages: 0 kB\n" 10862306a36Sopenharmony_ci"ShmemPmdMapped: 0 kB\n" 10962306a36Sopenharmony_ci"FilePmdMapped: 0 kB\n" 11062306a36Sopenharmony_ci"Shared_Hugetlb: 0 kB\n" 11162306a36Sopenharmony_ci"Private_Hugetlb: 0 kB\n" 11262306a36Sopenharmony_ci"Swap: 0 kB\n" 11362306a36Sopenharmony_ci"SwapPss: 0 kB\n" 11462306a36Sopenharmony_ci"Locked: 0 kB\n" 11562306a36Sopenharmony_ci"THPeligible: 0\n" 11662306a36Sopenharmony_ci/* 11762306a36Sopenharmony_ci * "ProtectionKey:" field is conditional. It is possible to check it as well, 11862306a36Sopenharmony_ci * but I'm too tired. 11962306a36Sopenharmony_ci */ 12062306a36Sopenharmony_ci; 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_cistatic void sigaction_SIGSEGV(int _, siginfo_t *__, void *___) 12362306a36Sopenharmony_ci{ 12462306a36Sopenharmony_ci _exit(EXIT_FAILURE); 12562306a36Sopenharmony_ci} 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci#ifdef TEST_VSYSCALL 12862306a36Sopenharmony_cistatic void sigaction_SIGSEGV_vsyscall(int _, siginfo_t *__, void *___) 12962306a36Sopenharmony_ci{ 13062306a36Sopenharmony_ci _exit(g_vsyscall); 13162306a36Sopenharmony_ci} 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci/* 13462306a36Sopenharmony_ci * vsyscall page can't be unmapped, probe it directly. 13562306a36Sopenharmony_ci */ 13662306a36Sopenharmony_cistatic void vsyscall(void) 13762306a36Sopenharmony_ci{ 13862306a36Sopenharmony_ci pid_t pid; 13962306a36Sopenharmony_ci int wstatus; 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci pid = fork(); 14262306a36Sopenharmony_ci if (pid < 0) { 14362306a36Sopenharmony_ci fprintf(stderr, "fork, errno %d\n", errno); 14462306a36Sopenharmony_ci exit(1); 14562306a36Sopenharmony_ci } 14662306a36Sopenharmony_ci if (pid == 0) { 14762306a36Sopenharmony_ci setrlimit(RLIMIT_CORE, &(struct rlimit){}); 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci /* Hide "segfault at ffffffffff600000" messages. */ 15062306a36Sopenharmony_ci struct sigaction act = {}; 15162306a36Sopenharmony_ci act.sa_flags = SA_SIGINFO; 15262306a36Sopenharmony_ci act.sa_sigaction = sigaction_SIGSEGV_vsyscall; 15362306a36Sopenharmony_ci sigaction(SIGSEGV, &act, NULL); 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci g_vsyscall = 0; 15662306a36Sopenharmony_ci /* gettimeofday(NULL, NULL); */ 15762306a36Sopenharmony_ci uint64_t rax = 0xffffffffff600000; 15862306a36Sopenharmony_ci asm volatile ( 15962306a36Sopenharmony_ci "call *%[rax]" 16062306a36Sopenharmony_ci : [rax] "+a" (rax) 16162306a36Sopenharmony_ci : "D" (NULL), "S" (NULL) 16262306a36Sopenharmony_ci : "rcx", "r11" 16362306a36Sopenharmony_ci ); 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci g_vsyscall = 1; 16662306a36Sopenharmony_ci *(volatile int *)0xffffffffff600000UL; 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci g_vsyscall = 2; 16962306a36Sopenharmony_ci exit(g_vsyscall); 17062306a36Sopenharmony_ci } 17162306a36Sopenharmony_ci waitpid(pid, &wstatus, 0); 17262306a36Sopenharmony_ci if (WIFEXITED(wstatus)) { 17362306a36Sopenharmony_ci g_vsyscall = WEXITSTATUS(wstatus); 17462306a36Sopenharmony_ci } else { 17562306a36Sopenharmony_ci fprintf(stderr, "error: vsyscall wstatus %08x\n", wstatus); 17662306a36Sopenharmony_ci exit(1); 17762306a36Sopenharmony_ci } 17862306a36Sopenharmony_ci} 17962306a36Sopenharmony_ci#endif 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_cistatic int test_proc_pid_maps(pid_t pid) 18262306a36Sopenharmony_ci{ 18362306a36Sopenharmony_ci char buf[4096]; 18462306a36Sopenharmony_ci snprintf(buf, sizeof(buf), "/proc/%u/maps", pid); 18562306a36Sopenharmony_ci int fd = open(buf, O_RDONLY); 18662306a36Sopenharmony_ci if (fd == -1) { 18762306a36Sopenharmony_ci perror("open /proc/${pid}/maps"); 18862306a36Sopenharmony_ci return EXIT_FAILURE; 18962306a36Sopenharmony_ci } else { 19062306a36Sopenharmony_ci ssize_t rv = read(fd, buf, sizeof(buf)); 19162306a36Sopenharmony_ci close(fd); 19262306a36Sopenharmony_ci if (g_vsyscall == 0) { 19362306a36Sopenharmony_ci assert(rv == 0); 19462306a36Sopenharmony_ci } else { 19562306a36Sopenharmony_ci size_t len = strlen(g_proc_pid_maps_vsyscall); 19662306a36Sopenharmony_ci assert(rv == len); 19762306a36Sopenharmony_ci assert(memcmp(buf, g_proc_pid_maps_vsyscall, len) == 0); 19862306a36Sopenharmony_ci } 19962306a36Sopenharmony_ci return EXIT_SUCCESS; 20062306a36Sopenharmony_ci } 20162306a36Sopenharmony_ci} 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_cistatic int test_proc_pid_numa_maps(pid_t pid) 20462306a36Sopenharmony_ci{ 20562306a36Sopenharmony_ci char buf[4096]; 20662306a36Sopenharmony_ci snprintf(buf, sizeof(buf), "/proc/%u/numa_maps", pid); 20762306a36Sopenharmony_ci int fd = open(buf, O_RDONLY); 20862306a36Sopenharmony_ci if (fd == -1) { 20962306a36Sopenharmony_ci if (errno == ENOENT) { 21062306a36Sopenharmony_ci /* 21162306a36Sopenharmony_ci * /proc/${pid}/numa_maps is under CONFIG_NUMA, 21262306a36Sopenharmony_ci * it doesn't necessarily exist. 21362306a36Sopenharmony_ci */ 21462306a36Sopenharmony_ci return EXIT_SUCCESS; 21562306a36Sopenharmony_ci } 21662306a36Sopenharmony_ci perror("open /proc/${pid}/numa_maps"); 21762306a36Sopenharmony_ci return EXIT_FAILURE; 21862306a36Sopenharmony_ci } else { 21962306a36Sopenharmony_ci ssize_t rv = read(fd, buf, sizeof(buf)); 22062306a36Sopenharmony_ci close(fd); 22162306a36Sopenharmony_ci assert(rv == 0); 22262306a36Sopenharmony_ci return EXIT_SUCCESS; 22362306a36Sopenharmony_ci } 22462306a36Sopenharmony_ci} 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_cistatic int test_proc_pid_smaps(pid_t pid) 22762306a36Sopenharmony_ci{ 22862306a36Sopenharmony_ci char buf[4096]; 22962306a36Sopenharmony_ci snprintf(buf, sizeof(buf), "/proc/%u/smaps", pid); 23062306a36Sopenharmony_ci int fd = open(buf, O_RDONLY); 23162306a36Sopenharmony_ci if (fd == -1) { 23262306a36Sopenharmony_ci if (errno == ENOENT) { 23362306a36Sopenharmony_ci /* 23462306a36Sopenharmony_ci * /proc/${pid}/smaps is under CONFIG_PROC_PAGE_MONITOR, 23562306a36Sopenharmony_ci * it doesn't necessarily exist. 23662306a36Sopenharmony_ci */ 23762306a36Sopenharmony_ci return EXIT_SUCCESS; 23862306a36Sopenharmony_ci } 23962306a36Sopenharmony_ci perror("open /proc/${pid}/smaps"); 24062306a36Sopenharmony_ci return EXIT_FAILURE; 24162306a36Sopenharmony_ci } else { 24262306a36Sopenharmony_ci ssize_t rv = read(fd, buf, sizeof(buf)); 24362306a36Sopenharmony_ci close(fd); 24462306a36Sopenharmony_ci if (g_vsyscall == 0) { 24562306a36Sopenharmony_ci assert(rv == 0); 24662306a36Sopenharmony_ci } else { 24762306a36Sopenharmony_ci size_t len = strlen(g_proc_pid_maps_vsyscall); 24862306a36Sopenharmony_ci /* TODO "ProtectionKey:" */ 24962306a36Sopenharmony_ci assert(rv > len); 25062306a36Sopenharmony_ci assert(memcmp(buf, g_proc_pid_maps_vsyscall, len) == 0); 25162306a36Sopenharmony_ci } 25262306a36Sopenharmony_ci return EXIT_SUCCESS; 25362306a36Sopenharmony_ci } 25462306a36Sopenharmony_ci} 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_cistatic const char g_smaps_rollup[] = 25762306a36Sopenharmony_ci"00000000-00000000 ---p 00000000 00:00 0 [rollup]\n" 25862306a36Sopenharmony_ci"Rss: 0 kB\n" 25962306a36Sopenharmony_ci"Pss: 0 kB\n" 26062306a36Sopenharmony_ci"Pss_Dirty: 0 kB\n" 26162306a36Sopenharmony_ci"Pss_Anon: 0 kB\n" 26262306a36Sopenharmony_ci"Pss_File: 0 kB\n" 26362306a36Sopenharmony_ci"Pss_Shmem: 0 kB\n" 26462306a36Sopenharmony_ci"Shared_Clean: 0 kB\n" 26562306a36Sopenharmony_ci"Shared_Dirty: 0 kB\n" 26662306a36Sopenharmony_ci"Private_Clean: 0 kB\n" 26762306a36Sopenharmony_ci"Private_Dirty: 0 kB\n" 26862306a36Sopenharmony_ci"Referenced: 0 kB\n" 26962306a36Sopenharmony_ci"Anonymous: 0 kB\n" 27062306a36Sopenharmony_ci"KSM: 0 kB\n" 27162306a36Sopenharmony_ci"LazyFree: 0 kB\n" 27262306a36Sopenharmony_ci"AnonHugePages: 0 kB\n" 27362306a36Sopenharmony_ci"ShmemPmdMapped: 0 kB\n" 27462306a36Sopenharmony_ci"FilePmdMapped: 0 kB\n" 27562306a36Sopenharmony_ci"Shared_Hugetlb: 0 kB\n" 27662306a36Sopenharmony_ci"Private_Hugetlb: 0 kB\n" 27762306a36Sopenharmony_ci"Swap: 0 kB\n" 27862306a36Sopenharmony_ci"SwapPss: 0 kB\n" 27962306a36Sopenharmony_ci"Locked: 0 kB\n" 28062306a36Sopenharmony_ci; 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_cistatic int test_proc_pid_smaps_rollup(pid_t pid) 28362306a36Sopenharmony_ci{ 28462306a36Sopenharmony_ci char buf[4096]; 28562306a36Sopenharmony_ci snprintf(buf, sizeof(buf), "/proc/%u/smaps_rollup", pid); 28662306a36Sopenharmony_ci int fd = open(buf, O_RDONLY); 28762306a36Sopenharmony_ci if (fd == -1) { 28862306a36Sopenharmony_ci if (errno == ENOENT) { 28962306a36Sopenharmony_ci /* 29062306a36Sopenharmony_ci * /proc/${pid}/smaps_rollup is under CONFIG_PROC_PAGE_MONITOR, 29162306a36Sopenharmony_ci * it doesn't necessarily exist. 29262306a36Sopenharmony_ci */ 29362306a36Sopenharmony_ci return EXIT_SUCCESS; 29462306a36Sopenharmony_ci } 29562306a36Sopenharmony_ci perror("open /proc/${pid}/smaps_rollup"); 29662306a36Sopenharmony_ci return EXIT_FAILURE; 29762306a36Sopenharmony_ci } else { 29862306a36Sopenharmony_ci ssize_t rv = read(fd, buf, sizeof(buf)); 29962306a36Sopenharmony_ci close(fd); 30062306a36Sopenharmony_ci assert(rv == sizeof(g_smaps_rollup) - 1); 30162306a36Sopenharmony_ci assert(memcmp(buf, g_smaps_rollup, sizeof(g_smaps_rollup) - 1) == 0); 30262306a36Sopenharmony_ci return EXIT_SUCCESS; 30362306a36Sopenharmony_ci } 30462306a36Sopenharmony_ci} 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ciint main(void) 30762306a36Sopenharmony_ci{ 30862306a36Sopenharmony_ci int rv = EXIT_SUCCESS; 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci#ifdef TEST_VSYSCALL 31162306a36Sopenharmony_ci vsyscall(); 31262306a36Sopenharmony_ci#endif 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci switch (g_vsyscall) { 31562306a36Sopenharmony_ci case 0: 31662306a36Sopenharmony_ci g_proc_pid_maps_vsyscall = proc_pid_maps_vsyscall_0; 31762306a36Sopenharmony_ci g_proc_pid_smaps_vsyscall = proc_pid_smaps_vsyscall_0; 31862306a36Sopenharmony_ci break; 31962306a36Sopenharmony_ci case 1: 32062306a36Sopenharmony_ci g_proc_pid_maps_vsyscall = proc_pid_maps_vsyscall_1; 32162306a36Sopenharmony_ci g_proc_pid_smaps_vsyscall = proc_pid_smaps_vsyscall_1; 32262306a36Sopenharmony_ci break; 32362306a36Sopenharmony_ci case 2: 32462306a36Sopenharmony_ci g_proc_pid_maps_vsyscall = proc_pid_maps_vsyscall_2; 32562306a36Sopenharmony_ci g_proc_pid_smaps_vsyscall = proc_pid_smaps_vsyscall_2; 32662306a36Sopenharmony_ci break; 32762306a36Sopenharmony_ci default: 32862306a36Sopenharmony_ci abort(); 32962306a36Sopenharmony_ci } 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci pid_t pid = fork(); 33262306a36Sopenharmony_ci if (pid == -1) { 33362306a36Sopenharmony_ci perror("fork"); 33462306a36Sopenharmony_ci return EXIT_FAILURE; 33562306a36Sopenharmony_ci } else if (pid == 0) { 33662306a36Sopenharmony_ci rv = ptrace(PTRACE_TRACEME, 0, NULL, NULL); 33762306a36Sopenharmony_ci if (rv != 0) { 33862306a36Sopenharmony_ci if (errno == EPERM) { 33962306a36Sopenharmony_ci fprintf(stderr, 34062306a36Sopenharmony_ci"Did you know? ptrace(PTRACE_TRACEME) doesn't work under strace.\n" 34162306a36Sopenharmony_ci ); 34262306a36Sopenharmony_ci kill(getppid(), SIGTERM); 34362306a36Sopenharmony_ci return EXIT_FAILURE; 34462306a36Sopenharmony_ci } 34562306a36Sopenharmony_ci perror("ptrace PTRACE_TRACEME"); 34662306a36Sopenharmony_ci return EXIT_FAILURE; 34762306a36Sopenharmony_ci } 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci /* 35062306a36Sopenharmony_ci * Hide "segfault at ..." messages. Signal handler won't run. 35162306a36Sopenharmony_ci */ 35262306a36Sopenharmony_ci struct sigaction act = {}; 35362306a36Sopenharmony_ci act.sa_flags = SA_SIGINFO; 35462306a36Sopenharmony_ci act.sa_sigaction = sigaction_SIGSEGV; 35562306a36Sopenharmony_ci sigaction(SIGSEGV, &act, NULL); 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci#ifdef __amd64__ 35862306a36Sopenharmony_ci munmap(NULL, ((size_t)1 << 47) - 4096); 35962306a36Sopenharmony_ci#elif defined __i386__ 36062306a36Sopenharmony_ci { 36162306a36Sopenharmony_ci size_t len; 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci for (len = -4096;; len -= 4096) { 36462306a36Sopenharmony_ci munmap(NULL, len); 36562306a36Sopenharmony_ci } 36662306a36Sopenharmony_ci } 36762306a36Sopenharmony_ci#else 36862306a36Sopenharmony_ci#error "implement 'unmap everything'" 36962306a36Sopenharmony_ci#endif 37062306a36Sopenharmony_ci return EXIT_FAILURE; 37162306a36Sopenharmony_ci } else { 37262306a36Sopenharmony_ci /* 37362306a36Sopenharmony_ci * TODO find reliable way to signal parent that munmap(2) completed. 37462306a36Sopenharmony_ci * Child can't do it directly because it effectively doesn't exist 37562306a36Sopenharmony_ci * anymore. Looking at child's VM files isn't 100% reliable either: 37662306a36Sopenharmony_ci * due to a bug they may not become empty or empty-like. 37762306a36Sopenharmony_ci */ 37862306a36Sopenharmony_ci sleep(1); 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci if (rv == EXIT_SUCCESS) { 38162306a36Sopenharmony_ci rv = test_proc_pid_maps(pid); 38262306a36Sopenharmony_ci } 38362306a36Sopenharmony_ci if (rv == EXIT_SUCCESS) { 38462306a36Sopenharmony_ci rv = test_proc_pid_numa_maps(pid); 38562306a36Sopenharmony_ci } 38662306a36Sopenharmony_ci if (rv == EXIT_SUCCESS) { 38762306a36Sopenharmony_ci rv = test_proc_pid_smaps(pid); 38862306a36Sopenharmony_ci } 38962306a36Sopenharmony_ci if (rv == EXIT_SUCCESS) { 39062306a36Sopenharmony_ci rv = test_proc_pid_smaps_rollup(pid); 39162306a36Sopenharmony_ci } 39262306a36Sopenharmony_ci /* 39362306a36Sopenharmony_ci * TODO test /proc/${pid}/statm, task_statm() 39462306a36Sopenharmony_ci * ->start_code, ->end_code aren't updated by munmap(). 39562306a36Sopenharmony_ci * Output can be "0 0 0 2 0 0 0\n" where "2" can be anything. 39662306a36Sopenharmony_ci */ 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci /* Cut the rope. */ 39962306a36Sopenharmony_ci int wstatus; 40062306a36Sopenharmony_ci waitpid(pid, &wstatus, 0); 40162306a36Sopenharmony_ci assert(WIFSTOPPED(wstatus)); 40262306a36Sopenharmony_ci assert(WSTOPSIG(wstatus) == SIGSEGV); 40362306a36Sopenharmony_ci } 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci return rv; 40662306a36Sopenharmony_ci} 40762306a36Sopenharmony_ci#else 40862306a36Sopenharmony_ciint main(void) 40962306a36Sopenharmony_ci{ 41062306a36Sopenharmony_ci return 4; 41162306a36Sopenharmony_ci} 41262306a36Sopenharmony_ci#endif 413