[nf-next] netfilter: nf_tables: don't break when vmap lookup yields no result

Message ID 20190202100955.822-1-fw@strlen.de
State Changes Requested
Delegated to: Pablo Neira
Headers show
Series
  • [nf-next] netfilter: nf_tables: don't break when vmap lookup yields no result
Related show

Commit Message

Florian Westphal Feb. 2, 2019, 10:09 a.m.
instead just let the eval loop continue with remaining expressions, if any.

This allows to catch non-matching packets in the same rule, e.g.:

 ip protocol vmap { tcp : jump tcp_tests,
                    udp : jump udp_tests } counter jump other

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 net/netfilter/nft_lookup.c | 18 +++++++++++-------
 1 file changed, 11 insertions(+), 7 deletions(-)

Comments

Pablo Neira Ayuso Feb. 2, 2019, 10:53 a.m. | #1
Hi Florian,

On Sat, Feb 02, 2019 at 11:09:55AM +0100, Florian Westphal wrote:
> instead just let the eval loop continue with remaining expressions, if any.
> 
> This allows to catch non-matching packets in the same rule, e.g.:
> 
>  ip protocol vmap { tcp : jump tcp_tests,
>                     udp : jump udp_tests } counter jump other

We still need a way to set default stateful object, not only jumps.

Please, let me explore a patch to add a catch-all case and then we can
pick the best solution for this, either this patch or a new catch-all
case code.

Thanks.

Patch

diff --git a/net/netfilter/nft_lookup.c b/net/netfilter/nft_lookup.c
index 227b2b15a19c..2d7c560343da 100644
--- a/net/netfilter/nft_lookup.c
+++ b/net/netfilter/nft_lookup.c
@@ -37,15 +37,19 @@  void nft_lookup_eval(const struct nft_expr *expr,
 
 	found = set->ops->lookup(nft_net(pkt), set, &regs->data[priv->sreg],
 				 &ext) ^ priv->invert;
-	if (!found) {
-		regs->verdict.code = NFT_BREAK;
-		return;
-	}
 
-	if (set->flags & NFT_SET_MAP)
-		nft_data_copy(&regs->data[priv->dreg],
-			      nft_set_ext_data(ext), set->dlen);
+	if (set->flags & NFT_SET_MAP) {
+		if (!found) {
+			if (priv->dreg != NFT_REG_VERDICT)
+				regs->verdict.code = NFT_BREAK;
+			return;
+		}
+                nft_data_copy(&regs->data[priv->dreg],
+                              nft_set_ext_data(ext), set->dlen);
 
+	} else if (!found) {
+		regs->verdict.code = NFT_BREAK;
+	}
 }
 
 static const struct nla_policy nft_lookup_policy[NFTA_LOOKUP_MAX + 1] = {