aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2014-05-21 01:24:19 -0400
committerDavid S. Miller <davem@davemloft.net>2014-05-21 01:24:19 -0400
commitd050de607f062233cf5e75b2e8f40f20c4b04b91 (patch)
treeddfa81805a7a4df07b4d95a27091909fe38ddb55 /net
parente1618d461ca18d40f9c3ef70598abb72e75d27ae (diff)
parent3b084e99a3fabaeb0f9c65a0806cde30f0b2835e (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf
Pablo Neira Ayuso says: ==================== Netfilter/nftables fixes for net The following patchset contains nftables fixes for your net tree, they are: 1) Fix crash when using the goto action in a rule by making sure that we always fall back on the base chain. Otherwise, this may try to access the counter memory area of non-base chains, which does not exists. 2) Fix several aspects of the rule tracing that are currently broken: * Reset rule number counter after goto/jump action, otherwise the tracing reports a bogus rule number. * Fix tracing of the goto action. * Fix bogus rule number counter after goto. * Fix missing return trace after finishing the walk through the non-base chain. * Fix missing trace when matching non-terminal rule. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/netfilter/nf_tables_core.c49
1 files changed, 23 insertions, 26 deletions
diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c
index 804105391b9a..345acfb1720b 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,13 +103,14 @@ 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];
126 int rulenum = 0; 112 struct nft_stats __percpu *stats;
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
129 * while traversing the ruleset. 116 * while traversing the ruleset.
@@ -131,6 +118,7 @@ nft_do_chain(struct nft_pktinfo *pkt, const struct nf_hook_ops *ops)
131 unsigned int gencursor = ACCESS_ONCE(chain->net->nft.gencursor); 118 unsigned int gencursor = ACCESS_ONCE(chain->net->nft.gencursor);
132 119
133do_chain: 120do_chain:
121 rulenum = 0;
134 rule = list_entry(&chain->rules, struct nft_rule, list); 122 rule = list_entry(&chain->rules, struct nft_rule, list);
135next_rule: 123next_rule:
136 data[NFT_REG_VERDICT].verdict = NFT_CONTINUE; 124 data[NFT_REG_VERDICT].verdict = NFT_CONTINUE;
@@ -156,8 +144,10 @@ next_rule:
156 switch (data[NFT_REG_VERDICT].verdict) { 144 switch (data[NFT_REG_VERDICT].verdict) {
157 case NFT_BREAK: 145 case NFT_BREAK:
158 data[NFT_REG_VERDICT].verdict = NFT_CONTINUE; 146 data[NFT_REG_VERDICT].verdict = NFT_CONTINUE;
159 /* fall through */ 147 continue;
160 case NFT_CONTINUE: 148 case NFT_CONTINUE:
149 if (unlikely(pkt->skb->nf_trace))
150 nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE);
161 continue; 151 continue;
162 } 152 }
163 break; 153 break;
@@ -183,37 +173,44 @@ next_rule:
183 jumpstack[stackptr].rule = rule; 173 jumpstack[stackptr].rule = rule;
184 jumpstack[stackptr].rulenum = rulenum; 174 jumpstack[stackptr].rulenum = rulenum;
185 stackptr++; 175 stackptr++;
186 /* fall through */ 176 chain = data[NFT_REG_VERDICT].chain;
177 goto do_chain;
187 case NFT_GOTO: 178 case NFT_GOTO:
179 if (unlikely(pkt->skb->nf_trace))
180 nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE);
181
188 chain = data[NFT_REG_VERDICT].chain; 182 chain = data[NFT_REG_VERDICT].chain;
189 goto do_chain; 183 goto do_chain;
190 case NFT_RETURN: 184 case NFT_RETURN:
191 if (unlikely(pkt->skb->nf_trace)) 185 if (unlikely(pkt->skb->nf_trace))
192 nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RETURN); 186 nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RETURN);
193 187 break;
194 /* fall through */
195 case NFT_CONTINUE: 188 case NFT_CONTINUE:
189 if (unlikely(pkt->skb->nf_trace && !(chain->flags & NFT_BASE_CHAIN)))
190 nft_trace_packet(pkt, chain, ++rulenum, NFT_TRACE_RETURN);
196 break; 191 break;
197 default: 192 default:
198 WARN_ON(1); 193 WARN_ON(1);
199 } 194 }
200 195
201 if (stackptr > 0) { 196 if (stackptr > 0) {
202 if (unlikely(pkt->skb->nf_trace))
203 nft_trace_packet(pkt, chain, ++rulenum, NFT_TRACE_RETURN);
204
205 stackptr--; 197 stackptr--;
206 chain = jumpstack[stackptr].chain; 198 chain = jumpstack[stackptr].chain;
207 rule = jumpstack[stackptr].rule; 199 rule = jumpstack[stackptr].rule;
208 rulenum = jumpstack[stackptr].rulenum; 200 rulenum = jumpstack[stackptr].rulenum;
209 goto next_rule; 201 goto next_rule;
210 } 202 }
211 nft_chain_stats(chain, pkt, jumpstack, stackptr);
212 203
213 if (unlikely(pkt->skb->nf_trace)) 204 if (unlikely(pkt->skb->nf_trace))
214 nft_trace_packet(pkt, chain, ++rulenum, NFT_TRACE_POLICY); 205 nft_trace_packet(pkt, basechain, -1, NFT_TRACE_POLICY);
206
207 rcu_read_lock_bh();
208 stats = rcu_dereference(nft_base_chain(basechain)->stats);
209 __this_cpu_inc(stats->pkts);
210 __this_cpu_add(stats->bytes, pkt->skb->len);
211 rcu_read_unlock_bh();
215 212
216 return nft_base_chain(chain)->policy; 213 return nft_base_chain(basechain)->policy;
217} 214}
218EXPORT_SYMBOL_GPL(nft_do_chain); 215EXPORT_SYMBOL_GPL(nft_do_chain);
219 216