diff options
Diffstat (limited to 'net')
50 files changed, 364 insertions, 191 deletions
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index a0b253ecada..a5bb0a769eb 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c @@ -1288,7 +1288,8 @@ static int batadv_iv_ogm_receive(struct sk_buff *skb,  	batadv_ogm_packet = (struct batadv_ogm_packet *)packet_buff;  	/* unpack the aggregated packets and process them one by one */ -	do { +	while (batadv_iv_ogm_aggr_packet(buff_pos, packet_len, +					 batadv_ogm_packet->tt_num_changes)) {  		tt_buff = packet_buff + buff_pos + BATADV_OGM_HLEN;  		batadv_iv_ogm_process(ethhdr, batadv_ogm_packet, tt_buff, @@ -1299,8 +1300,7 @@ static int batadv_iv_ogm_receive(struct sk_buff *skb,  		packet_pos = packet_buff + buff_pos;  		batadv_ogm_packet = (struct batadv_ogm_packet *)packet_pos; -	} while (batadv_iv_ogm_aggr_packet(buff_pos, packet_len, -					   batadv_ogm_packet->tt_num_changes)); +	}  	kfree_skb(skb);  	return NET_RX_SUCCESS; diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index d5f1d3fd4b2..314c73ed418 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -66,7 +66,7 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)  			goto out;  		} -		mdst = br_mdb_get(br, skb); +		mdst = br_mdb_get(br, skb, vid);  		if (mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb))  			br_multicast_deliver(mdst, skb);  		else diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index 48033015189..828e2bcc1f5 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c @@ -97,7 +97,7 @@ int br_handle_frame_finish(struct sk_buff *skb)  	if (is_broadcast_ether_addr(dest))  		skb2 = skb;  	else if (is_multicast_ether_addr(dest)) { -		mdst = br_mdb_get(br, skb); +		mdst = br_mdb_get(br, skb, vid);  		if (mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb)) {  			if ((mdst && mdst->mglist) ||  			    br_multicast_is_router(br)) diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c index 9f97b850fc6..ee79f3f2038 100644 --- a/net/bridge/br_mdb.c +++ b/net/bridge/br_mdb.c @@ -80,6 +80,7 @@ static int br_mdb_fill_info(struct sk_buff *skb, struct netlink_callback *cb,  				port = p->port;  				if (port) {  					struct br_mdb_entry e; +					memset(&e, 0, sizeof(e));  					e.ifindex = port->dev->ifindex;  					e.state = p->state;  					if (p->addr.proto == htons(ETH_P_IP)) @@ -136,6 +137,7 @@ static int br_mdb_dump(struct sk_buff *skb, struct netlink_callback *cb)  				break;  			bpm = nlmsg_data(nlh); +			memset(bpm, 0, sizeof(*bpm));  			bpm->ifindex = dev->ifindex;  			if (br_mdb_fill_info(skb, cb, dev) < 0)  				goto out; @@ -171,6 +173,7 @@ static int nlmsg_populate_mdb_fill(struct sk_buff *skb,  		return -EMSGSIZE;  	bpm = nlmsg_data(nlh); +	memset(bpm, 0, sizeof(*bpm));  	bpm->family  = AF_BRIDGE;  	bpm->ifindex = dev->ifindex;  	nest = nla_nest_start(skb, MDBA_MDB); @@ -228,6 +231,7 @@ void br_mdb_notify(struct net_device *dev, struct net_bridge_port *port,  {  	struct br_mdb_entry entry; +	memset(&entry, 0, sizeof(entry));  	entry.ifindex = port->dev->ifindex;  	entry.addr.proto = group->proto;  	entry.addr.u.ip4 = group->u.ip4; diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 10e6fce1bb6..923fbeaf7af 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -132,7 +132,7 @@ static struct net_bridge_mdb_entry *br_mdb_ip6_get(  #endif  struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br, -					struct sk_buff *skb) +					struct sk_buff *skb, u16 vid)  {  	struct net_bridge_mdb_htable *mdb = rcu_dereference(br->mdb);  	struct br_ip ip; @@ -144,6 +144,7 @@ struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br,  		return NULL;  	ip.proto = skb->protocol; +	ip.vid = vid;  	switch (skb->protocol) {  	case htons(ETH_P_IP): diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index 27aa3ee517c..299fc5f40a2 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@ -29,6 +29,7 @@ static inline size_t br_port_info_size(void)  		+ nla_total_size(1)	/* IFLA_BRPORT_MODE */  		+ nla_total_size(1)	/* IFLA_BRPORT_GUARD */  		+ nla_total_size(1)	/* IFLA_BRPORT_PROTECT */ +		+ nla_total_size(1)	/* IFLA_BRPORT_FAST_LEAVE */  		+ 0;  } @@ -329,6 +330,7 @@ static int br_setport(struct net_bridge_port *p, struct nlattr *tb[])  	br_set_port_flag(p, tb, IFLA_BRPORT_MODE, BR_HAIRPIN_MODE);  	br_set_port_flag(p, tb, IFLA_BRPORT_GUARD, BR_BPDU_GUARD);  	br_set_port_flag(p, tb, IFLA_BRPORT_FAST_LEAVE, BR_MULTICAST_FAST_LEAVE); +	br_set_port_flag(p, tb, IFLA_BRPORT_PROTECT, BR_ROOT_BLOCK);  	if (tb[IFLA_BRPORT_COST]) {  		err = br_stp_set_path_cost(p, nla_get_u32(tb[IFLA_BRPORT_COST])); diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 6d314c4e6bc..3cbf5beb3d4 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -442,7 +442,7 @@ extern int br_multicast_rcv(struct net_bridge *br,  			    struct net_bridge_port *port,  			    struct sk_buff *skb);  extern struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br, -					       struct sk_buff *skb); +					       struct sk_buff *skb, u16 vid);  extern void br_multicast_add_port(struct net_bridge_port *port);  extern void br_multicast_del_port(struct net_bridge_port *port);  extern void br_multicast_enable_port(struct net_bridge_port *port); @@ -504,7 +504,7 @@ static inline int br_multicast_rcv(struct net_bridge *br,  }  static inline struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br, -						      struct sk_buff *skb) +						      struct sk_buff *skb, u16 vid)  {  	return NULL;  } diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c index 69bc4bf89e3..4543b9aba40 100644 --- a/net/ceph/osdmap.c +++ b/net/ceph/osdmap.c @@ -654,6 +654,24 @@ static int osdmap_set_max_osd(struct ceph_osdmap *map, int max)  	return 0;  } +static int __decode_pgid(void **p, void *end, struct ceph_pg *pg) +{ +	u8 v; + +	ceph_decode_need(p, end, 1+8+4+4, bad); +	v = ceph_decode_8(p); +	if (v != 1) +		goto bad; +	pg->pool = ceph_decode_64(p); +	pg->seed = ceph_decode_32(p); +	*p += 4; /* skip preferred */ +	return 0; + +bad: +	dout("error decoding pgid\n"); +	return -EINVAL; +} +  /*   * decode a full map.   */ @@ -745,13 +763,12 @@ struct ceph_osdmap *osdmap_decode(void **p, void *end)  	for (i = 0; i < len; i++) {  		int n, j;  		struct ceph_pg pgid; -		struct ceph_pg_v1 pgid_v1;  		struct ceph_pg_mapping *pg; -		ceph_decode_need(p, end, sizeof(u32) + sizeof(u64), bad); -		ceph_decode_copy(p, &pgid_v1, sizeof(pgid_v1)); -		pgid.pool = le32_to_cpu(pgid_v1.pool); -		pgid.seed = le16_to_cpu(pgid_v1.ps); +		err = __decode_pgid(p, end, &pgid); +		if (err) +			goto bad; +		ceph_decode_need(p, end, sizeof(u32), bad);  		n = ceph_decode_32(p);  		err = -EINVAL;  		if (n > (UINT_MAX - sizeof(*pg)) / sizeof(u32)) @@ -818,8 +835,8 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end,  	u16 version;  	ceph_decode_16_safe(p, end, version, bad); -	if (version > 6) { -		pr_warning("got unknown v %d > %d of inc osdmap\n", version, 6); +	if (version != 6) { +		pr_warning("got unknown v %d != 6 of inc osdmap\n", version);  		goto bad;  	} @@ -963,15 +980,14 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end,  	while (len--) {  		struct ceph_pg_mapping *pg;  		int j; -		struct ceph_pg_v1 pgid_v1;  		struct ceph_pg pgid;  		u32 pglen; -		ceph_decode_need(p, end, sizeof(u64) + sizeof(u32), bad); -		ceph_decode_copy(p, &pgid_v1, sizeof(pgid_v1)); -		pgid.pool = le32_to_cpu(pgid_v1.pool); -		pgid.seed = le16_to_cpu(pgid_v1.ps); -		pglen = ceph_decode_32(p); +		err = __decode_pgid(p, end, &pgid); +		if (err) +			goto bad; +		ceph_decode_need(p, end, sizeof(u32), bad); +		pglen = ceph_decode_32(p);  		if (pglen) {  			ceph_decode_need(p, end, pglen*sizeof(u32), bad); diff --git a/net/core/dev.c b/net/core/dev.c index a06a7a58dd1..d540ced1f6c 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2219,9 +2219,9 @@ struct sk_buff *skb_mac_gso_segment(struct sk_buff *skb,  	struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT);  	struct packet_offload *ptype;  	__be16 type = skb->protocol; +	int vlan_depth = ETH_HLEN;  	while (type == htons(ETH_P_8021Q)) { -		int vlan_depth = ETH_HLEN;  		struct vlan_hdr *vh;  		if (unlikely(!pskb_may_pull(skb, vlan_depth + VLAN_HLEN))) @@ -3444,6 +3444,7 @@ ncls:  		}  		switch (rx_handler(&skb)) {  		case RX_HANDLER_CONSUMED: +			ret = NET_RX_SUCCESS;  			goto unlock;  		case RX_HANDLER_ANOTHER:  			goto another_round; @@ -4103,7 +4104,7 @@ static void net_rx_action(struct softirq_action *h)  		 * Allow this to run for 2 jiffies since which will allow  		 * an average latency of 1.5/HZ.  		 */ -		if (unlikely(budget <= 0 || time_after(jiffies, time_limit))) +		if (unlikely(budget <= 0 || time_after_eq(jiffies, time_limit)))  			goto softnet_break;  		local_irq_enable(); @@ -4780,7 +4781,7 @@ EXPORT_SYMBOL(dev_set_mac_address);  /**   *	dev_change_carrier - Change device carrier   *	@dev: device - *	@new_carries: new value + *	@new_carrier: new value   *   *	Change device carrier   */ diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index b376410ff25..5fb8d7e4729 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -979,6 +979,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,  			 * report anything.  			 */  			ivi.spoofchk = -1; +			memset(ivi.mac, 0, sizeof(ivi.mac));  			if (dev->netdev_ops->ndo_get_vf_config(dev, i, &ivi))  				break;  			vf_mac.vf = @@ -2620,7 +2621,7 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)  		struct rtattr *attr = (void *)nlh + NLMSG_ALIGN(min_len);  		while (RTA_OK(attr, attrlen)) { -			unsigned int flavor = attr->rta_type; +			unsigned int flavor = attr->rta_type & NLA_TYPE_MASK;  			if (flavor) {  				if (flavor > rta_max[sz_idx])  					return -EINVAL; diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c index 1b588e23cf8..21291f1abcd 100644 --- a/net/dcb/dcbnl.c +++ b/net/dcb/dcbnl.c @@ -284,6 +284,7 @@ static int dcbnl_getperm_hwaddr(struct net_device *netdev, struct nlmsghdr *nlh,  	if (!netdev->dcbnl_ops->getpermhwaddr)  		return -EOPNOTSUPP; +	memset(perm_addr, 0, sizeof(perm_addr));  	netdev->dcbnl_ops->getpermhwaddr(netdev, perm_addr);  	return nla_put(skb, DCB_ATTR_PERM_HWADDR, sizeof(perm_addr), perm_addr); @@ -1042,6 +1043,7 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev)  	if (ops->ieee_getets) {  		struct ieee_ets ets; +		memset(&ets, 0, sizeof(ets));  		err = ops->ieee_getets(netdev, &ets);  		if (!err &&  		    nla_put(skb, DCB_ATTR_IEEE_ETS, sizeof(ets), &ets)) @@ -1050,6 +1052,7 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev)  	if (ops->ieee_getmaxrate) {  		struct ieee_maxrate maxrate; +		memset(&maxrate, 0, sizeof(maxrate));  		err = ops->ieee_getmaxrate(netdev, &maxrate);  		if (!err) {  			err = nla_put(skb, DCB_ATTR_IEEE_MAXRATE, @@ -1061,6 +1064,7 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev)  	if (ops->ieee_getpfc) {  		struct ieee_pfc pfc; +		memset(&pfc, 0, sizeof(pfc));  		err = ops->ieee_getpfc(netdev, &pfc);  		if (!err &&  		    nla_put(skb, DCB_ATTR_IEEE_PFC, sizeof(pfc), &pfc)) @@ -1094,6 +1098,7 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev)  	/* get peer info if available */  	if (ops->ieee_peer_getets) {  		struct ieee_ets ets; +		memset(&ets, 0, sizeof(ets));  		err = ops->ieee_peer_getets(netdev, &ets);  		if (!err &&  		    nla_put(skb, DCB_ATTR_IEEE_PEER_ETS, sizeof(ets), &ets)) @@ -1102,6 +1107,7 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev)  	if (ops->ieee_peer_getpfc) {  		struct ieee_pfc pfc; +		memset(&pfc, 0, sizeof(pfc));  		err = ops->ieee_peer_getpfc(netdev, &pfc);  		if (!err &&  		    nla_put(skb, DCB_ATTR_IEEE_PEER_PFC, sizeof(pfc), &pfc)) @@ -1280,6 +1286,7 @@ static int dcbnl_cee_fill(struct sk_buff *skb, struct net_device *netdev)  	/* peer info if available */  	if (ops->cee_peer_getpg) {  		struct cee_pg pg; +		memset(&pg, 0, sizeof(pg));  		err = ops->cee_peer_getpg(netdev, &pg);  		if (!err &&  		    nla_put(skb, DCB_ATTR_CEE_PEER_PG, sizeof(pg), &pg)) @@ -1288,6 +1295,7 @@ static int dcbnl_cee_fill(struct sk_buff *skb, struct net_device *netdev)  	if (ops->cee_peer_getpfc) {  		struct cee_pfc pfc; +		memset(&pfc, 0, sizeof(pfc));  		err = ops->cee_peer_getpfc(netdev, &pfc);  		if (!err &&  		    nla_put(skb, DCB_ATTR_CEE_PEER_PFC, sizeof(pfc), &pfc)) diff --git a/net/ieee802154/6lowpan.h b/net/ieee802154/6lowpan.h index 8c2251fb0a3..bba5f833631 100644 --- a/net/ieee802154/6lowpan.h +++ b/net/ieee802154/6lowpan.h @@ -84,7 +84,7 @@  	(memcmp(addr1, addr2, length >> 3) == 0)  /* local link, i.e. FE80::/10 */ -#define is_addr_link_local(a) (((a)->s6_addr16[0]) == 0x80FE) +#define is_addr_link_local(a) (((a)->s6_addr16[0]) == htons(0xFE80))  /*   * check whether we can compress the IID to 16 bits, diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 7d1874be1df..786d97aee75 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -735,6 +735,7 @@ EXPORT_SYMBOL(inet_csk_destroy_sock);   * tcp/dccp_create_openreq_child().   */  void inet_csk_prepare_forced_close(struct sock *sk) +	__releases(&sk->sk_lock.slock)  {  	/* sk_clone_lock locked the socket and set refcnt to 2 */  	bh_unlock_sock(sk); diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c index 245ae078a07..f4fd23de9b1 100644 --- a/net/ipv4/inet_fragment.c +++ b/net/ipv4/inet_fragment.c @@ -21,6 +21,7 @@  #include <linux/rtnetlink.h>  #include <linux/slab.h> +#include <net/sock.h>  #include <net/inet_frag.h>  static void inet_frag_secret_rebuild(unsigned long dummy) @@ -277,6 +278,7 @@ struct inet_frag_queue *inet_frag_find(struct netns_frags *nf,  	__releases(&f->lock)  {  	struct inet_frag_queue *q; +	int depth = 0;  	hlist_for_each_entry(q, &f->hash[hash], list) {  		if (q->net == nf && f->match(q, key)) { @@ -284,9 +286,25 @@ struct inet_frag_queue *inet_frag_find(struct netns_frags *nf,  			read_unlock(&f->lock);  			return q;  		} +		depth++;  	}  	read_unlock(&f->lock); -	return inet_frag_create(nf, f, key); +	if (depth <= INETFRAGS_MAXDEPTH) +		return inet_frag_create(nf, f, key); +	else +		return ERR_PTR(-ENOBUFS);  }  EXPORT_SYMBOL(inet_frag_find); + +void inet_frag_maybe_warn_overflow(struct inet_frag_queue *q, +				   const char *prefix) +{ +	static const char msg[] = "inet_frag_find: Fragment hash bucket" +		" list length grew over limit " __stringify(INETFRAGS_MAXDEPTH) +		". Dropping fragment.\n"; + +	if (PTR_ERR(q) == -ENOBUFS) +		LIMIT_NETDEBUG(KERN_WARNING "%s%s", prefix, msg); +} +EXPORT_SYMBOL(inet_frag_maybe_warn_overflow); diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index b6d30acb600..a6445b843ef 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c @@ -292,14 +292,11 @@ static inline struct ipq *ip_find(struct net *net, struct iphdr *iph, u32 user)  	hash = ipqhashfn(iph->id, iph->saddr, iph->daddr, iph->protocol);  	q = inet_frag_find(&net->ipv4.frags, &ip4_frags, &arg, hash); -	if (q == NULL) -		goto out_nomem; - +	if (IS_ERR_OR_NULL(q)) { +		inet_frag_maybe_warn_overflow(q, pr_fmt()); +		return NULL; +	}  	return container_of(q, struct ipq, q); - -out_nomem: -	LIMIT_NETDEBUG(KERN_ERR pr_fmt("ip_frag_create: no memory left !\n")); -	return NULL;  }  /* Is the fragment too far ahead to be part of ipq? */ diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index d0ef0e674ec..91d66dbde9c 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -798,10 +798,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev  	if (dev->header_ops && dev->type == ARPHRD_IPGRE) {  		gre_hlen = 0; -		if (skb->protocol == htons(ETH_P_IP)) -			tiph = (const struct iphdr *)skb->data; -		else -			tiph = &tunnel->parms.iph; +		tiph = (const struct iphdr *)skb->data;  	} else {  		gre_hlen = tunnel->hlen;  		tiph = &tunnel->parms.iph; diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c index f6289bf6f33..ec7264514a8 100644 --- a/net/ipv4/ip_options.c +++ b/net/ipv4/ip_options.c @@ -370,7 +370,6 @@ int ip_options_compile(struct net *net,  				}  				switch (optptr[3]&0xF) {  				      case IPOPT_TS_TSONLY: -					opt->ts = optptr - iph;  					if (skb)  						timeptr = &optptr[optptr[2]-1];  					opt->ts_needtime = 1; @@ -381,7 +380,6 @@ int ip_options_compile(struct net *net,  						pp_ptr = optptr + 2;  						goto error;  					} -					opt->ts = optptr - iph;  					if (rt)  {  						spec_dst_fill(&spec_dst, skb);  						memcpy(&optptr[optptr[2]-1], &spec_dst, 4); @@ -396,7 +394,6 @@ int ip_options_compile(struct net *net,  						pp_ptr = optptr + 2;  						goto error;  					} -					opt->ts = optptr - iph;  					{  						__be32 addr;  						memcpy(&addr, &optptr[optptr[2]-1], 4); @@ -423,18 +420,18 @@ int ip_options_compile(struct net *net,  					put_unaligned_be32(midtime, timeptr);  					opt->is_changed = 1;  				} -			} else { +			} else if ((optptr[3]&0xF) != IPOPT_TS_PRESPEC) {  				unsigned int overflow = optptr[3]>>4;  				if (overflow == 15) {  					pp_ptr = optptr + 3;  					goto error;  				} -				opt->ts = optptr - iph;  				if (skb) {  					optptr[3] = (optptr[3]&0xF)|((overflow+1)<<4);  					opt->is_changed = 1;  				}  			} +			opt->ts = optptr - iph;  			break;  		      case IPOPT_RA:  			if (optlen < 4) { diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 47e854fcae2..e2202079070 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -775,7 +775,7 @@ struct sk_buff *sk_stream_alloc_skb(struct sock *sk, int size, gfp_t gfp)  			 * Make sure that we have exactly size bytes  			 * available to the caller, no more, no less.  			 */ -			skb->avail_size = size; +			skb->reserved_tailroom = skb->end - skb->tail - size;  			return skb;  		}  		__kfree_skb(skb); diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 4a8ec457310..d09203c6326 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -274,13 +274,6 @@ static void tcp_v4_mtu_reduced(struct sock *sk)  	struct inet_sock *inet = inet_sk(sk);  	u32 mtu = tcp_sk(sk)->mtu_info; -	/* We are not interested in TCP_LISTEN and open_requests (SYN-ACKs -	 * send out by Linux are always <576bytes so they should go through -	 * unfragmented). -	 */ -	if (sk->sk_state == TCP_LISTEN) -		return; -  	dst = inet_csk_update_pmtu(sk, mtu);  	if (!dst)  		return; @@ -408,6 +401,13 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info)  			goto out;  		if (code == ICMP_FRAG_NEEDED) { /* PMTU discovery (RFC1191) */ +			/* We are not interested in TCP_LISTEN and open_requests +			 * (SYN-ACKs send out by Linux are always <576bytes so +			 * they should go through unfragmented). +			 */ +			if (sk->sk_state == TCP_LISTEN) +				goto out; +  			tp->mtu_info = info;  			if (!sock_owned_by_user(sk)) {  				tcp_v4_mtu_reduced(sk); diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index e2b4461074d..817fbb396bc 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -1298,7 +1298,6 @@ static void __pskb_trim_head(struct sk_buff *skb, int len)  	eat = min_t(int, len, skb_headlen(skb));  	if (eat) {  		__skb_pull(skb, eat); -		skb->avail_size -= eat;  		len -= eat;  		if (!len)  			return; diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index b1876e52091..e33fe0ab256 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c @@ -281,7 +281,8 @@ int ip6_mc_input(struct sk_buff *skb)  	 *      IPv6 multicast router mode is now supported ;)  	 */  	if (dev_net(skb->dev)->ipv6.devconf_all->mc_forwarding && -	    !(ipv6_addr_type(&hdr->daddr) & IPV6_ADDR_LINKLOCAL) && +	    !(ipv6_addr_type(&hdr->daddr) & +	      (IPV6_ADDR_LOOPBACK|IPV6_ADDR_LINKLOCAL)) &&  	    likely(!(IP6CB(skb)->flags & IP6SKB_FORWARDED))) {  		/*  		 * Okay, we try to forward - split and duplicate diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 54087e96d7b..6700069949d 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c @@ -14,6 +14,8 @@   * 2 of the License, or (at your option) any later version.   */ +#define pr_fmt(fmt) "IPv6-nf: " fmt +  #include <linux/errno.h>  #include <linux/types.h>  #include <linux/string.h> @@ -180,13 +182,11 @@ static inline struct frag_queue *fq_find(struct net *net, __be32 id,  	q = inet_frag_find(&net->nf_frag.frags, &nf_frags, &arg, hash);  	local_bh_enable(); -	if (q == NULL) -		goto oom; - +	if (IS_ERR_OR_NULL(q)) { +		inet_frag_maybe_warn_overflow(q, pr_fmt()); +		return NULL; +	}  	return container_of(q, struct frag_queue, q); - -oom: -	return NULL;  } diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index 3c6a77290c6..196ab9347ad 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c @@ -26,6 +26,9 @@   *	YOSHIFUJI,H. @USAGI	Always remove fragment header to   *				calculate ICV correctly.   */ + +#define pr_fmt(fmt) "IPv6: " fmt +  #include <linux/errno.h>  #include <linux/types.h>  #include <linux/string.h> @@ -185,9 +188,10 @@ fq_find(struct net *net, __be32 id, const struct in6_addr *src, const struct in6  	hash = inet6_hash_frag(id, src, dst, ip6_frags.rnd);  	q = inet_frag_find(&net->ipv6.frags, &ip6_frags, &arg, hash); -	if (q == NULL) +	if (IS_ERR_OR_NULL(q)) { +		inet_frag_maybe_warn_overflow(q, pr_fmt());  		return NULL; - +	}  	return container_of(q, struct frag_queue, q);  } diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 9b6460055df..f6d629fd6ae 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -389,6 +389,13 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,  	}  	if (type == ICMPV6_PKT_TOOBIG) { +		/* We are not interested in TCP_LISTEN and open_requests +		 * (SYN-ACKs send out by Linux are always <576bytes so +		 * they should go through unfragmented). +		 */ +		if (sk->sk_state == TCP_LISTEN) +			goto out; +  		tp->mtu_info = ntohl(info);  		if (!sock_owned_by_user(sk))  			tcp_v6_mtu_reduced(sk); diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c index 9a5fd3c3e53..362ba47968e 100644 --- a/net/irda/ircomm/ircomm_tty.c +++ b/net/irda/ircomm/ircomm_tty.c @@ -280,7 +280,7 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,  	struct tty_port *port = &self->port;  	DECLARE_WAITQUEUE(wait, current);  	int		retval; -	int		do_clocal = 0, extra_count = 0; +	int		do_clocal = 0;  	unsigned long	flags;  	IRDA_DEBUG(2, "%s()\n", __func__ ); @@ -289,8 +289,15 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,  	 * If non-blocking mode is set, or the port is not enabled,  	 * then make the check up front and then exit.  	 */ -	if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){ -		/* nonblock mode is set or port is not enabled */ +	if (test_bit(TTY_IO_ERROR, &tty->flags)) { +		port->flags |= ASYNC_NORMAL_ACTIVE; +		return 0; +	} + +	if (filp->f_flags & O_NONBLOCK) { +		/* nonblock mode is set */ +		if (tty->termios.c_cflag & CBAUD) +			tty_port_raise_dtr_rts(port);  		port->flags |= ASYNC_NORMAL_ACTIVE;  		IRDA_DEBUG(1, "%s(), O_NONBLOCK requested!\n", __func__ );  		return 0; @@ -315,18 +322,16 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,  	      __FILE__, __LINE__, tty->driver->name, port->count);  	spin_lock_irqsave(&port->lock, flags); -	if (!tty_hung_up_p(filp)) { -		extra_count = 1; +	if (!tty_hung_up_p(filp))  		port->count--; -	} -	spin_unlock_irqrestore(&port->lock, flags);  	port->blocked_open++; +	spin_unlock_irqrestore(&port->lock, flags);  	while (1) {  		if (tty->termios.c_cflag & CBAUD)  			tty_port_raise_dtr_rts(port); -		current->state = TASK_INTERRUPTIBLE; +		set_current_state(TASK_INTERRUPTIBLE);  		if (tty_hung_up_p(filp) ||  		    !test_bit(ASYNCB_INITIALIZED, &port->flags)) { @@ -361,13 +366,11 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,  	__set_current_state(TASK_RUNNING);  	remove_wait_queue(&port->open_wait, &wait); -	if (extra_count) { -		/* ++ is not atomic, so this should be protected - Jean II */ -		spin_lock_irqsave(&port->lock, flags); +	spin_lock_irqsave(&port->lock, flags); +	if (!tty_hung_up_p(filp))  		port->count++; -		spin_unlock_irqrestore(&port->lock, flags); -	}  	port->blocked_open--; +	spin_unlock_irqrestore(&port->lock, flags);  	IRDA_DEBUG(1, "%s(%d):block_til_ready after blocking on %s open_count=%d\n",  	      __FILE__, __LINE__, tty->driver->name, port->count); diff --git a/net/key/af_key.c b/net/key/af_key.c index 556fdafdd1e..8555f331ea6 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -2201,7 +2201,7 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, const struct sadb_  		      XFRM_POLICY_BLOCK : XFRM_POLICY_ALLOW);  	xp->priority = pol->sadb_x_policy_priority; -	sa = ext_hdrs[SADB_EXT_ADDRESS_SRC-1], +	sa = ext_hdrs[SADB_EXT_ADDRESS_SRC-1];  	xp->family = pfkey_sadb_addr2xfrm_addr(sa, &xp->selector.saddr);  	if (!xp->family) {  		err = -EINVAL; @@ -2214,7 +2214,7 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, const struct sadb_  	if (xp->selector.sport)  		xp->selector.sport_mask = htons(0xffff); -	sa = ext_hdrs[SADB_EXT_ADDRESS_DST-1], +	sa = ext_hdrs[SADB_EXT_ADDRESS_DST-1];  	pfkey_sadb_addr2xfrm_addr(sa, &xp->selector.daddr);  	xp->selector.prefixlen_d = sa->sadb_address_prefixlen; @@ -2315,7 +2315,7 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, const struct sa  	memset(&sel, 0, sizeof(sel)); -	sa = ext_hdrs[SADB_EXT_ADDRESS_SRC-1], +	sa = ext_hdrs[SADB_EXT_ADDRESS_SRC-1];  	sel.family = pfkey_sadb_addr2xfrm_addr(sa, &sel.saddr);  	sel.prefixlen_s = sa->sadb_address_prefixlen;  	sel.proto = pfkey_proto_to_xfrm(sa->sadb_address_proto); @@ -2323,7 +2323,7 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, const struct sa  	if (sel.sport)  		sel.sport_mask = htons(0xffff); -	sa = ext_hdrs[SADB_EXT_ADDRESS_DST-1], +	sa = ext_hdrs[SADB_EXT_ADDRESS_DST-1];  	pfkey_sadb_addr2xfrm_addr(sa, &sel.daddr);  	sel.prefixlen_d = sa->sadb_address_prefixlen;  	sel.proto = pfkey_proto_to_xfrm(sa->sadb_address_proto); diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 808f5fcd1ce..fb306814576 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -3290,14 +3290,19 @@ static int ieee80211_cfg_get_channel(struct wiphy *wiphy,  	int ret = -ENODATA;  	rcu_read_lock(); -	if (local->use_chanctx) { -		chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); -		if (chanctx_conf) { -			*chandef = chanctx_conf->def; -			ret = 0; -		} -	} else if (local->open_count == local->monitors) { -		*chandef = local->monitor_chandef; +	chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); +	if (chanctx_conf) { +		*chandef = chanctx_conf->def; +		ret = 0; +	} else if (local->open_count > 0 && +		   local->open_count == local->monitors && +		   sdata->vif.type == NL80211_IFTYPE_MONITOR) { +		if (local->use_chanctx) +			*chandef = local->monitor_chandef; +		else +			cfg80211_chandef_create(chandef, +						local->_oper_channel, +						local->_oper_channel_type);  		ret = 0;  	}  	rcu_read_unlock(); diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 640afab304d..baaa8608e52 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -541,6 +541,9 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)  		ieee80211_adjust_monitor_flags(sdata, 1);  		ieee80211_configure_filter(local); +		mutex_lock(&local->mtx); +		ieee80211_recalc_idle(local); +		mutex_unlock(&local->mtx);  		netif_carrier_on(dev);  		break; @@ -812,6 +815,9 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,  		ieee80211_adjust_monitor_flags(sdata, -1);  		ieee80211_configure_filter(local); +		mutex_lock(&local->mtx); +		ieee80211_recalc_idle(local); +		mutex_unlock(&local->mtx);  		break;  	case NL80211_IFTYPE_P2P_DEVICE:  		/* relies on synchronize_rcu() below */ diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 9f6464f3e05..141577412d8 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -647,6 +647,9 @@ static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata,  		our_mcs = (le16_to_cpu(vht_cap.vht_mcs.rx_mcs_map) &  								mask) >> shift; +		if (our_mcs == IEEE80211_VHT_MCS_NOT_SUPPORTED) +			continue; +  		switch (ap_mcs) {  		default:  			if (our_mcs <= ap_mcs) @@ -3503,6 +3506,14 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata)  	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;  	/* +	 * Stop timers before deleting work items, as timers +	 * could race and re-add the work-items. They will be +	 * re-established on connection. +	 */ +	del_timer_sync(&ifmgd->conn_mon_timer); +	del_timer_sync(&ifmgd->bcn_mon_timer); + +	/*  	 * we need to use atomic bitops for the running bits  	 * only because both timers might fire at the same  	 * time -- the code here is properly synchronised. @@ -3516,13 +3527,9 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata)  	if (del_timer_sync(&ifmgd->timer))  		set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running); -	cancel_work_sync(&ifmgd->chswitch_work);  	if (del_timer_sync(&ifmgd->chswitch_timer))  		set_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running); - -	/* these will just be re-established on connection */ -	del_timer_sync(&ifmgd->conn_mon_timer); -	del_timer_sync(&ifmgd->bcn_mon_timer); +	cancel_work_sync(&ifmgd->chswitch_work);  }  void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata) @@ -4315,6 +4322,17 @@ void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata)  {  	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; +	/* +	 * Make sure some work items will not run after this, +	 * they will not do anything but might not have been +	 * cancelled when disconnecting. +	 */ +	cancel_work_sync(&ifmgd->monitor_work); +	cancel_work_sync(&ifmgd->beacon_connection_loss_work); +	cancel_work_sync(&ifmgd->request_smps_work); +	cancel_work_sync(&ifmgd->csa_connection_drop_work); +	cancel_work_sync(&ifmgd->chswitch_work); +  	mutex_lock(&ifmgd->mtx);  	if (ifmgd->assoc_data)  		ieee80211_destroy_assoc_data(sdata, false); diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index ce78d1149f1..8914d2d2881 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -2745,7 +2745,8 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw,  				cpu_to_le16(IEEE80211_FCTL_MOREDATA);  		} -		sdata = IEEE80211_DEV_TO_SUB_IF(skb->dev); +		if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) +			sdata = IEEE80211_DEV_TO_SUB_IF(skb->dev);  		if (!ieee80211_tx_prepare(sdata, &tx, skb))  			break;  		dev_kfree_skb_any(skb); diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c index a9740bd6fe5..94b4b9853f6 100644 --- a/net/netfilter/nf_conntrack_helper.c +++ b/net/netfilter/nf_conntrack_helper.c @@ -339,6 +339,13 @@ void nf_ct_helper_log(struct sk_buff *skb, const struct nf_conn *ct,  {  	const struct nf_conn_help *help;  	const struct nf_conntrack_helper *helper; +	struct va_format vaf; +	va_list args; + +	va_start(args, fmt); + +	vaf.fmt = fmt; +	vaf.va = &args;  	/* Called from the helper function, this call never fails */  	help = nfct_help(ct); @@ -347,7 +354,9 @@ void nf_ct_helper_log(struct sk_buff *skb, const struct nf_conn *ct,  	helper = rcu_dereference(help->helper);  	nf_log_packet(nf_ct_l3num(ct), 0, skb, NULL, NULL, NULL, -		      "nf_ct_%s: dropping packet: %s ", helper->name, fmt); +		      "nf_ct_%s: dropping packet: %pV ", helper->name, &vaf); + +	va_end(args);  }  EXPORT_SYMBOL_GPL(nf_ct_helper_log); diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c index d578ec25171..0b1b32cda30 100644 --- a/net/netfilter/nfnetlink.c +++ b/net/netfilter/nfnetlink.c @@ -62,11 +62,6 @@ void nfnl_unlock(__u8 subsys_id)  }  EXPORT_SYMBOL_GPL(nfnl_unlock); -static struct mutex *nfnl_get_lock(__u8 subsys_id) -{ -	return &table[subsys_id].mutex; -} -  int nfnetlink_subsys_register(const struct nfnetlink_subsystem *n)  {  	nfnl_lock(n->subsys_id); @@ -199,7 +194,7 @@ replay:  			rcu_read_unlock();  			nfnl_lock(subsys_id);  			if (rcu_dereference_protected(table[subsys_id].subsys, -				lockdep_is_held(nfnl_get_lock(subsys_id))) != ss || +				lockdep_is_held(&table[subsys_id].mutex)) != ss ||  			    nfnetlink_find_client(type, ss) != nc)  				err = -EAGAIN;  			else if (nc->call) diff --git a/net/netfilter/xt_AUDIT.c b/net/netfilter/xt_AUDIT.c index ba92824086f..3228d7f24eb 100644 --- a/net/netfilter/xt_AUDIT.c +++ b/net/netfilter/xt_AUDIT.c @@ -124,6 +124,9 @@ audit_tg(struct sk_buff *skb, const struct xt_action_param *par)  	const struct xt_audit_info *info = par->targinfo;  	struct audit_buffer *ab; +	if (audit_enabled == 0) +		goto errout; +  	ab = audit_log_start(NULL, GFP_ATOMIC, AUDIT_NETFILTER_PKT);  	if (ab == NULL)  		goto errout; diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c index 847d495cd4d..8a6c6ea466d 100644 --- a/net/netlabel/netlabel_unlabeled.c +++ b/net/netlabel/netlabel_unlabeled.c @@ -1189,8 +1189,6 @@ static int netlbl_unlabel_staticlist(struct sk_buff *skb,  	struct netlbl_unlhsh_walk_arg cb_arg;  	u32 skip_bkt = cb->args[0];  	u32 skip_chain = cb->args[1]; -	u32 skip_addr4 = cb->args[2]; -	u32 skip_addr6 = cb->args[3];  	u32 iter_bkt;  	u32 iter_chain = 0, iter_addr4 = 0, iter_addr6 = 0;  	struct netlbl_unlhsh_iface *iface; @@ -1215,7 +1213,7 @@ static int netlbl_unlabel_staticlist(struct sk_buff *skb,  				continue;  			netlbl_af4list_foreach_rcu(addr4,  						   &iface->addr4_list) { -				if (iter_addr4++ < skip_addr4) +				if (iter_addr4++ < cb->args[2])  					continue;  				if (netlbl_unlabel_staticlist_gen(  					      NLBL_UNLABEL_C_STATICLIST, @@ -1231,7 +1229,7 @@ static int netlbl_unlabel_staticlist(struct sk_buff *skb,  #if IS_ENABLED(CONFIG_IPV6)  			netlbl_af6list_foreach_rcu(addr6,  						   &iface->addr6_list) { -				if (iter_addr6++ < skip_addr6) +				if (iter_addr6++ < cb->args[3])  					continue;  				if (netlbl_unlabel_staticlist_gen(  					      NLBL_UNLABEL_C_STATICLIST, @@ -1250,10 +1248,10 @@ static int netlbl_unlabel_staticlist(struct sk_buff *skb,  unlabel_staticlist_return:  	rcu_read_unlock(); -	cb->args[0] = skip_bkt; -	cb->args[1] = skip_chain; -	cb->args[2] = skip_addr4; -	cb->args[3] = skip_addr6; +	cb->args[0] = iter_bkt; +	cb->args[1] = iter_chain; +	cb->args[2] = iter_addr4; +	cb->args[3] = iter_addr6;  	return skb->len;  } @@ -1273,12 +1271,9 @@ static int netlbl_unlabel_staticlistdef(struct sk_buff *skb,  {  	struct netlbl_unlhsh_walk_arg cb_arg;  	struct netlbl_unlhsh_iface *iface; -	u32 skip_addr4 = cb->args[0]; -	u32 skip_addr6 = cb->args[1]; -	u32 iter_addr4 = 0; +	u32 iter_addr4 = 0, iter_addr6 = 0;  	struct netlbl_af4list *addr4;  #if IS_ENABLED(CONFIG_IPV6) -	u32 iter_addr6 = 0;  	struct netlbl_af6list *addr6;  #endif @@ -1292,7 +1287,7 @@ static int netlbl_unlabel_staticlistdef(struct sk_buff *skb,  		goto unlabel_staticlistdef_return;  	netlbl_af4list_foreach_rcu(addr4, &iface->addr4_list) { -		if (iter_addr4++ < skip_addr4) +		if (iter_addr4++ < cb->args[0])  			continue;  		if (netlbl_unlabel_staticlist_gen(NLBL_UNLABEL_C_STATICLISTDEF,  					      iface, @@ -1305,7 +1300,7 @@ static int netlbl_unlabel_staticlistdef(struct sk_buff *skb,  	}  #if IS_ENABLED(CONFIG_IPV6)  	netlbl_af6list_foreach_rcu(addr6, &iface->addr6_list) { -		if (iter_addr6++ < skip_addr6) +		if (iter_addr6++ < cb->args[1])  			continue;  		if (netlbl_unlabel_staticlist_gen(NLBL_UNLABEL_C_STATICLISTDEF,  					      iface, @@ -1320,8 +1315,8 @@ static int netlbl_unlabel_staticlistdef(struct sk_buff *skb,  unlabel_staticlistdef_return:  	rcu_read_unlock(); -	cb->args[0] = skip_addr4; -	cb->args[1] = skip_addr6; +	cb->args[0] = iter_addr4; +	cb->args[1] = iter_addr6;  	return skb->len;  } diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c index 7f8266dd14c..b530afadd76 100644 --- a/net/nfc/llcp/llcp.c +++ b/net/nfc/llcp/llcp.c @@ -68,7 +68,8 @@ static void nfc_llcp_socket_purge(struct nfc_llcp_sock *sock)  	}  } -static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen) +static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen, +				    int err)  {  	struct sock *sk;  	struct hlist_node *tmp; @@ -100,7 +101,10 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen)  				nfc_llcp_accept_unlink(accept_sk); +				if (err) +					accept_sk->sk_err = err;  				accept_sk->sk_state = LLCP_CLOSED; +				accept_sk->sk_state_change(sk);  				bh_unlock_sock(accept_sk); @@ -123,7 +127,10 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen)  			continue;  		} +		if (err) +			sk->sk_err = err;  		sk->sk_state = LLCP_CLOSED; +		sk->sk_state_change(sk);  		bh_unlock_sock(sk); @@ -133,6 +140,36 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen)  	}  	write_unlock(&local->sockets.lock); + +	/* +	 * If we want to keep the listening sockets alive, +	 * we don't touch the RAW ones. +	 */ +	if (listen == true) +		return; + +	write_lock(&local->raw_sockets.lock); + +	sk_for_each_safe(sk, tmp, &local->raw_sockets.head) { +		llcp_sock = nfc_llcp_sock(sk); + +		bh_lock_sock(sk); + +		nfc_llcp_socket_purge(llcp_sock); + +		if (err) +			sk->sk_err = err; +		sk->sk_state = LLCP_CLOSED; +		sk->sk_state_change(sk); + +		bh_unlock_sock(sk); + +		sock_orphan(sk); + +		sk_del_node_init(sk); +	} + +	write_unlock(&local->raw_sockets.lock);  }  struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local) @@ -142,20 +179,25 @@ struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local)  	return local;  } -static void local_release(struct kref *ref) +static void local_cleanup(struct nfc_llcp_local *local, bool listen)  { -	struct nfc_llcp_local *local; - -	local = container_of(ref, struct nfc_llcp_local, ref); - -	list_del(&local->list); -	nfc_llcp_socket_release(local, false); +	nfc_llcp_socket_release(local, listen, ENXIO);  	del_timer_sync(&local->link_timer);  	skb_queue_purge(&local->tx_queue);  	cancel_work_sync(&local->tx_work);  	cancel_work_sync(&local->rx_work);  	cancel_work_sync(&local->timeout_work);  	kfree_skb(local->rx_pending); +} + +static void local_release(struct kref *ref) +{ +	struct nfc_llcp_local *local; + +	local = container_of(ref, struct nfc_llcp_local, ref); + +	list_del(&local->list); +	local_cleanup(local, false);  	kfree(local);  } @@ -1348,7 +1390,7 @@ void nfc_llcp_mac_is_down(struct nfc_dev *dev)  		return;  	/* Close and purge all existing sockets */ -	nfc_llcp_socket_release(local, true); +	nfc_llcp_socket_release(local, true, 0);  }  void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx, @@ -1427,6 +1469,8 @@ void nfc_llcp_unregister_device(struct nfc_dev *dev)  		return;  	} +	local_cleanup(local, false); +  	nfc_llcp_local_put(local);  } diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c index 5332751943a..5c7cdf3f2a8 100644 --- a/net/nfc/llcp/sock.c +++ b/net/nfc/llcp/sock.c @@ -278,6 +278,8 @@ struct sock *nfc_llcp_accept_dequeue(struct sock *parent,  			pr_debug("Returning sk state %d\n", sk->sk_state); +			sk_acceptq_removed(parent); +  			return sk;  		} diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c index ac2defeeba8..d4d5363c7ba 100644 --- a/net/openvswitch/actions.c +++ b/net/openvswitch/actions.c @@ -58,7 +58,7 @@ static int __pop_vlan_tci(struct sk_buff *skb, __be16 *current_tci)  	if (skb->ip_summed == CHECKSUM_COMPLETE)  		skb->csum = csum_sub(skb->csum, csum_partial(skb->data -					+ ETH_HLEN, VLAN_HLEN, 0)); +					+ (2 * ETH_ALEN), VLAN_HLEN, 0));  	vhdr = (struct vlan_hdr *)(skb->data + ETH_HLEN);  	*current_tci = vhdr->h_vlan_TCI; @@ -115,7 +115,7 @@ static int push_vlan(struct sk_buff *skb, const struct ovs_action_push_vlan *vla  		if (skb->ip_summed == CHECKSUM_COMPLETE)  			skb->csum = csum_add(skb->csum, csum_partial(skb->data -					+ ETH_HLEN, VLAN_HLEN, 0)); +					+ (2 * ETH_ALEN), VLAN_HLEN, 0));  	}  	__vlan_hwaccel_put_tag(skb, ntohs(vlan->vlan_tci) & ~VLAN_TAG_PRESENT); diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index e87a26506db..a4b724708a1 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c @@ -394,6 +394,7 @@ static int queue_userspace_packet(struct net *net, int dp_ifindex,  	skb_copy_and_csum_dev(skb, nla_data(nla)); +	genlmsg_end(user_skb, upcall);  	err = genlmsg_unicast(net, user_skb, upcall_info->portid);  out: @@ -1690,6 +1691,7 @@ static int ovs_vport_cmd_new(struct sk_buff *skb, struct genl_info *info)  	if (IS_ERR(vport))  		goto exit_unlock; +	err = 0;  	reply = ovs_vport_cmd_build_info(vport, info->snd_portid, info->snd_seq,  					 OVS_VPORT_CMD_NEW);  	if (IS_ERR(reply)) { @@ -1771,6 +1773,7 @@ static int ovs_vport_cmd_del(struct sk_buff *skb, struct genl_info *info)  	if (IS_ERR(reply))  		goto exit_unlock; +	err = 0;  	ovs_dp_detach_port(vport);  	genl_notify(reply, genl_info_net(info), info->snd_portid, diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c index 20605ecf100..fe0e4215c73 100644 --- a/net/openvswitch/flow.c +++ b/net/openvswitch/flow.c @@ -482,7 +482,11 @@ static __be16 parse_ethertype(struct sk_buff *skb)  		return htons(ETH_P_802_2);  	__skb_pull(skb, sizeof(struct llc_snap_hdr)); -	return llc->ethertype; + +	if (ntohs(llc->ethertype) >= 1536) +		return llc->ethertype; + +	return htons(ETH_P_802_2);  }  static int parse_icmpv6(struct sk_buff *skb, struct sw_flow_key *key, diff --git a/net/openvswitch/vport-netdev.c b/net/openvswitch/vport-netdev.c index 670cbc3518d..2130d61c384 100644 --- a/net/openvswitch/vport-netdev.c +++ b/net/openvswitch/vport-netdev.c @@ -43,8 +43,7 @@ static void netdev_port_receive(struct vport *vport, struct sk_buff *skb)  	/* Make our own copy of the packet.  Otherwise we will mangle the  	 * packet for anyone who came before us (e.g. tcpdump via AF_PACKET). -	 * (No one comes after us, since we tell handle_bridge() that we took -	 * the packet.) */ +	 */  	skb = skb_share_check(skb, GFP_ATOMIC);  	if (unlikely(!skb))  		return; diff --git a/net/openvswitch/vport.c b/net/openvswitch/vport.c index ba717cc038b..f6b8132ce4c 100644 --- a/net/openvswitch/vport.c +++ b/net/openvswitch/vport.c @@ -325,8 +325,7 @@ int ovs_vport_get_options(const struct vport *vport, struct sk_buff *skb)   * @skb: skb that was received   *   * Must be called with rcu_read_lock.  The packet cannot be shared and - * skb->data should point to the Ethernet header.  The caller must have already - * called compute_ip_summed() to initialize the checksumming fields. + * skb->data should point to the Ethernet header.   */  void ovs_vport_receive(struct vport *vport, struct sk_buff *skb)  { diff --git a/net/rds/stats.c b/net/rds/stats.c index 7be790d60b9..73be187d389 100644 --- a/net/rds/stats.c +++ b/net/rds/stats.c @@ -87,6 +87,7 @@ void rds_stats_info_copy(struct rds_info_iterator *iter,  	for (i = 0; i < nr; i++) {  		BUG_ON(strlen(names[i]) >= sizeof(ctr.name));  		strncpy(ctr.name, names[i], sizeof(ctr.name) - 1); +		ctr.name[sizeof(ctr.name) - 1] = '\0';  		ctr.value = values[i];  		rds_info_copy(iter, &ctr, sizeof(ctr)); diff --git a/net/sched/sch_qfq.c b/net/sched/sch_qfq.c index e9a77f621c3..d51852bba01 100644 --- a/net/sched/sch_qfq.c +++ b/net/sched/sch_qfq.c @@ -298,6 +298,10 @@ static void qfq_update_agg(struct qfq_sched *q, struct qfq_aggregate *agg,  	    new_num_classes == q->max_agg_classes - 1) /* agg no more full */  		hlist_add_head(&agg->nonfull_next, &q->nonfull_aggs); +	/* The next assignment may let +	 * agg->initial_budget > agg->budgetmax +	 * hold, we will take it into account in charge_actual_service(). +	 */  	agg->budgetmax = new_num_classes * agg->lmax;  	new_agg_weight = agg->class_weight * new_num_classes;  	agg->inv_w = ONE_FP/new_agg_weight; @@ -817,7 +821,7 @@ static void qfq_make_eligible(struct qfq_sched *q)  	unsigned long old_vslot = q->oldV >> q->min_slot_shift;  	if (vslot != old_vslot) { -		unsigned long mask = (1UL << fls(vslot ^ old_vslot)) - 1; +		unsigned long mask = (1ULL << fls(vslot ^ old_vslot)) - 1;  		qfq_move_groups(q, mask, IR, ER);  		qfq_move_groups(q, mask, IB, EB);  	} @@ -988,12 +992,23 @@ static inline struct sk_buff *qfq_peek_skb(struct qfq_aggregate *agg,  /* Update F according to the actual service received by the aggregate. */  static inline void charge_actual_service(struct qfq_aggregate *agg)  { -	/* compute the service received by the aggregate */ -	u32 service_received = agg->initial_budget - agg->budget; +	/* Compute the service received by the aggregate, taking into +	 * account that, after decreasing the number of classes in +	 * agg, it may happen that +	 * agg->initial_budget - agg->budget > agg->bugdetmax +	 */ +	u32 service_received = min(agg->budgetmax, +				   agg->initial_budget - agg->budget);  	agg->F = agg->S + (u64)service_received * agg->inv_w;  } +static inline void qfq_update_agg_ts(struct qfq_sched *q, +				     struct qfq_aggregate *agg, +				     enum update_reason reason); + +static void qfq_schedule_agg(struct qfq_sched *q, struct qfq_aggregate *agg); +  static struct sk_buff *qfq_dequeue(struct Qdisc *sch)  {  	struct qfq_sched *q = qdisc_priv(sch); @@ -1021,7 +1036,7 @@ static struct sk_buff *qfq_dequeue(struct Qdisc *sch)  		in_serv_agg->initial_budget = in_serv_agg->budget =  			in_serv_agg->budgetmax; -		if (!list_empty(&in_serv_agg->active)) +		if (!list_empty(&in_serv_agg->active)) {  			/*  			 * Still active: reschedule for  			 * service. Possible optimization: if no other @@ -1032,8 +1047,9 @@ static struct sk_buff *qfq_dequeue(struct Qdisc *sch)  			 * handle it, we would need to maintain an  			 * extra num_active_aggs field.  			*/ -			qfq_activate_agg(q, in_serv_agg, requeue); -		else if (sch->q.qlen == 0) { /* no aggregate to serve */ +			qfq_update_agg_ts(q, in_serv_agg, requeue); +			qfq_schedule_agg(q, in_serv_agg); +		} else if (sch->q.qlen == 0) { /* no aggregate to serve */  			q->in_serv_agg = NULL;  			return NULL;  		} @@ -1052,7 +1068,15 @@ static struct sk_buff *qfq_dequeue(struct Qdisc *sch)  	qdisc_bstats_update(sch, skb);  	agg_dequeue(in_serv_agg, cl, len); -	in_serv_agg->budget -= len; +	/* If lmax is lowered, through qfq_change_class, for a class +	 * owning pending packets with larger size than the new value +	 * of lmax, then the following condition may hold. +	 */ +	if (unlikely(in_serv_agg->budget < len)) +		in_serv_agg->budget = 0; +	else +		in_serv_agg->budget -= len; +  	q->V += (u64)len * IWSUM;  	pr_debug("qfq dequeue: len %u F %lld now %lld\n",  		 len, (unsigned long long) in_serv_agg->F, @@ -1217,17 +1241,11 @@ static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch)  	cl->deficit = agg->lmax;  	list_add_tail(&cl->alist, &agg->active); -	if (list_first_entry(&agg->active, struct qfq_class, alist) != cl) -		return err; /* aggregate was not empty, nothing else to do */ +	if (list_first_entry(&agg->active, struct qfq_class, alist) != cl || +	    q->in_serv_agg == agg) +		return err; /* non-empty or in service, nothing else to do */ -	/* recharge budget */ -	agg->initial_budget = agg->budget = agg->budgetmax; - -	qfq_update_agg_ts(q, agg, enqueue); -	if (q->in_serv_agg == NULL) -		q->in_serv_agg = agg; -	else if (agg != q->in_serv_agg) -		qfq_schedule_agg(q, agg); +	qfq_activate_agg(q, agg, enqueue);  	return err;  } @@ -1261,7 +1279,8 @@ static void qfq_schedule_agg(struct qfq_sched *q, struct qfq_aggregate *agg)  		/* group was surely ineligible, remove */  		__clear_bit(grp->index, &q->bitmaps[IR]);  		__clear_bit(grp->index, &q->bitmaps[IB]); -	} else if (!q->bitmaps[ER] && qfq_gt(roundedS, q->V)) +	} else if (!q->bitmaps[ER] && qfq_gt(roundedS, q->V) && +		   q->in_serv_agg == NULL)  		q->V = roundedS;  	grp->S = roundedS; @@ -1284,8 +1303,15 @@ skip_update:  static void qfq_activate_agg(struct qfq_sched *q, struct qfq_aggregate *agg,  			     enum update_reason reason)  { +	agg->initial_budget = agg->budget = agg->budgetmax; /* recharge budg. */ +  	qfq_update_agg_ts(q, agg, reason); -	qfq_schedule_agg(q, agg); +	if (q->in_serv_agg == NULL) { /* no aggr. in service or scheduled */ +		q->in_serv_agg = agg; /* start serving this aggregate */ +		 /* update V: to be in service, agg must be eligible */ +		q->oldV = q->V = agg->S; +	} else if (agg != q->in_serv_agg) +		qfq_schedule_agg(q, agg);  }  static void qfq_slot_remove(struct qfq_sched *q, struct qfq_group *grp, @@ -1357,8 +1383,6 @@ static void qfq_deactivate_agg(struct qfq_sched *q, struct qfq_aggregate *agg)  			__set_bit(grp->index, &q->bitmaps[s]);  		}  	} - -	qfq_update_eligible(q);  }  static void qfq_qlen_notify(struct Qdisc *sch, unsigned long arg) diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 43cd0dd9149..d2709e2b7be 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -1079,7 +1079,7 @@ struct sctp_transport *sctp_assoc_lookup_tsn(struct sctp_association *asoc,  			transports) {  		if (transport == active) -			break; +			continue;  		list_for_each_entry(chunk, &transport->transmitted,  				transmitted_list) {  			if (key == chunk->subh.data_hdr->tsn) { diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 5131fcfedb0..de1a0138317 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -2082,7 +2082,7 @@ sctp_disposition_t sctp_sf_do_5_2_4_dupcook(struct net *net,  	}  	/* Delete the tempory new association. */ -	sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(new_asoc)); +	sctp_add_cmd_sf(commands, SCTP_CMD_SET_ASOC, SCTP_ASOC(new_asoc));  	sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL());  	/* Restore association pointer to provide SCTP command interpeter diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index f7d34e7b6f8..5ead6055089 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c @@ -447,17 +447,21 @@ static int rsc_parse(struct cache_detail *cd,  	else {  		int N, i; +		/* +		 * NOTE: we skip uid_valid()/gid_valid() checks here: +		 * instead, * -1 id's are later mapped to the +		 * (export-specific) anonymous id by nfsd_setuser. +		 * +		 * (But supplementary gid's get no such special +		 * treatment so are checked for validity here.) +		 */  		/* uid */  		rsci.cred.cr_uid = make_kuid(&init_user_ns, id); -		if (!uid_valid(rsci.cred.cr_uid)) -			goto out;  		/* gid */  		if (get_int(&mesg, &id))  			goto out;  		rsci.cred.cr_gid = make_kgid(&init_user_ns, id); -		if (!gid_valid(rsci.cred.cr_gid)) -			goto out;  		/* number of additional gid's */  		if (get_int(&mesg, &N)) diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index a0f48a51e14..a9129f8d707 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -1175,6 +1175,7 @@ static struct file_system_type rpc_pipe_fs_type = {  	.kill_sb	= rpc_kill_sb,  };  MODULE_ALIAS_FS("rpc_pipefs"); +MODULE_ALIAS("rpc_pipefs");  static void  init_once(void *foo) diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index c1d8476b769..3d02130828d 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -849,6 +849,14 @@ static void xs_tcp_close(struct rpc_xprt *xprt)  		xs_tcp_shutdown(xprt);  } +static void xs_local_destroy(struct rpc_xprt *xprt) +{ +	xs_close(xprt); +	xs_free_peer_addresses(xprt); +	xprt_free(xprt); +	module_put(THIS_MODULE); +} +  /**   * xs_destroy - prepare to shutdown a transport   * @xprt: doomed transport @@ -862,10 +870,7 @@ static void xs_destroy(struct rpc_xprt *xprt)  	cancel_delayed_work_sync(&transport->connect_worker); -	xs_close(xprt); -	xs_free_peer_addresses(xprt); -	xprt_free(xprt); -	module_put(THIS_MODULE); +	xs_local_destroy(xprt);  }  static inline struct rpc_xprt *xprt_from_sock(struct sock *sk) @@ -2482,7 +2487,7 @@ static struct rpc_xprt_ops xs_local_ops = {  	.send_request		= xs_local_send_request,  	.set_retrans_timeout	= xprt_set_retrans_timeout_def,  	.close			= xs_close, -	.destroy		= xs_destroy, +	.destroy		= xs_local_destroy,  	.print_stats		= xs_local_print_stats,  }; diff --git a/net/wireless/core.c b/net/wireless/core.c index 5ffff039b01..ea4155fe973 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -367,8 +367,7 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)  	rdev->wiphy.rts_threshold = (u32) -1;  	rdev->wiphy.coverage_class = 0; -	rdev->wiphy.features = NL80211_FEATURE_SCAN_FLUSH | -			       NL80211_FEATURE_ADVERTISE_CHAN_LIMITS; +	rdev->wiphy.features = NL80211_FEATURE_SCAN_FLUSH;  	return &rdev->wiphy;  } diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index e652d05ff71..d44ab216c0e 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -557,18 +557,6 @@ static int nl80211_msg_put_channel(struct sk_buff *msg,  	if ((chan->flags & IEEE80211_CHAN_RADAR) &&  	    nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR))  		goto nla_put_failure; -	if ((chan->flags & IEEE80211_CHAN_NO_HT40MINUS) && -	    nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HT40_MINUS)) -		goto nla_put_failure; -	if ((chan->flags & IEEE80211_CHAN_NO_HT40PLUS) && -	    nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HT40_PLUS)) -		goto nla_put_failure; -	if ((chan->flags & IEEE80211_CHAN_NO_80MHZ) && -	    nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_80MHZ)) -		goto nla_put_failure; -	if ((chan->flags & IEEE80211_CHAN_NO_160MHZ) && -	    nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_160MHZ)) -		goto nla_put_failure;  	if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER,  			DBM_TO_MBM(chan->max_power))) @@ -1310,15 +1298,6 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flag  			dev->wiphy.max_acl_mac_addrs))  		goto nla_put_failure; -	if (dev->wiphy.extended_capabilities && -	    (nla_put(msg, NL80211_ATTR_EXT_CAPA, -		     dev->wiphy.extended_capabilities_len, -		     dev->wiphy.extended_capabilities) || -	     nla_put(msg, NL80211_ATTR_EXT_CAPA_MASK, -		     dev->wiphy.extended_capabilities_len, -		     dev->wiphy.extended_capabilities_mask))) -		goto nla_put_failure; -  	return genlmsg_end(msg, hdr);   nla_put_failure: @@ -1328,7 +1307,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flag  static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)  { -	int idx = 0; +	int idx = 0, ret;  	int start = cb->args[0];  	struct cfg80211_registered_device *dev; @@ -1338,9 +1317,29 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)  			continue;  		if (++idx <= start)  			continue; -		if (nl80211_send_wiphy(skb, NETLINK_CB(cb->skb).portid, -				       cb->nlh->nlmsg_seq, NLM_F_MULTI, -				       dev) < 0) { +		ret = nl80211_send_wiphy(skb, NETLINK_CB(cb->skb).portid, +					 cb->nlh->nlmsg_seq, NLM_F_MULTI, +					 dev); +		if (ret < 0) { +			/* +			 * If sending the wiphy data didn't fit (ENOBUFS or +			 * EMSGSIZE returned), this SKB is still empty (so +			 * it's not too big because another wiphy dataset is +			 * already in the skb) and we've not tried to adjust +			 * the dump allocation yet ... then adjust the alloc +			 * size to be bigger, and return 1 but with the empty +			 * skb. This results in an empty message being RX'ed +			 * in userspace, but that is ignored. +			 * +			 * We can then retry with the larger buffer. +			 */ +			if ((ret == -ENOBUFS || ret == -EMSGSIZE) && +			    !skb->len && +			    cb->min_dump_alloc < 4096) { +				cb->min_dump_alloc = 4096; +				mutex_unlock(&cfg80211_mutex); +				return 1; +			}  			idx--;  			break;  		} @@ -1357,7 +1356,7 @@ static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info)  	struct sk_buff *msg;  	struct cfg80211_registered_device *dev = info->user_ptr[0]; -	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); +	msg = nlmsg_new(4096, GFP_KERNEL);  	if (!msg)  		return -ENOMEM;  |