From patchwork Tue Dec 6 21:25:02 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Willem de Bruijn X-Patchwork-Id: 703351 X-Patchwork-Delegate: pablo@netfilter.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3tYF5q1wf0z9t1L for ; Wed, 7 Dec 2016 08:25:19 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="fez8mVMs"; dkim-atps=neutral Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751388AbcLFVZI (ORCPT ); Tue, 6 Dec 2016 16:25:08 -0500 Received: from mail-qt0-f195.google.com ([209.85.216.195]:33075 "EHLO mail-qt0-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750785AbcLFVZG (ORCPT ); Tue, 6 Dec 2016 16:25:06 -0500 Received: by mail-qt0-f195.google.com with SMTP id n6so42025842qtd.0; Tue, 06 Dec 2016 13:25:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id; bh=+RSlLy6jBl6sfssOTz7ZvgtOp1CBfrgPaMUhXL1mFlI=; b=fez8mVMsrtd+T8RQ1HKdhZRXQ07hsNlsZ85jaaQNlYW0FM5OWGgxbr9Fk8KYYytEFd kNLWSLHyjBYIKuY4/05vTlKk6oh+gQxz1DT//OYV4ivCytYqxwHrPqcu3aBagaML5AZ0 m7xobSoUsRjf4K+nvzPmiIMDhZaXuOylzUx6qWDF7poSz3nacU0p4A/fPHMfk+i1zfxX Wh0bIhWaiXLx+Jcs9deJi0ALENEzgVM/rIFGPni6NBJo8rbYVo7VbUweqfBX+4rpbRDA ra17/MDzPIprWrLGWucwqccY0v1wahH5vLMW+OqNVib29F33pN/I6bYz4MDsNZ3YAlBg T/tA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=+RSlLy6jBl6sfssOTz7ZvgtOp1CBfrgPaMUhXL1mFlI=; b=g5PHHtTRoBuD/4wuoCKUGNW7pFM/SkzoZhEe+PeH5d4v3wlUZ71yBt+P3S+svDrsLj vKfnJQ+rFa/f0fk143bnREcGuddbvwBHHABdTztMaesikqK8p4blf5GrAh1Uz9yOoLjL s9gIvTway7yBnKGdz9XIYw7wYKlsHdAeyukmDv6GoPFSz3qm92+vYxdjAO9bxutjcEDX D5oH3OozvPZ2UyaBEbJ+whAwq/uMhLLneYFwJQ4Rwlpga+4fJj+SHDYGEk7q/FVQua4G /OXS4WJEZj+A1ezZdCMMPWDZF2N+4Oxi2/xPVkCx/0AX3caPPbZM5oWoNpw5bSHHdCgQ joAQ== X-Gm-Message-State: AKaTC03N8pZNF5yP2WYTMsNizgUGFQUA1oozsVFDhoFNfrBVCdPx+SpAL3cLEpIqam2wzA== X-Received: by 10.200.50.202 with SMTP id a10mr62633355qtb.232.1481059505543; Tue, 06 Dec 2016 13:25:05 -0800 (PST) Received: from willemb1.nyc.corp.google.com ([100.101.230.128]) by smtp.gmail.com with ESMTPSA id f2sm10267372qtg.22.2016.12.06.13.25.04 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 06 Dec 2016 13:25:05 -0800 (PST) From: Willem de Bruijn To: netfilter-devel@vger.kernel.org Cc: fw@strlen.de, eric.dumazet@gmail.com, pablo@netfilter.org, netdev@vger.kernel.org, daniel@iogearbox.net, Willem de Bruijn Subject: [PATCH nf-next v2] netfilter: xt_bpf: support ebpf Date: Tue, 6 Dec 2016 16:25:02 -0500 Message-Id: <1481059502-47824-1-git-send-email-willemdebruijn.kernel@gmail.com> X-Mailer: git-send-email 2.8.0.rc3.226.g39d4020 Sender: netfilter-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org From: Willem de Bruijn Add support for attaching an eBPF object by file descriptor. The iptables binary can be called with a path to an elf object or a pinned bpf object. Also pass the mode and path to the kernel to be able to return it later for iptables dump and save. Signed-off-by: Willem de Bruijn --- Changes v1 -> v2 - define XT_BPF_PATH_MAX (== 512: does not grow structure size) --- include/uapi/linux/netfilter/xt_bpf.h | 21 ++++++++ net/netfilter/xt_bpf.c | 96 +++++++++++++++++++++++++++++------ 2 files changed, 101 insertions(+), 16 deletions(-) diff --git a/include/uapi/linux/netfilter/xt_bpf.h b/include/uapi/linux/netfilter/xt_bpf.h index 1fad2c2..b97725a 100644 --- a/include/uapi/linux/netfilter/xt_bpf.h +++ b/include/uapi/linux/netfilter/xt_bpf.h @@ -2,9 +2,11 @@ #define _XT_BPF_H #include +#include #include #define XT_BPF_MAX_NUM_INSTR 64 +#define XT_BPF_PATH_MAX (XT_BPF_MAX_NUM_INSTR * sizeof(struct sock_filter)) struct bpf_prog; @@ -16,4 +18,23 @@ struct xt_bpf_info { struct bpf_prog *filter __attribute__((aligned(8))); }; +enum xt_bpf_modes { + XT_BPF_MODE_BYTECODE, + XT_BPF_MODE_FD_PINNED, + XT_BPF_MODE_FD_ELF, +}; + +struct xt_bpf_info_v1 { + __u16 mode; + __u16 bpf_program_num_elem; + __s32 fd; + union { + struct sock_filter bpf_program[XT_BPF_MAX_NUM_INSTR]; + char path[XT_BPF_PATH_MAX]; + }; + + /* only used in the kernel */ + struct bpf_prog *filter __attribute__((aligned(8))); +}; + #endif /*_XT_BPF_H */ diff --git a/net/netfilter/xt_bpf.c b/net/netfilter/xt_bpf.c index dffee9d47..2dedaa2 100644 --- a/net/netfilter/xt_bpf.c +++ b/net/netfilter/xt_bpf.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -20,15 +21,15 @@ MODULE_LICENSE("GPL"); MODULE_ALIAS("ipt_bpf"); MODULE_ALIAS("ip6t_bpf"); -static int bpf_mt_check(const struct xt_mtchk_param *par) +static int __bpf_mt_check_bytecode(struct sock_filter *insns, __u16 len, + struct bpf_prog **ret) { - struct xt_bpf_info *info = par->matchinfo; struct sock_fprog_kern program; - program.len = info->bpf_program_num_elem; - program.filter = info->bpf_program; + program.len = len; + program.filter = insns; - if (bpf_prog_create(&info->filter, &program)) { + if (bpf_prog_create(ret, &program)) { pr_info("bpf: check failed: parse error\n"); return -EINVAL; } @@ -36,6 +37,42 @@ static int bpf_mt_check(const struct xt_mtchk_param *par) return 0; } +static int __bpf_mt_check_fd(int fd, struct bpf_prog **ret) +{ + struct bpf_prog *prog; + + prog = bpf_prog_get_type(fd, BPF_PROG_TYPE_SOCKET_FILTER); + if (IS_ERR(prog)) + return PTR_ERR(prog); + + *ret = prog; + return 0; +} + +static int bpf_mt_check(const struct xt_mtchk_param *par) +{ + struct xt_bpf_info *info = par->matchinfo; + + return __bpf_mt_check_bytecode(info->bpf_program, + info->bpf_program_num_elem, + &info->filter); +} + +static int bpf_mt_check_v1(const struct xt_mtchk_param *par) +{ + struct xt_bpf_info_v1 *info = par->matchinfo; + + if (info->mode == XT_BPF_MODE_BYTECODE) + return __bpf_mt_check_bytecode(info->bpf_program, + info->bpf_program_num_elem, + &info->filter); + else if (info->mode == XT_BPF_MODE_FD_PINNED || + info->mode == XT_BPF_MODE_FD_ELF) + return __bpf_mt_check_fd(info->fd, &info->filter); + else + return -EINVAL; +} + static bool bpf_mt(const struct sk_buff *skb, struct xt_action_param *par) { const struct xt_bpf_info *info = par->matchinfo; @@ -43,31 +80,58 @@ static bool bpf_mt(const struct sk_buff *skb, struct xt_action_param *par) return BPF_PROG_RUN(info->filter, skb); } +static bool bpf_mt_v1(const struct sk_buff *skb, struct xt_action_param *par) +{ + const struct xt_bpf_info_v1 *info = par->matchinfo; + + return !!bpf_prog_run_save_cb(info->filter, (struct sk_buff *) skb); +} + static void bpf_mt_destroy(const struct xt_mtdtor_param *par) { const struct xt_bpf_info *info = par->matchinfo; + + bpf_prog_destroy(info->filter); +} + +static void bpf_mt_destroy_v1(const struct xt_mtdtor_param *par) +{ + const struct xt_bpf_info_v1 *info = par->matchinfo; + bpf_prog_destroy(info->filter); } -static struct xt_match bpf_mt_reg __read_mostly = { - .name = "bpf", - .revision = 0, - .family = NFPROTO_UNSPEC, - .checkentry = bpf_mt_check, - .match = bpf_mt, - .destroy = bpf_mt_destroy, - .matchsize = sizeof(struct xt_bpf_info), - .me = THIS_MODULE, +static struct xt_match bpf_mt_reg[] __read_mostly = { + { + .name = "bpf", + .revision = 0, + .family = NFPROTO_UNSPEC, + .checkentry = bpf_mt_check, + .match = bpf_mt, + .destroy = bpf_mt_destroy, + .matchsize = sizeof(struct xt_bpf_info), + .me = THIS_MODULE, + }, + { + .name = "bpf", + .revision = 1, + .family = NFPROTO_UNSPEC, + .checkentry = bpf_mt_check_v1, + .match = bpf_mt_v1, + .destroy = bpf_mt_destroy_v1, + .matchsize = sizeof(struct xt_bpf_info_v1), + .me = THIS_MODULE, + }, }; static int __init bpf_mt_init(void) { - return xt_register_match(&bpf_mt_reg); + return xt_register_matches(bpf_mt_reg, ARRAY_SIZE(bpf_mt_reg)); } static void __exit bpf_mt_exit(void) { - xt_unregister_match(&bpf_mt_reg); + xt_unregister_matches(bpf_mt_reg, ARRAY_SIZE(bpf_mt_reg)); } module_init(bpf_mt_init);