aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2014-05-10 12:33:11 -0400
committerPablo Neira Ayuso <pablo@netfilter.org>2014-05-12 10:32:41 -0400
commit5467a512216753d54f757314c73dbc60f659f9e6 (patch)
tree1e5bbf0c9fcae75c7076baf0aee64123698ac8c0
parentd088be8042841f024156ee68fecfef7503d660cb (diff)
netfilter: nf_tables: fix goto action
This patch fixes a crash when trying to access the counters and the default chain policy from the non-base chain that we have reached via the goto chain. Fix this by falling back on the original base chain after returning from the custom chain. While fixing this, kill the inline function to account chain statistics to improve source code readability. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--net/netfilter/nf_tables_core.c28
1 files changed, 10 insertions, 18 deletions
diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c
index 4368c5850548..7d83a49fd8e5 100644
--- a/net/netfilter/nf_tables_core.c
+++ b/net/netfilter/nf_tables_core.c
@@ -66,20 +66,6 @@ struct nft_jumpstack {
66 int rulenum; 66 int rulenum;
67}; 67};
68 68
69static inline void
70nft_chain_stats(const struct nft_chain *this, const struct nft_pktinfo *pkt,
71 struct nft_jumpstack *jumpstack, unsigned int stackptr)
72{
73 struct nft_stats __percpu *stats;
74 const struct nft_chain *chain = stackptr ? jumpstack[0].chain : this;
75
76 rcu_read_lock_bh();
77 stats = rcu_dereference(nft_base_chain(chain)->stats);
78 __this_cpu_inc(stats->pkts);
79 __this_cpu_add(stats->bytes, pkt->skb->len);
80 rcu_read_unlock_bh();
81}
82
83enum nft_trace { 69enum nft_trace {
84 NFT_TRACE_RULE, 70 NFT_TRACE_RULE,
85 NFT_TRACE_RETURN, 71 NFT_TRACE_RETURN,
@@ -117,12 +103,13 @@ static void nft_trace_packet(const struct nft_pktinfo *pkt,
117unsigned int 103unsigned int
118nft_do_chain(struct nft_pktinfo *pkt, const struct nf_hook_ops *ops) 104nft_do_chain(struct nft_pktinfo *pkt, const struct nf_hook_ops *ops)
119{ 105{
120 const struct nft_chain *chain = ops->priv; 106 const struct nft_chain *chain = ops->priv, *basechain = chain;
121 const struct nft_rule *rule; 107 const struct nft_rule *rule;
122 const struct nft_expr *expr, *last; 108 const struct nft_expr *expr, *last;
123 struct nft_data data[NFT_REG_MAX + 1]; 109 struct nft_data data[NFT_REG_MAX + 1];
124 unsigned int stackptr = 0; 110 unsigned int stackptr = 0;
125 struct nft_jumpstack jumpstack[NFT_JUMP_STACK_SIZE]; 111 struct nft_jumpstack jumpstack[NFT_JUMP_STACK_SIZE];
112 struct nft_stats __percpu *stats;
126 int rulenum; 113 int rulenum;
127 /* 114 /*
128 * Cache cursor to avoid problems in case that the cursor is updated 115 * Cache cursor to avoid problems in case that the cursor is updated
@@ -209,12 +196,17 @@ next_rule:
209 rulenum = jumpstack[stackptr].rulenum; 196 rulenum = jumpstack[stackptr].rulenum;
210 goto next_rule; 197 goto next_rule;
211 } 198 }
212 nft_chain_stats(chain, pkt, jumpstack, stackptr);
213 199
214 if (unlikely(pkt->skb->nf_trace)) 200 if (unlikely(pkt->skb->nf_trace))
215 nft_trace_packet(pkt, chain, ++rulenum, NFT_TRACE_POLICY); 201 nft_trace_packet(pkt, basechain, ++rulenum, NFT_TRACE_POLICY);
202
203 rcu_read_lock_bh();
204 stats = rcu_dereference(nft_base_chain(basechain)->stats);
205 __this_cpu_inc(stats->pkts);
206 __this_cpu_add(stats->bytes, pkt->skb->len);
207 rcu_read_unlock_bh();
216 208
217 return nft_base_chain(chain)->policy; 209 return nft_base_chain(basechain)->policy;
218} 210}
219EXPORT_SYMBOL_GPL(nft_do_chain); 211EXPORT_SYMBOL_GPL(nft_do_chain);
220 212