From: Phil Sutter <p...@nwl.cc>

nft_meta_get_eval()'s tendency to bail out setting NFT_BREAK verdict in
situations where required data is missing leads to unexpected behaviour
with inverted checks like so:

| meta iifname != eth0 accept

This rule will never match if there is no input interface (or it is not
known) which is not intuitive and, what's worse, breaks consistency of
iptables-nft with iptables-legacy.

Fix this by falling back to placing a value in dreg which never matches
(avoiding accidental matches), i.e. zero for interface index and an
empty string for interface name.

Signed-off-by: Phil Sutter <p...@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pa...@netfilter.org>
---
 net/bridge/netfilter/nft_meta_bridge.c |  6 +-----
 net/netfilter/nft_meta.c               | 16 ++++------------
 2 files changed, 5 insertions(+), 17 deletions(-)

diff --git a/net/bridge/netfilter/nft_meta_bridge.c 
b/net/bridge/netfilter/nft_meta_bridge.c
index bed66f536b34..a98dec2cf0cf 100644
--- a/net/bridge/netfilter/nft_meta_bridge.c
+++ b/net/bridge/netfilter/nft_meta_bridge.c
@@ -30,13 +30,9 @@ static void nft_meta_bridge_get_eval(const struct nft_expr 
*expr,
        switch (priv->key) {
        case NFT_META_BRI_IIFNAME:
                br_dev = nft_meta_get_bridge(in);
-               if (!br_dev)
-                       goto err;
                break;
        case NFT_META_BRI_OIFNAME:
                br_dev = nft_meta_get_bridge(out);
-               if (!br_dev)
-                       goto err;
                break;
        case NFT_META_BRI_IIFPVID: {
                u16 p_pvid;
@@ -64,7 +60,7 @@ static void nft_meta_bridge_get_eval(const struct nft_expr 
*expr,
                goto out;
        }
 
-       strncpy((char *)dest, br_dev->name, IFNAMSIZ);
+       strncpy((char *)dest, br_dev ? br_dev->name : "", IFNAMSIZ);
        return;
 out:
        return nft_meta_get_eval(expr, regs, pkt);
diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c
index f1b1d948c07b..f69afb9ff3cb 100644
--- a/net/netfilter/nft_meta.c
+++ b/net/netfilter/nft_meta.c
@@ -60,24 +60,16 @@ void nft_meta_get_eval(const struct nft_expr *expr,
                *dest = skb->mark;
                break;
        case NFT_META_IIF:
-               if (in == NULL)
-                       goto err;
-               *dest = in->ifindex;
+               *dest = in ? in->ifindex : 0;
                break;
        case NFT_META_OIF:
-               if (out == NULL)
-                       goto err;
-               *dest = out->ifindex;
+               *dest = out ? out->ifindex : 0;
                break;
        case NFT_META_IIFNAME:
-               if (in == NULL)
-                       goto err;
-               strncpy((char *)dest, in->name, IFNAMSIZ);
+               strncpy((char *)dest, in ? in->name : "", IFNAMSIZ);
                break;
        case NFT_META_OIFNAME:
-               if (out == NULL)
-                       goto err;
-               strncpy((char *)dest, out->name, IFNAMSIZ);
+               strncpy((char *)dest, out ? out->name : "", IFNAMSIZ);
                break;
        case NFT_META_IIFTYPE:
                if (in == NULL)
-- 
2.11.0

Reply via email to