Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7210e4e3 authored by Pablo Neira Ayuso's avatar Pablo Neira Ayuso
Browse files

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: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent ab2d7251
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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;
+3 −0
Original line number Diff line number Diff line
@@ -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_ */
+1 −0
Original line number Diff line number Diff line
@@ -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 = {
+1 −0
Original line number Diff line number Diff line
@@ -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 = {
+14 −0
Original line number Diff line number Diff line
@@ -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
Loading