OSDN Git Service

selftests/seccomp: Improve calibration loop
authorKees Cook <keescook@chromium.org>
Sat, 6 Jun 2020 16:37:17 +0000 (09:37 -0700)
committerKees Cook <keescook@chromium.org>
Fri, 10 Jul 2020 23:01:52 +0000 (16:01 -0700)
The seccomp benchmark calibration loop did not need to take so long.
Instead, use a simple 1 second timeout and multiply up to target. It
does not need to be accurate.

Signed-off-by: Kees Cook <keescook@chromium.org>
tools/testing/selftests/seccomp/seccomp_benchmark.c

index eca13fe..91f5a89 100644 (file)
@@ -18,9 +18,9 @@
 
 unsigned long long timing(clockid_t clk_id, unsigned long long samples)
 {
-       pid_t pid, ret;
-       unsigned long long i;
        struct timespec start, finish;
+       unsigned long long i;
+       pid_t pid, ret;
 
        pid = getpid();
        assert(clock_gettime(clk_id, &start) == 0);
@@ -31,30 +31,43 @@ unsigned long long timing(clockid_t clk_id, unsigned long long samples)
        assert(clock_gettime(clk_id, &finish) == 0);
 
        i = finish.tv_sec - start.tv_sec;
-       i *= 1000000000;
+       i *= 1000000000ULL;
        i += finish.tv_nsec - start.tv_nsec;
 
-       printf("%lu.%09lu - %lu.%09lu = %llu\n",
+       printf("%lu.%09lu - %lu.%09lu = %llu (%.1fs)\n",
                finish.tv_sec, finish.tv_nsec,
                start.tv_sec, start.tv_nsec,
-               i);
+               i, (double)i / 1000000000.0);
 
        return i;
 }
 
 unsigned long long calibrate(void)
 {
-       unsigned long long i;
-
-       printf("Calibrating reasonable sample size...\n");
+       struct timespec start, finish;
+       unsigned long long i, samples, step = 9973;
+       pid_t pid, ret;
+       int seconds = 15;
 
-       for (i = 5; ; i++) {
-               unsigned long long samples = 1 << i;
+       printf("Calibrating sample size for %d seconds worth of syscalls ...\n", seconds);
 
-               /* Find something that takes more than 5 seconds to run. */
-               if (timing(CLOCK_REALTIME, samples) / 1000000000ULL > 5)
-                       return samples;
-       }
+       samples = 0;
+       pid = getpid();
+       assert(clock_gettime(CLOCK_MONOTONIC, &start) == 0);
+       do {
+               for (i = 0; i < step; i++) {
+                       ret = syscall(__NR_getpid);
+                       assert(pid == ret);
+               }
+               assert(clock_gettime(CLOCK_MONOTONIC, &finish) == 0);
+
+               samples += step;
+               i = finish.tv_sec - start.tv_sec;
+               i *= 1000000000ULL;
+               i += finish.tv_nsec - start.tv_nsec;
+       } while (i < 1000000000ULL);
+
+       return samples * seconds;
 }
 
 int main(int argc, char *argv[])
@@ -70,15 +83,16 @@ int main(int argc, char *argv[])
        unsigned long long samples;
        unsigned long long native, filter1, filter2;
 
+       printf("Current BPF sysctl settings:\n");
+       system("sysctl net.core.bpf_jit_enable");
+       system("sysctl net.core.bpf_jit_harden");
+
        if (argc > 1)
                samples = strtoull(argv[1], NULL, 0);
        else
                samples = calibrate();
 
-       printf("Current BPF sysctl settings:\n");
-       system("sysctl net.core.bpf_jit_enable");
-       system("sysctl net.core.bpf_jit_harden");
-       printf("Benchmarking %llu samples...\n", samples);
+       printf("Benchmarking %llu syscalls...\n", samples);
 
        /* Native call */
        native = timing(CLOCK_PROCESS_CPUTIME_ID, samples) / samples;