162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * 32-bit syscall ABI conformance test. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2015 Denys Vlasenko 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci/* 862306a36Sopenharmony_ci * Can be built statically: 962306a36Sopenharmony_ci * gcc -Os -Wall -static -m32 test_syscall_vdso.c thunks_32.S 1062306a36Sopenharmony_ci */ 1162306a36Sopenharmony_ci#undef _GNU_SOURCE 1262306a36Sopenharmony_ci#define _GNU_SOURCE 1 1362306a36Sopenharmony_ci#undef __USE_GNU 1462306a36Sopenharmony_ci#define __USE_GNU 1 1562306a36Sopenharmony_ci#include <unistd.h> 1662306a36Sopenharmony_ci#include <stdlib.h> 1762306a36Sopenharmony_ci#include <string.h> 1862306a36Sopenharmony_ci#include <stdio.h> 1962306a36Sopenharmony_ci#include <signal.h> 2062306a36Sopenharmony_ci#include <sys/types.h> 2162306a36Sopenharmony_ci#include <sys/select.h> 2262306a36Sopenharmony_ci#include <sys/time.h> 2362306a36Sopenharmony_ci#include <elf.h> 2462306a36Sopenharmony_ci#include <sys/ptrace.h> 2562306a36Sopenharmony_ci#include <sys/wait.h> 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci#if !defined(__i386__) 2862306a36Sopenharmony_ciint main(int argc, char **argv, char **envp) 2962306a36Sopenharmony_ci{ 3062306a36Sopenharmony_ci printf("[SKIP]\tNot a 32-bit x86 userspace\n"); 3162306a36Sopenharmony_ci return 0; 3262306a36Sopenharmony_ci} 3362306a36Sopenharmony_ci#else 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_cilong syscall_addr; 3662306a36Sopenharmony_cilong get_syscall(char **envp) 3762306a36Sopenharmony_ci{ 3862306a36Sopenharmony_ci Elf32_auxv_t *auxv; 3962306a36Sopenharmony_ci while (*envp++ != NULL) 4062306a36Sopenharmony_ci continue; 4162306a36Sopenharmony_ci for (auxv = (void *)envp; auxv->a_type != AT_NULL; auxv++) 4262306a36Sopenharmony_ci if (auxv->a_type == AT_SYSINFO) 4362306a36Sopenharmony_ci return auxv->a_un.a_val; 4462306a36Sopenharmony_ci printf("[WARN]\tAT_SYSINFO not supplied\n"); 4562306a36Sopenharmony_ci return 0; 4662306a36Sopenharmony_ci} 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ciasm ( 4962306a36Sopenharmony_ci " .pushsection .text\n" 5062306a36Sopenharmony_ci " .global int80\n" 5162306a36Sopenharmony_ci "int80:\n" 5262306a36Sopenharmony_ci " int $0x80\n" 5362306a36Sopenharmony_ci " ret\n" 5462306a36Sopenharmony_ci " .popsection\n" 5562306a36Sopenharmony_ci); 5662306a36Sopenharmony_ciextern char int80; 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_cistruct regs64 { 5962306a36Sopenharmony_ci uint64_t rax, rbx, rcx, rdx; 6062306a36Sopenharmony_ci uint64_t rsi, rdi, rbp, rsp; 6162306a36Sopenharmony_ci uint64_t r8, r9, r10, r11; 6262306a36Sopenharmony_ci uint64_t r12, r13, r14, r15; 6362306a36Sopenharmony_ci}; 6462306a36Sopenharmony_cistruct regs64 regs64; 6562306a36Sopenharmony_ciint kernel_is_64bit; 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ciasm ( 6862306a36Sopenharmony_ci " .pushsection .text\n" 6962306a36Sopenharmony_ci " .code64\n" 7062306a36Sopenharmony_ci "get_regs64:\n" 7162306a36Sopenharmony_ci " push %rax\n" 7262306a36Sopenharmony_ci " mov $regs64, %eax\n" 7362306a36Sopenharmony_ci " pop 0*8(%rax)\n" 7462306a36Sopenharmony_ci " movq %rbx, 1*8(%rax)\n" 7562306a36Sopenharmony_ci " movq %rcx, 2*8(%rax)\n" 7662306a36Sopenharmony_ci " movq %rdx, 3*8(%rax)\n" 7762306a36Sopenharmony_ci " movq %rsi, 4*8(%rax)\n" 7862306a36Sopenharmony_ci " movq %rdi, 5*8(%rax)\n" 7962306a36Sopenharmony_ci " movq %rbp, 6*8(%rax)\n" 8062306a36Sopenharmony_ci " movq %rsp, 7*8(%rax)\n" 8162306a36Sopenharmony_ci " movq %r8, 8*8(%rax)\n" 8262306a36Sopenharmony_ci " movq %r9, 9*8(%rax)\n" 8362306a36Sopenharmony_ci " movq %r10, 10*8(%rax)\n" 8462306a36Sopenharmony_ci " movq %r11, 11*8(%rax)\n" 8562306a36Sopenharmony_ci " movq %r12, 12*8(%rax)\n" 8662306a36Sopenharmony_ci " movq %r13, 13*8(%rax)\n" 8762306a36Sopenharmony_ci " movq %r14, 14*8(%rax)\n" 8862306a36Sopenharmony_ci " movq %r15, 15*8(%rax)\n" 8962306a36Sopenharmony_ci " ret\n" 9062306a36Sopenharmony_ci "poison_regs64:\n" 9162306a36Sopenharmony_ci " movq $0x7f7f7f7f, %r8\n" 9262306a36Sopenharmony_ci " shl $32, %r8\n" 9362306a36Sopenharmony_ci " orq $0x7f7f7f7f, %r8\n" 9462306a36Sopenharmony_ci " movq %r8, %r9\n" 9562306a36Sopenharmony_ci " incq %r9\n" 9662306a36Sopenharmony_ci " movq %r9, %r10\n" 9762306a36Sopenharmony_ci " incq %r10\n" 9862306a36Sopenharmony_ci " movq %r10, %r11\n" 9962306a36Sopenharmony_ci " incq %r11\n" 10062306a36Sopenharmony_ci " movq %r11, %r12\n" 10162306a36Sopenharmony_ci " incq %r12\n" 10262306a36Sopenharmony_ci " movq %r12, %r13\n" 10362306a36Sopenharmony_ci " incq %r13\n" 10462306a36Sopenharmony_ci " movq %r13, %r14\n" 10562306a36Sopenharmony_ci " incq %r14\n" 10662306a36Sopenharmony_ci " movq %r14, %r15\n" 10762306a36Sopenharmony_ci " incq %r15\n" 10862306a36Sopenharmony_ci " ret\n" 10962306a36Sopenharmony_ci " .code32\n" 11062306a36Sopenharmony_ci " .popsection\n" 11162306a36Sopenharmony_ci); 11262306a36Sopenharmony_ciextern void get_regs64(void); 11362306a36Sopenharmony_ciextern void poison_regs64(void); 11462306a36Sopenharmony_ciextern unsigned long call64_from_32(void (*function)(void)); 11562306a36Sopenharmony_civoid print_regs64(void) 11662306a36Sopenharmony_ci{ 11762306a36Sopenharmony_ci if (!kernel_is_64bit) 11862306a36Sopenharmony_ci return; 11962306a36Sopenharmony_ci printf("ax:%016llx bx:%016llx cx:%016llx dx:%016llx\n", regs64.rax, regs64.rbx, regs64.rcx, regs64.rdx); 12062306a36Sopenharmony_ci printf("si:%016llx di:%016llx bp:%016llx sp:%016llx\n", regs64.rsi, regs64.rdi, regs64.rbp, regs64.rsp); 12162306a36Sopenharmony_ci printf(" 8:%016llx 9:%016llx 10:%016llx 11:%016llx\n", regs64.r8 , regs64.r9 , regs64.r10, regs64.r11); 12262306a36Sopenharmony_ci printf("12:%016llx 13:%016llx 14:%016llx 15:%016llx\n", regs64.r12, regs64.r13, regs64.r14, regs64.r15); 12362306a36Sopenharmony_ci} 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ciint check_regs64(void) 12662306a36Sopenharmony_ci{ 12762306a36Sopenharmony_ci int err = 0; 12862306a36Sopenharmony_ci int num = 8; 12962306a36Sopenharmony_ci uint64_t *r64 = ®s64.r8; 13062306a36Sopenharmony_ci uint64_t expected = 0x7f7f7f7f7f7f7f7fULL; 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci if (!kernel_is_64bit) 13362306a36Sopenharmony_ci return 0; 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci do { 13662306a36Sopenharmony_ci if (*r64 == expected++) 13762306a36Sopenharmony_ci continue; /* register did not change */ 13862306a36Sopenharmony_ci if (syscall_addr != (long)&int80) { 13962306a36Sopenharmony_ci /* 14062306a36Sopenharmony_ci * Non-INT80 syscall entrypoints are allowed to clobber R8+ regs: 14162306a36Sopenharmony_ci * either clear them to 0, or for R11, load EFLAGS. 14262306a36Sopenharmony_ci */ 14362306a36Sopenharmony_ci if (*r64 == 0) 14462306a36Sopenharmony_ci continue; 14562306a36Sopenharmony_ci if (num == 11) { 14662306a36Sopenharmony_ci printf("[NOTE]\tR11 has changed:%016llx - assuming clobbered by SYSRET insn\n", *r64); 14762306a36Sopenharmony_ci continue; 14862306a36Sopenharmony_ci } 14962306a36Sopenharmony_ci } else { 15062306a36Sopenharmony_ci /* 15162306a36Sopenharmony_ci * INT80 syscall entrypoint can be used by 15262306a36Sopenharmony_ci * 64-bit programs too, unlike SYSCALL/SYSENTER. 15362306a36Sopenharmony_ci * Therefore it must preserve R12+ 15462306a36Sopenharmony_ci * (they are callee-saved registers in 64-bit C ABI). 15562306a36Sopenharmony_ci * 15662306a36Sopenharmony_ci * Starting in Linux 4.17 (and any kernel that 15762306a36Sopenharmony_ci * backports the change), R8..11 are preserved. 15862306a36Sopenharmony_ci * Historically (and probably unintentionally), they 15962306a36Sopenharmony_ci * were clobbered or zeroed. 16062306a36Sopenharmony_ci */ 16162306a36Sopenharmony_ci } 16262306a36Sopenharmony_ci printf("[FAIL]\tR%d has changed:%016llx\n", num, *r64); 16362306a36Sopenharmony_ci err++; 16462306a36Sopenharmony_ci } while (r64++, ++num < 16); 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci if (!err) 16762306a36Sopenharmony_ci printf("[OK]\tR8..R15 did not leak kernel data\n"); 16862306a36Sopenharmony_ci return err; 16962306a36Sopenharmony_ci} 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ciint nfds; 17262306a36Sopenharmony_cifd_set rfds; 17362306a36Sopenharmony_cifd_set wfds; 17462306a36Sopenharmony_cifd_set efds; 17562306a36Sopenharmony_cistruct timespec timeout; 17662306a36Sopenharmony_cisigset_t sigmask; 17762306a36Sopenharmony_cistruct { 17862306a36Sopenharmony_ci sigset_t *sp; 17962306a36Sopenharmony_ci int sz; 18062306a36Sopenharmony_ci} sigmask_desc; 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_civoid prep_args() 18362306a36Sopenharmony_ci{ 18462306a36Sopenharmony_ci nfds = 42; 18562306a36Sopenharmony_ci FD_ZERO(&rfds); 18662306a36Sopenharmony_ci FD_ZERO(&wfds); 18762306a36Sopenharmony_ci FD_ZERO(&efds); 18862306a36Sopenharmony_ci FD_SET(0, &rfds); 18962306a36Sopenharmony_ci FD_SET(1, &wfds); 19062306a36Sopenharmony_ci FD_SET(2, &efds); 19162306a36Sopenharmony_ci timeout.tv_sec = 0; 19262306a36Sopenharmony_ci timeout.tv_nsec = 123; 19362306a36Sopenharmony_ci sigemptyset(&sigmask); 19462306a36Sopenharmony_ci sigaddset(&sigmask, SIGINT); 19562306a36Sopenharmony_ci sigaddset(&sigmask, SIGUSR2); 19662306a36Sopenharmony_ci sigaddset(&sigmask, SIGRTMAX); 19762306a36Sopenharmony_ci sigmask_desc.sp = &sigmask; 19862306a36Sopenharmony_ci sigmask_desc.sz = 8; /* bytes */ 19962306a36Sopenharmony_ci} 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_cistatic void print_flags(const char *name, unsigned long r) 20262306a36Sopenharmony_ci{ 20362306a36Sopenharmony_ci static const char *bitarray[] = { 20462306a36Sopenharmony_ci "\n" ,"c\n" ,/* Carry Flag */ 20562306a36Sopenharmony_ci "0 " ,"1 " ,/* Bit 1 - always on */ 20662306a36Sopenharmony_ci "" ,"p " ,/* Parity Flag */ 20762306a36Sopenharmony_ci "0 " ,"3? " , 20862306a36Sopenharmony_ci "" ,"a " ,/* Auxiliary carry Flag */ 20962306a36Sopenharmony_ci "0 " ,"5? " , 21062306a36Sopenharmony_ci "" ,"z " ,/* Zero Flag */ 21162306a36Sopenharmony_ci "" ,"s " ,/* Sign Flag */ 21262306a36Sopenharmony_ci "" ,"t " ,/* Trap Flag */ 21362306a36Sopenharmony_ci "" ,"i " ,/* Interrupt Flag */ 21462306a36Sopenharmony_ci "" ,"d " ,/* Direction Flag */ 21562306a36Sopenharmony_ci "" ,"o " ,/* Overflow Flag */ 21662306a36Sopenharmony_ci "0 " ,"1 " ,/* I/O Privilege Level (2 bits) */ 21762306a36Sopenharmony_ci "0" ,"1" ,/* I/O Privilege Level (2 bits) */ 21862306a36Sopenharmony_ci "" ,"n " ,/* Nested Task */ 21962306a36Sopenharmony_ci "0 " ,"15? ", 22062306a36Sopenharmony_ci "" ,"r " ,/* Resume Flag */ 22162306a36Sopenharmony_ci "" ,"v " ,/* Virtual Mode */ 22262306a36Sopenharmony_ci "" ,"ac " ,/* Alignment Check/Access Control */ 22362306a36Sopenharmony_ci "" ,"vif ",/* Virtual Interrupt Flag */ 22462306a36Sopenharmony_ci "" ,"vip ",/* Virtual Interrupt Pending */ 22562306a36Sopenharmony_ci "" ,"id " ,/* CPUID detection */ 22662306a36Sopenharmony_ci NULL 22762306a36Sopenharmony_ci }; 22862306a36Sopenharmony_ci const char **bitstr; 22962306a36Sopenharmony_ci int bit; 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci printf("%s=%016lx ", name, r); 23262306a36Sopenharmony_ci bitstr = bitarray + 42; 23362306a36Sopenharmony_ci bit = 21; 23462306a36Sopenharmony_ci if ((r >> 22) != 0) 23562306a36Sopenharmony_ci printf("(extra bits are set) "); 23662306a36Sopenharmony_ci do { 23762306a36Sopenharmony_ci if (bitstr[(r >> bit) & 1][0]) 23862306a36Sopenharmony_ci fputs(bitstr[(r >> bit) & 1], stdout); 23962306a36Sopenharmony_ci bitstr -= 2; 24062306a36Sopenharmony_ci bit--; 24162306a36Sopenharmony_ci } while (bit >= 0); 24262306a36Sopenharmony_ci} 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ciint run_syscall(void) 24562306a36Sopenharmony_ci{ 24662306a36Sopenharmony_ci long flags, bad_arg; 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci prep_args(); 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci if (kernel_is_64bit) 25162306a36Sopenharmony_ci call64_from_32(poison_regs64); 25262306a36Sopenharmony_ci /*print_regs64();*/ 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci asm("\n" 25562306a36Sopenharmony_ci /* Try 6-arg syscall: pselect. It should return quickly */ 25662306a36Sopenharmony_ci " push %%ebp\n" 25762306a36Sopenharmony_ci " mov $308, %%eax\n" /* PSELECT */ 25862306a36Sopenharmony_ci " mov nfds, %%ebx\n" /* ebx arg1 */ 25962306a36Sopenharmony_ci " mov $rfds, %%ecx\n" /* ecx arg2 */ 26062306a36Sopenharmony_ci " mov $wfds, %%edx\n" /* edx arg3 */ 26162306a36Sopenharmony_ci " mov $efds, %%esi\n" /* esi arg4 */ 26262306a36Sopenharmony_ci " mov $timeout, %%edi\n" /* edi arg5 */ 26362306a36Sopenharmony_ci " mov $sigmask_desc, %%ebp\n" /* %ebp arg6 */ 26462306a36Sopenharmony_ci " push $0x200ed7\n" /* set almost all flags */ 26562306a36Sopenharmony_ci " popf\n" /* except TF, IOPL, NT, RF, VM, AC, VIF, VIP */ 26662306a36Sopenharmony_ci " call *syscall_addr\n" 26762306a36Sopenharmony_ci /* Check that registers are not clobbered */ 26862306a36Sopenharmony_ci " pushf\n" 26962306a36Sopenharmony_ci " pop %%eax\n" 27062306a36Sopenharmony_ci " cld\n" 27162306a36Sopenharmony_ci " cmp nfds, %%ebx\n" /* ebx arg1 */ 27262306a36Sopenharmony_ci " mov $1, %%ebx\n" 27362306a36Sopenharmony_ci " jne 1f\n" 27462306a36Sopenharmony_ci " cmp $rfds, %%ecx\n" /* ecx arg2 */ 27562306a36Sopenharmony_ci " mov $2, %%ebx\n" 27662306a36Sopenharmony_ci " jne 1f\n" 27762306a36Sopenharmony_ci " cmp $wfds, %%edx\n" /* edx arg3 */ 27862306a36Sopenharmony_ci " mov $3, %%ebx\n" 27962306a36Sopenharmony_ci " jne 1f\n" 28062306a36Sopenharmony_ci " cmp $efds, %%esi\n" /* esi arg4 */ 28162306a36Sopenharmony_ci " mov $4, %%ebx\n" 28262306a36Sopenharmony_ci " jne 1f\n" 28362306a36Sopenharmony_ci " cmp $timeout, %%edi\n" /* edi arg5 */ 28462306a36Sopenharmony_ci " mov $5, %%ebx\n" 28562306a36Sopenharmony_ci " jne 1f\n" 28662306a36Sopenharmony_ci " cmpl $sigmask_desc, %%ebp\n" /* %ebp arg6 */ 28762306a36Sopenharmony_ci " mov $6, %%ebx\n" 28862306a36Sopenharmony_ci " jne 1f\n" 28962306a36Sopenharmony_ci " mov $0, %%ebx\n" 29062306a36Sopenharmony_ci "1:\n" 29162306a36Sopenharmony_ci " pop %%ebp\n" 29262306a36Sopenharmony_ci : "=a" (flags), "=b" (bad_arg) 29362306a36Sopenharmony_ci : 29462306a36Sopenharmony_ci : "cx", "dx", "si", "di" 29562306a36Sopenharmony_ci ); 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci if (kernel_is_64bit) { 29862306a36Sopenharmony_ci memset(®s64, 0x77, sizeof(regs64)); 29962306a36Sopenharmony_ci call64_from_32(get_regs64); 30062306a36Sopenharmony_ci /*print_regs64();*/ 30162306a36Sopenharmony_ci } 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci /* 30462306a36Sopenharmony_ci * On paravirt kernels, flags are not preserved across syscalls. 30562306a36Sopenharmony_ci * Thus, we do not consider it a bug if some are changed. 30662306a36Sopenharmony_ci * We just show ones which do. 30762306a36Sopenharmony_ci */ 30862306a36Sopenharmony_ci if ((0x200ed7 ^ flags) != 0) { 30962306a36Sopenharmony_ci print_flags("[WARN]\tFlags before", 0x200ed7); 31062306a36Sopenharmony_ci print_flags("[WARN]\tFlags after", flags); 31162306a36Sopenharmony_ci print_flags("[WARN]\tFlags change", (0x200ed7 ^ flags)); 31262306a36Sopenharmony_ci } 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci if (bad_arg) { 31562306a36Sopenharmony_ci printf("[FAIL]\targ#%ld clobbered\n", bad_arg); 31662306a36Sopenharmony_ci return 1; 31762306a36Sopenharmony_ci } 31862306a36Sopenharmony_ci printf("[OK]\tArguments are preserved across syscall\n"); 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci return check_regs64(); 32162306a36Sopenharmony_ci} 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ciint run_syscall_twice() 32462306a36Sopenharmony_ci{ 32562306a36Sopenharmony_ci int exitcode = 0; 32662306a36Sopenharmony_ci long sv; 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci if (syscall_addr) { 32962306a36Sopenharmony_ci printf("[RUN]\tExecuting 6-argument 32-bit syscall via VDSO\n"); 33062306a36Sopenharmony_ci exitcode = run_syscall(); 33162306a36Sopenharmony_ci } 33262306a36Sopenharmony_ci sv = syscall_addr; 33362306a36Sopenharmony_ci syscall_addr = (long)&int80; 33462306a36Sopenharmony_ci printf("[RUN]\tExecuting 6-argument 32-bit syscall via INT 80\n"); 33562306a36Sopenharmony_ci exitcode += run_syscall(); 33662306a36Sopenharmony_ci syscall_addr = sv; 33762306a36Sopenharmony_ci return exitcode; 33862306a36Sopenharmony_ci} 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_civoid ptrace_me() 34162306a36Sopenharmony_ci{ 34262306a36Sopenharmony_ci pid_t pid; 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci fflush(NULL); 34562306a36Sopenharmony_ci pid = fork(); 34662306a36Sopenharmony_ci if (pid < 0) 34762306a36Sopenharmony_ci exit(1); 34862306a36Sopenharmony_ci if (pid == 0) { 34962306a36Sopenharmony_ci /* child */ 35062306a36Sopenharmony_ci if (ptrace(PTRACE_TRACEME, 0L, 0L, 0L) != 0) 35162306a36Sopenharmony_ci exit(0); 35262306a36Sopenharmony_ci raise(SIGSTOP); 35362306a36Sopenharmony_ci return; 35462306a36Sopenharmony_ci } 35562306a36Sopenharmony_ci /* parent */ 35662306a36Sopenharmony_ci printf("[RUN]\tRunning tests under ptrace\n"); 35762306a36Sopenharmony_ci while (1) { 35862306a36Sopenharmony_ci int status; 35962306a36Sopenharmony_ci pid = waitpid(-1, &status, __WALL); 36062306a36Sopenharmony_ci if (WIFEXITED(status)) 36162306a36Sopenharmony_ci exit(WEXITSTATUS(status)); 36262306a36Sopenharmony_ci if (WIFSIGNALED(status)) 36362306a36Sopenharmony_ci exit(WTERMSIG(status)); 36462306a36Sopenharmony_ci if (pid <= 0 || !WIFSTOPPED(status)) /* paranoia */ 36562306a36Sopenharmony_ci exit(255); 36662306a36Sopenharmony_ci /* 36762306a36Sopenharmony_ci * Note: we do not inject sig = WSTOPSIG(status). 36862306a36Sopenharmony_ci * We probably should, but careful: do not inject SIGTRAP 36962306a36Sopenharmony_ci * generated by syscall entry/exit stops. 37062306a36Sopenharmony_ci * That kills the child. 37162306a36Sopenharmony_ci */ 37262306a36Sopenharmony_ci ptrace(PTRACE_SYSCALL, pid, 0L, 0L /*sig*/); 37362306a36Sopenharmony_ci } 37462306a36Sopenharmony_ci} 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ciint main(int argc, char **argv, char **envp) 37762306a36Sopenharmony_ci{ 37862306a36Sopenharmony_ci int exitcode = 0; 37962306a36Sopenharmony_ci int cs; 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ci asm("\n" 38262306a36Sopenharmony_ci " movl %%cs, %%eax\n" 38362306a36Sopenharmony_ci : "=a" (cs) 38462306a36Sopenharmony_ci ); 38562306a36Sopenharmony_ci kernel_is_64bit = (cs == 0x23); 38662306a36Sopenharmony_ci if (!kernel_is_64bit) 38762306a36Sopenharmony_ci printf("[NOTE]\tNot a 64-bit kernel, won't test R8..R15 leaks\n"); 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci /* This only works for non-static builds: 39062306a36Sopenharmony_ci * syscall_addr = dlsym(dlopen("linux-gate.so.1", RTLD_NOW), "__kernel_vsyscall"); 39162306a36Sopenharmony_ci */ 39262306a36Sopenharmony_ci syscall_addr = get_syscall(envp); 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci exitcode += run_syscall_twice(); 39562306a36Sopenharmony_ci ptrace_me(); 39662306a36Sopenharmony_ci exitcode += run_syscall_twice(); 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci return exitcode; 39962306a36Sopenharmony_ci} 40062306a36Sopenharmony_ci#endif 401