~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/x86/syscall_arg_fault.c

Version: ~ [ linux-5.16-rc3 ] ~ [ linux-5.15.5 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.82 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.162 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.218 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.256 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.291 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.293 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-only
  2 /*
  3  * syscall_arg_fault.c - tests faults 32-bit fast syscall stack args
  4  * Copyright (c) 2015 Andrew Lutomirski
  5  */
  6 
  7 #define _GNU_SOURCE
  8 
  9 #include <stdlib.h>
 10 #include <stdio.h>
 11 #include <string.h>
 12 #include <sys/signal.h>
 13 #include <sys/ucontext.h>
 14 #include <err.h>
 15 #include <setjmp.h>
 16 #include <errno.h>
 17 
 18 /* Our sigaltstack scratch space. */
 19 static unsigned char altstack_data[SIGSTKSZ];
 20 
 21 static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
 22                        int flags)
 23 {
 24         struct sigaction sa;
 25         memset(&sa, 0, sizeof(sa));
 26         sa.sa_sigaction = handler;
 27         sa.sa_flags = SA_SIGINFO | flags;
 28         sigemptyset(&sa.sa_mask);
 29         if (sigaction(sig, &sa, 0))
 30                 err(1, "sigaction");
 31 }
 32 
 33 static volatile sig_atomic_t sig_traps;
 34 static sigjmp_buf jmpbuf;
 35 
 36 static volatile sig_atomic_t n_errs;
 37 
 38 static void sigsegv_or_sigbus(int sig, siginfo_t *info, void *ctx_void)
 39 {
 40         ucontext_t *ctx = (ucontext_t*)ctx_void;
 41 
 42         if (ctx->uc_mcontext.gregs[REG_EAX] != -EFAULT) {
 43                 printf("[FAIL]\tAX had the wrong value: 0x%x\n",
 44                        ctx->uc_mcontext.gregs[REG_EAX]);
 45                 n_errs++;
 46         } else {
 47                 printf("[OK]\tSeems okay\n");
 48         }
 49 
 50         siglongjmp(jmpbuf, 1);
 51 }
 52 
 53 static void sigill(int sig, siginfo_t *info, void *ctx_void)
 54 {
 55         printf("[SKIP]\tIllegal instruction\n");
 56         siglongjmp(jmpbuf, 1);
 57 }
 58 
 59 int main()
 60 {
 61         stack_t stack = {
 62                 .ss_sp = altstack_data,
 63                 .ss_size = SIGSTKSZ,
 64         };
 65         if (sigaltstack(&stack, NULL) != 0)
 66                 err(1, "sigaltstack");
 67 
 68         sethandler(SIGSEGV, sigsegv_or_sigbus, SA_ONSTACK);
 69         /*
 70          * The actual exception can vary.  On Atom CPUs, we get #SS
 71          * instead of #PF when the vDSO fails to access the stack when
 72          * ESP is too close to 2^32, and #SS causes SIGBUS.
 73          */
 74         sethandler(SIGBUS, sigsegv_or_sigbus, SA_ONSTACK);
 75         sethandler(SIGILL, sigill, SA_ONSTACK);
 76 
 77         /*
 78          * Exercise another nasty special case.  The 32-bit SYSCALL
 79          * and SYSENTER instructions (even in compat mode) each
 80          * clobber one register.  A Linux system call has a syscall
 81          * number and six arguments, and the user stack pointer
 82          * needs to live in some register on return.  That means
 83          * that we need eight registers, but SYSCALL and SYSENTER
 84          * only preserve seven registers.  As a result, one argument
 85          * ends up on the stack.  The stack is user memory, which
 86          * means that the kernel can fail to read it.
 87          *
 88          * The 32-bit fast system calls don't have a defined ABI:
 89          * we're supposed to invoke them through the vDSO.  So we'll
 90          * fudge it: we set all regs to invalid pointer values and
 91          * invoke the entry instruction.  The return will fail no
 92          * matter what, and we completely lose our program state,
 93          * but we can fix it up with a signal handler.
 94          */
 95 
 96         printf("[RUN]\tSYSENTER with invalid state\n");
 97         if (sigsetjmp(jmpbuf, 1) == 0) {
 98                 asm volatile (
 99                         "movl $-1, %%eax\n\t"
100                         "movl $-1, %%ebx\n\t"
101                         "movl $-1, %%ecx\n\t"
102                         "movl $-1, %%edx\n\t"
103                         "movl $-1, %%esi\n\t"
104                         "movl $-1, %%edi\n\t"
105                         "movl $-1, %%ebp\n\t"
106                         "movl $-1, %%esp\n\t"
107                         "sysenter"
108                         : : : "memory", "flags");
109         }
110 
111         printf("[RUN]\tSYSCALL with invalid state\n");
112         if (sigsetjmp(jmpbuf, 1) == 0) {
113                 asm volatile (
114                         "movl $-1, %%eax\n\t"
115                         "movl $-1, %%ebx\n\t"
116                         "movl $-1, %%ecx\n\t"
117                         "movl $-1, %%edx\n\t"
118                         "movl $-1, %%esi\n\t"
119                         "movl $-1, %%edi\n\t"
120                         "movl $-1, %%ebp\n\t"
121                         "movl $-1, %%esp\n\t"
122                         "syscall\n\t"
123                         "pushl $0"      /* make sure we segfault cleanly */
124                         : : : "memory", "flags");
125         }
126 
127         return 0;
128 }
129 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp