提交 7210e4e3 编写于 作者: P Pablo Neira Ayuso

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: NPablo Neira Ayuso <pablo@netfilter.org>
上级 ab2d7251
...@@ -530,6 +530,9 @@ enum nft_chain_type { ...@@ -530,6 +530,9 @@ enum nft_chain_type {
NFT_CHAIN_T_MAX NFT_CHAIN_T_MAX
}; };
int nft_chain_validate_dependency(const struct nft_chain *chain,
enum nft_chain_type type);
struct nft_stats { struct nft_stats {
u64 bytes; u64 bytes;
u64 pkts; u64 pkts;
......
...@@ -13,4 +13,7 @@ int nft_masq_init(const struct nft_ctx *ctx, ...@@ -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_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_ */ #endif /* _NFT_MASQ_H_ */
...@@ -39,6 +39,7 @@ static const struct nft_expr_ops nft_masq_ipv4_ops = { ...@@ -39,6 +39,7 @@ static const struct nft_expr_ops nft_masq_ipv4_ops = {
.eval = nft_masq_ipv4_eval, .eval = nft_masq_ipv4_eval,
.init = nft_masq_init, .init = nft_masq_init,
.dump = nft_masq_dump, .dump = nft_masq_dump,
.validate = nft_masq_validate,
}; };
static struct nft_expr_type nft_masq_ipv4_type __read_mostly = { 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 = { ...@@ -39,6 +39,7 @@ static const struct nft_expr_ops nft_masq_ipv6_ops = {
.eval = nft_masq_ipv6_eval, .eval = nft_masq_ipv6_eval,
.init = nft_masq_init, .init = nft_masq_init,
.dump = nft_masq_dump, .dump = nft_masq_dump,
.validate = nft_masq_validate,
}; };
static struct nft_expr_type nft_masq_ipv6_type __read_mostly = { static struct nft_expr_type nft_masq_ipv6_type __read_mostly = {
......
...@@ -3744,6 +3744,20 @@ static const struct nfnetlink_subsystem nf_tables_subsys = { ...@@ -3744,6 +3744,20 @@ static const struct nfnetlink_subsystem nf_tables_subsys = {
.abort = nf_tables_abort, .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 * 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 * 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, ...@@ -26,6 +26,11 @@ int nft_masq_init(const struct nft_ctx *ctx,
const struct nlattr * const tb[]) const struct nlattr * const tb[])
{ {
struct nft_masq *priv = nft_expr_priv(expr); 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) if (tb[NFTA_MASQ_FLAGS] == NULL)
return 0; return 0;
...@@ -55,5 +60,12 @@ int nft_masq_dump(struct sk_buff *skb, const struct nft_expr *expr) ...@@ -55,5 +60,12 @@ int nft_masq_dump(struct sk_buff *skb, const struct nft_expr *expr)
} }
EXPORT_SYMBOL_GPL(nft_masq_dump); 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_LICENSE("GPL");
MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>"); 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, ...@@ -95,6 +95,10 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
u32 family; u32 family;
int err; int err;
err = nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT);
if (err < 0)
return err;
if (tb[NFTA_NAT_TYPE] == NULL) if (tb[NFTA_NAT_TYPE] == NULL)
return -EINVAL; return -EINVAL;
...@@ -205,6 +209,13 @@ static int nft_nat_dump(struct sk_buff *skb, const struct nft_expr *expr) ...@@ -205,6 +209,13 @@ static int nft_nat_dump(struct sk_buff *skb, const struct nft_expr *expr)
return -1; 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 struct nft_expr_type nft_nat_type;
static const struct nft_expr_ops nft_nat_ops = { static const struct nft_expr_ops nft_nat_ops = {
.type = &nft_nat_type, .type = &nft_nat_type,
...@@ -212,6 +223,7 @@ static const struct nft_expr_ops nft_nat_ops = { ...@@ -212,6 +223,7 @@ static const struct nft_expr_ops nft_nat_ops = {
.eval = nft_nat_eval, .eval = nft_nat_eval,
.init = nft_nat_init, .init = nft_nat_init,
.dump = nft_nat_dump, .dump = nft_nat_dump,
.validate = nft_nat_validate,
}; };
static struct nft_expr_type nft_nat_type __read_mostly = { static struct nft_expr_type nft_nat_type __read_mostly = {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册