Commit d0009eff authored by Pablo Neira Ayuso's avatar Pablo Neira Ayuso

netfilter: nf_tables: validate NFPROTO_* family

Several expressions explicitly refer to NF_INET_* hook definitions
from expr->ops->validate, however, family is not validated.

Bail out with EOPNOTSUPP in case they are used from unsupported
families.

Fixes: 0ca743a5 ("netfilter: nf_tables: add compatibility layer for x_tables")
Fixes: a3c90f7a ("netfilter: nf_tables: flow offload expression")
Fixes: 2fa84193 ("netfilter: nf_tables: introduce routing expression")
Fixes: 554ced0a ("netfilter: nf_tables: add support for native socket matching")
Fixes: ad49d86e ("netfilter: nf_tables: Add synproxy support")
Fixes: 4ed8eb65 ("netfilter: nf_tables: Add native tproxy support")
Fixes: 6c472602 ("netfilter: nf_tables: add xfrm expression")
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent f342de4e
...@@ -350,6 +350,12 @@ static int nft_target_validate(const struct nft_ctx *ctx, ...@@ -350,6 +350,12 @@ static int nft_target_validate(const struct nft_ctx *ctx,
unsigned int hook_mask = 0; unsigned int hook_mask = 0;
int ret; int ret;
if (ctx->family != NFPROTO_IPV4 &&
ctx->family != NFPROTO_IPV6 &&
ctx->family != NFPROTO_BRIDGE &&
ctx->family != NFPROTO_ARP)
return -EOPNOTSUPP;
if (nft_is_base_chain(ctx->chain)) { if (nft_is_base_chain(ctx->chain)) {
const struct nft_base_chain *basechain = const struct nft_base_chain *basechain =
nft_base_chain(ctx->chain); nft_base_chain(ctx->chain);
...@@ -595,6 +601,12 @@ static int nft_match_validate(const struct nft_ctx *ctx, ...@@ -595,6 +601,12 @@ static int nft_match_validate(const struct nft_ctx *ctx,
unsigned int hook_mask = 0; unsigned int hook_mask = 0;
int ret; int ret;
if (ctx->family != NFPROTO_IPV4 &&
ctx->family != NFPROTO_IPV6 &&
ctx->family != NFPROTO_BRIDGE &&
ctx->family != NFPROTO_ARP)
return -EOPNOTSUPP;
if (nft_is_base_chain(ctx->chain)) { if (nft_is_base_chain(ctx->chain)) {
const struct nft_base_chain *basechain = const struct nft_base_chain *basechain =
nft_base_chain(ctx->chain); nft_base_chain(ctx->chain);
......
...@@ -384,6 +384,11 @@ static int nft_flow_offload_validate(const struct nft_ctx *ctx, ...@@ -384,6 +384,11 @@ static int nft_flow_offload_validate(const struct nft_ctx *ctx,
{ {
unsigned int hook_mask = (1 << NF_INET_FORWARD); unsigned int hook_mask = (1 << NF_INET_FORWARD);
if (ctx->family != NFPROTO_IPV4 &&
ctx->family != NFPROTO_IPV6 &&
ctx->family != NFPROTO_INET)
return -EOPNOTSUPP;
return nft_chain_validate_hooks(ctx->chain, hook_mask); return nft_chain_validate_hooks(ctx->chain, hook_mask);
} }
......
...@@ -143,6 +143,11 @@ static int nft_nat_validate(const struct nft_ctx *ctx, ...@@ -143,6 +143,11 @@ static int nft_nat_validate(const struct nft_ctx *ctx,
struct nft_nat *priv = nft_expr_priv(expr); struct nft_nat *priv = nft_expr_priv(expr);
int err; int err;
if (ctx->family != NFPROTO_IPV4 &&
ctx->family != NFPROTO_IPV6 &&
ctx->family != NFPROTO_INET)
return -EOPNOTSUPP;
err = nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT); err = nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT);
if (err < 0) if (err < 0)
return err; return err;
......
...@@ -166,6 +166,11 @@ static int nft_rt_validate(const struct nft_ctx *ctx, const struct nft_expr *exp ...@@ -166,6 +166,11 @@ static int nft_rt_validate(const struct nft_ctx *ctx, const struct nft_expr *exp
const struct nft_rt *priv = nft_expr_priv(expr); const struct nft_rt *priv = nft_expr_priv(expr);
unsigned int hooks; unsigned int hooks;
if (ctx->family != NFPROTO_IPV4 &&
ctx->family != NFPROTO_IPV6 &&
ctx->family != NFPROTO_INET)
return -EOPNOTSUPP;
switch (priv->key) { switch (priv->key) {
case NFT_RT_NEXTHOP4: case NFT_RT_NEXTHOP4:
case NFT_RT_NEXTHOP6: case NFT_RT_NEXTHOP6:
......
...@@ -242,6 +242,11 @@ static int nft_socket_validate(const struct nft_ctx *ctx, ...@@ -242,6 +242,11 @@ static int nft_socket_validate(const struct nft_ctx *ctx,
const struct nft_expr *expr, const struct nft_expr *expr,
const struct nft_data **data) const struct nft_data **data)
{ {
if (ctx->family != NFPROTO_IPV4 &&
ctx->family != NFPROTO_IPV6 &&
ctx->family != NFPROTO_INET)
return -EOPNOTSUPP;
return nft_chain_validate_hooks(ctx->chain, return nft_chain_validate_hooks(ctx->chain,
(1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_PRE_ROUTING) |
(1 << NF_INET_LOCAL_IN) | (1 << NF_INET_LOCAL_IN) |
......
...@@ -186,7 +186,6 @@ static int nft_synproxy_do_init(const struct nft_ctx *ctx, ...@@ -186,7 +186,6 @@ static int nft_synproxy_do_init(const struct nft_ctx *ctx,
break; break;
#endif #endif
case NFPROTO_INET: case NFPROTO_INET:
case NFPROTO_BRIDGE:
err = nf_synproxy_ipv4_init(snet, ctx->net); err = nf_synproxy_ipv4_init(snet, ctx->net);
if (err) if (err)
goto nf_ct_failure; goto nf_ct_failure;
...@@ -219,7 +218,6 @@ static void nft_synproxy_do_destroy(const struct nft_ctx *ctx) ...@@ -219,7 +218,6 @@ static void nft_synproxy_do_destroy(const struct nft_ctx *ctx)
break; break;
#endif #endif
case NFPROTO_INET: case NFPROTO_INET:
case NFPROTO_BRIDGE:
nf_synproxy_ipv4_fini(snet, ctx->net); nf_synproxy_ipv4_fini(snet, ctx->net);
nf_synproxy_ipv6_fini(snet, ctx->net); nf_synproxy_ipv6_fini(snet, ctx->net);
break; break;
...@@ -253,6 +251,11 @@ static int nft_synproxy_validate(const struct nft_ctx *ctx, ...@@ -253,6 +251,11 @@ static int nft_synproxy_validate(const struct nft_ctx *ctx,
const struct nft_expr *expr, const struct nft_expr *expr,
const struct nft_data **data) const struct nft_data **data)
{ {
if (ctx->family != NFPROTO_IPV4 &&
ctx->family != NFPROTO_IPV6 &&
ctx->family != NFPROTO_INET)
return -EOPNOTSUPP;
return nft_chain_validate_hooks(ctx->chain, (1 << NF_INET_LOCAL_IN) | return nft_chain_validate_hooks(ctx->chain, (1 << NF_INET_LOCAL_IN) |
(1 << NF_INET_FORWARD)); (1 << NF_INET_FORWARD));
} }
......
...@@ -316,6 +316,11 @@ static int nft_tproxy_validate(const struct nft_ctx *ctx, ...@@ -316,6 +316,11 @@ static int nft_tproxy_validate(const struct nft_ctx *ctx,
const struct nft_expr *expr, const struct nft_expr *expr,
const struct nft_data **data) const struct nft_data **data)
{ {
if (ctx->family != NFPROTO_IPV4 &&
ctx->family != NFPROTO_IPV6 &&
ctx->family != NFPROTO_INET)
return -EOPNOTSUPP;
return nft_chain_validate_hooks(ctx->chain, 1 << NF_INET_PRE_ROUTING); return nft_chain_validate_hooks(ctx->chain, 1 << NF_INET_PRE_ROUTING);
} }
......
...@@ -235,6 +235,11 @@ static int nft_xfrm_validate(const struct nft_ctx *ctx, const struct nft_expr *e ...@@ -235,6 +235,11 @@ static int nft_xfrm_validate(const struct nft_ctx *ctx, const struct nft_expr *e
const struct nft_xfrm *priv = nft_expr_priv(expr); const struct nft_xfrm *priv = nft_expr_priv(expr);
unsigned int hooks; unsigned int hooks;
if (ctx->family != NFPROTO_IPV4 &&
ctx->family != NFPROTO_IPV6 &&
ctx->family != NFPROTO_INET)
return -EOPNOTSUPP;
switch (priv->dir) { switch (priv->dir) {
case XFRM_POLICY_IN: case XFRM_POLICY_IN:
hooks = (1 << NF_INET_FORWARD) | hooks = (1 << NF_INET_FORWARD) |
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment