0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #define _GNU_SOURCE
0012
0013 #include <stdlib.h>
0014 #include <unistd.h>
0015 #include <stdio.h>
0016 #include <string.h>
0017 #include <sys/mman.h>
0018 #include <err.h>
0019 #include <stddef.h>
0020 #include <stdbool.h>
0021 #include <pthread.h>
0022
0023 static void *threadproc(void *ctx)
0024 {
0025
0026
0027
0028
0029 while (true)
0030 ;
0031
0032 return NULL;
0033 }
0034
0035 #ifdef __x86_64__
0036 extern unsigned long call32_from_64(void *stack, void (*function)(void));
0037
0038 asm (".pushsection .text\n\t"
0039 ".code32\n\t"
0040 "test_ss:\n\t"
0041 "pushl $0\n\t"
0042 "popl %eax\n\t"
0043 "ret\n\t"
0044 ".code64");
0045 extern void test_ss(void);
0046 #endif
0047
0048 int main()
0049 {
0050
0051
0052
0053
0054
0055 cpu_set_t cpuset;
0056 CPU_ZERO(&cpuset);
0057 CPU_SET(0, &cpuset);
0058 if (sched_setaffinity(0, sizeof(cpuset), &cpuset) != 0)
0059 printf("[WARN]\tsched_setaffinity failed\n");
0060
0061 pthread_t thread;
0062 if (pthread_create(&thread, 0, threadproc, 0) != 0)
0063 err(1, "pthread_create");
0064
0065 #ifdef __x86_64__
0066 unsigned char *stack32 = mmap(NULL, 4096, PROT_READ | PROT_WRITE,
0067 MAP_32BIT | MAP_ANONYMOUS | MAP_PRIVATE,
0068 -1, 0);
0069 if (stack32 == MAP_FAILED)
0070 err(1, "mmap");
0071 #endif
0072
0073 printf("[RUN]\tSyscalls followed by SS validation\n");
0074
0075 for (int i = 0; i < 1000; i++) {
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085 usleep(2);
0086
0087 #ifdef __x86_64__
0088
0089
0090
0091
0092
0093 call32_from_64(stack32 + 4088, test_ss);
0094 #endif
0095 }
0096
0097 printf("[OK]\tWe survived\n");
0098
0099 #ifdef __x86_64__
0100 munmap(stack32, 4096);
0101 #endif
0102
0103 return 0;
0104 }