Skip to content

Commit

Permalink
netfilter: nf_tables: restrict nat/masq expressions to nat chain type
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Pablo Neira Ayuso committed Oct 13, 2014
1 parent ab2d725 commit 7210e4e
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 0 deletions.
3 changes: 3 additions & 0 deletions include/net/netfilter/nf_tables.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
3 changes: 3 additions & 0 deletions include/net/netfilter/nft_masq.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 change: 1 addition & 0 deletions net/ipv4/netfilter/nft_masq_ipv4.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down
1 change: 1 addition & 0 deletions net/ipv6/netfilter/nft_masq_ipv6.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down
14 changes: 14 additions & 0 deletions net/netfilter/nf_tables_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 12 additions & 0 deletions net/netfilter/nft_masq.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -55,5 +60,12 @@ int nft_masq_dump(struct sk_buff *skb, const struct nft_expr *expr)
}
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>");
12 changes: 12 additions & 0 deletions net/netfilter/nft_nat.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -205,13 +209,21 @@ static int nft_nat_dump(struct sk_buff *skb, const struct nft_expr *expr)
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,
.size = NFT_EXPR_SIZE(sizeof(struct nft_nat)),
.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 = {
Expand Down

0 comments on commit 7210e4e

Please sign in to comment.