Commit d050de60 authored by David S. Miller's avatar David S. Miller

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: default avatarDavid S. Miller <davem@davemloft.net>
parents e1618d46 3b084e99
...@@ -66,20 +66,6 @@ struct nft_jumpstack { ...@@ -66,20 +66,6 @@ struct nft_jumpstack {
int rulenum; int rulenum;
}; };
static inline void
nft_chain_stats(const struct nft_chain *this, const struct nft_pktinfo *pkt,
struct nft_jumpstack *jumpstack, unsigned int stackptr)
{
struct nft_stats __percpu *stats;
const struct nft_chain *chain = stackptr ? jumpstack[0].chain : this;
rcu_read_lock_bh();
stats = rcu_dereference(nft_base_chain(chain)->stats);
__this_cpu_inc(stats->pkts);
__this_cpu_add(stats->bytes, pkt->skb->len);
rcu_read_unlock_bh();
}
enum nft_trace { enum nft_trace {
NFT_TRACE_RULE, NFT_TRACE_RULE,
NFT_TRACE_RETURN, NFT_TRACE_RETURN,
...@@ -117,13 +103,14 @@ static void nft_trace_packet(const struct nft_pktinfo *pkt, ...@@ -117,13 +103,14 @@ static void nft_trace_packet(const struct nft_pktinfo *pkt,
unsigned int unsigned int
nft_do_chain(struct nft_pktinfo *pkt, const struct nf_hook_ops *ops) nft_do_chain(struct nft_pktinfo *pkt, const struct nf_hook_ops *ops)
{ {
const struct nft_chain *chain = ops->priv; const struct nft_chain *chain = ops->priv, *basechain = chain;
const struct nft_rule *rule; const struct nft_rule *rule;
const struct nft_expr *expr, *last; const struct nft_expr *expr, *last;
struct nft_data data[NFT_REG_MAX + 1]; struct nft_data data[NFT_REG_MAX + 1];
unsigned int stackptr = 0; unsigned int stackptr = 0;
struct nft_jumpstack jumpstack[NFT_JUMP_STACK_SIZE]; struct nft_jumpstack jumpstack[NFT_JUMP_STACK_SIZE];
int rulenum = 0; struct nft_stats __percpu *stats;
int rulenum;
/* /*
* Cache cursor to avoid problems in case that the cursor is updated * Cache cursor to avoid problems in case that the cursor is updated
* while traversing the ruleset. * while traversing the ruleset.
...@@ -131,6 +118,7 @@ nft_do_chain(struct nft_pktinfo *pkt, const struct nf_hook_ops *ops) ...@@ -131,6 +118,7 @@ nft_do_chain(struct nft_pktinfo *pkt, const struct nf_hook_ops *ops)
unsigned int gencursor = ACCESS_ONCE(chain->net->nft.gencursor); unsigned int gencursor = ACCESS_ONCE(chain->net->nft.gencursor);
do_chain: do_chain:
rulenum = 0;
rule = list_entry(&chain->rules, struct nft_rule, list); rule = list_entry(&chain->rules, struct nft_rule, list);
next_rule: next_rule:
data[NFT_REG_VERDICT].verdict = NFT_CONTINUE; data[NFT_REG_VERDICT].verdict = NFT_CONTINUE;
...@@ -156,8 +144,10 @@ nft_do_chain(struct nft_pktinfo *pkt, const struct nf_hook_ops *ops) ...@@ -156,8 +144,10 @@ nft_do_chain(struct nft_pktinfo *pkt, const struct nf_hook_ops *ops)
switch (data[NFT_REG_VERDICT].verdict) { switch (data[NFT_REG_VERDICT].verdict) {
case NFT_BREAK: case NFT_BREAK:
data[NFT_REG_VERDICT].verdict = NFT_CONTINUE; data[NFT_REG_VERDICT].verdict = NFT_CONTINUE;
/* fall through */ continue;
case NFT_CONTINUE: case NFT_CONTINUE:
if (unlikely(pkt->skb->nf_trace))
nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE);
continue; continue;
} }
break; break;
...@@ -183,37 +173,44 @@ nft_do_chain(struct nft_pktinfo *pkt, const struct nf_hook_ops *ops) ...@@ -183,37 +173,44 @@ nft_do_chain(struct nft_pktinfo *pkt, const struct nf_hook_ops *ops)
jumpstack[stackptr].rule = rule; jumpstack[stackptr].rule = rule;
jumpstack[stackptr].rulenum = rulenum; jumpstack[stackptr].rulenum = rulenum;
stackptr++; stackptr++;
/* fall through */ chain = data[NFT_REG_VERDICT].chain;
goto do_chain;
case NFT_GOTO: case NFT_GOTO:
if (unlikely(pkt->skb->nf_trace))
nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE);
chain = data[NFT_REG_VERDICT].chain; chain = data[NFT_REG_VERDICT].chain;
goto do_chain; goto do_chain;
case NFT_RETURN: case NFT_RETURN:
if (unlikely(pkt->skb->nf_trace)) if (unlikely(pkt->skb->nf_trace))
nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RETURN); nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RETURN);
break;
/* fall through */
case NFT_CONTINUE: case NFT_CONTINUE:
if (unlikely(pkt->skb->nf_trace && !(chain->flags & NFT_BASE_CHAIN)))
nft_trace_packet(pkt, chain, ++rulenum, NFT_TRACE_RETURN);
break; break;
default: default:
WARN_ON(1); WARN_ON(1);
} }
if (stackptr > 0) { if (stackptr > 0) {
if (unlikely(pkt->skb->nf_trace))
nft_trace_packet(pkt, chain, ++rulenum, NFT_TRACE_RETURN);
stackptr--; stackptr--;
chain = jumpstack[stackptr].chain; chain = jumpstack[stackptr].chain;
rule = jumpstack[stackptr].rule; rule = jumpstack[stackptr].rule;
rulenum = jumpstack[stackptr].rulenum; rulenum = jumpstack[stackptr].rulenum;
goto next_rule; goto next_rule;
} }
nft_chain_stats(chain, pkt, jumpstack, stackptr);
if (unlikely(pkt->skb->nf_trace)) if (unlikely(pkt->skb->nf_trace))
nft_trace_packet(pkt, chain, ++rulenum, NFT_TRACE_POLICY); nft_trace_packet(pkt, basechain, -1, NFT_TRACE_POLICY);
rcu_read_lock_bh();
stats = rcu_dereference(nft_base_chain(basechain)->stats);
__this_cpu_inc(stats->pkts);
__this_cpu_add(stats->bytes, pkt->skb->len);
rcu_read_unlock_bh();
return nft_base_chain(chain)->policy; return nft_base_chain(basechain)->policy;
} }
EXPORT_SYMBOL_GPL(nft_do_chain); EXPORT_SYMBOL_GPL(nft_do_chain);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment