diff options
Diffstat (limited to 'net')
33 files changed, 208 insertions, 116 deletions
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 5ad7da21747..3c094e78dde 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -29,6 +29,7 @@  #include <net/bluetooth/bluetooth.h>  #include <net/bluetooth/hci_core.h>  #include <net/bluetooth/a2mp.h> +#include <net/bluetooth/smp.h>  static void hci_le_connect(struct hci_conn *conn)  { @@ -619,6 +620,9 @@ int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)  {  	BT_DBG("hcon %p", conn); +	if (conn->type == LE_LINK) +		return smp_conn_security(conn, sec_level); +  	/* For sdp we don't need the link key. */  	if (sec_level == BT_SECURITY_SDP)  		return 1; diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index daa149b7003..4ea1710a478 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -1199,14 +1199,15 @@ clean:  static void l2cap_conn_ready(struct l2cap_conn *conn)  {  	struct l2cap_chan *chan; +	struct hci_conn *hcon = conn->hcon;  	BT_DBG("conn %p", conn); -	if (!conn->hcon->out && conn->hcon->type == LE_LINK) +	if (!hcon->out && hcon->type == LE_LINK)  		l2cap_le_conn_ready(conn); -	if (conn->hcon->out && conn->hcon->type == LE_LINK) -		smp_conn_security(conn, conn->hcon->pending_sec_level); +	if (hcon->out && hcon->type == LE_LINK) +		smp_conn_security(hcon, hcon->pending_sec_level);  	mutex_lock(&conn->chan_lock); @@ -1219,8 +1220,8 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)  			continue;  		} -		if (conn->hcon->type == LE_LINK) { -			if (smp_conn_security(conn, chan->sec_level)) +		if (hcon->type == LE_LINK) { +			if (smp_conn_security(hcon, chan->sec_level))  				l2cap_chan_ready(chan);  		} else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 1497edd191a..34bbe1c5e38 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -616,7 +616,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch  				break;  			} -			if (smp_conn_security(conn, sec.level)) +			if (smp_conn_security(conn->hcon, sec.level))  				break;  			sk->sk_state = BT_CONFIG;  			chan->state = BT_CONFIG; diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 901a616c808..8c225ef349c 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -267,10 +267,10 @@ static void smp_failure(struct l2cap_conn *conn, u8 reason, u8 send)  	mgmt_auth_failed(conn->hcon->hdev, conn->dst, hcon->type,  			 hcon->dst_type, reason); -	if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) { -		cancel_delayed_work_sync(&conn->security_timer); +	cancel_delayed_work_sync(&conn->security_timer); + +	if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))  		smp_chan_destroy(conn); -	}  }  #define JUST_WORKS	0x00 @@ -760,9 +760,9 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)  	return 0;  } -int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level) +int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)  { -	struct hci_conn *hcon = conn->hcon; +	struct l2cap_conn *conn = hcon->l2cap_data;  	struct smp_chan *smp = conn->smp_chan;  	__u8 authreq; diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c index f88ee537fb2..92de5e5f9db 100644 --- a/net/bridge/netfilter/ebt_log.c +++ b/net/bridge/netfilter/ebt_log.c @@ -80,7 +80,7 @@ ebt_log_packet(u_int8_t pf, unsigned int hooknum,  	unsigned int bitmask;  	spin_lock_bh(&ebt_log_lock); -	printk("<%c>%s IN=%s OUT=%s MAC source = %pM MAC dest = %pM proto = 0x%04x", +	printk(KERN_SOH "%c%s IN=%s OUT=%s MAC source = %pM MAC dest = %pM proto = 0x%04x",  	       '0' + loginfo->u.log.level, prefix,  	       in ? in->name : "", out ? out->name : "",  	       eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest, diff --git a/net/caif/cfsrvl.c b/net/caif/cfsrvl.c index dd485f6128e..ba217e90765 100644 --- a/net/caif/cfsrvl.c +++ b/net/caif/cfsrvl.c @@ -211,9 +211,10 @@ void caif_client_register_refcnt(struct cflayer *adapt_layer,  					void (*put)(struct cflayer *lyr))  {  	struct cfsrvl *service; -	service = container_of(adapt_layer->dn, struct cfsrvl, layer); -	WARN_ON(adapt_layer == NULL || adapt_layer->dn == NULL); +	if (WARN_ON(adapt_layer == NULL || adapt_layer->dn == NULL)) +		return; +	service = container_of(adapt_layer->dn, struct cfsrvl, layer);  	service->hold = hold;  	service->put = put;  } diff --git a/net/core/dev.c b/net/core/dev.c index 83988362805..d7fe32c946c 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2647,15 +2647,16 @@ void __skb_get_rxhash(struct sk_buff *skb)  	if (!skb_flow_dissect(skb, &keys))  		return; -	if (keys.ports) { -		if ((__force u16)keys.port16[1] < (__force u16)keys.port16[0]) -			swap(keys.port16[0], keys.port16[1]); +	if (keys.ports)  		skb->l4_rxhash = 1; -	}  	/* get a consistent hash (same value on both flow directions) */ -	if ((__force u32)keys.dst < (__force u32)keys.src) +	if (((__force u32)keys.dst < (__force u32)keys.src) || +	    (((__force u32)keys.dst == (__force u32)keys.src) && +	     ((__force u16)keys.port16[1] < (__force u16)keys.port16[0]))) {  		swap(keys.dst, keys.src); +		swap(keys.port16[0], keys.port16[1]); +	}  	hash = jhash_3words((__force u32)keys.dst,  			    (__force u32)keys.src, diff --git a/net/core/pktgen.c b/net/core/pktgen.c index cce9e53528b..148e73d2c45 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -2721,7 +2721,7 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,  	/* Eth + IPh + UDPh + mpls */  	datalen = pkt_dev->cur_pkt_size - 14 - 20 - 8 -  		  pkt_dev->pkt_overhead; -	if (datalen < sizeof(struct pktgen_hdr)) +	if (datalen < 0 || datalen < sizeof(struct pktgen_hdr))  		datalen = sizeof(struct pktgen_hdr);  	udph->source = htons(pkt_dev->cur_udp_src); diff --git a/net/core/sock.c b/net/core/sock.c index 8f67ced8d6a..30579207612 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1523,7 +1523,14 @@ EXPORT_SYMBOL(sock_rfree);  void sock_edemux(struct sk_buff *skb)  { -	sock_put(skb->sk); +	struct sock *sk = skb->sk; + +#ifdef CONFIG_INET +	if (sk->sk_state == TCP_TIME_WAIT) +		inet_twsk_put(inet_twsk(sk)); +	else +#endif +		sock_put(sk);  }  EXPORT_SYMBOL(sock_edemux); diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 6f6d1aca3c3..2814f66dac6 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1226,6 +1226,11 @@ try_again:  	if (unlikely(err)) {  		trace_kfree_skb(skb, udp_recvmsg); +		if (!peeked) { +			atomic_inc(&sk->sk_drops); +			UDP_INC_STATS_USER(sock_net(sk), +					   UDP_MIB_INERRORS, is_udplite); +		}  		goto out_free;  	} diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index a3e60cc04a8..acd32e3f1b6 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -403,8 +403,9 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,  		tp->mtu_info = ntohl(info);  		if (!sock_owned_by_user(sk))  			tcp_v6_mtu_reduced(sk); -		else -			set_bit(TCP_MTU_REDUCED_DEFERRED, &tp->tsq_flags); +		else if (!test_and_set_bit(TCP_MTU_REDUCED_DEFERRED, +					   &tp->tsq_flags)) +			sock_hold(sk);  		goto out;  	} diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 99d0077b56b..07e2bfef684 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -394,6 +394,17 @@ try_again:  	}  	if (unlikely(err)) {  		trace_kfree_skb(skb, udpv6_recvmsg); +		if (!peeked) { +			atomic_inc(&sk->sk_drops); +			if (is_udp4) +				UDP_INC_STATS_USER(sock_net(sk), +						   UDP_MIB_INERRORS, +						   is_udplite); +			else +				UDP6_INC_STATS_USER(sock_net(sk), +						    UDP_MIB_INERRORS, +						    is_udplite); +		}  		goto out_free;  	}  	if (!peeked) { diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index 513cab08a98..1a9f3723c13 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c @@ -1501,6 +1501,8 @@ out:  	return err;  } +static struct lock_class_key l2tp_socket_class; +  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)  {  	struct l2tp_tunnel *tunnel = NULL; @@ -1605,6 +1607,8 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32  	tunnel->old_sk_destruct = sk->sk_destruct;  	sk->sk_destruct = &l2tp_tunnel_destruct;  	tunnel->sock = sk; +	lockdep_set_class_and_name(&sk->sk_lock.slock, &l2tp_socket_class, "l2tp_sock"); +  	sk->sk_allocation = GFP_ATOMIC;  	/* Add tunnel to our list */ diff --git a/net/l2tp/l2tp_eth.c b/net/l2tp/l2tp_eth.c index f9ee74deeac..3bfb34aaee2 100644 --- a/net/l2tp/l2tp_eth.c +++ b/net/l2tp/l2tp_eth.c @@ -153,7 +153,7 @@ static void l2tp_eth_dev_recv(struct l2tp_session *session, struct sk_buff *skb,  		print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, skb->data, length);  	} -	if (!pskb_may_pull(skb, sizeof(ETH_HLEN))) +	if (!pskb_may_pull(skb, ETH_HLEN))  		goto error;  	secpath_reset(skb); diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index d41974aacf5..a58c0b649ba 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1378,6 +1378,8 @@ static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop,  	else  		memset(next_hop, 0, ETH_ALEN); +	memset(pinfo, 0, sizeof(*pinfo)); +  	pinfo->generation = mesh_paths_generation;  	pinfo->filled = MPATH_INFO_FRAME_QLEN | @@ -1396,7 +1398,6 @@ static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop,  	pinfo->discovery_timeout =  			jiffies_to_msecs(mpath->discovery_timeout);  	pinfo->discovery_retries = mpath->discovery_retries; -	pinfo->flags = 0;  	if (mpath->flags & MESH_PATH_ACTIVE)  		pinfo->flags |= NL80211_MPATH_FLAG_ACTIVE;  	if (mpath->flags & MESH_PATH_RESOLVING) @@ -1405,10 +1406,8 @@ static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop,  		pinfo->flags |= NL80211_MPATH_FLAG_SN_VALID;  	if (mpath->flags & MESH_PATH_FIXED)  		pinfo->flags |= NL80211_MPATH_FLAG_FIXED; -	if (mpath->flags & MESH_PATH_RESOLVING) -		pinfo->flags |= NL80211_MPATH_FLAG_RESOLVING; - -	pinfo->flags = mpath->flags; +	if (mpath->flags & MESH_PATH_RESOLVED) +		pinfo->flags |= NL80211_MPATH_FLAG_RESOLVED;  }  static int ieee80211_get_mpath(struct wiphy *wiphy, struct net_device *dev, diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index a4a5acdbaa4..f76b83341cf 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -3248,6 +3248,8 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,  	goto out_unlock;   err_clear: +	memset(ifmgd->bssid, 0, ETH_ALEN); +	ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);  	ifmgd->auth_data = NULL;   err_free:  	kfree(auth_data); @@ -3439,6 +3441,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,  	err = 0;  	goto out;   err_clear: +	memset(ifmgd->bssid, 0, ETH_ALEN); +	ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);  	ifmgd->assoc_data = NULL;   err_free:  	kfree(assoc_data); diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index a5ac11ebef3..e046b3756aa 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c @@ -158,21 +158,18 @@ static const u8 tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = {   *	sCL -> sSS   */  /* 	     sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2	*/ -/*synack*/ { sIV, sIV, sIG, sIG, sIG, sIG, sIG, sIG, sIG, sSR }, +/*synack*/ { sIV, sIV, sSR, sIV, sIV, sIV, sIV, sIV, sIV, sSR },  /*   *	sNO -> sIV	Too late and no reason to do anything   *	sSS -> sIV	Client can't send SYN and then SYN/ACK   *	sS2 -> sSR	SYN/ACK sent to SYN2 in simultaneous open - *	sSR -> sIG - *	sES -> sIG	Error: SYNs in window outside the SYN_SENT state - *			are errors. Receiver will reply with RST - *			and close the connection. - *			Or we are not in sync and hold a dead connection. - *	sFW -> sIG - *	sCW -> sIG - *	sLA -> sIG - *	sTW -> sIG - *	sCL -> sIG + *	sSR -> sSR	Late retransmitted SYN/ACK in simultaneous open + *	sES -> sIV	Invalid SYN/ACK packets sent by the client + *	sFW -> sIV + *	sCW -> sIV + *	sLA -> sIV + *	sTW -> sIV + *	sCL -> sIV   */  /* 	     sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2	*/  /*fin*/    { sIV, sIV, sFW, sFW, sLA, sLA, sLA, sTW, sCL, sIV }, @@ -633,15 +630,9 @@ static bool tcp_in_window(const struct nf_conn *ct,  		ack = sack = receiver->td_end;  	} -	if (seq == end -	    && (!tcph->rst -		|| (seq == 0 && state->state == TCP_CONNTRACK_SYN_SENT))) +	if (tcph->rst && seq == 0 && state->state == TCP_CONNTRACK_SYN_SENT)  		/* -		 * Packets contains no data: we assume it is valid -		 * and check the ack value only. -		 * However RST segments are always validated by their -		 * SEQ number, except when seq == 0 (reset sent answering -		 * SYN. +		 * RST sent answering SYN.  		 */  		seq = end = sender->td_end; diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 14e2f390314..5cfb5bedb2b 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -381,6 +381,7 @@ __build_packet_message(struct nfulnl_instance *inst,  	struct nlmsghdr *nlh;  	struct nfgenmsg *nfmsg;  	sk_buff_data_t old_tail = inst->skb->tail; +	struct sock *sk;  	nlh = nlmsg_put(inst->skb, 0, 0,  			NFNL_SUBSYS_ULOG << 8 | NFULNL_MSG_PACKET, @@ -499,18 +500,19 @@ __build_packet_message(struct nfulnl_instance *inst,  	}  	/* UID */ -	if (skb->sk) { -		read_lock_bh(&skb->sk->sk_callback_lock); -		if (skb->sk->sk_socket && skb->sk->sk_socket->file) { -			struct file *file = skb->sk->sk_socket->file; +	sk = skb->sk; +	if (sk && sk->sk_state != TCP_TIME_WAIT) { +		read_lock_bh(&sk->sk_callback_lock); +		if (sk->sk_socket && sk->sk_socket->file) { +			struct file *file = sk->sk_socket->file;  			__be32 uid = htonl(file->f_cred->fsuid);  			__be32 gid = htonl(file->f_cred->fsgid); -			read_unlock_bh(&skb->sk->sk_callback_lock); +			read_unlock_bh(&sk->sk_callback_lock);  			if (nla_put_be32(inst->skb, NFULA_UID, uid) ||  			    nla_put_be32(inst->skb, NFULA_GID, gid))  				goto nla_put_failure;  		} else -			read_unlock_bh(&skb->sk->sk_callback_lock); +			read_unlock_bh(&sk->sk_callback_lock);  	}  	/* local sequence number */ diff --git a/net/netfilter/xt_LOG.c b/net/netfilter/xt_LOG.c index ff5f75fddb1..91e9af4d1f4 100644 --- a/net/netfilter/xt_LOG.c +++ b/net/netfilter/xt_LOG.c @@ -145,6 +145,19 @@ static int dump_tcp_header(struct sbuff *m, const struct sk_buff *skb,  	return 0;  } +static void dump_sk_uid_gid(struct sbuff *m, struct sock *sk) +{ +	if (!sk || sk->sk_state == TCP_TIME_WAIT) +		return; + +	read_lock_bh(&sk->sk_callback_lock); +	if (sk->sk_socket && sk->sk_socket->file) +		sb_add(m, "UID=%u GID=%u ", +			sk->sk_socket->file->f_cred->fsuid, +			sk->sk_socket->file->f_cred->fsgid); +	read_unlock_bh(&sk->sk_callback_lock); +} +  /* One level of recursion won't kill us */  static void dump_ipv4_packet(struct sbuff *m,  			const struct nf_loginfo *info, @@ -361,14 +374,8 @@ static void dump_ipv4_packet(struct sbuff *m,  	}  	/* Max length: 15 "UID=4294967295 " */ -	if ((logflags & XT_LOG_UID) && !iphoff && skb->sk) { -		read_lock_bh(&skb->sk->sk_callback_lock); -		if (skb->sk->sk_socket && skb->sk->sk_socket->file) -			sb_add(m, "UID=%u GID=%u ", -				skb->sk->sk_socket->file->f_cred->fsuid, -				skb->sk->sk_socket->file->f_cred->fsgid); -		read_unlock_bh(&skb->sk->sk_callback_lock); -	} +	if ((logflags & XT_LOG_UID) && !iphoff) +		dump_sk_uid_gid(m, skb->sk);  	/* Max length: 16 "MARK=0xFFFFFFFF " */  	if (!iphoff && skb->mark) @@ -436,8 +443,8 @@ log_packet_common(struct sbuff *m,  		  const struct nf_loginfo *loginfo,  		  const char *prefix)  { -	sb_add(m, "<%d>%sIN=%s OUT=%s ", loginfo->u.log.level, -	       prefix, +	sb_add(m, KERN_SOH "%c%sIN=%s OUT=%s ", +	       '0' + loginfo->u.log.level, prefix,  	       in ? in->name : "",  	       out ? out->name : "");  #ifdef CONFIG_BRIDGE_NETFILTER @@ -717,14 +724,8 @@ static void dump_ipv6_packet(struct sbuff *m,  	}  	/* Max length: 15 "UID=4294967295 " */ -	if ((logflags & XT_LOG_UID) && recurse && skb->sk) { -		read_lock_bh(&skb->sk->sk_callback_lock); -		if (skb->sk->sk_socket && skb->sk->sk_socket->file) -			sb_add(m, "UID=%u GID=%u ", -				skb->sk->sk_socket->file->f_cred->fsuid, -				skb->sk->sk_socket->file->f_cred->fsgid); -		read_unlock_bh(&skb->sk->sk_callback_lock); -	} +	if ((logflags & XT_LOG_UID) && recurse) +		dump_sk_uid_gid(m, skb->sk);  	/* Max length: 16 "MARK=0xFFFFFFFF " */  	if (!recurse && skb->mark) diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index 06592d8b4a2..1b9024ee963 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c @@ -1169,7 +1169,12 @@ static int nr_recvmsg(struct kiocb *iocb, struct socket *sock,  		msg->msg_flags |= MSG_TRUNC;  	} -	skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); +	er = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); +	if (er < 0) { +		skb_free_datagram(sk, skb); +		release_sock(sk); +		return er; +	}  	if (sax != NULL) {  		sax->sax25_family = AF_NETROM; diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c index f3f96badf5a..954405ceae9 100644 --- a/net/openvswitch/actions.c +++ b/net/openvswitch/actions.c @@ -45,7 +45,7 @@ static int make_writable(struct sk_buff *skb, int write_len)  	return pskb_expand_head(skb, 0, 0, GFP_ATOMIC);  } -/* remove VLAN header from packet and update csum accrodingly. */ +/* remove VLAN header from packet and update csum accordingly. */  static int __pop_vlan_tci(struct sk_buff *skb, __be16 *current_tci)  {  	struct vlan_hdr *vhdr; diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index d8277d29e71..cf58cedad08 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c @@ -425,10 +425,10 @@ static int validate_sample(const struct nlattr *attr,  static int validate_tp_port(const struct sw_flow_key *flow_key)  {  	if (flow_key->eth.type == htons(ETH_P_IP)) { -		if (flow_key->ipv4.tp.src && flow_key->ipv4.tp.dst) +		if (flow_key->ipv4.tp.src || flow_key->ipv4.tp.dst)  			return 0;  	} else if (flow_key->eth.type == htons(ETH_P_IPV6)) { -		if (flow_key->ipv6.tp.src && flow_key->ipv6.tp.dst) +		if (flow_key->ipv6.tp.src || flow_key->ipv6.tp.dst)  			return 0;  	} @@ -460,7 +460,7 @@ static int validate_set(const struct nlattr *a,  		if (flow_key->eth.type != htons(ETH_P_IP))  			return -EINVAL; -		if (!flow_key->ipv4.addr.src || !flow_key->ipv4.addr.dst) +		if (!flow_key->ip.proto)  			return -EINVAL;  		ipv4_key = nla_data(ovs_key); diff --git a/net/openvswitch/flow.h b/net/openvswitch/flow.h index 9b75617ca4e..c30df1a10c6 100644 --- a/net/openvswitch/flow.h +++ b/net/openvswitch/flow.h @@ -145,15 +145,17 @@ u64 ovs_flow_used_time(unsigned long flow_jiffies);   *  OVS_KEY_ATTR_PRIORITY      4    --     4      8   *  OVS_KEY_ATTR_IN_PORT       4    --     4      8   *  OVS_KEY_ATTR_ETHERNET     12    --     4     16 + *  OVS_KEY_ATTR_ETHERTYPE     2     2     4      8  (outer VLAN ethertype)   *  OVS_KEY_ATTR_8021Q         4    --     4      8 - *  OVS_KEY_ATTR_ETHERTYPE     2     2     4      8 + *  OVS_KEY_ATTR_ENCAP         0    --     4      4  (VLAN encapsulation) + *  OVS_KEY_ATTR_ETHERTYPE     2     2     4      8  (inner VLAN ethertype)   *  OVS_KEY_ATTR_IPV6         40    --     4     44   *  OVS_KEY_ATTR_ICMPV6        2     2     4      8   *  OVS_KEY_ATTR_ND           28    --     4     32   *  ------------------------------------------------- - *  total                                       132 + *  total                                       144   */ -#define FLOW_BUFSIZE 132 +#define FLOW_BUFSIZE 144  int ovs_flow_to_nlattrs(const struct sw_flow_key *, struct sk_buff *);  int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp, diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c index 6aabd77d1cf..564b9fc8efd 100644 --- a/net/sched/sch_cbq.c +++ b/net/sched/sch_cbq.c @@ -250,10 +250,11 @@ cbq_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)  			else if ((cl = defmap[res.classid & TC_PRIO_MAX]) == NULL)  				cl = defmap[TC_PRIO_BESTEFFORT]; -			if (cl == NULL || cl->level >= head->level) +			if (cl == NULL)  				goto fallback;  		} - +		if (cl->level >= head->level) +			goto fallback;  #ifdef CONFIG_NET_CLS_ACT  		switch (result) {  		case TC_ACT_QUEUED: diff --git a/net/sched/sch_fq_codel.c b/net/sched/sch_fq_codel.c index 9fc1c62ec80..4e606fcb253 100644 --- a/net/sched/sch_fq_codel.c +++ b/net/sched/sch_fq_codel.c @@ -191,7 +191,6 @@ static int fq_codel_enqueue(struct sk_buff *skb, struct Qdisc *sch)  	if (list_empty(&flow->flowchain)) {  		list_add_tail(&flow->flowchain, &q->new_flows); -		codel_vars_init(&flow->cvars);  		q->new_flow_count++;  		flow->deficit = q->quantum;  		flow->dropped = 0; @@ -418,6 +417,7 @@ static int fq_codel_init(struct Qdisc *sch, struct nlattr *opt)  			struct fq_codel_flow *flow = q->flows + i;  			INIT_LIST_HEAD(&flow->flowchain); +			codel_vars_init(&flow->cvars);  		}  	}  	if (sch->limit >= 1) diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index e901583e4ea..d42234c0f13 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c @@ -102,9 +102,8 @@ static inline int gred_wred_mode_check(struct Qdisc *sch)  		if (q == NULL)  			continue; -		for (n = 0; n < table->DPs; n++) -			if (table->tab[n] && table->tab[n] != q && -			    table->tab[n]->prio == q->prio) +		for (n = i + 1; n < table->DPs; n++) +			if (table->tab[n] && table->tab[n]->prio == q->prio)  				return 1;  	} @@ -137,6 +136,7 @@ static inline void gred_store_wred_set(struct gred_sched *table,  				       struct gred_sched_data *q)  {  	table->wred_set.qavg = q->vars.qavg; +	table->wred_set.qidlestart = q->vars.qidlestart;  }  static inline int gred_use_ecn(struct gred_sched *t) @@ -176,7 +176,7 @@ static int gred_enqueue(struct sk_buff *skb, struct Qdisc *sch)  		skb->tc_index = (skb->tc_index & ~GRED_VQ_MASK) | dp;  	} -	/* sum up all the qaves of prios <= to ours to get the new qave */ +	/* sum up all the qaves of prios < ours to get the new qave */  	if (!gred_wred_mode(t) && gred_rio_mode(t)) {  		int i; @@ -260,16 +260,18 @@ static struct sk_buff *gred_dequeue(struct Qdisc *sch)  		} else {  			q->backlog -= qdisc_pkt_len(skb); -			if (!q->backlog && !gred_wred_mode(t)) -				red_start_of_idle_period(&q->vars); +			if (gred_wred_mode(t)) { +				if (!sch->qstats.backlog) +					red_start_of_idle_period(&t->wred_set); +			} else { +				if (!q->backlog) +					red_start_of_idle_period(&q->vars); +			}  		}  		return skb;  	} -	if (gred_wred_mode(t) && !red_is_idling(&t->wred_set)) -		red_start_of_idle_period(&t->wred_set); -  	return NULL;  } @@ -291,19 +293,20 @@ static unsigned int gred_drop(struct Qdisc *sch)  			q->backlog -= len;  			q->stats.other++; -			if (!q->backlog && !gred_wred_mode(t)) -				red_start_of_idle_period(&q->vars); +			if (gred_wred_mode(t)) { +				if (!sch->qstats.backlog) +					red_start_of_idle_period(&t->wred_set); +			} else { +				if (!q->backlog) +					red_start_of_idle_period(&q->vars); +			}  		}  		qdisc_drop(skb, sch);  		return len;  	} -	if (gred_wred_mode(t) && !red_is_idling(&t->wred_set)) -		red_start_of_idle_period(&t->wred_set); -  	return 0; -  }  static void gred_reset(struct Qdisc *sch) @@ -535,6 +538,7 @@ static int gred_dump(struct Qdisc *sch, struct sk_buff *skb)  	for (i = 0; i < MAX_DPs; i++) {  		struct gred_sched_data *q = table->tab[i];  		struct tc_gred_qopt opt; +		unsigned long qavg;  		memset(&opt, 0, sizeof(opt)); @@ -566,7 +570,9 @@ static int gred_dump(struct Qdisc *sch, struct sk_buff *skb)  		if (gred_wred_mode(table))  			gred_load_wred_set(table, q); -		opt.qave = red_calc_qavg(&q->parms, &q->vars, q->vars.qavg); +		qavg = red_calc_qavg(&q->parms, &q->vars, +				     q->vars.qavg >> q->parms.Wlog); +		opt.qave = qavg >> q->parms.Wlog;  append_opt:  		if (nla_append(skb, sizeof(opt), &opt) < 0) diff --git a/net/sctp/output.c b/net/sctp/output.c index 838e18b4d7e..be50aa234dc 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c @@ -364,6 +364,25 @@ finish:  	return retval;  } +static void sctp_packet_release_owner(struct sk_buff *skb) +{ +	sk_free(skb->sk); +} + +static void sctp_packet_set_owner_w(struct sk_buff *skb, struct sock *sk) +{ +	skb_orphan(skb); +	skb->sk = sk; +	skb->destructor = sctp_packet_release_owner; + +	/* +	 * The data chunks have already been accounted for in sctp_sendmsg(), +	 * therefore only reserve a single byte to keep socket around until +	 * the packet has been transmitted. +	 */ +	atomic_inc(&sk->sk_wmem_alloc); +} +  /* All packets are sent to the network through this function from   * sctp_outq_tail().   * @@ -405,7 +424,7 @@ int sctp_packet_transmit(struct sctp_packet *packet)  	/* Set the owning socket so that we know where to get the  	 * destination IP address.  	 */ -	skb_set_owner_w(nskb, sk); +	sctp_packet_set_owner_w(nskb, sk);  	if (!sctp_transport_dst_check(tp)) {  		sctp_transport_route(tp, NULL, sctp_sk(sk)); diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index a5a402a7d21..5d7f61d7559 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c @@ -969,11 +969,11 @@ static bool xprt_dynamic_free_slot(struct rpc_xprt *xprt, struct rpc_rqst *req)  	return false;  } -static void xprt_alloc_slot(struct rpc_task *task) +void xprt_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task)  { -	struct rpc_xprt	*xprt = task->tk_xprt;  	struct rpc_rqst *req; +	spin_lock(&xprt->reserve_lock);  	if (!list_empty(&xprt->free)) {  		req = list_entry(xprt->free.next, struct rpc_rqst, rq_list);  		list_del(&req->rq_list); @@ -994,12 +994,29 @@ static void xprt_alloc_slot(struct rpc_task *task)  	default:  		task->tk_status = -EAGAIN;  	} +	spin_unlock(&xprt->reserve_lock);  	return;  out_init_req:  	task->tk_status = 0;  	task->tk_rqstp = req;  	xprt_request_init(task, xprt); +	spin_unlock(&xprt->reserve_lock); +} +EXPORT_SYMBOL_GPL(xprt_alloc_slot); + +void xprt_lock_and_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task) +{ +	/* Note: grabbing the xprt_lock_write() ensures that we throttle +	 * new slot allocation if the transport is congested (i.e. when +	 * reconnecting a stream transport or when out of socket write +	 * buffer space). +	 */ +	if (xprt_lock_write(xprt, task)) { +		xprt_alloc_slot(xprt, task); +		xprt_release_write(xprt, task); +	}  } +EXPORT_SYMBOL_GPL(xprt_lock_and_alloc_slot);  static void xprt_free_slot(struct rpc_xprt *xprt, struct rpc_rqst *req)  { @@ -1083,20 +1100,9 @@ void xprt_reserve(struct rpc_task *task)  	if (task->tk_rqstp != NULL)  		return; -	/* Note: grabbing the xprt_lock_write() here is not strictly needed, -	 * but ensures that we throttle new slot allocation if the transport -	 * is congested (e.g. if reconnecting or if we're out of socket -	 * write buffer space). -	 */  	task->tk_timeout = 0;  	task->tk_status = -EAGAIN; -	if (!xprt_lock_write(xprt, task)) -		return; - -	spin_lock(&xprt->reserve_lock); -	xprt_alloc_slot(task); -	spin_unlock(&xprt->reserve_lock); -	xprt_release_write(xprt, task); +	xprt->ops->alloc_slot(xprt, task);  }  static inline __be32 xprt_alloc_xid(struct rpc_xprt *xprt) diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c index 06cdbff79e4..5d9202dc7cb 100644 --- a/net/sunrpc/xprtrdma/transport.c +++ b/net/sunrpc/xprtrdma/transport.c @@ -713,6 +713,7 @@ static void xprt_rdma_print_stats(struct rpc_xprt *xprt, struct seq_file *seq)  static struct rpc_xprt_ops xprt_rdma_procs = {  	.reserve_xprt		= xprt_rdma_reserve_xprt,  	.release_xprt		= xprt_release_xprt_cong, /* sunrpc/xprt.c */ +	.alloc_slot		= xprt_alloc_slot,  	.release_request	= xprt_release_rqst_cong,       /* ditto */  	.set_retrans_timeout	= xprt_set_retrans_timeout_def, /* ditto */  	.rpcbind		= rpcb_getport_async,	/* sunrpc/rpcb_clnt.c */ diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 400567243f8..a35b8e52e55 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -2473,6 +2473,7 @@ static void bc_destroy(struct rpc_xprt *xprt)  static struct rpc_xprt_ops xs_local_ops = {  	.reserve_xprt		= xprt_reserve_xprt,  	.release_xprt		= xs_tcp_release_xprt, +	.alloc_slot		= xprt_alloc_slot,  	.rpcbind		= xs_local_rpcbind,  	.set_port		= xs_local_set_port,  	.connect		= xs_connect, @@ -2489,6 +2490,7 @@ static struct rpc_xprt_ops xs_udp_ops = {  	.set_buffer_size	= xs_udp_set_buffer_size,  	.reserve_xprt		= xprt_reserve_xprt_cong,  	.release_xprt		= xprt_release_xprt_cong, +	.alloc_slot		= xprt_alloc_slot,  	.rpcbind		= rpcb_getport_async,  	.set_port		= xs_set_port,  	.connect		= xs_connect, @@ -2506,6 +2508,7 @@ static struct rpc_xprt_ops xs_udp_ops = {  static struct rpc_xprt_ops xs_tcp_ops = {  	.reserve_xprt		= xprt_reserve_xprt,  	.release_xprt		= xs_tcp_release_xprt, +	.alloc_slot		= xprt_lock_and_alloc_slot,  	.rpcbind		= rpcb_getport_async,  	.set_port		= xs_set_port,  	.connect		= xs_connect, diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 97026f3b215..1e37dbf00cb 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -5633,8 +5633,10 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)  		       sizeof(connect.ht_capa_mask));  	if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) { -		if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]) +		if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]) { +			kfree(connkeys);  			return -EINVAL; +		}  		memcpy(&connect.ht_capa,  		       nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]),  		       sizeof(connect.ht_capa)); diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c index 54a0dc2e2f8..ab2bb42fe09 100644 --- a/net/xfrm/xfrm_input.c +++ b/net/xfrm/xfrm_input.c @@ -212,7 +212,7 @@ resume:  		/* only the first xfrm gets the encap type */  		encap_type = 0; -		if (async && x->repl->check(x, skb, seq)) { +		if (async && x->repl->recheck(x, skb, seq)) {  			XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATESEQERROR);  			goto drop_unlock;  		} diff --git a/net/xfrm/xfrm_replay.c b/net/xfrm/xfrm_replay.c index 2f6d11d04a2..3efb07d3eb2 100644 --- a/net/xfrm/xfrm_replay.c +++ b/net/xfrm/xfrm_replay.c @@ -420,6 +420,18 @@ err:  	return -EINVAL;  } +static int xfrm_replay_recheck_esn(struct xfrm_state *x, +				   struct sk_buff *skb, __be32 net_seq) +{ +	if (unlikely(XFRM_SKB_CB(skb)->seq.input.hi != +		     htonl(xfrm_replay_seqhi(x, net_seq)))) { +			x->stats.replay_window++; +			return -EINVAL; +	} + +	return xfrm_replay_check_esn(x, skb, net_seq); +} +  static void xfrm_replay_advance_esn(struct xfrm_state *x, __be32 net_seq)  {  	unsigned int bitnr, nr, i; @@ -479,6 +491,7 @@ static void xfrm_replay_advance_esn(struct xfrm_state *x, __be32 net_seq)  static struct xfrm_replay xfrm_replay_legacy = {  	.advance	= xfrm_replay_advance,  	.check		= xfrm_replay_check, +	.recheck	= xfrm_replay_check,  	.notify		= xfrm_replay_notify,  	.overflow	= xfrm_replay_overflow,  }; @@ -486,6 +499,7 @@ static struct xfrm_replay xfrm_replay_legacy = {  static struct xfrm_replay xfrm_replay_bmp = {  	.advance	= xfrm_replay_advance_bmp,  	.check		= xfrm_replay_check_bmp, +	.recheck	= xfrm_replay_check_bmp,  	.notify		= xfrm_replay_notify_bmp,  	.overflow	= xfrm_replay_overflow_bmp,  }; @@ -493,6 +507,7 @@ static struct xfrm_replay xfrm_replay_bmp = {  static struct xfrm_replay xfrm_replay_esn = {  	.advance	= xfrm_replay_advance_esn,  	.check		= xfrm_replay_check_esn, +	.recheck	= xfrm_replay_recheck_esn,  	.notify		= xfrm_replay_notify_bmp,  	.overflow	= xfrm_replay_overflow_esn,  };  |