Commit bd2d5c54 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files
Pablo Neira Ayuso says:

====================
Netfilter fixes for net

1) Fix insufficient validation of IPSET_ATTR_IPADDR_IPV6 reported
   by syzbot.

2) Remove spurious reports on nf_tables when lockdep gets disabled,
   from Florian Westphal.

3) Fix memleak in the error path of error path of
   ip_vs_control_net_init(), from Wang Hai.

4) Fix missing control data in flow dissector, otherwise IP address
   matching in hardware offload infra does not work.

5) Fix hardware offload match on prefix IP address when userspace
   does not send a bitwise expression to represent the prefix.

* git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf:
  netfilter: nftables_offload: build mask based from the matching bytes
  netfilter: nftables_offload: set address type in control dissector
  ipvs: fix possible memory leak in ip_vs_control_net_init
  netfilter: nf_tables: avoid false-postive lockdep splat
  netfilter: ipset: prevent uninit-value in hash_ip6_add
====================

Link: https://lore.kernel.org/r/20201127190313.24947-1-pablo@netfilter.org


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents e14038a7 a5d45bc0
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ void nft_offload_update_dependency(struct nft_offload_ctx *ctx,

struct nft_flow_key {
	struct flow_dissector_key_basic			basic;
	struct flow_dissector_key_control		control;
	union {
		struct flow_dissector_key_ipv4_addrs	ipv4;
		struct flow_dissector_key_ipv6_addrs	ipv6;
@@ -62,6 +63,9 @@ struct nft_flow_rule {

#define NFT_OFFLOAD_F_ACTION	(1 << 0)

void nft_flow_rule_set_addr_type(struct nft_flow_rule *flow,
				 enum flow_dissector_key_id addr_type);

struct nft_rule;
struct nft_flow_rule *nft_flow_rule_create(struct net *net, const struct nft_rule *rule);
void nft_flow_rule_destroy(struct nft_flow_rule *flow);
@@ -74,6 +78,9 @@ int nft_flow_rule_offload_commit(struct net *net);
		offsetof(struct nft_flow_key, __base.__field);		\
	(__reg)->len		= __len;				\
	(__reg)->key		= __key;				\

#define NFT_OFFLOAD_MATCH_EXACT(__key, __base, __field, __len, __reg)	\
	NFT_OFFLOAD_MATCH(__key, __base, __field, __len, __reg)		\
	memset(&(__reg)->mask, 0xff, (__reg)->len);

int nft_chain_offload_priority(struct nft_base_chain *basechain);
+1 −2
Original line number Diff line number Diff line
@@ -271,8 +271,7 @@ flag_nested(const struct nlattr *nla)

static const struct nla_policy ipaddr_policy[IPSET_ATTR_IPADDR_MAX + 1] = {
	[IPSET_ATTR_IPADDR_IPV4]	= { .type = NLA_U32 },
	[IPSET_ATTR_IPADDR_IPV6]	= { .type = NLA_BINARY,
					    .len = sizeof(struct in6_addr) },
	[IPSET_ATTR_IPADDR_IPV6]	= NLA_POLICY_EXACT_LEN(sizeof(struct in6_addr)),
};

int
+25 −6
Original line number Diff line number Diff line
@@ -4167,12 +4167,18 @@ int __net_init ip_vs_control_net_init(struct netns_ipvs *ipvs)

	spin_lock_init(&ipvs->tot_stats.lock);

	proc_create_net("ip_vs", 0, ipvs->net->proc_net, &ip_vs_info_seq_ops,
			sizeof(struct ip_vs_iter));
	proc_create_net_single("ip_vs_stats", 0, ipvs->net->proc_net,
			ip_vs_stats_show, NULL);
	proc_create_net_single("ip_vs_stats_percpu", 0, ipvs->net->proc_net,
			ip_vs_stats_percpu_show, NULL);
#ifdef CONFIG_PROC_FS
	if (!proc_create_net("ip_vs", 0, ipvs->net->proc_net,
			     &ip_vs_info_seq_ops, sizeof(struct ip_vs_iter)))
		goto err_vs;
	if (!proc_create_net_single("ip_vs_stats", 0, ipvs->net->proc_net,
				    ip_vs_stats_show, NULL))
		goto err_stats;
	if (!proc_create_net_single("ip_vs_stats_percpu", 0,
				    ipvs->net->proc_net,
				    ip_vs_stats_percpu_show, NULL))
		goto err_percpu;
#endif

	if (ip_vs_control_net_init_sysctl(ipvs))
		goto err;
@@ -4180,6 +4186,17 @@ int __net_init ip_vs_control_net_init(struct netns_ipvs *ipvs)
	return 0;

err:
#ifdef CONFIG_PROC_FS
	remove_proc_entry("ip_vs_stats_percpu", ipvs->net->proc_net);

err_percpu:
	remove_proc_entry("ip_vs_stats", ipvs->net->proc_net);

err_stats:
	remove_proc_entry("ip_vs", ipvs->net->proc_net);

err_vs:
#endif
	free_percpu(ipvs->tot_stats.cpustats);
	return -ENOMEM;
}
@@ -4188,9 +4205,11 @@ void __net_exit ip_vs_control_net_cleanup(struct netns_ipvs *ipvs)
{
	ip_vs_trash_cleanup(ipvs);
	ip_vs_control_net_cleanup_sysctl(ipvs);
#ifdef CONFIG_PROC_FS
	remove_proc_entry("ip_vs_stats_percpu", ipvs->net->proc_net);
	remove_proc_entry("ip_vs_stats", ipvs->net->proc_net);
	remove_proc_entry("ip_vs", ipvs->net->proc_net);
#endif
	free_percpu(ipvs->tot_stats.cpustats);
}

+2 −1
Original line number Diff line number Diff line
@@ -619,6 +619,7 @@ static int nft_request_module(struct net *net, const char *fmt, ...)
static void lockdep_nfnl_nft_mutex_not_held(void)
{
#ifdef CONFIG_PROVE_LOCKING
	if (debug_locks)
		WARN_ON_ONCE(lockdep_nfnl_is_held(NFNL_SUBSYS_NFTABLES));
#endif
}
+17 −0
Original line number Diff line number Diff line
@@ -28,6 +28,23 @@ static struct nft_flow_rule *nft_flow_rule_alloc(int num_actions)
	return flow;
}

void nft_flow_rule_set_addr_type(struct nft_flow_rule *flow,
				 enum flow_dissector_key_id addr_type)
{
	struct nft_flow_match *match = &flow->match;
	struct nft_flow_key *mask = &match->mask;
	struct nft_flow_key *key = &match->key;

	if (match->dissector.used_keys & BIT(FLOW_DISSECTOR_KEY_CONTROL))
		return;

	key->control.addr_type = addr_type;
	mask->control.addr_type = 0xffff;
	match->dissector.used_keys |= BIT(FLOW_DISSECTOR_KEY_CONTROL);
	match->dissector.offset[FLOW_DISSECTOR_KEY_CONTROL] =
		offsetof(struct nft_flow_key, control);
}

struct nft_flow_rule *nft_flow_rule_create(struct net *net,
					   const struct nft_rule *rule)
{
Loading