Skip to content

Commit

Permalink
netfilter: x_tables: add xt_bpf match
Browse files Browse the repository at this point in the history
Support arbitrary linux socket filter (BPF) programs as x_tables
match rules. This allows for very expressive filters, and on
platforms with BPF JIT appears competitive with traditional
hardcoded iptables rules using the u32 match.

The size of the filter has been artificially limited to 64
instructions maximum to avoid bloating the size of each rule
using this new match.

Signed-off-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
  • Loading branch information
Willem de Bruijn authored and Pablo Neira Ayuso committed Jan 21, 2013
1 parent 5a406b0 commit e6f30c7
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 0 deletions.
17 changes: 17 additions & 0 deletions include/uapi/linux/netfilter/xt_bpf.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#ifndef _XT_BPF_H
#define _XT_BPF_H

#include <linux/filter.h>
#include <linux/types.h>

#define XT_BPF_MAX_NUM_INSTR 64

struct xt_bpf_info {
__u16 bpf_program_num_elem;
struct sock_filter bpf_program[XT_BPF_MAX_NUM_INSTR];

/* only used in the kernel */
struct sk_filter *filter __attribute__((aligned(8)));
};

#endif /*_XT_BPF_H */
9 changes: 9 additions & 0 deletions net/netfilter/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -811,6 +811,15 @@ config NETFILTER_XT_MATCH_ADDRTYPE
If you want to compile it as a module, say M here and read
<file:Documentation/kbuild/modules.txt>. If unsure, say `N'.

config NETFILTER_XT_MATCH_BPF
tristate '"bpf" match support'
depends on NETFILTER_ADVANCED
help
BPF matching applies a linux socket filter to each packet and
accepts those for which the filter returns non-zero.

To compile it as a module, choose M here. If unsure, say N.

config NETFILTER_XT_MATCH_CLUSTER
tristate '"cluster" match support'
depends on NF_CONNTRACK
Expand Down
1 change: 1 addition & 0 deletions net/netfilter/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_IDLETIMER) += xt_IDLETIMER.o

# matches
obj-$(CONFIG_NETFILTER_XT_MATCH_ADDRTYPE) += xt_addrtype.o
obj-$(CONFIG_NETFILTER_XT_MATCH_BPF) += xt_bpf.o
obj-$(CONFIG_NETFILTER_XT_MATCH_CLUSTER) += xt_cluster.o
obj-$(CONFIG_NETFILTER_XT_MATCH_COMMENT) += xt_comment.o
obj-$(CONFIG_NETFILTER_XT_MATCH_CONNBYTES) += xt_connbytes.o
Expand Down
73 changes: 73 additions & 0 deletions net/netfilter/xt_bpf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/* Xtables module to match packets using a BPF filter.
* Copyright 2013 Google Inc.
* Written by Willem de Bruijn <willemb@google.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/

#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/filter.h>

#include <linux/netfilter/xt_bpf.h>
#include <linux/netfilter/x_tables.h>

MODULE_AUTHOR("Willem de Bruijn <willemb@google.com>");
MODULE_DESCRIPTION("Xtables: BPF filter match");
MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_bpf");
MODULE_ALIAS("ip6t_bpf");

static int bpf_mt_check(const struct xt_mtchk_param *par)
{
struct xt_bpf_info *info = par->matchinfo;
struct sock_fprog program;

program.len = info->bpf_program_num_elem;
program.filter = (struct sock_filter __user *) info->bpf_program;
if (sk_unattached_filter_create(&info->filter, &program)) {
pr_info("bpf: check failed: parse error\n");
return -EINVAL;
}

return 0;
}

static bool bpf_mt(const struct sk_buff *skb, struct xt_action_param *par)
{
const struct xt_bpf_info *info = par->matchinfo;

return SK_RUN_FILTER(info->filter, skb);
}

static void bpf_mt_destroy(const struct xt_mtdtor_param *par)
{
const struct xt_bpf_info *info = par->matchinfo;
sk_unattached_filter_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 int __init bpf_mt_init(void)
{
return xt_register_match(&bpf_mt_reg);
}

static void __exit bpf_mt_exit(void)
{
xt_unregister_match(&bpf_mt_reg);
}

module_init(bpf_mt_init);
module_exit(bpf_mt_exit);

0 comments on commit e6f30c7

Please sign in to comment.