From patchwork Thu Aug 4 07:11:53 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sargun Dhillon X-Patchwork-Id: 9262797 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 745BF60839 for ; Thu, 4 Aug 2016 07:12:29 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 61D34280F4 for ; Thu, 4 Aug 2016 07:12:29 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 55F0028308; Thu, 4 Aug 2016 07:12:29 +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=unavailable 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 A2ECD280F4 for ; Thu, 4 Aug 2016 07:12:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756802AbcHDHL7 (ORCPT ); Thu, 4 Aug 2016 03:11:59 -0400 Received: from mail-io0-f177.google.com ([209.85.223.177]:33004 "EHLO mail-io0-f177.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756674AbcHDHL4 (ORCPT ); Thu, 4 Aug 2016 03:11:56 -0400 Received: by mail-io0-f177.google.com with SMTP id 38so264363039iol.0 for ; Thu, 04 Aug 2016 00:11:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sargun.me; s=google; h=date:from:to:cc:subject:message-id:mime-version:content-disposition :user-agent; bh=p7G6RRPX2oNRgwP3YZUWwwe5gnzOdmLdyLFNvRXHmWU=; b=h+P7PyP1ZllkBQ5Xzo2jFjR+PhELdC5P7JryUACMv9C+PUn2u2kHQRzVun9XFQrOJI ZkBJyGT5lRcX5U7DYj7G3jW1rJOmsxrmuwlZy1kpX6CbTie1sB5KTgLhbBglKEjM+UCp o9cqH/J15HW7hqvJ3vZTbffkpqhfx8xkwSwN0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:date:from:to:cc:subject:message-id:mime-version :content-disposition:user-agent; bh=p7G6RRPX2oNRgwP3YZUWwwe5gnzOdmLdyLFNvRXHmWU=; b=gODla1mkYFKwqTNzRBItKDmZuQldoPrgxeZAy8RQ4DnjYUlyS0CHBHhFUDaE7J76U7 yxQeTsrONVMUM4cg2/uDNehaaY5GAYluC5IwR5Fp9FSmSa9e1DZSJ6zz/SGw6iMv87D8 +Ou+qZ9ZTxY+TA+y40lx/tEpPZZvn5JEBVwcDZ7HSb3a97H9cRuihH1mgS7a9pihJStn LMqxUZUT6BDshMX8OJDhiv1TMqPiqf/RTCclJ3EsYn5X5Z0bX2vDGgxE8Clih/iezKoS f+5B0DFGX1IlkQ/fuTlNSl79kfyZ3miFg16kBcXbI+7AgPVQShXpEvWjRmsk69NaNxfD jxKA== X-Gm-Message-State: AEkoousCn4IzLwLOrrnryfJmQ4u5GsO4Of5AuLoTjrobA3wCGJAkhTnjYH8mY6VSJY9vMA== X-Received: by 10.107.17.68 with SMTP id z65mr71810390ioi.150.1470294715338; Thu, 04 Aug 2016 00:11:55 -0700 (PDT) Received: from ircssh.c.rugged-nimbus-611.internal (55.145.251.23.bc.googleusercontent.com. [23.251.145.55]) by smtp.gmail.com with ESMTPSA id 97sm5214530ioi.12.2016.08.04.00.11.55 (version=TLS1_2 cipher=AES128-SHA bits=128/128); Thu, 04 Aug 2016 00:11:55 -0700 (PDT) Date: Thu, 4 Aug 2016 00:11:53 -0700 From: Sargun Dhillon To: linux-kernel@vger.kernel.org Cc: alexei.starovoitov@gmail.com, daniel@iogearbox.net, linux-security-module@vger.kernel.org, netdev@vger.kernel.org Subject: [RFC 3/4] security/checmate: Add Checmate sample Message-ID: <20160804071152.GA19128@ircssh.c.rugged-nimbus-611.internal> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: X-Virus-Scanned: ClamAV using ClamSMTP The Checmate sample installs a policy barring new AF_INET connections to port 1. We install the hook, and show an example of connect returning EPERM, and then reset the policy. If this is running concurrently with other policy engines, bad things could happen. Signed-off-by: Sargun Dhillon --- samples/bpf/Makefile | 4 ++++ samples/bpf/bpf_load.c | 11 ++++++--- samples/bpf/checmate1_kern.c | 27 ++++++++++++++++++++++ samples/bpf/checmate1_user.c | 54 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 93 insertions(+), 3 deletions(-) create mode 100644 samples/bpf/checmate1_kern.c create mode 100644 samples/bpf/checmate1_user.c diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile index 90ebf7d..83e1da8 100644 --- a/samples/bpf/Makefile +++ b/samples/bpf/Makefile @@ -24,6 +24,7 @@ hostprogs-y += test_overhead hostprogs-y += test_cgrp2_array_pin hostprogs-y += xdp1 hostprogs-y += xdp2 +hostprogs-y += checmate1 test_verifier-objs := test_verifier.o libbpf.o test_maps-objs := test_maps.o libbpf.o @@ -49,6 +50,7 @@ test_cgrp2_array_pin-objs := libbpf.o test_cgrp2_array_pin.o xdp1-objs := bpf_load.o libbpf.o xdp1_user.o # reuse xdp1 source intentionally xdp2-objs := bpf_load.o libbpf.o xdp1_user.o +checmate1-objs := bpf_load.o libbpf.o checmate1_user.o # Tell kbuild to always build the programs always := $(hostprogs-y) @@ -74,6 +76,7 @@ always += parse_varlen.o parse_simple.o parse_ldabs.o always += test_cgrp2_tc_kern.o always += xdp1_kern.o always += xdp2_kern.o +always += checmate1_kern.o HOSTCFLAGS += -I$(objtree)/usr/include @@ -97,6 +100,7 @@ HOSTLOADLIBES_map_perf_test += -lelf -lrt HOSTLOADLIBES_test_overhead += -lelf -lrt HOSTLOADLIBES_xdp1 += -lelf HOSTLOADLIBES_xdp2 += -lelf +HOSTLOADLIBES_checmate1 += -lelf # Allows pointing LLC/CLANG to a LLVM backend with bpf support, redefine on cmdline: # make samples/bpf/ LLC=~/git/llvm/build/bin/llc CLANG=~/git/llvm/build/bin/clang diff --git a/samples/bpf/bpf_load.c b/samples/bpf/bpf_load.c index 0cfda23..49e84e7b 100644 --- a/samples/bpf/bpf_load.c +++ b/samples/bpf/bpf_load.c @@ -51,6 +51,7 @@ static int load_and_attach(const char *event, struct bpf_insn *prog, int size) bool is_kretprobe = strncmp(event, "kretprobe/", 10) == 0; bool is_tracepoint = strncmp(event, "tracepoint/", 11) == 0; bool is_xdp = strncmp(event, "xdp", 3) == 0; + bool is_checmate = strncmp(event, "checmate", 8) == 0; enum bpf_prog_type prog_type; char buf[256]; int fd, efd, err, id; @@ -69,6 +70,8 @@ static int load_and_attach(const char *event, struct bpf_insn *prog, int size) prog_type = BPF_PROG_TYPE_TRACEPOINT; } else if (is_xdp) { prog_type = BPF_PROG_TYPE_XDP; + } else if (is_checmate) { + prog_type = BPF_PROG_TYPE_CHECMATE; } else { printf("Unknown event '%s'\n", event); return -1; @@ -82,7 +85,7 @@ static int load_and_attach(const char *event, struct bpf_insn *prog, int size) prog_fd[prog_cnt++] = fd; - if (is_xdp) + if (is_xdp || is_checmate) return 0; if (is_socket) { @@ -326,7 +329,8 @@ int load_bpf_file(char *path) memcmp(shname_prog, "kretprobe/", 10) == 0 || memcmp(shname_prog, "tracepoint/", 11) == 0 || memcmp(shname_prog, "xdp", 3) == 0 || - memcmp(shname_prog, "socket", 6) == 0) + memcmp(shname_prog, "socket", 6) == 0 || + memcpy(shname_prog, "checmate", 8) == 0) load_and_attach(shname_prog, insns, data_prog->d_size); } } @@ -344,7 +348,8 @@ int load_bpf_file(char *path) memcmp(shname, "kretprobe/", 10) == 0 || memcmp(shname, "tracepoint/", 11) == 0 || memcmp(shname, "xdp", 3) == 0 || - memcmp(shname, "socket", 6) == 0) + memcmp(shname, "socket", 6) == 0 || + memcmp(shname, "checmate", 8) == 0) load_and_attach(shname, data->d_buf, data->d_size); } diff --git a/samples/bpf/checmate1_kern.c b/samples/bpf/checmate1_kern.c new file mode 100644 index 0000000..f78b66b --- /dev/null +++ b/samples/bpf/checmate1_kern.c @@ -0,0 +1,27 @@ +#include +#include +#include +#include +#include "bpf_helpers.h" + +SEC("checmate") +int prog(struct checmate_ctx *ctx) +{ + struct sockaddr address; + struct sockaddr_in *in_addr; + char fmt[] = "Denying access on port 1\n"; + + bpf_probe_read(&address, sizeof(struct sockaddr_in), + ctx->socket_connect_ctx.address); + if (address.sa_family == AF_INET) { + in_addr = (struct sockaddr_in *) &address; + if (be16_to_cpu(in_addr->sin_port) == 1) { + bpf_trace_printk(fmt, sizeof(fmt)); + return -EPERM; + } + } + return 0; +} + +char _license[] SEC("license") = "GPL"; + diff --git a/samples/bpf/checmate1_user.c b/samples/bpf/checmate1_user.c new file mode 100644 index 0000000..94b7040 --- /dev/null +++ b/samples/bpf/checmate1_user.c @@ -0,0 +1,54 @@ +#include +#include +#include +#include +#include +#include +#include +#include "bpf_load.h" +#include "libbpf.h" +#include +#include +#include + +int main(int ac, char **argv) +{ + char filename[256]; + int rc = 0; + int sockfd; + struct sockaddr_in in_addr; + + snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); + if (load_bpf_file(filename)) { + printf("%s", bpf_log_buf); + return 1; + } + if (!prog_fd[0]) { + printf("load_bpf_file: %s\n", strerror(errno)); + return 1; + } + rc = prctl(PR_CHECMATE, CHECMATE_INSTALL_HOOK, + CHECMATE_HOOK_SOCKET_CONNECT, prog_fd[0]); + if (rc) { + printf("Failed to install hook: %s\n", strerror(errno)); + return 1; + } + assert((sockfd = socket(AF_INET, SOCK_STREAM, 0)) > 0); + + /* Fake destination address (on loopback) on port 1 */ + in_addr.sin_family = AF_INET; + in_addr.sin_port = htons(1); + in_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + assert(connect(sockfd, (const struct sockaddr *)&in_addr, + sizeof(in_addr)) != 0); + assert(errno = -EPERM); + + rc = prctl(PR_CHECMATE, CHECMATE_RESET, + CHECMATE_HOOK_SOCKET_CONNECT, prog_fd[0]); + if (rc) { + printf("Failed to reset hook: %s\n", strerror(errno)); + return 1; + } + + return rc; +}