netfilter: nft_compat: run xt_check_hooks_{match,target}() from .validate
Several matches and one target check that the hook is correct from
checkentry(), however, the basechain is only available from
nft_table_validate().
This patch uses xt_check_hooks_{match,target}() from the nft_compat
expression .validate path.
This patch sets the table in the nft_ctx struct in nft_table_validate()
which is required by this patch.
Based on patch from Florian Westphal.
Fixes: 0ca743a559 ("netfilter: nf_tables: add compatibility layer for x_tables")
Reported-by: Xiang Mei <xmei5@asu.edu>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
master
parent
6813985ca4
commit
2f768d638d
|
|
@ -4205,6 +4205,7 @@ static int nft_table_validate(struct net *net, const struct nft_table *table)
|
|||
struct nft_chain *chain;
|
||||
struct nft_ctx ctx = {
|
||||
.net = net,
|
||||
.table = (struct nft_table *)table,
|
||||
.family = table->family,
|
||||
};
|
||||
int err = 0;
|
||||
|
|
|
|||
|
|
@ -261,10 +261,10 @@ nft_target_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
|
|||
return ret;
|
||||
}
|
||||
|
||||
nft_target_set_tgchk_param(&par, ctx, target, info, &e, proto, inv);
|
||||
|
||||
nft_compat_wait_for_destructors(ctx->net);
|
||||
|
||||
nft_target_set_tgchk_param(&par, ctx, target, info, &e, proto, inv);
|
||||
|
||||
ret = xt_check_target(&par, size, proto, inv);
|
||||
if (ret < 0) {
|
||||
if (ret == -ENOENT) {
|
||||
|
|
@ -353,8 +353,6 @@ nla_put_failure:
|
|||
static int nft_target_validate(const struct nft_ctx *ctx,
|
||||
const struct nft_expr *expr)
|
||||
{
|
||||
struct xt_target *target = expr->ops->data;
|
||||
unsigned int hook_mask = 0;
|
||||
int ret;
|
||||
|
||||
if (ctx->family != NFPROTO_IPV4 &&
|
||||
|
|
@ -377,11 +375,21 @@ static int nft_target_validate(const struct nft_ctx *ctx,
|
|||
const struct nft_base_chain *basechain =
|
||||
nft_base_chain(ctx->chain);
|
||||
const struct nf_hook_ops *ops = &basechain->ops;
|
||||
unsigned int hook_mask = 1 << ops->hooknum;
|
||||
struct xt_target *target = expr->ops->data;
|
||||
void *info = nft_expr_priv(expr);
|
||||
struct xt_tgchk_param par;
|
||||
union nft_entry e = {};
|
||||
|
||||
hook_mask = 1 << ops->hooknum;
|
||||
if (target->hooks && !(hook_mask & target->hooks))
|
||||
return -EINVAL;
|
||||
|
||||
nft_target_set_tgchk_param(&par, ctx, target, info, &e, 0, false);
|
||||
|
||||
ret = xt_check_hooks_target(&par);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = nft_compat_chain_validate_dependency(ctx, target->table);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
|
@ -515,10 +523,10 @@ __nft_match_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
|
|||
return ret;
|
||||
}
|
||||
|
||||
nft_match_set_mtchk_param(&par, ctx, match, info, &e, proto, inv);
|
||||
|
||||
nft_compat_wait_for_destructors(ctx->net);
|
||||
|
||||
nft_match_set_mtchk_param(&par, ctx, match, info, &e, proto, inv);
|
||||
|
||||
return xt_check_match(&par, size, proto, inv);
|
||||
}
|
||||
|
||||
|
|
@ -614,8 +622,6 @@ static int nft_match_large_dump(struct sk_buff *skb,
|
|||
static int nft_match_validate(const struct nft_ctx *ctx,
|
||||
const struct nft_expr *expr)
|
||||
{
|
||||
struct xt_match *match = expr->ops->data;
|
||||
unsigned int hook_mask = 0;
|
||||
int ret;
|
||||
|
||||
if (ctx->family != NFPROTO_IPV4 &&
|
||||
|
|
@ -638,11 +644,30 @@ static int nft_match_validate(const struct nft_ctx *ctx,
|
|||
const struct nft_base_chain *basechain =
|
||||
nft_base_chain(ctx->chain);
|
||||
const struct nf_hook_ops *ops = &basechain->ops;
|
||||
unsigned int hook_mask = 1 << ops->hooknum;
|
||||
struct xt_match *match = expr->ops->data;
|
||||
size_t size = XT_ALIGN(match->matchsize);
|
||||
struct xt_mtchk_param par;
|
||||
union nft_entry e = {};
|
||||
void *info;
|
||||
|
||||
hook_mask = 1 << ops->hooknum;
|
||||
if (match->hooks && !(hook_mask & match->hooks))
|
||||
return -EINVAL;
|
||||
|
||||
if (NFT_EXPR_SIZE(size) > NFT_MATCH_LARGE_THRESH) {
|
||||
struct nft_xt_match_priv *priv = nft_expr_priv(expr);
|
||||
|
||||
info = priv->info;
|
||||
} else {
|
||||
info = nft_expr_priv(expr);
|
||||
}
|
||||
|
||||
nft_match_set_mtchk_param(&par, ctx, match, info, &e, 0, false);
|
||||
|
||||
ret = xt_check_hooks_match(&par);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = nft_compat_chain_validate_dependency(ctx, match->table);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
|
|
|||
Loading…
Reference in New Issue