1 /* 2 * Strictly speaking, this is not a test. But it can report during test 3 * runs so relative performace can be measured. 4 */ 5 #define _GNU_SOURCE 6 #include <assert.h> 7 #include <stdio.h> 8 #include <stdlib.h> 9 #include <time.h> 10 #include <unistd.h> 11 #include <linux/filter.h> 12 #include <linux/seccomp.h> 13 #include <sys/prctl.h> 14 #include <sys/syscall.h> 15 #include <sys/types.h> 16 17 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) 18 19 unsigned long long timing(clockid_t clk_id, unsigned long long samples) 20 { 21 pid_t pid, ret; 22 unsigned long long i; 23 struct timespec start, finish; 24 25 pid = getpid(); 26 assert(clock_gettime(clk_id, &start) == 0); 27 for (i = 0; i < samples; i++) { 28 ret = syscall(__NR_getpid); 29 assert(pid == ret); 30 } 31 assert(clock_gettime(clk_id, &finish) == 0); 32 33 i = finish.tv_sec - start.tv_sec; 34 i *= 1000000000; 35 i += finish.tv_nsec - start.tv_nsec; 36 37 printf("%lu.%09lu - %lu.%09lu = %llu\n", 38 finish.tv_sec, finish.tv_nsec, 39 start.tv_sec, start.tv_nsec, 40 i); 41 42 return i; 43 } 44 45 unsigned long long calibrate(void) 46 { 47 unsigned long long i; 48 49 printf("Calibrating reasonable sample size...\n"); 50 51 for (i = 5; ; i++) { 52 unsigned long long samples = 1 << i; 53 54 /* Find something that takes more than 5 seconds to run. */ 55 if (timing(CLOCK_REALTIME, samples) / 1000000000ULL > 5) 56 return samples; 57 } 58 } 59 60 int main(int argc, char *argv[]) 61 { 62 struct sock_filter filter[] = { 63 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW), 64 }; 65 struct sock_fprog prog = { 66 .len = (unsigned short)ARRAY_SIZE(filter), 67 .filter = filter, 68 }; 69 long ret; 70 unsigned long long samples; 71 unsigned long long native, filtered; 72 73 if (argc > 1) 74 samples = strtoull(argv[1], NULL, 0); 75 else 76 samples = calibrate(); 77 78 printf("Benchmarking %llu samples...\n", samples); 79 80 native = timing(CLOCK_PROCESS_CPUTIME_ID, samples) / samples; 81 printf("getpid native: %llu ns\n", native); 82 83 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); 84 assert(ret == 0); 85 86 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog); 87 assert(ret == 0); 88 89 filtered = timing(CLOCK_PROCESS_CPUTIME_ID, samples) / samples; 90 printf("getpid RET_ALLOW: %llu ns\n", filtered); 91 92 printf("Estimated seccomp overhead per syscall: %llu ns\n", 93 filtered - native); 94 95 if (filtered == native) 96 printf("Trying running again with more samples.\n"); 97 98 return 0; 99 } 100