From patchwork Mon Aug 14 20:53:49 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 9900141 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id AFF39602D9 for ; Mon, 14 Aug 2017 20:53:54 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A08CB28737 for ; Mon, 14 Aug 2017 20:53:54 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9455D28739; Mon, 14 Aug 2017 20:53:54 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D84F128737 for ; Mon, 14 Aug 2017 20:53:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752241AbdHNUxw (ORCPT ); Mon, 14 Aug 2017 16:53:52 -0400 Received: from mail-pg0-f52.google.com ([74.125.83.52]:37094 "EHLO mail-pg0-f52.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751644AbdHNUxv (ORCPT ); Mon, 14 Aug 2017 16:53:51 -0400 Received: by mail-pg0-f52.google.com with SMTP id y129so54397680pgy.4 for ; Mon, 14 Aug 2017 13:53:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=date:from:to:cc:subject:message-id:mime-version:content-disposition; bh=IulGxy5yy+uIzuDxhFBmyWN+qoCLaF+ZNbo6X3mG7Nc=; b=m7qGW9z0leK0tH8GFc3dzt5ZxpxC+o9vTqldhN5cU469+6RaGyKKUMfHowLwRcR31O BfHPRb43r8wZFUV1fe1QnApRmtZD9iB4RmMY8SYdJnzQAGfda0ilLBsDovVvYHQy/nJg IrETcnxwv0sxK5uPrQX/YX4hYZs3YkF0yWl/k= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:mime-version :content-disposition; bh=IulGxy5yy+uIzuDxhFBmyWN+qoCLaF+ZNbo6X3mG7Nc=; b=DcyKLNhidVb/tjvSPKI15UZCVfd+fj1WmH6wZykEVhcpndleGWp3L2Yc9XX3D7qrjX n0e7+FyIjLuRCFHJA6s++MG5IxT4sHM98X4pYxKk6o7kB7n61aF+GY7Dtt/M3D6nWNI8 sdiiAoM8hpjRbD3SoWSiLF710gHikJJceXre7asGxWeVjbNlY1BtYC+U4KBjSFueDzGW /NqC03oOlzm9Ujoj2q5j7Fz3lGcsNrODXtqtMuMFo/JuL/PwieuYyvYRU7xjocasz4I0 Gyruoq3ji3uhsLqIIaMi3yZgl/eoeLodzioc6/AKngrrS47rQPlxuzIwS2kJ3vmhNn1/ kIOA== X-Gm-Message-State: AHYfb5iXfL2rwWt+w6w4Ywu+y3cMw6bMgIGtH2LeerwWaaitEb/kQ5TC pRk92GV1/Bq5fseY X-Received: by 10.98.79.151 with SMTP id f23mr25651301pfj.57.1502744031140; Mon, 14 Aug 2017 13:53:51 -0700 (PDT) Received: from www.outflux.net (173-164-112-133-Oregon.hfc.comcastbusiness.net. [173.164.112.133]) by smtp.gmail.com with ESMTPSA id m2sm13470724pgs.72.2017.08.14.13.53.50 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 14 Aug 2017 13:53:50 -0700 (PDT) Date: Mon, 14 Aug 2017 13:53:49 -0700 From: Kees Cook To: Shuah Khan Cc: Shuah Khan , linux-kselftest@vger.kernel.org, Andy Lutomirski , Will Drewry , linux-security-module@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH] selftests/seccomp: Add simple seccomp overhead benchmark Message-ID: <20170814205349.GA60377@beast> MIME-Version: 1.0 Content-Disposition: inline Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: X-Virus-Scanned: ClamAV using ClamSMTP This attempts to produce a comparison between native getpid() and a RET_ALLOW-filtered getpid(), to measure the overhead cost of using seccomp(). Signed-off-by: Kees Cook --- As with the other, I'd like this to go via the seccomp tree. Getting an Ack would be great. :) Thanks! --- tools/testing/selftests/seccomp/Makefile | 18 ++-- .../testing/selftests/seccomp/seccomp_benchmark.c | 99 ++++++++++++++++++++++ 2 files changed, 112 insertions(+), 5 deletions(-) create mode 100644 tools/testing/selftests/seccomp/seccomp_benchmark.c diff --git a/tools/testing/selftests/seccomp/Makefile b/tools/testing/selftests/seccomp/Makefile index aeb0c805f3ca..553d870b4ca9 100644 --- a/tools/testing/selftests/seccomp/Makefile +++ b/tools/testing/selftests/seccomp/Makefile @@ -1,8 +1,16 @@ -TEST_GEN_PROGS := seccomp_bpf -CFLAGS += -Wl,-no-as-needed -Wall -LDFLAGS += -lpthread +all: include ../lib.mk -$(TEST_GEN_PROGS): seccomp_bpf.c ../kselftest_harness.h - $(CC) $(CFLAGS) $(LDFLAGS) $< -o $@ +.PHONY: all clean + +BINARIES := seccomp_bpf seccomp_benchmark +CFLAGS += -Wl,-no-as-needed -Wall + +seccomp_bpf: seccomp_bpf.c ../kselftest_harness.h + $(CC) $(CFLAGS) $(LDFLAGS) -lpthread $< -o $@ + +TEST_PROGS += $(BINARIES) +EXTRA_CLEAN := $(BINARIES) + +all: $(BINARIES) diff --git a/tools/testing/selftests/seccomp/seccomp_benchmark.c b/tools/testing/selftests/seccomp/seccomp_benchmark.c new file mode 100644 index 000000000000..5838c8697ec3 --- /dev/null +++ b/tools/testing/selftests/seccomp/seccomp_benchmark.c @@ -0,0 +1,99 @@ +/* + * Strictly speaking, this is not a test. But it can report during test + * runs so relative performace can be measured. + */ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) + +unsigned long long timing(clockid_t clk_id, unsigned long long samples) +{ + pid_t pid, ret; + unsigned long long i; + struct timespec start, finish; + + pid = getpid(); + assert(clock_gettime(clk_id, &start) == 0); + for (i = 0; i < samples; i++) { + ret = syscall(__NR_getpid); + assert(pid == ret); + } + assert(clock_gettime(clk_id, &finish) == 0); + + i = finish.tv_sec - start.tv_sec; + i *= 1000000000; + i += finish.tv_nsec - start.tv_nsec; + + printf("%lu.%09lu - %lu.%09lu = %llu\n", + finish.tv_sec, finish.tv_nsec, + start.tv_sec, start.tv_nsec, + i); + + return i; +} + +unsigned long long calibrate(void) +{ + unsigned long long i; + + printf("Calibrating reasonable sample size...\n"); + + for (i = 5; ; i++) { + unsigned long long samples = 1 << i; + + /* Find something that takes more than 5 seconds to run. */ + if (timing(CLOCK_REALTIME, samples) / 1000000000ULL > 5) + return samples; + } +} + +int main(int argc, char *argv[]) +{ + struct sock_filter filter[] = { + BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW), + }; + struct sock_fprog prog = { + .len = (unsigned short)ARRAY_SIZE(filter), + .filter = filter, + }; + long ret; + unsigned long long samples; + unsigned long long native, filtered; + + if (argc > 1) + samples = strtoull(argv[1], NULL, 0); + else + samples = calibrate(); + + printf("Benchmarking %llu samples...\n", samples); + + native = timing(CLOCK_PROCESS_CPUTIME_ID, samples) / samples; + printf("getpid native: %llu ns\n", native); + + ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); + assert(ret == 0); + + ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog); + assert(ret == 0); + + filtered = timing(CLOCK_PROCESS_CPUTIME_ID, samples) / samples; + printf("getpid RET_ALLOW: %llu ns\n", filtered); + + printf("Estimated seccomp overhead per syscall: %llu ns\n", + filtered - native); + + if (filtered == native) + printf("Trying running again with more samples.\n"); + + return 0; +}