netfilter: x_tables: add context to know if extension runs from nft_compat
authorPablo Neira Ayuso <pablo@netfilter.org>
Thu, 14 May 2015 12:57:23 +0000 (14:57 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Fri, 15 May 2015 18:14:07 +0000 (20:14 +0200)
Currently, we have four xtables extensions that cannot be used from the
xt over nft compat layer. The problem is that they need real access to
the full blown xt_entry to validate that the rule comes with the right
dependencies. This check was introduced to overcome the lack of
sufficient userspace dependency validation in iptables.

To resolve this problem, this patch introduces a new field to the
xt_tgchk_param structure that tell us if the extension is run from
nft_compat context.

The three affected extensions are:

1) CLUSTERIP, this target has been superseded by xt_cluster. So just
   bail out by returning -EINVAL.

2) TCPMSS. Relax the checking when used from nft_compat. If used with
   the wrong configuration, it will corrupt !syn packets by adding TCP
   MSS option.

3) ebt_stp. Relax the check to make sure it uses the reserved
   destination MAC address for STP.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Tested-by: Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
include/linux/netfilter/x_tables.h
net/bridge/netfilter/ebt_stp.c
net/ipv4/netfilter/ipt_CLUSTERIP.c
net/netfilter/nft_compat.c
net/netfilter/xt_TCPMSS.c

index a3e215bb0241d47379bce4ff6e81ba2b4995d3c3..09f38206c18ff0948c003ffc452a88dd0a433536 100644 (file)
@@ -62,6 +62,7 @@ struct xt_mtchk_param {
        void *matchinfo;
        unsigned int hook_mask;
        u_int8_t family;
+       bool nft_compat;
 };
 
 /**
@@ -92,6 +93,7 @@ struct xt_tgchk_param {
        void *targinfo;
        unsigned int hook_mask;
        u_int8_t family;
+       bool nft_compat;
 };
 
 /* Target destructor parameters */
index 071d87214dde44754f2ec98da167fcd8477a541c..0c40570069ba28ce87d2fcd9883224e0ff4588e6 100644 (file)
@@ -164,8 +164,10 @@ static int ebt_stp_mt_check(const struct xt_mtchk_param *par)
            !(info->bitmask & EBT_STP_MASK))
                return -EINVAL;
        /* Make sure the match only receives stp frames */
-       if (!ether_addr_equal(e->destmac, bridge_ula) ||
-           !ether_addr_equal(e->destmsk, msk) || !(e->bitmask & EBT_DESTMAC))
+       if (!par->nft_compat &&
+           (!ether_addr_equal(e->destmac, bridge_ula) ||
+            !ether_addr_equal(e->destmsk, msk) ||
+            !(e->bitmask & EBT_DESTMAC)))
                return -EINVAL;
 
        return 0;
index 771ab3d01ad3dc303ac999e539a9c8ab5845baf2..45cb16a6a4a337c564d880485c45ca46229cb152 100644 (file)
@@ -367,6 +367,11 @@ static int clusterip_tg_check(const struct xt_tgchk_param *par)
        struct clusterip_config *config;
        int ret;
 
+       if (par->nft_compat) {
+               pr_err("cannot use CLUSTERIP target from nftables compat\n");
+               return -EOPNOTSUPP;
+       }
+
        if (cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP &&
            cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP_SPT &&
            cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP_SPT_DPT) {
index 7f29cfc76349f56d7408f4519213a98d564ab135..66def315eb5619a26b64da8a1a5525af7d4a5e3f 100644 (file)
@@ -161,6 +161,7 @@ nft_target_set_tgchk_param(struct xt_tgchk_param *par,
                par->hook_mask = 0;
        }
        par->family     = ctx->afi->family;
+       par->nft_compat = true;
 }
 
 static void target_compat_from_user(struct xt_target *t, void *in, void *out)
@@ -377,6 +378,7 @@ nft_match_set_mtchk_param(struct xt_mtchk_param *par, const struct nft_ctx *ctx,
                par->hook_mask = 0;
        }
        par->family     = ctx->afi->family;
+       par->nft_compat = true;
 }
 
 static void match_compat_from_user(struct xt_match *m, void *in, void *out)
index e762de5ee89bfa480b1789ce164cb024ac35e91e..8c3190e2fc6abad6394ba5498762ba0502c34d58 100644 (file)
@@ -277,6 +277,9 @@ static int tcpmss_tg4_check(const struct xt_tgchk_param *par)
                        "FORWARD, OUTPUT and POSTROUTING hooks\n");
                return -EINVAL;
        }
+       if (par->nft_compat)
+               return 0;
+
        xt_ematch_foreach(ematch, e)
                if (find_syn_match(ematch))
                        return 0;
@@ -299,6 +302,9 @@ static int tcpmss_tg6_check(const struct xt_tgchk_param *par)
                        "FORWARD, OUTPUT and POSTROUTING hooks\n");
                return -EINVAL;
        }
+       if (par->nft_compat)
+               return 0;
+
        xt_ematch_foreach(ematch, e)
                if (find_syn_match(ematch))
                        return 0;