netfilter: nf_tables: restrict nat/masq expressions to nat chain type
This adds the missing validation code to avoid the use of nat/masq from non-nat chains. The validation assumes two possible configuration scenarios: 1) Use of nat from base chain that is not of nat type. Reject this configuration from the nft_*_init() path of the expression. 2) Use of nat from non-base chain. In this case, we have to wait until the non-base chain is referenced by at least one base chain via jump/goto. This is resolved from the nft_*_validate() path which is called from nf_tables_check_loops(). The user gets an -EOPNOTSUPP in both cases. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
parent
ab2d7251d6
commit
7210e4e38f
@ -530,6 +530,9 @@ enum nft_chain_type {
|
||||
NFT_CHAIN_T_MAX
|
||||
};
|
||||
|
||||
int nft_chain_validate_dependency(const struct nft_chain *chain,
|
||||
enum nft_chain_type type);
|
||||
|
||||
struct nft_stats {
|
||||
u64 bytes;
|
||||
u64 pkts;
|
||||
|
@ -13,4 +13,7 @@ int nft_masq_init(const struct nft_ctx *ctx,
|
||||
|
||||
int nft_masq_dump(struct sk_buff *skb, const struct nft_expr *expr);
|
||||
|
||||
int nft_masq_validate(const struct nft_ctx *ctx, const struct nft_expr *expr,
|
||||
const struct nft_data **data);
|
||||
|
||||
#endif /* _NFT_MASQ_H_ */
|
||||
|
@ -39,6 +39,7 @@ static const struct nft_expr_ops nft_masq_ipv4_ops = {
|
||||
.eval = nft_masq_ipv4_eval,
|
||||
.init = nft_masq_init,
|
||||
.dump = nft_masq_dump,
|
||||
.validate = nft_masq_validate,
|
||||
};
|
||||
|
||||
static struct nft_expr_type nft_masq_ipv4_type __read_mostly = {
|
||||
|
@ -39,6 +39,7 @@ static const struct nft_expr_ops nft_masq_ipv6_ops = {
|
||||
.eval = nft_masq_ipv6_eval,
|
||||
.init = nft_masq_init,
|
||||
.dump = nft_masq_dump,
|
||||
.validate = nft_masq_validate,
|
||||
};
|
||||
|
||||
static struct nft_expr_type nft_masq_ipv6_type __read_mostly = {
|
||||
|
@ -3744,6 +3744,20 @@ static const struct nfnetlink_subsystem nf_tables_subsys = {
|
||||
.abort = nf_tables_abort,
|
||||
};
|
||||
|
||||
int nft_chain_validate_dependency(const struct nft_chain *chain,
|
||||
enum nft_chain_type type)
|
||||
{
|
||||
const struct nft_base_chain *basechain;
|
||||
|
||||
if (chain->flags & NFT_BASE_CHAIN) {
|
||||
basechain = nft_base_chain(chain);
|
||||
if (basechain->type->type != type)
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nft_chain_validate_dependency);
|
||||
|
||||
/*
|
||||
* Loop detection - walk through the ruleset beginning at the destination chain
|
||||
* of a new jump until either the source chain is reached (loop) or all
|
||||
|
@ -26,6 +26,11 @@ int nft_masq_init(const struct nft_ctx *ctx,
|
||||
const struct nlattr * const tb[])
|
||||
{
|
||||
struct nft_masq *priv = nft_expr_priv(expr);
|
||||
int err;
|
||||
|
||||
err = nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (tb[NFTA_MASQ_FLAGS] == NULL)
|
||||
return 0;
|
||||
@ -55,5 +60,12 @@ nla_put_failure:
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nft_masq_dump);
|
||||
|
||||
int nft_masq_validate(const struct nft_ctx *ctx, const struct nft_expr *expr,
|
||||
const struct nft_data **data)
|
||||
{
|
||||
return nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nft_masq_validate);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>");
|
||||
|
@ -95,6 +95,10 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
|
||||
u32 family;
|
||||
int err;
|
||||
|
||||
err = nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (tb[NFTA_NAT_TYPE] == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
@ -205,6 +209,13 @@ nla_put_failure:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int nft_nat_validate(const struct nft_ctx *ctx,
|
||||
const struct nft_expr *expr,
|
||||
const struct nft_data **data)
|
||||
{
|
||||
return nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT);
|
||||
}
|
||||
|
||||
static struct nft_expr_type nft_nat_type;
|
||||
static const struct nft_expr_ops nft_nat_ops = {
|
||||
.type = &nft_nat_type,
|
||||
@ -212,6 +223,7 @@ static const struct nft_expr_ops nft_nat_ops = {
|
||||
.eval = nft_nat_eval,
|
||||
.init = nft_nat_init,
|
||||
.dump = nft_nat_dump,
|
||||
.validate = nft_nat_validate,
|
||||
};
|
||||
|
||||
static struct nft_expr_type nft_nat_type __read_mostly = {
|
||||
|
Loading…
Reference in New Issue
Block a user