Commit 55917a21 authored by Pablo Neira Ayuso's avatar Pablo Neira Ayuso

netfilter: x_tables: add context to know if extension runs from nft_compat

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: default avatarPablo Neira Ayuso <pablo@netfilter.org>
Tested-by: default avatarArturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
parent 12b7ed29
...@@ -62,6 +62,7 @@ struct xt_mtchk_param { ...@@ -62,6 +62,7 @@ struct xt_mtchk_param {
void *matchinfo; void *matchinfo;
unsigned int hook_mask; unsigned int hook_mask;
u_int8_t family; u_int8_t family;
bool nft_compat;
}; };
/** /**
...@@ -92,6 +93,7 @@ struct xt_tgchk_param { ...@@ -92,6 +93,7 @@ struct xt_tgchk_param {
void *targinfo; void *targinfo;
unsigned int hook_mask; unsigned int hook_mask;
u_int8_t family; u_int8_t family;
bool nft_compat;
}; };
/* Target destructor parameters */ /* Target destructor parameters */
......
...@@ -164,8 +164,10 @@ static int ebt_stp_mt_check(const struct xt_mtchk_param *par) ...@@ -164,8 +164,10 @@ static int ebt_stp_mt_check(const struct xt_mtchk_param *par)
!(info->bitmask & EBT_STP_MASK)) !(info->bitmask & EBT_STP_MASK))
return -EINVAL; return -EINVAL;
/* Make sure the match only receives stp frames */ /* Make sure the match only receives stp frames */
if (!ether_addr_equal(e->destmac, bridge_ula) || if (!par->nft_compat &&
!ether_addr_equal(e->destmsk, msk) || !(e->bitmask & EBT_DESTMAC)) (!ether_addr_equal(e->destmac, bridge_ula) ||
!ether_addr_equal(e->destmsk, msk) ||
!(e->bitmask & EBT_DESTMAC)))
return -EINVAL; return -EINVAL;
return 0; return 0;
......
...@@ -367,6 +367,11 @@ static int clusterip_tg_check(const struct xt_tgchk_param *par) ...@@ -367,6 +367,11 @@ static int clusterip_tg_check(const struct xt_tgchk_param *par)
struct clusterip_config *config; struct clusterip_config *config;
int ret; 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 && if (cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP &&
cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP_SPT && cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP_SPT &&
cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP_SPT_DPT) { cipinfo->hash_mode != CLUSTERIP_HASHMODE_SIP_SPT_DPT) {
......
...@@ -161,6 +161,7 @@ nft_target_set_tgchk_param(struct xt_tgchk_param *par, ...@@ -161,6 +161,7 @@ nft_target_set_tgchk_param(struct xt_tgchk_param *par,
par->hook_mask = 0; par->hook_mask = 0;
} }
par->family = ctx->afi->family; par->family = ctx->afi->family;
par->nft_compat = true;
} }
static void target_compat_from_user(struct xt_target *t, void *in, void *out) 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, ...@@ -377,6 +378,7 @@ nft_match_set_mtchk_param(struct xt_mtchk_param *par, const struct nft_ctx *ctx,
par->hook_mask = 0; par->hook_mask = 0;
} }
par->family = ctx->afi->family; par->family = ctx->afi->family;
par->nft_compat = true;
} }
static void match_compat_from_user(struct xt_match *m, void *in, void *out) static void match_compat_from_user(struct xt_match *m, void *in, void *out)
......
...@@ -277,6 +277,9 @@ static int tcpmss_tg4_check(const struct xt_tgchk_param *par) ...@@ -277,6 +277,9 @@ static int tcpmss_tg4_check(const struct xt_tgchk_param *par)
"FORWARD, OUTPUT and POSTROUTING hooks\n"); "FORWARD, OUTPUT and POSTROUTING hooks\n");
return -EINVAL; return -EINVAL;
} }
if (par->nft_compat)
return 0;
xt_ematch_foreach(ematch, e) xt_ematch_foreach(ematch, e)
if (find_syn_match(ematch)) if (find_syn_match(ematch))
return 0; return 0;
...@@ -299,6 +302,9 @@ static int tcpmss_tg6_check(const struct xt_tgchk_param *par) ...@@ -299,6 +302,9 @@ static int tcpmss_tg6_check(const struct xt_tgchk_param *par)
"FORWARD, OUTPUT and POSTROUTING hooks\n"); "FORWARD, OUTPUT and POSTROUTING hooks\n");
return -EINVAL; return -EINVAL;
} }
if (par->nft_compat)
return 0;
xt_ematch_foreach(ematch, e) xt_ematch_foreach(ematch, e)
if (find_syn_match(ematch)) if (find_syn_match(ematch))
return 0; return 0;
......
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