mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	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:0ca743a559("netfilter: nf_tables: add compatibility layer for x_tables") Fixes:a3c90f7a23("netfilter: nf_tables: flow offload expression") Fixes:2fa841938c("netfilter: nf_tables: introduce routing expression") Fixes:554ced0a6e("netfilter: nf_tables: add support for native socket matching") Fixes:ad49d86e07("netfilter: nf_tables: Add synproxy support") Fixes:4ed8eb6570("netfilter: nf_tables: Add native tproxy support") Fixes:6c47260250("netfilter: nf_tables: add xfrm expression") Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
		
							parent
							
								
									f342de4e2f
								
							
						
					
					
						commit
						d0009effa8
					
				
					 8 changed files with 47 additions and 2 deletions
				
			
		| 
						 | 
					@ -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,
 | 
				
			||||||
	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,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	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,
 | 
				
			||||||
	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
 | 
				
			||||||
	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,
 | 
				
			||||||
			       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,
 | 
				
			||||||
		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)
 | 
				
			||||||
		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,
 | 
				
			||||||
				 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,
 | 
				
			||||||
			       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
 | 
				
			||||||
	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) |
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue