summaryrefslogtreecommitdiff
path: root/include/linux
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2015-04-04 15:23:15 -0400
committerDavid S. Miller <davem@davemloft.net>2015-04-04 15:23:15 -0400
commit5888b93b750609680735d6b8b737703083ef40ff (patch)
tree181f959eaf7d8084ff33f64d3356e3213c5f01bf /include/linux
parentb81b7be6ae830a507d15cf4fc626be02cc9ab79b (diff)
parentb85c3dc9bd5347ad9540ec8d103b7c049c48b7cd (diff)
Merge branch 'nf-hook-compress'
netfilter: Compress hook function signatures. Currently netfilter hooks have a function signature that is huge and has many arguments. This propagates from the hook entry points down into the individual hook implementations themselves. This means that if, for example, we want to change the type of one of these arguments then we have to touch hundreds of locations. The main initial motivation behind this is that we'd like to change the signature of "okfn" so that a socket pointer can be passed in (and reference counted properly) for the sake of using the proper socket context in the case of tunnels whilst not releasing the top level user socket from skb->sk (and thus releasing it's socket memory quota usage) in order to accomodate this. This also makes it clear who actually uses 'okfn', nf_queue(). It is absolutely critical to make this obvious because any user of 'okfn' down in these hook chains have the be strictly audited for escapability. Specifically, escapability of references to objects outside of the packet processing path. And that's exactly what nf_queue() does via it's packet reinjection framework. In fact this points out a bug in Jiri's original attempt to push the socket pointer down through netfilter's okfn. It didn't grab and drop a reference to the socket in net/netfilter/nf_queue.c as needed. Furthermore, so many code paths are simplified, and should in fact be more efficient because we aren't passing in arguments that often are simply not used by the netfilter hook at all. Further simplifications are probably possible, but this series takes care of the main cases. Unfortunately I couldn't convert ebt_do_table() because ebtables is complete and utter crap and uses ebt_do_table() outside of the hook call chains. But that should not be news to anyone. Signed-off-by: David S. Miller <davem@davemloft.net> Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/netfilter.h32
-rw-r--r--include/linux/netfilter_arp/arp_tables.h3
-rw-r--r--include/linux/netfilter_ipv4/ip_tables.h3
-rw-r--r--include/linux/netfilter_ipv6/ip6_tables.h3
4 files changed, 27 insertions, 14 deletions
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index 2517ece98820..c480c43ad8f7 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -44,11 +44,19 @@ int netfilter_init(void);
struct sk_buff;
struct nf_hook_ops;
+
+struct nf_hook_state {
+ unsigned int hook;
+ int thresh;
+ u_int8_t pf;
+ struct net_device *in;
+ struct net_device *out;
+ int (*okfn)(struct sk_buff *);
+};
+
typedef unsigned int nf_hookfn(const struct nf_hook_ops *ops,
struct sk_buff *skb,
- const struct net_device *in,
- const struct net_device *out,
- int (*okfn)(struct sk_buff *));
+ const struct nf_hook_state *state);
struct nf_hook_ops {
struct list_head list;
@@ -118,9 +126,7 @@ static inline bool nf_hooks_active(u_int8_t pf, unsigned int hook)
}
#endif
-int nf_hook_slow(u_int8_t pf, unsigned int hook, struct sk_buff *skb,
- struct net_device *indev, struct net_device *outdev,
- int (*okfn)(struct sk_buff *), int thresh);
+int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state);
/**
* nf_hook_thresh - call a netfilter hook
@@ -135,8 +141,18 @@ static inline int nf_hook_thresh(u_int8_t pf, unsigned int hook,
struct net_device *outdev,
int (*okfn)(struct sk_buff *), int thresh)
{
- if (nf_hooks_active(pf, hook))
- return nf_hook_slow(pf, hook, skb, indev, outdev, okfn, thresh);
+ if (nf_hooks_active(pf, hook)) {
+ struct nf_hook_state state = {
+ .hook = hook,
+ .thresh = thresh,
+ .pf = pf,
+ .in = indev,
+ .out = outdev,
+ .okfn = okfn
+ };
+
+ return nf_hook_slow(skb, &state);
+ }
return 1;
}
diff --git a/include/linux/netfilter_arp/arp_tables.h b/include/linux/netfilter_arp/arp_tables.h
index cfb7191e6efa..c22a7fb8d0df 100644
--- a/include/linux/netfilter_arp/arp_tables.h
+++ b/include/linux/netfilter_arp/arp_tables.h
@@ -54,8 +54,7 @@ extern struct xt_table *arpt_register_table(struct net *net,
extern void arpt_unregister_table(struct xt_table *table);
extern unsigned int arpt_do_table(struct sk_buff *skb,
unsigned int hook,
- const struct net_device *in,
- const struct net_device *out,
+ const struct nf_hook_state *state,
struct xt_table *table);
#ifdef CONFIG_COMPAT
diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h
index 901e84db847d..4073510da485 100644
--- a/include/linux/netfilter_ipv4/ip_tables.h
+++ b/include/linux/netfilter_ipv4/ip_tables.h
@@ -65,8 +65,7 @@ struct ipt_error {
extern void *ipt_alloc_initial_table(const struct xt_table *);
extern unsigned int ipt_do_table(struct sk_buff *skb,
unsigned int hook,
- const struct net_device *in,
- const struct net_device *out,
+ const struct nf_hook_state *state,
struct xt_table *table);
#ifdef CONFIG_COMPAT
diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h
index 610208b18c05..b40d2b635778 100644
--- a/include/linux/netfilter_ipv6/ip6_tables.h
+++ b/include/linux/netfilter_ipv6/ip6_tables.h
@@ -31,8 +31,7 @@ extern struct xt_table *ip6t_register_table(struct net *net,
extern void ip6t_unregister_table(struct net *net, struct xt_table *table);
extern unsigned int ip6t_do_table(struct sk_buff *skb,
unsigned int hook,
- const struct net_device *in,
- const struct net_device *out,
+ const struct nf_hook_state *state,
struct xt_table *table);
/* Check for an extension */