diff options
Diffstat (limited to 'net')
95 files changed, 850 insertions, 667 deletions
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index a18714469bf..85addcd9372 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c @@ -86,13 +86,6 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head)  	grp = &vlan_info->grp; -	/* Take it out of our own structures, but be sure to interlock with -	 * HW accelerating devices or SW vlan input packet processing if -	 * VLAN is not 0 (leave it there for 802.1p). -	 */ -	if (vlan_id) -		vlan_vid_del(real_dev, vlan_id); -  	grp->nr_vlan_devs--;  	if (vlan->flags & VLAN_FLAG_MVRP) @@ -114,6 +107,13 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head)  		vlan_gvrp_uninit_applicant(real_dev);  	} +	/* Take it out of our own structures, but be sure to interlock with +	 * HW accelerating devices or SW vlan input packet processing if +	 * VLAN is not 0 (leave it there for 802.1p). +	 */ +	if (vlan_id) +		vlan_vid_del(real_dev, vlan_id); +  	/* Get rid of the vlan's reference to real_dev */  	dev_put(real_dev);  } diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index 74dea377fe5..de2e950a0a7 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c @@ -655,7 +655,7 @@ static struct p9_trans_module p9_virtio_trans = {  	.create = p9_virtio_create,  	.close = p9_virtio_close,  	.request = p9_virtio_request, -	//.zc_request = p9_virtio_zc_request, +	.zc_request = p9_virtio_zc_request,  	.cancel = p9_virtio_cancel,  	/*  	 * We leave one entry for input and one entry for response 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/bluetooth/sco.c b/net/bluetooth/sco.c index 79d87d8d4f5..fad0302bdb3 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -359,6 +359,7 @@ static void __sco_sock_close(struct sock *sk)  			sco_chan_del(sk, ECONNRESET);  		break; +	case BT_CONNECT2:  	case BT_CONNECT:  	case BT_DISCONN:  		sco_chan_del(sk, ECONNRESET); 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_fdb.c b/net/bridge/br_fdb.c index b0812c91c0f..bab338e6270 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c @@ -423,7 +423,7 @@ static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source,  			return 0;  		br_warn(br, "adding interface %s with same address "  		       "as a received packet\n", -		       source->dev->name); +		       source ? source->dev->name : br->dev->name);  		fdb_delete(br, fdb);  	} 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/caif/caif_dev.c b/net/caif/caif_dev.c index 1ae1d9cb278..21760f00897 100644 --- a/net/caif/caif_dev.c +++ b/net/caif/caif_dev.c @@ -118,7 +118,7 @@ static struct caif_device_entry *caif_get(struct net_device *dev)  	return NULL;  } -void caif_flow_cb(struct sk_buff *skb) +static void caif_flow_cb(struct sk_buff *skb)  {  	struct caif_device_entry *caifd;  	void (*dtor)(struct sk_buff *skb) = NULL; diff --git a/net/caif/caif_usb.c b/net/caif/caif_usb.c index 3ebc8cbc91f..ef8ebaa993c 100644 --- a/net/caif/caif_usb.c +++ b/net/caif/caif_usb.c @@ -81,8 +81,8 @@ static void cfusbl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,  		layr->up->ctrlcmd(layr->up, ctrl, layr->id);  } -struct cflayer *cfusbl_create(int phyid, u8 ethaddr[ETH_ALEN], -					u8 braddr[ETH_ALEN]) +static struct cflayer *cfusbl_create(int phyid, u8 ethaddr[ETH_ALEN], +				      u8 braddr[ETH_ALEN])  {  	struct cfusbl *this = kmalloc(sizeof(struct cfusbl), GFP_ATOMIC); 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..b13e5c766c1 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1545,7 +1545,6 @@ void net_enable_timestamp(void)  		return;  	}  #endif -	WARN_ON(in_interrupt());  	static_key_slow_inc(&netstamp_needed);  }  EXPORT_SYMBOL(net_enable_timestamp); @@ -2219,9 +2218,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 +3443,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 +4103,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 +4780,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/flow_dissector.c b/net/core/flow_dissector.c index 9d4c7201400..e187bf06d67 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c @@ -140,6 +140,8 @@ ipv6:  			flow->ports = *ports;  	} +	flow->thoff = (u16) nhoff; +  	return true;  }  EXPORT_SYMBOL(skb_flow_dissect); 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/core/scm.c b/net/core/scm.c index 905dcc6ad1e..2dc6cdaaae8 100644 --- a/net/core/scm.c +++ b/net/core/scm.c @@ -24,6 +24,7 @@  #include <linux/interrupt.h>  #include <linux/netdevice.h>  #include <linux/security.h> +#include <linux/pid_namespace.h>  #include <linux/pid.h>  #include <linux/nsproxy.h>  #include <linux/slab.h> @@ -52,7 +53,8 @@ static __inline__ int scm_check_creds(struct ucred *creds)  	if (!uid_valid(uid) || !gid_valid(gid))  		return -EINVAL; -	if ((creds->pid == task_tgid_vnr(current) || nsown_capable(CAP_SYS_ADMIN)) && +	if ((creds->pid == task_tgid_vnr(current) || +	     ns_capable(current->nsproxy->pid_ns->user_ns, CAP_SYS_ADMIN)) &&  	    ((uid_eq(uid, cred->uid)   || uid_eq(uid, cred->euid) ||  	      uid_eq(uid, cred->suid)) || nsown_capable(CAP_SETUID)) &&  	    ((gid_eq(gid, cred->gid)   || gid_eq(gid, cred->egid) || 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/af_inet.c b/net/ipv4/af_inet.c index 68f6a94f766..c929d9c1c4b 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -1333,8 +1333,7 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb,  				iph->frag_off |= htons(IP_MF);  			offset += (skb->len - skb->mac_len - iph->ihl * 4);  		} else  { -			if (!(iph->frag_off & htons(IP_DF))) -				iph->id = htons(id++); +			iph->id = htons(id++);  		}  		iph->tot_len = htons(skb->len - skb->mac_len);  		iph->check = 0; 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_input.c b/net/ipv4/ip_input.c index 87abd3e2bd3..2bdf802e28e 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c @@ -228,9 +228,11 @@ static int ip_local_deliver_finish(struct sk_buff *skb)  					icmp_send(skb, ICMP_DEST_UNREACH,  						  ICMP_PROT_UNREACH, 0);  				} -			} else +				kfree_skb(skb); +			} else {  				IP_INC_STATS_BH(net, IPSTATS_MIB_INDELIVERS); -			kfree_skb(skb); +				consume_skb(skb); +			}  		}  	}   out: 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/ipconfig.c b/net/ipv4/ipconfig.c index 98cbc687701..bf6c5cf31ae 100644 --- a/net/ipv4/ipconfig.c +++ b/net/ipv4/ipconfig.c @@ -1522,7 +1522,8 @@ static int __init ip_auto_config(void)  		}  	for (i++; i < CONF_NAMESERVERS_MAX; i++)  		if (ic_nameservers[i] != NONE) -			pr_cont(", nameserver%u=%pI4\n", i, &ic_nameservers[i]); +			pr_cont(", nameserver%u=%pI4", i, &ic_nameservers[i]); +	pr_cont("\n");  #endif /* !SILENT */  	return 0; diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index ce2d43e1f09..0d755c50994 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig @@ -36,19 +36,6 @@ config NF_CONNTRACK_PROC_COMPAT  	  If unsure, say Y. -config IP_NF_QUEUE -	tristate "IP Userspace queueing via NETLINK (OBSOLETE)" -	depends on NETFILTER_ADVANCED -	help -	  Netfilter has the ability to queue packets to user space: the -	  netlink device can be used to access them using this driver. - -	  This option enables the old IPv4-only "ip_queue" implementation -	  which has been obsoleted by the new "nfnetlink_queue" code (see -	  CONFIG_NETFILTER_NETLINK_QUEUE). - -	  To compile it as a module, choose M here.  If unsure, say N. -  config IP_NF_IPTABLES  	tristate "IP tables support (required for filtering/masq/NAT)"  	default m if NETFILTER_ADVANCED=n 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_input.c b/net/ipv4/tcp_input.c index a759e19496d..3bd55bad230 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -2059,11 +2059,8 @@ void tcp_enter_loss(struct sock *sk, int how)  	if (tcp_is_reno(tp))  		tcp_reset_reno_sack(tp); -	if (!how) { -		/* Push undo marker, if it was plain RTO and nothing -		 * was retransmitted. */ -		tp->undo_marker = tp->snd_una; -	} else { +	tp->undo_marker = tp->snd_una; +	if (how) {  		tp->sacked_out = 0;  		tp->fackets_out = 0;  	} @@ -5485,6 +5482,9 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb,  				if (tcp_checksum_complete_user(sk, skb))  					goto csum_error; +				if ((int)skb->truesize > sk->sk_forward_alloc) +					goto step5; +  				/* Predicted packet is in window by definition.  				 * seq == rcv_nxt and rcv_wup <= rcv_nxt.  				 * Hence, check seq<=rcv_wup reduces to: @@ -5496,9 +5496,6 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb,  				tcp_rcv_rtt_measure_ts(sk, skb); -				if ((int)skb->truesize > sk->sk_forward_alloc) -					goto step5; -  				NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPHPHITS);  				/* Bulk data transfer: receiver */ 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..5d0b4387cba 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; @@ -1810,8 +1809,11 @@ static bool tcp_tso_should_defer(struct sock *sk, struct sk_buff *skb)  			goto send_now;  	} -	/* Ok, it looks like it is advisable to defer.  */ -	tp->tso_deferred = 1 | (jiffies << 1); +	/* Ok, it looks like it is advisable to defer. +	 * Do not rearm the timer if already set to not break TCP ACK clocking. +	 */ +	if (!tp->tso_deferred) +		tp->tso_deferred = 1 | (jiffies << 1);  	return true; diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 265c42cf963..0a073a26372 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1762,9 +1762,16 @@ int udp_rcv(struct sk_buff *skb)  void udp_destroy_sock(struct sock *sk)  { +	struct udp_sock *up = udp_sk(sk);  	bool slow = lock_sock_fast(sk);  	udp_flush_pending_frames(sk);  	unlock_sock_fast(sk, slow); +	if (static_key_false(&udp_encap_needed) && up->encap_type) { +		void (*encap_destroy)(struct sock *sk); +		encap_destroy = ACCESS_ONCE(up->encap_destroy); +		if (encap_destroy) +			encap_destroy(sk); +	}  }  /* diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index f2c7e615f90..26512250e09 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -4784,26 +4784,20 @@ static void addrconf_sysctl_unregister(struct inet6_dev *idev)  static int __net_init addrconf_init_net(struct net *net)  { -	int err; +	int err = -ENOMEM;  	struct ipv6_devconf *all, *dflt; -	err = -ENOMEM; -	all = &ipv6_devconf; -	dflt = &ipv6_devconf_dflt; +	all = kmemdup(&ipv6_devconf, sizeof(ipv6_devconf), GFP_KERNEL); +	if (all == NULL) +		goto err_alloc_all; -	if (!net_eq(net, &init_net)) { -		all = kmemdup(all, sizeof(ipv6_devconf), GFP_KERNEL); -		if (all == NULL) -			goto err_alloc_all; +	dflt = kmemdup(&ipv6_devconf_dflt, sizeof(ipv6_devconf_dflt), GFP_KERNEL); +	if (dflt == NULL) +		goto err_alloc_dflt; -		dflt = kmemdup(dflt, sizeof(ipv6_devconf_dflt), GFP_KERNEL); -		if (dflt == NULL) -			goto err_alloc_dflt; -	} else { -		/* these will be inherited by all namespaces */ -		dflt->autoconf = ipv6_defaults.autoconf; -		dflt->disable_ipv6 = ipv6_defaults.disable_ipv6; -	} +	/* these will be inherited by all namespaces */ +	dflt->autoconf = ipv6_defaults.autoconf; +	dflt->disable_ipv6 = ipv6_defaults.disable_ipv6;  	net->ipv6.devconf_all = all;  	net->ipv6.devconf_dflt = dflt; diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index 5b10414e619..e33fe0ab256 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c @@ -241,9 +241,11 @@ resubmit:  				icmpv6_send(skb, ICMPV6_PARAMPROB,  					    ICMPV6_UNK_NEXTHDR, nhoff);  			} -		} else +			kfree_skb(skb); +		} else {  			IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INDELIVERS); -		kfree_skb(skb); +			consume_skb(skb); +		}  	}  	rcu_read_unlock();  	return 0; @@ -279,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/ip6t_NPT.c b/net/ipv6/netfilter/ip6t_NPT.c index 83acc1405a1..33608c61027 100644 --- a/net/ipv6/netfilter/ip6t_NPT.c +++ b/net/ipv6/netfilter/ip6t_NPT.c @@ -114,6 +114,7 @@ ip6t_dnpt_tg(struct sk_buff *skb, const struct xt_action_param *par)  static struct xt_target ip6t_npt_target_reg[] __read_mostly = {  	{  		.name		= "SNPT", +		.table		= "mangle",  		.target		= ip6t_snpt_tg,  		.targetsize	= sizeof(struct ip6t_npt_tginfo),  		.checkentry	= ip6t_npt_checkentry, @@ -124,6 +125,7 @@ static struct xt_target ip6t_npt_target_reg[] __read_mostly = {  	},  	{  		.name		= "DNPT", +		.table		= "mangle",  		.target		= ip6t_dnpt_tg,  		.targetsize	= sizeof(struct ip6t_npt_tginfo),  		.checkentry	= ip6t_npt_checkentry, 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/route.c b/net/ipv6/route.c index 92826656968..e5fe0041adf 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -1915,7 +1915,8 @@ void rt6_purge_dflt_routers(struct net *net)  restart:  	read_lock_bh(&table->tb6_lock);  	for (rt = table->tb6_root.leaf; rt; rt = rt->dst.rt6_next) { -		if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) { +		if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF) && +		    (!rt->rt6i_idev || rt->rt6i_idev->cnf.accept_ra != 2)) {  			dst_hold(&rt->dst);  			read_unlock_bh(&table->tb6_lock);  			ip6_del_rt(rt); 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/ipv6/udp.c b/net/ipv6/udp.c index 599e1ba6d1c..d8e5e852fc7 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -1285,10 +1285,18 @@ do_confirm:  void udpv6_destroy_sock(struct sock *sk)  { +	struct udp_sock *up = udp_sk(sk);  	lock_sock(sk);  	udp_v6_flush_pending_frames(sk);  	release_sock(sk); +	if (static_key_false(&udpv6_encap_needed) && up->encap_type) { +		void (*encap_destroy)(struct sock *sk); +		encap_destroy = ACCESS_ONCE(up->encap_destroy); +		if (encap_destroy) +			encap_destroy(sk); +	} +  	inet6_destroy_sock(sk);  } diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c index d07e3a62644..d28e7f014cc 100644 --- a/net/irda/af_irda.c +++ b/net/irda/af_irda.c @@ -2583,8 +2583,10 @@ bed:  				    NULL, NULL, NULL);  		/* Check if the we got some results */ -		if (!self->cachedaddr) -			return -EAGAIN;		/* Didn't find any devices */ +		if (!self->cachedaddr) { +			err = -EAGAIN;		/* Didn't find any devices */ +			goto out; +		}  		daddr = self->cachedaddr;  		/* Cleanup */  		self->cachedaddr = 0; 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/irda/iriap.c b/net/irda/iriap.c index e71e85ba2bf..29340a9a6fb 100644 --- a/net/irda/iriap.c +++ b/net/irda/iriap.c @@ -495,8 +495,11 @@ static void iriap_getvaluebyclass_confirm(struct iriap_cb *self,  /*		case CS_ISO_8859_9: */  /*		case CS_UNICODE: */  		default: -			IRDA_DEBUG(0, "%s(), charset %s, not supported\n", -				   __func__, ias_charset_types[charset]); +			IRDA_DEBUG(0, "%s(), charset [%d] %s, not supported\n", +				   __func__, charset, +				   charset < ARRAY_SIZE(ias_charset_types) ? +					ias_charset_types[charset] : +					"(unknown)");  			/* Aborting, close connection! */  			iriap_disconnect_request(self); 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/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index d36875f3427..8aecf5df665 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c @@ -114,7 +114,6 @@ struct l2tp_net {  static void l2tp_session_set_header_len(struct l2tp_session *session, int version);  static void l2tp_tunnel_free(struct l2tp_tunnel *tunnel); -static void l2tp_tunnel_closeall(struct l2tp_tunnel *tunnel);  static inline struct l2tp_net *l2tp_pernet(struct net *net)  { @@ -192,6 +191,7 @@ struct sock *l2tp_tunnel_sock_lookup(struct l2tp_tunnel *tunnel)  	} else {  		/* Socket is owned by kernelspace */  		sk = tunnel->sock; +		sock_hold(sk);  	}  out: @@ -210,6 +210,7 @@ void l2tp_tunnel_sock_put(struct sock *sk)  		}  		sock_put(sk);  	} +	sock_put(sk);  }  EXPORT_SYMBOL_GPL(l2tp_tunnel_sock_put); @@ -373,10 +374,8 @@ static void l2tp_recv_queue_skb(struct l2tp_session *session, struct sk_buff *sk  	struct sk_buff *skbp;  	struct sk_buff *tmp;  	u32 ns = L2TP_SKB_CB(skb)->ns; -	struct l2tp_stats *sstats;  	spin_lock_bh(&session->reorder_q.lock); -	sstats = &session->stats;  	skb_queue_walk_safe(&session->reorder_q, skbp, tmp) {  		if (L2TP_SKB_CB(skbp)->ns > ns) {  			__skb_queue_before(&session->reorder_q, skbp, skb); @@ -384,9 +383,7 @@ static void l2tp_recv_queue_skb(struct l2tp_session *session, struct sk_buff *sk  				 "%s: pkt %hu, inserted before %hu, reorder_q len=%d\n",  				 session->name, ns, L2TP_SKB_CB(skbp)->ns,  				 skb_queue_len(&session->reorder_q)); -			u64_stats_update_begin(&sstats->syncp); -			sstats->rx_oos_packets++; -			u64_stats_update_end(&sstats->syncp); +			atomic_long_inc(&session->stats.rx_oos_packets);  			goto out;  		}  	} @@ -403,23 +400,16 @@ static void l2tp_recv_dequeue_skb(struct l2tp_session *session, struct sk_buff *  {  	struct l2tp_tunnel *tunnel = session->tunnel;  	int length = L2TP_SKB_CB(skb)->length; -	struct l2tp_stats *tstats, *sstats;  	/* We're about to requeue the skb, so return resources  	 * to its current owner (a socket receive buffer).  	 */  	skb_orphan(skb); -	tstats = &tunnel->stats; -	u64_stats_update_begin(&tstats->syncp); -	sstats = &session->stats; -	u64_stats_update_begin(&sstats->syncp); -	tstats->rx_packets++; -	tstats->rx_bytes += length; -	sstats->rx_packets++; -	sstats->rx_bytes += length; -	u64_stats_update_end(&tstats->syncp); -	u64_stats_update_end(&sstats->syncp); +	atomic_long_inc(&tunnel->stats.rx_packets); +	atomic_long_add(length, &tunnel->stats.rx_bytes); +	atomic_long_inc(&session->stats.rx_packets); +	atomic_long_add(length, &session->stats.rx_bytes);  	if (L2TP_SKB_CB(skb)->has_seq) {  		/* Bump our Nr */ @@ -450,7 +440,6 @@ static void l2tp_recv_dequeue(struct l2tp_session *session)  {  	struct sk_buff *skb;  	struct sk_buff *tmp; -	struct l2tp_stats *sstats;  	/* If the pkt at the head of the queue has the nr that we  	 * expect to send up next, dequeue it and any other @@ -458,13 +447,10 @@ static void l2tp_recv_dequeue(struct l2tp_session *session)  	 */  start:  	spin_lock_bh(&session->reorder_q.lock); -	sstats = &session->stats;  	skb_queue_walk_safe(&session->reorder_q, skb, tmp) {  		if (time_after(jiffies, L2TP_SKB_CB(skb)->expires)) { -			u64_stats_update_begin(&sstats->syncp); -			sstats->rx_seq_discards++; -			sstats->rx_errors++; -			u64_stats_update_end(&sstats->syncp); +			atomic_long_inc(&session->stats.rx_seq_discards); +			atomic_long_inc(&session->stats.rx_errors);  			l2tp_dbg(session, L2TP_MSG_SEQ,  				 "%s: oos pkt %u len %d discarded (too old), waiting for %u, reorder_q_len=%d\n",  				 session->name, L2TP_SKB_CB(skb)->ns, @@ -623,7 +609,6 @@ void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb,  	struct l2tp_tunnel *tunnel = session->tunnel;  	int offset;  	u32 ns, nr; -	struct l2tp_stats *sstats = &session->stats;  	/* The ref count is increased since we now hold a pointer to  	 * the session. Take care to decrement the refcnt when exiting @@ -640,9 +625,7 @@ void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb,  				  "%s: cookie mismatch (%u/%u). Discarding.\n",  				  tunnel->name, tunnel->tunnel_id,  				  session->session_id); -			u64_stats_update_begin(&sstats->syncp); -			sstats->rx_cookie_discards++; -			u64_stats_update_end(&sstats->syncp); +			atomic_long_inc(&session->stats.rx_cookie_discards);  			goto discard;  		}  		ptr += session->peer_cookie_len; @@ -711,9 +694,7 @@ void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb,  			l2tp_warn(session, L2TP_MSG_SEQ,  				  "%s: recv data has no seq numbers when required. Discarding.\n",  				  session->name); -			u64_stats_update_begin(&sstats->syncp); -			sstats->rx_seq_discards++; -			u64_stats_update_end(&sstats->syncp); +			atomic_long_inc(&session->stats.rx_seq_discards);  			goto discard;  		} @@ -732,9 +713,7 @@ void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb,  			l2tp_warn(session, L2TP_MSG_SEQ,  				  "%s: recv data has no seq numbers when required. Discarding.\n",  				  session->name); -			u64_stats_update_begin(&sstats->syncp); -			sstats->rx_seq_discards++; -			u64_stats_update_end(&sstats->syncp); +			atomic_long_inc(&session->stats.rx_seq_discards);  			goto discard;  		}  	} @@ -788,9 +767,7 @@ void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb,  			 * packets  			 */  			if (L2TP_SKB_CB(skb)->ns != session->nr) { -				u64_stats_update_begin(&sstats->syncp); -				sstats->rx_seq_discards++; -				u64_stats_update_end(&sstats->syncp); +				atomic_long_inc(&session->stats.rx_seq_discards);  				l2tp_dbg(session, L2TP_MSG_SEQ,  					 "%s: oos pkt %u len %d discarded, waiting for %u, reorder_q_len=%d\n",  					 session->name, L2TP_SKB_CB(skb)->ns, @@ -816,9 +793,7 @@ void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb,  	return;  discard: -	u64_stats_update_begin(&sstats->syncp); -	sstats->rx_errors++; -	u64_stats_update_end(&sstats->syncp); +	atomic_long_inc(&session->stats.rx_errors);  	kfree_skb(skb);  	if (session->deref) @@ -828,6 +803,23 @@ discard:  }  EXPORT_SYMBOL(l2tp_recv_common); +/* Drop skbs from the session's reorder_q + */ +int l2tp_session_queue_purge(struct l2tp_session *session) +{ +	struct sk_buff *skb = NULL; +	BUG_ON(!session); +	BUG_ON(session->magic != L2TP_SESSION_MAGIC); +	while ((skb = skb_dequeue(&session->reorder_q))) { +		atomic_long_inc(&session->stats.rx_errors); +		kfree_skb(skb); +		if (session->deref) +			(*session->deref)(session); +	} +	return 0; +} +EXPORT_SYMBOL_GPL(l2tp_session_queue_purge); +  /* Internal UDP receive frame. Do the real work of receiving an L2TP data frame   * here. The skb is not on a list when we get here.   * Returns 0 if the packet was a data packet and was successfully passed on. @@ -843,7 +835,6 @@ static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb,  	u32 tunnel_id, session_id;  	u16 version;  	int length; -	struct l2tp_stats *tstats;  	if (tunnel->sock && l2tp_verify_udp_checksum(tunnel->sock, skb))  		goto discard_bad_csum; @@ -932,10 +923,7 @@ static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb,  discard_bad_csum:  	LIMIT_NETDEBUG("%s: UDP: bad checksum\n", tunnel->name);  	UDP_INC_STATS_USER(tunnel->l2tp_net, UDP_MIB_INERRORS, 0); -	tstats = &tunnel->stats; -	u64_stats_update_begin(&tstats->syncp); -	tstats->rx_errors++; -	u64_stats_update_end(&tstats->syncp); +	atomic_long_inc(&tunnel->stats.rx_errors);  	kfree_skb(skb);  	return 0; @@ -1062,7 +1050,6 @@ static int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb,  	struct l2tp_tunnel *tunnel = session->tunnel;  	unsigned int len = skb->len;  	int error; -	struct l2tp_stats *tstats, *sstats;  	/* Debug */  	if (session->send_seq) @@ -1091,21 +1078,15 @@ static int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb,  		error = ip_queue_xmit(skb, fl);  	/* Update stats */ -	tstats = &tunnel->stats; -	u64_stats_update_begin(&tstats->syncp); -	sstats = &session->stats; -	u64_stats_update_begin(&sstats->syncp);  	if (error >= 0) { -		tstats->tx_packets++; -		tstats->tx_bytes += len; -		sstats->tx_packets++; -		sstats->tx_bytes += len; +		atomic_long_inc(&tunnel->stats.tx_packets); +		atomic_long_add(len, &tunnel->stats.tx_bytes); +		atomic_long_inc(&session->stats.tx_packets); +		atomic_long_add(len, &session->stats.tx_bytes);  	} else { -		tstats->tx_errors++; -		sstats->tx_errors++; +		atomic_long_inc(&tunnel->stats.tx_errors); +		atomic_long_inc(&session->stats.tx_errors);  	} -	u64_stats_update_end(&tstats->syncp); -	u64_stats_update_end(&sstats->syncp);  	return 0;  } @@ -1282,6 +1263,7 @@ static void l2tp_tunnel_destruct(struct sock *sk)  		/* No longer an encapsulation socket. See net/ipv4/udp.c */  		(udp_sk(sk))->encap_type = 0;  		(udp_sk(sk))->encap_rcv = NULL; +		(udp_sk(sk))->encap_destroy = NULL;  		break;  	case L2TP_ENCAPTYPE_IP:  		break; @@ -1311,7 +1293,7 @@ end:  /* When the tunnel is closed, all the attached sessions need to go too.   */ -static void l2tp_tunnel_closeall(struct l2tp_tunnel *tunnel) +void l2tp_tunnel_closeall(struct l2tp_tunnel *tunnel)  {  	int hash;  	struct hlist_node *walk; @@ -1334,25 +1316,13 @@ again:  			hlist_del_init(&session->hlist); -			/* Since we should hold the sock lock while -			 * doing any unbinding, we need to release the -			 * lock we're holding before taking that lock. -			 * Hold a reference to the sock so it doesn't -			 * disappear as we're jumping between locks. -			 */  			if (session->ref != NULL)  				(*session->ref)(session);  			write_unlock_bh(&tunnel->hlist_lock); -			if (tunnel->version != L2TP_HDR_VER_2) { -				struct l2tp_net *pn = l2tp_pernet(tunnel->l2tp_net); - -				spin_lock_bh(&pn->l2tp_session_hlist_lock); -				hlist_del_init_rcu(&session->global_hlist); -				spin_unlock_bh(&pn->l2tp_session_hlist_lock); -				synchronize_rcu(); -			} +			__l2tp_session_unhash(session); +			l2tp_session_queue_purge(session);  			if (session->session_close != NULL)  				(*session->session_close)(session); @@ -1360,6 +1330,8 @@ again:  			if (session->deref != NULL)  				(*session->deref)(session); +			l2tp_session_dec_refcount(session); +  			write_lock_bh(&tunnel->hlist_lock);  			/* Now restart from the beginning of this hash @@ -1372,6 +1344,17 @@ again:  	}  	write_unlock_bh(&tunnel->hlist_lock);  } +EXPORT_SYMBOL_GPL(l2tp_tunnel_closeall); + +/* Tunnel socket destroy hook for UDP encapsulation */ +static void l2tp_udp_encap_destroy(struct sock *sk) +{ +	struct l2tp_tunnel *tunnel = l2tp_sock_to_tunnel(sk); +	if (tunnel) { +		l2tp_tunnel_closeall(tunnel); +		sock_put(sk); +	} +}  /* Really kill the tunnel.   * Come here only when all sessions have been cleared from the tunnel. @@ -1397,19 +1380,21 @@ static void l2tp_tunnel_del_work(struct work_struct *work)  		return;  	sock = sk->sk_socket; -	BUG_ON(!sock); -	/* If the tunnel socket was created directly by the kernel, use the -	 * sk_* API to release the socket now.  Otherwise go through the -	 * inet_* layer to shut the socket down, and let userspace close it. +	/* If the tunnel socket was created by userspace, then go through the +	 * inet layer to shut the socket down, and let userspace close it. +	 * Otherwise, if we created the socket directly within the kernel, use +	 * the sk API to release it here.  	 * In either case the tunnel resources are freed in the socket  	 * destructor when the tunnel socket goes away.  	 */ -	if (sock->file == NULL) { -		kernel_sock_shutdown(sock, SHUT_RDWR); -		sk_release_kernel(sk); +	if (tunnel->fd >= 0) { +		if (sock) +			inet_shutdown(sock, 2);  	} else { -		inet_shutdown(sock, 2); +		if (sock) +			kernel_sock_shutdown(sock, SHUT_RDWR); +		sk_release_kernel(sk);  	}  	l2tp_tunnel_sock_put(sk); @@ -1668,6 +1653,7 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32  		/* Mark socket as an encapsulation socket. See net/ipv4/udp.c */  		udp_sk(sk)->encap_type = UDP_ENCAP_L2TPINUDP;  		udp_sk(sk)->encap_rcv = l2tp_udp_encap_recv; +		udp_sk(sk)->encap_destroy = l2tp_udp_encap_destroy;  #if IS_ENABLED(CONFIG_IPV6)  		if (sk->sk_family == PF_INET6)  			udpv6_encap_enable(); @@ -1723,6 +1709,7 @@ EXPORT_SYMBOL_GPL(l2tp_tunnel_create);   */  int l2tp_tunnel_delete(struct l2tp_tunnel *tunnel)  { +	l2tp_tunnel_closeall(tunnel);  	return (false == queue_work(l2tp_wq, &tunnel->del_work));  }  EXPORT_SYMBOL_GPL(l2tp_tunnel_delete); @@ -1731,62 +1718,71 @@ EXPORT_SYMBOL_GPL(l2tp_tunnel_delete);   */  void l2tp_session_free(struct l2tp_session *session)  { -	struct l2tp_tunnel *tunnel; +	struct l2tp_tunnel *tunnel = session->tunnel;  	BUG_ON(atomic_read(&session->ref_count) != 0); -	tunnel = session->tunnel; -	if (tunnel != NULL) { +	if (tunnel) {  		BUG_ON(tunnel->magic != L2TP_TUNNEL_MAGIC); +		if (session->session_id != 0) +			atomic_dec(&l2tp_session_count); +		sock_put(tunnel->sock); +		session->tunnel = NULL; +		l2tp_tunnel_dec_refcount(tunnel); +	} + +	kfree(session); -		/* Delete the session from the hash */ +	return; +} +EXPORT_SYMBOL_GPL(l2tp_session_free); + +/* Remove an l2tp session from l2tp_core's hash lists. + * Provides a tidyup interface for pseudowire code which can't just route all + * shutdown via. l2tp_session_delete and a pseudowire-specific session_close + * callback. + */ +void __l2tp_session_unhash(struct l2tp_session *session) +{ +	struct l2tp_tunnel *tunnel = session->tunnel; + +	/* Remove the session from core hashes */ +	if (tunnel) { +		/* Remove from the per-tunnel hash */  		write_lock_bh(&tunnel->hlist_lock);  		hlist_del_init(&session->hlist);  		write_unlock_bh(&tunnel->hlist_lock); -		/* Unlink from the global hash if not L2TPv2 */ +		/* For L2TPv3 we have a per-net hash: remove from there, too */  		if (tunnel->version != L2TP_HDR_VER_2) {  			struct l2tp_net *pn = l2tp_pernet(tunnel->l2tp_net); -  			spin_lock_bh(&pn->l2tp_session_hlist_lock);  			hlist_del_init_rcu(&session->global_hlist);  			spin_unlock_bh(&pn->l2tp_session_hlist_lock);  			synchronize_rcu();  		} - -		if (session->session_id != 0) -			atomic_dec(&l2tp_session_count); - -		sock_put(tunnel->sock); - -		/* This will delete the tunnel context if this -		 * is the last session on the tunnel. -		 */ -		session->tunnel = NULL; -		l2tp_tunnel_dec_refcount(tunnel);  	} - -	kfree(session); - -	return;  } -EXPORT_SYMBOL_GPL(l2tp_session_free); +EXPORT_SYMBOL_GPL(__l2tp_session_unhash);  /* This function is used by the netlink SESSION_DELETE command and by     pseudowire modules.   */  int l2tp_session_delete(struct l2tp_session *session)  { +	if (session->ref) +		(*session->ref)(session); +	__l2tp_session_unhash(session); +	l2tp_session_queue_purge(session);  	if (session->session_close != NULL)  		(*session->session_close)(session); - +	if (session->deref) +		(*session->ref)(session);  	l2tp_session_dec_refcount(session); -  	return 0;  }  EXPORT_SYMBOL_GPL(l2tp_session_delete); -  /* We come here whenever a session's send_seq, cookie_len or   * l2specific_len parameters are set.   */ diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h index 8eb8f1d47f3..485a490fd99 100644 --- a/net/l2tp/l2tp_core.h +++ b/net/l2tp/l2tp_core.h @@ -36,16 +36,15 @@ enum {  struct sk_buff;  struct l2tp_stats { -	u64			tx_packets; -	u64			tx_bytes; -	u64			tx_errors; -	u64			rx_packets; -	u64			rx_bytes; -	u64			rx_seq_discards; -	u64			rx_oos_packets; -	u64			rx_errors; -	u64			rx_cookie_discards; -	struct u64_stats_sync	syncp; +	atomic_long_t		tx_packets; +	atomic_long_t		tx_bytes; +	atomic_long_t		tx_errors; +	atomic_long_t		rx_packets; +	atomic_long_t		rx_bytes; +	atomic_long_t		rx_seq_discards; +	atomic_long_t		rx_oos_packets; +	atomic_long_t		rx_errors; +	atomic_long_t		rx_cookie_discards;  };  struct l2tp_tunnel; @@ -240,11 +239,14 @@ extern struct l2tp_tunnel *l2tp_tunnel_find(struct net *net, u32 tunnel_id);  extern struct l2tp_tunnel *l2tp_tunnel_find_nth(struct net *net, int nth);  extern int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32 peer_tunnel_id, struct l2tp_tunnel_cfg *cfg, struct l2tp_tunnel **tunnelp); +extern void l2tp_tunnel_closeall(struct l2tp_tunnel *tunnel);  extern int l2tp_tunnel_delete(struct l2tp_tunnel *tunnel);  extern struct l2tp_session *l2tp_session_create(int priv_size, struct l2tp_tunnel *tunnel, u32 session_id, u32 peer_session_id, struct l2tp_session_cfg *cfg); +extern void __l2tp_session_unhash(struct l2tp_session *session);  extern int l2tp_session_delete(struct l2tp_session *session);  extern void l2tp_session_free(struct l2tp_session *session);  extern void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb, unsigned char *ptr, unsigned char *optr, u16 hdrflags, int length, int (*payload_hook)(struct sk_buff *skb)); +extern int l2tp_session_queue_purge(struct l2tp_session *session);  extern int l2tp_udp_encap_recv(struct sock *sk, struct sk_buff *skb);  extern int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len); diff --git a/net/l2tp/l2tp_debugfs.c b/net/l2tp/l2tp_debugfs.c index c3813bc8455..072d7202e18 100644 --- a/net/l2tp/l2tp_debugfs.c +++ b/net/l2tp/l2tp_debugfs.c @@ -146,14 +146,14 @@ static void l2tp_dfs_seq_tunnel_show(struct seq_file *m, void *v)  		   tunnel->sock ? atomic_read(&tunnel->sock->sk_refcnt) : 0,  		   atomic_read(&tunnel->ref_count)); -	seq_printf(m, " %08x rx %llu/%llu/%llu rx %llu/%llu/%llu\n", +	seq_printf(m, " %08x rx %ld/%ld/%ld rx %ld/%ld/%ld\n",  		   tunnel->debug, -		   (unsigned long long)tunnel->stats.tx_packets, -		   (unsigned long long)tunnel->stats.tx_bytes, -		   (unsigned long long)tunnel->stats.tx_errors, -		   (unsigned long long)tunnel->stats.rx_packets, -		   (unsigned long long)tunnel->stats.rx_bytes, -		   (unsigned long long)tunnel->stats.rx_errors); +		   atomic_long_read(&tunnel->stats.tx_packets), +		   atomic_long_read(&tunnel->stats.tx_bytes), +		   atomic_long_read(&tunnel->stats.tx_errors), +		   atomic_long_read(&tunnel->stats.rx_packets), +		   atomic_long_read(&tunnel->stats.rx_bytes), +		   atomic_long_read(&tunnel->stats.rx_errors));  	if (tunnel->show != NULL)  		tunnel->show(m, tunnel); @@ -203,14 +203,14 @@ static void l2tp_dfs_seq_session_show(struct seq_file *m, void *v)  		seq_printf(m, "\n");  	} -	seq_printf(m, "   %hu/%hu tx %llu/%llu/%llu rx %llu/%llu/%llu\n", +	seq_printf(m, "   %hu/%hu tx %ld/%ld/%ld rx %ld/%ld/%ld\n",  		   session->nr, session->ns, -		   (unsigned long long)session->stats.tx_packets, -		   (unsigned long long)session->stats.tx_bytes, -		   (unsigned long long)session->stats.tx_errors, -		   (unsigned long long)session->stats.rx_packets, -		   (unsigned long long)session->stats.rx_bytes, -		   (unsigned long long)session->stats.rx_errors); +		   atomic_long_read(&session->stats.tx_packets), +		   atomic_long_read(&session->stats.tx_bytes), +		   atomic_long_read(&session->stats.tx_errors), +		   atomic_long_read(&session->stats.rx_packets), +		   atomic_long_read(&session->stats.rx_bytes), +		   atomic_long_read(&session->stats.rx_errors));  	if (session->show != NULL)  		session->show(m, session); diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c index 7f41b705126..571db8dd229 100644 --- a/net/l2tp/l2tp_ip.c +++ b/net/l2tp/l2tp_ip.c @@ -228,10 +228,16 @@ static void l2tp_ip_close(struct sock *sk, long timeout)  static void l2tp_ip_destroy_sock(struct sock *sk)  {  	struct sk_buff *skb; +	struct l2tp_tunnel *tunnel = l2tp_sock_to_tunnel(sk);  	while ((skb = __skb_dequeue_tail(&sk->sk_write_queue)) != NULL)  		kfree_skb(skb); +	if (tunnel) { +		l2tp_tunnel_closeall(tunnel); +		sock_put(sk); +	} +  	sk_refcnt_debug_dec(sk);  } diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c index 41f2f8126eb..c74f5a91ff6 100644 --- a/net/l2tp/l2tp_ip6.c +++ b/net/l2tp/l2tp_ip6.c @@ -241,10 +241,17 @@ static void l2tp_ip6_close(struct sock *sk, long timeout)  static void l2tp_ip6_destroy_sock(struct sock *sk)  { +	struct l2tp_tunnel *tunnel = l2tp_sock_to_tunnel(sk); +  	lock_sock(sk);  	ip6_flush_pending_frames(sk);  	release_sock(sk); +	if (tunnel) { +		l2tp_tunnel_closeall(tunnel); +		sock_put(sk); +	} +  	inet6_destroy_sock(sk);  } diff --git a/net/l2tp/l2tp_netlink.c b/net/l2tp/l2tp_netlink.c index c1bab22db85..0825ff26e11 100644 --- a/net/l2tp/l2tp_netlink.c +++ b/net/l2tp/l2tp_netlink.c @@ -246,8 +246,6 @@ static int l2tp_nl_tunnel_send(struct sk_buff *skb, u32 portid, u32 seq, int fla  #if IS_ENABLED(CONFIG_IPV6)  	struct ipv6_pinfo *np = NULL;  #endif -	struct l2tp_stats stats; -	unsigned int start;  	hdr = genlmsg_put(skb, portid, seq, &l2tp_nl_family, flags,  			  L2TP_CMD_TUNNEL_GET); @@ -265,28 +263,22 @@ static int l2tp_nl_tunnel_send(struct sk_buff *skb, u32 portid, u32 seq, int fla  	if (nest == NULL)  		goto nla_put_failure; -	do { -		start = u64_stats_fetch_begin(&tunnel->stats.syncp); -		stats.tx_packets = tunnel->stats.tx_packets; -		stats.tx_bytes = tunnel->stats.tx_bytes; -		stats.tx_errors = tunnel->stats.tx_errors; -		stats.rx_packets = tunnel->stats.rx_packets; -		stats.rx_bytes = tunnel->stats.rx_bytes; -		stats.rx_errors = tunnel->stats.rx_errors; -		stats.rx_seq_discards = tunnel->stats.rx_seq_discards; -		stats.rx_oos_packets = tunnel->stats.rx_oos_packets; -	} while (u64_stats_fetch_retry(&tunnel->stats.syncp, start)); - -	if (nla_put_u64(skb, L2TP_ATTR_TX_PACKETS, stats.tx_packets) || -	    nla_put_u64(skb, L2TP_ATTR_TX_BYTES, stats.tx_bytes) || -	    nla_put_u64(skb, L2TP_ATTR_TX_ERRORS, stats.tx_errors) || -	    nla_put_u64(skb, L2TP_ATTR_RX_PACKETS, stats.rx_packets) || -	    nla_put_u64(skb, L2TP_ATTR_RX_BYTES, stats.rx_bytes) || +	if (nla_put_u64(skb, L2TP_ATTR_TX_PACKETS, +		    atomic_long_read(&tunnel->stats.tx_packets)) || +	    nla_put_u64(skb, L2TP_ATTR_TX_BYTES, +		    atomic_long_read(&tunnel->stats.tx_bytes)) || +	    nla_put_u64(skb, L2TP_ATTR_TX_ERRORS, +		    atomic_long_read(&tunnel->stats.tx_errors)) || +	    nla_put_u64(skb, L2TP_ATTR_RX_PACKETS, +		    atomic_long_read(&tunnel->stats.rx_packets)) || +	    nla_put_u64(skb, L2TP_ATTR_RX_BYTES, +		    atomic_long_read(&tunnel->stats.rx_bytes)) ||  	    nla_put_u64(skb, L2TP_ATTR_RX_SEQ_DISCARDS, -			stats.rx_seq_discards) || +		    atomic_long_read(&tunnel->stats.rx_seq_discards)) ||  	    nla_put_u64(skb, L2TP_ATTR_RX_OOS_PACKETS, -			stats.rx_oos_packets) || -	    nla_put_u64(skb, L2TP_ATTR_RX_ERRORS, stats.rx_errors)) +		    atomic_long_read(&tunnel->stats.rx_oos_packets)) || +	    nla_put_u64(skb, L2TP_ATTR_RX_ERRORS, +		    atomic_long_read(&tunnel->stats.rx_errors)))  		goto nla_put_failure;  	nla_nest_end(skb, nest); @@ -612,8 +604,6 @@ static int l2tp_nl_session_send(struct sk_buff *skb, u32 portid, u32 seq, int fl  	struct nlattr *nest;  	struct l2tp_tunnel *tunnel = session->tunnel;  	struct sock *sk = NULL; -	struct l2tp_stats stats; -	unsigned int start;  	sk = tunnel->sock; @@ -656,28 +646,22 @@ static int l2tp_nl_session_send(struct sk_buff *skb, u32 portid, u32 seq, int fl  	if (nest == NULL)  		goto nla_put_failure; -	do { -		start = u64_stats_fetch_begin(&session->stats.syncp); -		stats.tx_packets = session->stats.tx_packets; -		stats.tx_bytes = session->stats.tx_bytes; -		stats.tx_errors = session->stats.tx_errors; -		stats.rx_packets = session->stats.rx_packets; -		stats.rx_bytes = session->stats.rx_bytes; -		stats.rx_errors = session->stats.rx_errors; -		stats.rx_seq_discards = session->stats.rx_seq_discards; -		stats.rx_oos_packets = session->stats.rx_oos_packets; -	} while (u64_stats_fetch_retry(&session->stats.syncp, start)); - -	if (nla_put_u64(skb, L2TP_ATTR_TX_PACKETS, stats.tx_packets) || -	    nla_put_u64(skb, L2TP_ATTR_TX_BYTES, stats.tx_bytes) || -	    nla_put_u64(skb, L2TP_ATTR_TX_ERRORS, stats.tx_errors) || -	    nla_put_u64(skb, L2TP_ATTR_RX_PACKETS, stats.rx_packets) || -	    nla_put_u64(skb, L2TP_ATTR_RX_BYTES, stats.rx_bytes) || +	if (nla_put_u64(skb, L2TP_ATTR_TX_PACKETS, +		atomic_long_read(&session->stats.tx_packets)) || +	    nla_put_u64(skb, L2TP_ATTR_TX_BYTES, +		atomic_long_read(&session->stats.tx_bytes)) || +	    nla_put_u64(skb, L2TP_ATTR_TX_ERRORS, +		atomic_long_read(&session->stats.tx_errors)) || +	    nla_put_u64(skb, L2TP_ATTR_RX_PACKETS, +		atomic_long_read(&session->stats.rx_packets)) || +	    nla_put_u64(skb, L2TP_ATTR_RX_BYTES, +		atomic_long_read(&session->stats.rx_bytes)) ||  	    nla_put_u64(skb, L2TP_ATTR_RX_SEQ_DISCARDS, -			stats.rx_seq_discards) || +		atomic_long_read(&session->stats.rx_seq_discards)) ||  	    nla_put_u64(skb, L2TP_ATTR_RX_OOS_PACKETS, -			stats.rx_oos_packets) || -	    nla_put_u64(skb, L2TP_ATTR_RX_ERRORS, stats.rx_errors)) +		atomic_long_read(&session->stats.rx_oos_packets)) || +	    nla_put_u64(skb, L2TP_ATTR_RX_ERRORS, +		atomic_long_read(&session->stats.rx_errors)))  		goto nla_put_failure;  	nla_nest_end(skb, nest); diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c index 3f4e3afc191..637a341c1e2 100644 --- a/net/l2tp/l2tp_ppp.c +++ b/net/l2tp/l2tp_ppp.c @@ -97,6 +97,7 @@  #include <net/ip.h>  #include <net/udp.h>  #include <net/xfrm.h> +#include <net/inet_common.h>  #include <asm/byteorder.h>  #include <linux/atomic.h> @@ -259,7 +260,7 @@ static void pppol2tp_recv(struct l2tp_session *session, struct sk_buff *skb, int  			  session->name);  		/* Not bound. Nothing we can do, so discard. */ -		session->stats.rx_errors++; +		atomic_long_inc(&session->stats.rx_errors);  		kfree_skb(skb);  	} @@ -355,6 +356,7 @@ static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msgh  	l2tp_xmit_skb(session, skb, session->hdr_len);  	sock_put(ps->tunnel_sock); +	sock_put(sk);  	return error; @@ -446,34 +448,16 @@ static void pppol2tp_session_close(struct l2tp_session *session)  {  	struct pppol2tp_session *ps = l2tp_session_priv(session);  	struct sock *sk = ps->sock; -	struct sk_buff *skb; +	struct socket *sock = sk->sk_socket;  	BUG_ON(session->magic != L2TP_SESSION_MAGIC); -	if (session->session_id == 0) -		goto out; - -	if (sk != NULL) { -		lock_sock(sk); - -		if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND)) { -			pppox_unbind_sock(sk); -			sk->sk_state = PPPOX_DEAD; -			sk->sk_state_change(sk); -		} - -		/* Purge any queued data */ -		skb_queue_purge(&sk->sk_receive_queue); -		skb_queue_purge(&sk->sk_write_queue); -		while ((skb = skb_dequeue(&session->reorder_q))) { -			kfree_skb(skb); -			sock_put(sk); -		} -		release_sock(sk); +	if (sock) { +		inet_shutdown(sock, 2); +		/* Don't let the session go away before our socket does */ +		l2tp_session_inc_refcount(session);  	} - -out:  	return;  } @@ -482,19 +466,12 @@ out:   */  static void pppol2tp_session_destruct(struct sock *sk)  { -	struct l2tp_session *session; - -	if (sk->sk_user_data != NULL) { -		session = sk->sk_user_data; -		if (session == NULL) -			goto out; - +	struct l2tp_session *session = sk->sk_user_data; +	if (session) {  		sk->sk_user_data = NULL;  		BUG_ON(session->magic != L2TP_SESSION_MAGIC);  		l2tp_session_dec_refcount(session);  	} - -out:  	return;  } @@ -524,16 +501,13 @@ static int pppol2tp_release(struct socket *sock)  	session = pppol2tp_sock_to_session(sk);  	/* Purge any queued data */ -	skb_queue_purge(&sk->sk_receive_queue); -	skb_queue_purge(&sk->sk_write_queue);  	if (session != NULL) { -		struct sk_buff *skb; -		while ((skb = skb_dequeue(&session->reorder_q))) { -			kfree_skb(skb); -			sock_put(sk); -		} +		__l2tp_session_unhash(session); +		l2tp_session_queue_purge(session);  		sock_put(sk);  	} +	skb_queue_purge(&sk->sk_receive_queue); +	skb_queue_purge(&sk->sk_write_queue);  	release_sock(sk); @@ -879,18 +853,6 @@ out:  	return error;  } -/* Called when deleting sessions via the netlink interface. - */ -static int pppol2tp_session_delete(struct l2tp_session *session) -{ -	struct pppol2tp_session *ps = l2tp_session_priv(session); - -	if (ps->sock == NULL) -		l2tp_session_dec_refcount(session); - -	return 0; -} -  #endif /* CONFIG_L2TP_V3 */  /* getname() support. @@ -1024,14 +986,14 @@ end:  static void pppol2tp_copy_stats(struct pppol2tp_ioc_stats *dest,  				struct l2tp_stats *stats)  { -	dest->tx_packets = stats->tx_packets; -	dest->tx_bytes = stats->tx_bytes; -	dest->tx_errors = stats->tx_errors; -	dest->rx_packets = stats->rx_packets; -	dest->rx_bytes = stats->rx_bytes; -	dest->rx_seq_discards = stats->rx_seq_discards; -	dest->rx_oos_packets = stats->rx_oos_packets; -	dest->rx_errors = stats->rx_errors; +	dest->tx_packets = atomic_long_read(&stats->tx_packets); +	dest->tx_bytes = atomic_long_read(&stats->tx_bytes); +	dest->tx_errors = atomic_long_read(&stats->tx_errors); +	dest->rx_packets = atomic_long_read(&stats->rx_packets); +	dest->rx_bytes = atomic_long_read(&stats->rx_bytes); +	dest->rx_seq_discards = atomic_long_read(&stats->rx_seq_discards); +	dest->rx_oos_packets = atomic_long_read(&stats->rx_oos_packets); +	dest->rx_errors = atomic_long_read(&stats->rx_errors);  }  /* Session ioctl helper. @@ -1665,14 +1627,14 @@ static void pppol2tp_seq_tunnel_show(struct seq_file *m, void *v)  		   tunnel->name,  		   (tunnel == tunnel->sock->sk_user_data) ? 'Y' : 'N',  		   atomic_read(&tunnel->ref_count) - 1); -	seq_printf(m, " %08x %llu/%llu/%llu %llu/%llu/%llu\n", +	seq_printf(m, " %08x %ld/%ld/%ld %ld/%ld/%ld\n",  		   tunnel->debug, -		   (unsigned long long)tunnel->stats.tx_packets, -		   (unsigned long long)tunnel->stats.tx_bytes, -		   (unsigned long long)tunnel->stats.tx_errors, -		   (unsigned long long)tunnel->stats.rx_packets, -		   (unsigned long long)tunnel->stats.rx_bytes, -		   (unsigned long long)tunnel->stats.rx_errors); +		   atomic_long_read(&tunnel->stats.tx_packets), +		   atomic_long_read(&tunnel->stats.tx_bytes), +		   atomic_long_read(&tunnel->stats.tx_errors), +		   atomic_long_read(&tunnel->stats.rx_packets), +		   atomic_long_read(&tunnel->stats.rx_bytes), +		   atomic_long_read(&tunnel->stats.rx_errors));  }  static void pppol2tp_seq_session_show(struct seq_file *m, void *v) @@ -1707,14 +1669,14 @@ static void pppol2tp_seq_session_show(struct seq_file *m, void *v)  		   session->lns_mode ? "LNS" : "LAC",  		   session->debug,  		   jiffies_to_msecs(session->reorder_timeout)); -	seq_printf(m, "   %hu/%hu %llu/%llu/%llu %llu/%llu/%llu\n", +	seq_printf(m, "   %hu/%hu %ld/%ld/%ld %ld/%ld/%ld\n",  		   session->nr, session->ns, -		   (unsigned long long)session->stats.tx_packets, -		   (unsigned long long)session->stats.tx_bytes, -		   (unsigned long long)session->stats.tx_errors, -		   (unsigned long long)session->stats.rx_packets, -		   (unsigned long long)session->stats.rx_bytes, -		   (unsigned long long)session->stats.rx_errors); +		   atomic_long_read(&session->stats.tx_packets), +		   atomic_long_read(&session->stats.tx_bytes), +		   atomic_long_read(&session->stats.tx_errors), +		   atomic_long_read(&session->stats.rx_packets), +		   atomic_long_read(&session->stats.rx_bytes), +		   atomic_long_read(&session->stats.rx_errors));  	if (po)  		seq_printf(m, "   interface %s\n", ppp_dev_name(&po->chan)); @@ -1838,7 +1800,7 @@ static const struct pppox_proto pppol2tp_proto = {  static const struct l2tp_nl_cmd_ops pppol2tp_nl_cmd_ops = {  	.session_create	= pppol2tp_session_create, -	.session_delete	= pppol2tp_session_delete, +	.session_delete	= l2tp_session_delete,  };  #endif /* CONFIG_L2TP_V3 */ diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 09d96a8f6c2..fb306814576 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -3285,6 +3285,7 @@ static int ieee80211_cfg_get_channel(struct wiphy *wiphy,  				     struct cfg80211_chan_def *chandef)  {  	struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); +	struct ieee80211_local *local = wiphy_priv(wiphy);  	struct ieee80211_chanctx_conf *chanctx_conf;  	int ret = -ENODATA; @@ -3293,6 +3294,16 @@ static int ieee80211_cfg_get_channel(struct wiphy *wiphy,  	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 2c059e54e88..baaa8608e52 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -107,7 +107,7 @@ void ieee80211_recalc_idle(struct ieee80211_local *local)  	lockdep_assert_held(&local->mtx); -	active = !list_empty(&local->chanctx_list); +	active = !list_empty(&local->chanctx_list) || local->monitors;  	if (!local->ops->remain_on_channel) {  		list_for_each_entry(roc, &local->roc_list, list) { @@ -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 de8548bf0a7..8914d2d2881 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1231,34 +1231,40 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local,  		if (local->queue_stop_reasons[q] ||  		    (!txpending && !skb_queue_empty(&local->pending[q]))) {  			if (unlikely(info->flags & -					IEEE80211_TX_INTFL_OFFCHAN_TX_OK && -				     local->queue_stop_reasons[q] & -					~BIT(IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL))) { +				     IEEE80211_TX_INTFL_OFFCHAN_TX_OK)) { +				if (local->queue_stop_reasons[q] & +				    ~BIT(IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL)) { +					/* +					 * Drop off-channel frames if queues +					 * are stopped for any reason other +					 * than off-channel operation. Never +					 * queue them. +					 */ +					spin_unlock_irqrestore( +						&local->queue_stop_reason_lock, +						flags); +					ieee80211_purge_tx_queue(&local->hw, +								 skbs); +					return true; +				} +			} else { +  				/* -				 * Drop off-channel frames if queues are stopped -				 * for any reason other than off-channel -				 * operation. Never queue them. +				 * Since queue is stopped, queue up frames for +				 * later transmission from the tx-pending +				 * tasklet when the queue is woken again.  				 */ -				spin_unlock_irqrestore( -					&local->queue_stop_reason_lock, flags); -				ieee80211_purge_tx_queue(&local->hw, skbs); -				return true; -			} - -			/* -			 * Since queue is stopped, queue up frames for later -			 * transmission from the tx-pending tasklet when the -			 * queue is woken again. -			 */ -			if (txpending) -				skb_queue_splice_init(skbs, &local->pending[q]); -			else -				skb_queue_splice_tail_init(skbs, -							   &local->pending[q]); +				if (txpending) +					skb_queue_splice_init(skbs, +							      &local->pending[q]); +				else +					skb_queue_splice_tail_init(skbs, +								   &local->pending[q]); -			spin_unlock_irqrestore(&local->queue_stop_reason_lock, -					       flags); -			return false; +				spin_unlock_irqrestore(&local->queue_stop_reason_lock, +						       flags); +				return false; +			}  		}  		spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); @@ -1844,9 +1850,24 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,  		}  		if (!is_multicast_ether_addr(skb->data)) { +			struct sta_info *next_hop; +			bool mpp_lookup = true; +  			mpath = mesh_path_lookup(sdata, skb->data); -			if (!mpath) +			if (mpath) { +				mpp_lookup = false; +				next_hop = rcu_dereference(mpath->next_hop); +				if (!next_hop || +				    !(mpath->flags & (MESH_PATH_ACTIVE | +						      MESH_PATH_RESOLVING))) +					mpp_lookup = true; +			} + +			if (mpp_lookup)  				mppath = mpp_path_lookup(sdata, skb->data); + +			if (mppath && mpath) +				mesh_path_del(mpath->sdata, mpath->dst);  		}  		/* @@ -2350,9 +2371,9 @@ static int ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,  	if (local->tim_in_locked_section) {  		__ieee80211_beacon_add_tim(sdata, ps, skb);  	} else { -		spin_lock(&local->tim_lock); +		spin_lock_bh(&local->tim_lock);  		__ieee80211_beacon_add_tim(sdata, ps, skb); -		spin_unlock(&local->tim_lock); +		spin_unlock_bh(&local->tim_lock);  	}  	return 0; @@ -2724,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/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c index f82b2e606cf..1ba9dbc0e10 100644 --- a/net/netfilter/ipset/ip_set_core.c +++ b/net/netfilter/ipset/ip_set_core.c @@ -1470,7 +1470,8 @@ ip_set_utest(struct sock *ctnl, struct sk_buff *skb,  	if (ret == -EAGAIN)  		ret = 1; -	return ret < 0 ? ret : ret > 0 ? 0 : -IPSET_ERR_EXIST; +	return (ret < 0 && ret != -ENOTEMPTY) ? ret : +		ret > 0 ? 0 : -IPSET_ERR_EXIST;  }  /* Get headed data of a set */ diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index 47edf5a40a5..61f49d24171 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c @@ -1394,10 +1394,8 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum)  			skb_reset_network_header(skb);  			IP_VS_DBG(12, "ICMP for IPIP %pI4->%pI4: mtu=%u\n",  				&ip_hdr(skb)->saddr, &ip_hdr(skb)->daddr, mtu); -			rcu_read_lock();  			ipv4_update_pmtu(skb, dev_net(skb->dev),  					 mtu, 0, 0, 0, 0); -			rcu_read_unlock();  			/* Client uses PMTUD? */  			if (!(cih->frag_off & htons(IP_DF)))  				goto ignore_ipip; @@ -1577,7 +1575,8 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)  	}  	/* ipvs enabled in this netns ? */  	net = skb_net(skb); -	if (!net_ipvs(net)->enable) +	ipvs = net_ipvs(net); +	if (unlikely(sysctl_backup_only(ipvs) || !ipvs->enable))  		return NF_ACCEPT;  	ip_vs_fill_iph_skb(af, skb, &iph); @@ -1654,7 +1653,6 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)  	}  	IP_VS_DBG_PKT(11, af, pp, skb, 0, "Incoming packet"); -	ipvs = net_ipvs(net);  	/* Check the server status */  	if (cp->dest && !(cp->dest->flags & IP_VS_DEST_F_AVAILABLE)) {  		/* the destination server is not available */ @@ -1815,13 +1813,15 @@ ip_vs_forward_icmp(unsigned int hooknum, struct sk_buff *skb,  {  	int r;  	struct net *net; +	struct netns_ipvs *ipvs;  	if (ip_hdr(skb)->protocol != IPPROTO_ICMP)  		return NF_ACCEPT;  	/* ipvs enabled in this netns ? */  	net = skb_net(skb); -	if (!net_ipvs(net)->enable) +	ipvs = net_ipvs(net); +	if (unlikely(sysctl_backup_only(ipvs) || !ipvs->enable))  		return NF_ACCEPT;  	return ip_vs_in_icmp(skb, &r, hooknum); @@ -1835,6 +1835,7 @@ ip_vs_forward_icmp_v6(unsigned int hooknum, struct sk_buff *skb,  {  	int r;  	struct net *net; +	struct netns_ipvs *ipvs;  	struct ip_vs_iphdr iphdr;  	ip_vs_fill_iph_skb(AF_INET6, skb, &iphdr); @@ -1843,7 +1844,8 @@ ip_vs_forward_icmp_v6(unsigned int hooknum, struct sk_buff *skb,  	/* ipvs enabled in this netns ? */  	net = skb_net(skb); -	if (!net_ipvs(net)->enable) +	ipvs = net_ipvs(net); +	if (unlikely(sysctl_backup_only(ipvs) || !ipvs->enable))  		return NF_ACCEPT;  	return ip_vs_in_icmp_v6(skb, &r, hooknum, &iphdr); diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index c68198bf912..9e2d1cccd1e 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -1808,6 +1808,12 @@ static struct ctl_table vs_vars[] = {  		.mode		= 0644,  		.proc_handler	= proc_dointvec,  	}, +	{ +		.procname	= "backup_only", +		.maxlen		= sizeof(int), +		.mode		= 0644, +		.proc_handler	= proc_dointvec, +	},  #ifdef CONFIG_IP_VS_DEBUG  	{  		.procname	= "debug_level", @@ -3741,6 +3747,7 @@ static int __net_init ip_vs_control_net_init_sysctl(struct net *net)  	tbl[idx++].data = &ipvs->sysctl_nat_icmp_send;  	ipvs->sysctl_pmtu_disc = 1;  	tbl[idx++].data = &ipvs->sysctl_pmtu_disc; +	tbl[idx++].data = &ipvs->sysctl_backup_only;  	ipvs->sysctl_hdr = register_net_sysctl(net, "net/ipv4/vs", tbl); diff --git a/net/netfilter/ipvs/ip_vs_proto_sctp.c b/net/netfilter/ipvs/ip_vs_proto_sctp.c index ae8ec6f2768..cd1d7298f7b 100644 --- a/net/netfilter/ipvs/ip_vs_proto_sctp.c +++ b/net/netfilter/ipvs/ip_vs_proto_sctp.c @@ -906,7 +906,7 @@ set_sctp_state(struct ip_vs_proto_data *pd, struct ip_vs_conn *cp,  	sctp_chunkhdr_t _sctpch, *sch;  	unsigned char chunk_type;  	int event, next_state; -	int ihl; +	int ihl, cofs;  #ifdef CONFIG_IP_VS_IPV6  	ihl = cp->af == AF_INET ? ip_hdrlen(skb) : sizeof(struct ipv6hdr); @@ -914,8 +914,8 @@ set_sctp_state(struct ip_vs_proto_data *pd, struct ip_vs_conn *cp,  	ihl = ip_hdrlen(skb);  #endif -	sch = skb_header_pointer(skb, ihl + sizeof(sctp_sctphdr_t), -				sizeof(_sctpch), &_sctpch); +	cofs = ihl + sizeof(sctp_sctphdr_t); +	sch = skb_header_pointer(skb, cofs, sizeof(_sctpch), &_sctpch);  	if (sch == NULL)  		return; @@ -933,10 +933,12 @@ set_sctp_state(struct ip_vs_proto_data *pd, struct ip_vs_conn *cp,  	 */  	if ((sch->type == SCTP_CID_COOKIE_ECHO) ||  	    (sch->type == SCTP_CID_COOKIE_ACK)) { -		sch = skb_header_pointer(skb, (ihl + sizeof(sctp_sctphdr_t) + -				sch->length), sizeof(_sctpch), &_sctpch); -		if (sch) { -			if (sch->type == SCTP_CID_ABORT) +		int clen = ntohs(sch->length); + +		if (clen >= sizeof(sctp_chunkhdr_t)) { +			sch = skb_header_pointer(skb, cofs + ALIGN(clen, 4), +						 sizeof(_sctpch), &_sctpch); +			if (sch && sch->type == SCTP_CID_ABORT)  				chunk_type = sch->type;  		}  	} 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/nf_conntrack_proto_dccp.c b/net/netfilter/nf_conntrack_proto_dccp.c index 432f9578000..ba65b2041eb 100644 --- a/net/netfilter/nf_conntrack_proto_dccp.c +++ b/net/netfilter/nf_conntrack_proto_dccp.c @@ -969,6 +969,10 @@ static int __init nf_conntrack_proto_dccp_init(void)  {  	int ret; +	ret = register_pernet_subsys(&dccp_net_ops); +	if (ret < 0) +		goto out_pernet; +  	ret = nf_ct_l4proto_register(&dccp_proto4);  	if (ret < 0)  		goto out_dccp4; @@ -977,16 +981,12 @@ static int __init nf_conntrack_proto_dccp_init(void)  	if (ret < 0)  		goto out_dccp6; -	ret = register_pernet_subsys(&dccp_net_ops); -	if (ret < 0) -		goto out_pernet; -  	return 0; -out_pernet: -	nf_ct_l4proto_unregister(&dccp_proto6);  out_dccp6:  	nf_ct_l4proto_unregister(&dccp_proto4);  out_dccp4: +	unregister_pernet_subsys(&dccp_net_ops); +out_pernet:  	return ret;  } diff --git a/net/netfilter/nf_conntrack_proto_gre.c b/net/netfilter/nf_conntrack_proto_gre.c index bd7d01d9c7e..155ce9f8a0d 100644 --- a/net/netfilter/nf_conntrack_proto_gre.c +++ b/net/netfilter/nf_conntrack_proto_gre.c @@ -420,18 +420,18 @@ static int __init nf_ct_proto_gre_init(void)  {  	int ret; -	ret = nf_ct_l4proto_register(&nf_conntrack_l4proto_gre4); -	if (ret < 0) -		goto out_gre4; -  	ret = register_pernet_subsys(&proto_gre_net_ops);  	if (ret < 0)  		goto out_pernet; +	ret = nf_ct_l4proto_register(&nf_conntrack_l4proto_gre4); +	if (ret < 0) +		goto out_gre4; +  	return 0; -out_pernet: -	nf_ct_l4proto_unregister(&nf_conntrack_l4proto_gre4);  out_gre4: +	unregister_pernet_subsys(&proto_gre_net_ops); +out_pernet:  	return ret;  } diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c index 480f616d593..ec83536def9 100644 --- a/net/netfilter/nf_conntrack_proto_sctp.c +++ b/net/netfilter/nf_conntrack_proto_sctp.c @@ -888,6 +888,10 @@ static int __init nf_conntrack_proto_sctp_init(void)  {  	int ret; +	ret = register_pernet_subsys(&sctp_net_ops); +	if (ret < 0) +		goto out_pernet; +  	ret = nf_ct_l4proto_register(&nf_conntrack_l4proto_sctp4);  	if (ret < 0)  		goto out_sctp4; @@ -896,16 +900,12 @@ static int __init nf_conntrack_proto_sctp_init(void)  	if (ret < 0)  		goto out_sctp6; -	ret = register_pernet_subsys(&sctp_net_ops); -	if (ret < 0) -		goto out_pernet; -  	return 0; -out_pernet: -	nf_ct_l4proto_unregister(&nf_conntrack_l4proto_sctp6);  out_sctp6:  	nf_ct_l4proto_unregister(&nf_conntrack_l4proto_sctp4);  out_sctp4: +	unregister_pernet_subsys(&sctp_net_ops); +out_pernet:  	return ret;  } diff --git a/net/netfilter/nf_conntrack_proto_udplite.c b/net/netfilter/nf_conntrack_proto_udplite.c index 157489581c3..ca969f6273f 100644 --- a/net/netfilter/nf_conntrack_proto_udplite.c +++ b/net/netfilter/nf_conntrack_proto_udplite.c @@ -371,6 +371,10 @@ static int __init nf_conntrack_proto_udplite_init(void)  {  	int ret; +	ret = register_pernet_subsys(&udplite_net_ops); +	if (ret < 0) +		goto out_pernet; +  	ret = nf_ct_l4proto_register(&nf_conntrack_l4proto_udplite4);  	if (ret < 0)  		goto out_udplite4; @@ -379,16 +383,12 @@ static int __init nf_conntrack_proto_udplite_init(void)  	if (ret < 0)  		goto out_udplite6; -	ret = register_pernet_subsys(&udplite_net_ops); -	if (ret < 0) -		goto out_pernet; -  	return 0; -out_pernet: -	nf_ct_l4proto_unregister(&nf_conntrack_l4proto_udplite6);  out_udplite6:  	nf_ct_l4proto_unregister(&nf_conntrack_l4proto_udplite4);  out_udplite4: +	unregister_pernet_subsys(&udplite_net_ops); +out_pernet:  	return ret;  } 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/nfnetlink_queue_core.c b/net/netfilter/nfnetlink_queue_core.c index 858fd52c104..1cb48540f86 100644 --- a/net/netfilter/nfnetlink_queue_core.c +++ b/net/netfilter/nfnetlink_queue_core.c @@ -112,7 +112,7 @@ instance_create(u_int16_t queue_num, int portid)  	inst->queue_num = queue_num;  	inst->peer_portid = portid;  	inst->queue_maxlen = NFQNL_QMAX_DEFAULT; -	inst->copy_range = 0xfffff; +	inst->copy_range = 0xffff;  	inst->copy_mode = NFQNL_COPY_NONE;  	spin_lock_init(&inst->lock);  	INIT_LIST_HEAD(&inst->queue_list); 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/netlink/genetlink.c b/net/netlink/genetlink.c index f2aabb6f410..5a55be3f17a 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -142,6 +142,7 @@ int genl_register_mc_group(struct genl_family *family,  	int err = 0;  	BUG_ON(grp->name[0] == '\0'); +	BUG_ON(memchr(grp->name, '\0', GENL_NAMSIZ) == NULL);  	genl_lock(); 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/message.c b/net/rds/message.c index f0a4658f327..aba232f9f30 100644 --- a/net/rds/message.c +++ b/net/rds/message.c @@ -82,10 +82,7 @@ static void rds_message_purge(struct rds_message *rm)  void rds_message_put(struct rds_message *rm)  {  	rdsdebug("put rm %p ref %d\n", rm, atomic_read(&rm->m_refcount)); -	if (atomic_read(&rm->m_refcount) == 0) { -printk(KERN_CRIT "danger refcount zero on %p\n", rm); -WARN_ON(1); -	} +	WARN(!atomic_read(&rm->m_refcount), "danger refcount zero on %p\n", rm);  	if (atomic_dec_and_test(&rm->m_refcount)) {  		BUG_ON(!list_empty(&rm->m_sock_item));  		BUG_ON(!list_empty(&rm->m_conn_item)); @@ -197,6 +194,9 @@ struct rds_message *rds_message_alloc(unsigned int extra_len, gfp_t gfp)  {  	struct rds_message *rm; +	if (extra_len > KMALLOC_MAX_SIZE - sizeof(struct rds_message)) +		return NULL; +  	rm = kzalloc(sizeof(struct rds_message) + extra_len, gfp);  	if (!rm)  		goto out; 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/endpointola.c b/net/sctp/endpointola.c index 2b3ef03c609..12ed45dbe75 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c @@ -155,7 +155,7 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,  	/* SCTP-AUTH extensions*/  	INIT_LIST_HEAD(&ep->endpoint_shared_keys); -	null_key = sctp_auth_shkey_create(0, GFP_KERNEL); +	null_key = sctp_auth_shkey_create(0, gfp);  	if (!null_key)  		goto nomem; 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/sctp/socket.c b/net/sctp/socket.c index c99458df3f3..b9070736b8d 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -5653,6 +5653,9 @@ static int sctp_getsockopt_assoc_stats(struct sock *sk, int len,  	if (len < sizeof(sctp_assoc_t))  		return -EINVAL; +	/* Allow the struct to grow and fill in as much as possible */ +	len = min_t(size_t, len, sizeof(sas)); +  	if (copy_from_user(&sas, optval, len))  		return -EFAULT; @@ -5686,9 +5689,6 @@ static int sctp_getsockopt_assoc_stats(struct sock *sk, int len,  	/* Mark beginning of a new observation period */  	asoc->stats.max_obs_rto = asoc->rto_min; -	/* Allow the struct to grow and fill in as much as possible */ -	len = min_t(size_t, len, sizeof(sas)); -  	if (put_user(len, optlen))  		return -EFAULT; diff --git a/net/sctp/ssnmap.c b/net/sctp/ssnmap.c index 442ad4ed631..825ea94415b 100644 --- a/net/sctp/ssnmap.c +++ b/net/sctp/ssnmap.c @@ -41,8 +41,6 @@  #include <net/sctp/sctp.h>  #include <net/sctp/sm.h> -#define MAX_KMALLOC_SIZE	131072 -  static struct sctp_ssnmap *sctp_ssnmap_init(struct sctp_ssnmap *map, __u16 in,  					    __u16 out); @@ -65,7 +63,7 @@ struct sctp_ssnmap *sctp_ssnmap_new(__u16 in, __u16 out,  	int size;  	size = sctp_ssnmap_size(in, out); -	if (size <= MAX_KMALLOC_SIZE) +	if (size <= KMALLOC_MAX_SIZE)  		retval = kmalloc(size, gfp);  	else  		retval = (struct sctp_ssnmap *) @@ -82,7 +80,7 @@ struct sctp_ssnmap *sctp_ssnmap_new(__u16 in, __u16 out,  	return retval;  fail_map: -	if (size <= MAX_KMALLOC_SIZE) +	if (size <= KMALLOC_MAX_SIZE)  		kfree(retval);  	else  		free_pages((unsigned long)retval, get_order(size)); @@ -124,7 +122,7 @@ void sctp_ssnmap_free(struct sctp_ssnmap *map)  		int size;  		size = sctp_ssnmap_size(map->in.len, map->out.len); -		if (size <= MAX_KMALLOC_SIZE) +		if (size <= KMALLOC_MAX_SIZE)  			kfree(map);  		else  			free_pages((unsigned long)map, get_order(size)); diff --git a/net/sctp/tsnmap.c b/net/sctp/tsnmap.c index 5f25e0c92c3..396c45174e5 100644 --- a/net/sctp/tsnmap.c +++ b/net/sctp/tsnmap.c @@ -51,7 +51,7 @@  static void sctp_tsnmap_update(struct sctp_tsnmap *map);  static void sctp_tsnmap_find_gap_ack(unsigned long *map, __u16 off,  				     __u16 len, __u16 *start, __u16 *end); -static int sctp_tsnmap_grow(struct sctp_tsnmap *map, u16 gap); +static int sctp_tsnmap_grow(struct sctp_tsnmap *map, u16 size);  /* Initialize a block of memory as a tsnmap.  */  struct sctp_tsnmap *sctp_tsnmap_init(struct sctp_tsnmap *map, __u16 len, @@ -124,7 +124,7 @@ int sctp_tsnmap_mark(struct sctp_tsnmap *map, __u32 tsn,  	gap = tsn - map->base_tsn; -	if (gap >= map->len && !sctp_tsnmap_grow(map, gap)) +	if (gap >= map->len && !sctp_tsnmap_grow(map, gap + 1))  		return -ENOMEM;  	if (!sctp_tsnmap_has_gap(map) && gap == 0) { @@ -360,23 +360,24 @@ __u16 sctp_tsnmap_num_gabs(struct sctp_tsnmap *map,  	return ngaps;  } -static int sctp_tsnmap_grow(struct sctp_tsnmap *map, u16 gap) +static int sctp_tsnmap_grow(struct sctp_tsnmap *map, u16 size)  {  	unsigned long *new;  	unsigned long inc;  	u16  len; -	if (gap >= SCTP_TSN_MAP_SIZE) +	if (size > SCTP_TSN_MAP_SIZE)  		return 0; -	inc = ALIGN((gap - map->len),BITS_PER_LONG) + SCTP_TSN_MAP_INCREMENT; +	inc = ALIGN((size - map->len), BITS_PER_LONG) + SCTP_TSN_MAP_INCREMENT;  	len = min_t(u16, map->len + inc, SCTP_TSN_MAP_SIZE);  	new = kzalloc(len>>3, GFP_ATOMIC);  	if (!new)  		return 0; -	bitmap_copy(new, map->tsn_map, map->max_tsn_seen - map->base_tsn); +	bitmap_copy(new, map->tsn_map, +		map->max_tsn_seen - map->cumulative_tsn_ack_point);  	kfree(map->tsn_map);  	map->tsn_map = new;  	map->len = len; diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c index ada17464b65..0fd5b3d2df0 100644 --- a/net/sctp/ulpqueue.c +++ b/net/sctp/ulpqueue.c @@ -106,6 +106,7 @@ int sctp_ulpq_tail_data(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk,  {  	struct sk_buff_head temp;  	struct sctp_ulpevent *event; +	int event_eor = 0;  	/* Create an event from the incoming chunk. */  	event = sctp_ulpevent_make_rcvmsg(chunk->asoc, chunk, gfp); @@ -127,10 +128,12 @@ int sctp_ulpq_tail_data(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk,  	/* Send event to the ULP.  'event' is the sctp_ulpevent for  	 * very first SKB on the 'temp' list.  	 */ -	if (event) +	if (event) { +		event_eor = (event->msg_flags & MSG_EOR) ? 1 : 0;  		sctp_ulpq_tail_event(ulpq, event); +	} -	return 0; +	return event_eor;  }  /* Add a new event for propagation to the ULP.  */ @@ -540,14 +543,19 @@ static struct sctp_ulpevent *sctp_ulpq_retrieve_partial(struct sctp_ulpq *ulpq)  		ctsn = cevent->tsn;  		switch (cevent->msg_flags & SCTP_DATA_FRAG_MASK) { +		case SCTP_DATA_FIRST_FRAG: +			if (!first_frag) +				return NULL; +			goto done;  		case SCTP_DATA_MIDDLE_FRAG:  			if (!first_frag) {  				first_frag = pos;  				next_tsn = ctsn + 1;  				last_frag = pos; -			} else if (next_tsn == ctsn) +			} else if (next_tsn == ctsn) {  				next_tsn++; -			else +				last_frag = pos; +			} else  				goto done;  			break;  		case SCTP_DATA_LAST_FRAG: @@ -651,6 +659,14 @@ static struct sctp_ulpevent *sctp_ulpq_retrieve_first(struct sctp_ulpq *ulpq)  			} else  				goto done;  			break; + +		case SCTP_DATA_LAST_FRAG: +			if (!first_frag) +				return NULL; +			else +				goto done; +			break; +  		default:  			return NULL;  		} @@ -962,20 +978,43 @@ static __u16 sctp_ulpq_renege_list(struct sctp_ulpq *ulpq,  		struct sk_buff_head *list, __u16 needed)  {  	__u16 freed = 0; -	__u32 tsn; -	struct sk_buff *skb; +	__u32 tsn, last_tsn; +	struct sk_buff *skb, *flist, *last;  	struct sctp_ulpevent *event;  	struct sctp_tsnmap *tsnmap;  	tsnmap = &ulpq->asoc->peer.tsn_map; -	while ((skb = __skb_dequeue_tail(list)) != NULL) { -		freed += skb_headlen(skb); +	while ((skb = skb_peek_tail(list)) != NULL) {  		event = sctp_skb2event(skb);  		tsn = event->tsn; +		/* Don't renege below the Cumulative TSN ACK Point. */ +		if (TSN_lte(tsn, sctp_tsnmap_get_ctsn(tsnmap))) +			break; + +		/* Events in ordering queue may have multiple fragments +		 * corresponding to additional TSNs.  Sum the total +		 * freed space; find the last TSN. +		 */ +		freed += skb_headlen(skb); +		flist = skb_shinfo(skb)->frag_list; +		for (last = flist; flist; flist = flist->next) { +			last = flist; +			freed += skb_headlen(last); +		} +		if (last) +			last_tsn = sctp_skb2event(last)->tsn; +		else +			last_tsn = tsn; + +		/* Unlink the event, then renege all applicable TSNs. */ +		__skb_unlink(skb, list);  		sctp_ulpevent_free(event); -		sctp_tsnmap_renege(tsnmap, tsn); +		while (TSN_lte(tsn, last_tsn)) { +			sctp_tsnmap_renege(tsnmap, tsn); +			tsn++; +		}  		if (freed >= needed)  			return freed;  	} @@ -1002,16 +1041,28 @@ void sctp_ulpq_partial_delivery(struct sctp_ulpq *ulpq,  	struct sctp_ulpevent *event;  	struct sctp_association *asoc;  	struct sctp_sock *sp; +	__u32 ctsn; +	struct sk_buff *skb;  	asoc = ulpq->asoc;  	sp = sctp_sk(asoc->base.sk);  	/* If the association is already in Partial Delivery mode -	 * we have noting to do. +	 * we have nothing to do.  	 */  	if (ulpq->pd_mode)  		return; +	/* Data must be at or below the Cumulative TSN ACK Point to +	 * start partial delivery. +	 */ +	skb = skb_peek(&asoc->ulpq.reasm); +	if (skb != NULL) { +		ctsn = sctp_skb2event(skb)->tsn; +		if (!TSN_lte(ctsn, sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map))) +			return; +	} +  	/* If the user enabled fragment interleave socket option,  	 * multiple associations can enter partial delivery.  	 * Otherwise, we can only enter partial delivery if the @@ -1054,12 +1105,16 @@ void sctp_ulpq_renege(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk,  	}  	/* If able to free enough room, accept this chunk. */  	if (chunk && (freed >= needed)) { -		__u32 tsn; -		tsn = ntohl(chunk->subh.data_hdr->tsn); -		sctp_tsnmap_mark(&asoc->peer.tsn_map, tsn, chunk->transport); -		sctp_ulpq_tail_data(ulpq, chunk, gfp); - -		sctp_ulpq_partial_delivery(ulpq, gfp); +		int retval; +		retval = sctp_ulpq_tail_data(ulpq, chunk, gfp); +		/* +		 * Enter partial delivery if chunk has not been +		 * delivered; otherwise, drain the reassembly queue. +		 */ +		if (retval <= 0) +			sctp_ulpq_partial_delivery(ulpq, gfp); +		else if (retval == 1) +			sctp_ulpq_reasm_drain(ulpq);  	}  	sk_mem_reclaim(asoc->base.sk); 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 7b9b40224a2..a9129f8d707 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -1174,6 +1174,8 @@ static struct file_system_type rpc_pipe_fs_type = {  	.mount		= rpc_mount,  	.kill_sb	= rpc_kill_sb,  }; +MODULE_ALIAS_FS("rpc_pipefs"); +MODULE_ALIAS("rpc_pipefs");  static void  init_once(void *foo) @@ -1218,6 +1220,3 @@ void unregister_rpc_pipefs(void)  	kmem_cache_destroy(rpc_inode_cachep);  	unregister_filesystem(&rpc_pipe_fs_type);  } - -/* Make 'mount -t rpc_pipefs ...' autoload this module. */ -MODULE_ALIAS("rpc_pipefs"); diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index fb20f25ddec..f8529fc8e54 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -180,6 +180,8 @@ static void __rpc_add_wait_queue(struct rpc_wait_queue *queue,  		list_add_tail(&task->u.tk_wait.list, &queue->tasks[0]);  	task->tk_waitqueue = queue;  	queue->qlen++; +	/* barrier matches the read in rpc_wake_up_task_queue_locked() */ +	smp_wmb();  	rpc_set_queued(task);  	dprintk("RPC: %5u added to queue %p \"%s\"\n", @@ -430,8 +432,11 @@ static void __rpc_do_wake_up_task(struct rpc_wait_queue *queue, struct rpc_task   */  static void rpc_wake_up_task_queue_locked(struct rpc_wait_queue *queue, struct rpc_task *task)  { -	if (RPC_IS_QUEUED(task) && task->tk_waitqueue == queue) -		__rpc_do_wake_up_task(queue, task); +	if (RPC_IS_QUEUED(task)) { +		smp_rmb(); +		if (task->tk_waitqueue == queue) +			__rpc_do_wake_up_task(queue, task); +	}  }  /* 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/unix/af_unix.c b/net/unix/af_unix.c index 51be64f163e..971282b6f6a 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -382,7 +382,7 @@ static void unix_sock_destructor(struct sock *sk)  #endif  } -static int unix_release_sock(struct sock *sk, int embrion) +static void unix_release_sock(struct sock *sk, int embrion)  {  	struct unix_sock *u = unix_sk(sk);  	struct path path; @@ -451,8 +451,6 @@ static int unix_release_sock(struct sock *sk, int embrion)  	if (unix_tot_inflight)  		unix_gc();		/* Garbage collect fds */ - -	return 0;  }  static void init_peercred(struct sock *sk) @@ -699,9 +697,10 @@ static int unix_release(struct socket *sock)  	if (!sk)  		return 0; +	unix_release_sock(sk, 0);  	sock->sk = NULL; -	return unix_release_sock(sk, 0); +	return 0;  }  static int unix_autobind(struct socket *sock) @@ -1413,8 +1412,8 @@ static void maybe_add_creds(struct sk_buff *skb, const struct socket *sock,  	if (UNIXCB(skb).cred)  		return;  	if (test_bit(SOCK_PASSCRED, &sock->flags) || -	    !other->sk_socket || -	    test_bit(SOCK_PASSCRED, &other->sk_socket->flags)) { +	    (other->sk_socket && +	    test_bit(SOCK_PASSCRED, &other->sk_socket->flags))) {  		UNIXCB(skb).pid  = get_pid(task_tgid(current));  		UNIXCB(skb).cred = get_current_cred();  	} 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 35545ccc30f..d44ab216c0e 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -554,27 +554,8 @@ static int nl80211_msg_put_channel(struct sk_buff *msg,  	if ((chan->flags & IEEE80211_CHAN_NO_IBSS) &&  	    nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_IBSS))  		goto nla_put_failure; -	if (chan->flags & IEEE80211_CHAN_RADAR) { -		u32 time = elapsed_jiffies_msecs(chan->dfs_state_entered); -		if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR)) -			goto nla_put_failure; -		if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_STATE, -				chan->dfs_state)) -			goto nla_put_failure; -		if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_TIME, time)) -			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)) +	if ((chan->flags & IEEE80211_CHAN_RADAR) && +	    nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR))  		goto nla_put_failure;  	if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER, @@ -900,9 +881,6 @@ static int nl80211_put_iface_combinations(struct wiphy *wiphy,  		    nla_put_u32(msg, NL80211_IFACE_COMB_MAXNUM,  				c->max_interfaces))  			goto nla_put_failure; -		if (nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS, -				c->radar_detect_widths)) -			goto nla_put_failure;  		nla_nest_end(msg, nl_combi);  	} @@ -914,48 +892,6 @@ nla_put_failure:  	return -ENOBUFS;  } -#ifdef CONFIG_PM -static int nl80211_send_wowlan_tcp_caps(struct cfg80211_registered_device *rdev, -					struct sk_buff *msg) -{ -	const struct wiphy_wowlan_tcp_support *tcp = rdev->wiphy.wowlan.tcp; -	struct nlattr *nl_tcp; - -	if (!tcp) -		return 0; - -	nl_tcp = nla_nest_start(msg, NL80211_WOWLAN_TRIG_TCP_CONNECTION); -	if (!nl_tcp) -		return -ENOBUFS; - -	if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD, -			tcp->data_payload_max)) -		return -ENOBUFS; - -	if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD, -			tcp->data_payload_max)) -		return -ENOBUFS; - -	if (tcp->seq && nla_put_flag(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ)) -		return -ENOBUFS; - -	if (tcp->tok && nla_put(msg, NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN, -				sizeof(*tcp->tok), tcp->tok)) -		return -ENOBUFS; - -	if (nla_put_u32(msg, NL80211_WOWLAN_TCP_DATA_INTERVAL, -			tcp->data_interval_max)) -		return -ENOBUFS; - -	if (nla_put_u32(msg, NL80211_WOWLAN_TCP_WAKE_PAYLOAD, -			tcp->wake_payload_max)) -		return -ENOBUFS; - -	nla_nest_end(msg, nl_tcp); -	return 0; -} -#endif -  static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flags,  			      struct cfg80211_registered_device *dev)  { @@ -1330,9 +1266,6 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flag  				goto nla_put_failure;  		} -		if (nl80211_send_wowlan_tcp_caps(dev, msg)) -			goto nla_put_failure; -  		nla_nest_end(msg, nl_wowlan);  	}  #endif @@ -1365,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: @@ -1383,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; @@ -1393,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;  		} @@ -1412,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;  |