Commit cb81572e authored by Phil Sutter's avatar Phil Sutter Committed by Pablo Neira Ayuso

netfilter: nf_tables: Make nft_meta expression more robust

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: default avatarPhil Sutter <phil@nwl.cc>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent 15a78ba1
...@@ -30,13 +30,9 @@ static void nft_meta_bridge_get_eval(const struct nft_expr *expr, ...@@ -30,13 +30,9 @@ static void nft_meta_bridge_get_eval(const struct nft_expr *expr,
switch (priv->key) { switch (priv->key) {
case NFT_META_BRI_IIFNAME: case NFT_META_BRI_IIFNAME:
br_dev = nft_meta_get_bridge(in); br_dev = nft_meta_get_bridge(in);
if (!br_dev)
goto err;
break; break;
case NFT_META_BRI_OIFNAME: case NFT_META_BRI_OIFNAME:
br_dev = nft_meta_get_bridge(out); br_dev = nft_meta_get_bridge(out);
if (!br_dev)
goto err;
break; break;
case NFT_META_BRI_IIFPVID: { case NFT_META_BRI_IIFPVID: {
u16 p_pvid; u16 p_pvid;
...@@ -64,7 +60,7 @@ static void nft_meta_bridge_get_eval(const struct nft_expr *expr, ...@@ -64,7 +60,7 @@ static void nft_meta_bridge_get_eval(const struct nft_expr *expr,
goto out; goto out;
} }
strncpy((char *)dest, br_dev->name, IFNAMSIZ); strncpy((char *)dest, br_dev ? br_dev->name : "", IFNAMSIZ);
return; return;
out: out:
return nft_meta_get_eval(expr, regs, pkt); return nft_meta_get_eval(expr, regs, pkt);
......
...@@ -60,24 +60,16 @@ void nft_meta_get_eval(const struct nft_expr *expr, ...@@ -60,24 +60,16 @@ void nft_meta_get_eval(const struct nft_expr *expr,
*dest = skb->mark; *dest = skb->mark;
break; break;
case NFT_META_IIF: case NFT_META_IIF:
if (in == NULL) *dest = in ? in->ifindex : 0;
goto err;
*dest = in->ifindex;
break; break;
case NFT_META_OIF: case NFT_META_OIF:
if (out == NULL) *dest = out ? out->ifindex : 0;
goto err;
*dest = out->ifindex;
break; break;
case NFT_META_IIFNAME: case NFT_META_IIFNAME:
if (in == NULL) strncpy((char *)dest, in ? in->name : "", IFNAMSIZ);
goto err;
strncpy((char *)dest, in->name, IFNAMSIZ);
break; break;
case NFT_META_OIFNAME: case NFT_META_OIFNAME:
if (out == NULL) strncpy((char *)dest, out ? out->name : "", IFNAMSIZ);
goto err;
strncpy((char *)dest, out->name, IFNAMSIZ);
break; break;
case NFT_META_IIFTYPE: case NFT_META_IIFTYPE:
if (in == NULL) if (in == NULL)
......
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