diff options
Diffstat (limited to 'net')
33 files changed, 206 insertions, 176 deletions
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index e877af8bdd1..469daabd90c 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c @@ -642,7 +642,8 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,  	struct batadv_neigh_node *router = NULL;  	struct batadv_orig_node *orig_node_tmp;  	struct hlist_node *node; -	uint8_t bcast_own_sum_orig, bcast_own_sum_neigh; +	int if_num; +	uint8_t sum_orig, sum_neigh;  	uint8_t *neigh_addr;  	batadv_dbg(BATADV_DBG_BATMAN, bat_priv, @@ -727,17 +728,17 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,  	if (router && (neigh_node->tq_avg == router->tq_avg)) {  		orig_node_tmp = router->orig_node;  		spin_lock_bh(&orig_node_tmp->ogm_cnt_lock); -		bcast_own_sum_orig = -			orig_node_tmp->bcast_own_sum[if_incoming->if_num]; +		if_num = router->if_incoming->if_num; +		sum_orig = orig_node_tmp->bcast_own_sum[if_num];  		spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock);  		orig_node_tmp = neigh_node->orig_node;  		spin_lock_bh(&orig_node_tmp->ogm_cnt_lock); -		bcast_own_sum_neigh = -			orig_node_tmp->bcast_own_sum[if_incoming->if_num]; +		if_num = neigh_node->if_incoming->if_num; +		sum_neigh = orig_node_tmp->bcast_own_sum[if_num];  		spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock); -		if (bcast_own_sum_orig >= bcast_own_sum_neigh) +		if (sum_orig >= sum_neigh)  			goto update_tt;  	} diff --git a/net/batman-adv/bitarray.h b/net/batman-adv/bitarray.h index a081ce1c051..cebaae7e148 100644 --- a/net/batman-adv/bitarray.h +++ b/net/batman-adv/bitarray.h @@ -20,8 +20,8 @@  #ifndef _NET_BATMAN_ADV_BITARRAY_H_  #define _NET_BATMAN_ADV_BITARRAY_H_ -/* returns true if the corresponding bit in the given seq_bits indicates true - * and curr_seqno is within range of last_seqno +/* Returns 1 if the corresponding bit in the given seq_bits indicates true + * and curr_seqno is within range of last_seqno. Otherwise returns 0.   */  static inline int batadv_test_bit(const unsigned long *seq_bits,  				  uint32_t last_seqno, uint32_t curr_seqno) @@ -32,7 +32,7 @@ static inline int batadv_test_bit(const unsigned long *seq_bits,  	if (diff < 0 || diff >= BATADV_TQ_LOCAL_WINDOW_SIZE)  		return 0;  	else -		return  test_bit(diff, seq_bits); +		return test_bit(diff, seq_bits) != 0;  }  /* turn corresponding bit on, so we can remember that we got the packet */ diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index 109ea2aae96..21c53577c8d 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@ -100,18 +100,21 @@ static int batadv_interface_set_mac_addr(struct net_device *dev, void *p)  {  	struct batadv_priv *bat_priv = netdev_priv(dev);  	struct sockaddr *addr = p; +	uint8_t old_addr[ETH_ALEN];  	if (!is_valid_ether_addr(addr->sa_data))  		return -EADDRNOTAVAIL; +	memcpy(old_addr, dev->dev_addr, ETH_ALEN); +	memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); +  	/* only modify transtable if it has been initialized before */  	if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_ACTIVE) { -		batadv_tt_local_remove(bat_priv, dev->dev_addr, +		batadv_tt_local_remove(bat_priv, old_addr,  				       "mac address changed", false);  		batadv_tt_local_add(dev, addr->sa_data, BATADV_NULL_IFINDEX);  	} -	memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);  	dev->addr_assign_type &= ~NET_ADDR_RANDOM;  	return 0;  } diff --git a/net/bluetooth/bnep/sock.c b/net/bluetooth/bnep/sock.c index 5e5f5b410e0..1eaacf10d19 100644 --- a/net/bluetooth/bnep/sock.c +++ b/net/bluetooth/bnep/sock.c @@ -58,7 +58,7 @@ static int bnep_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long  	switch (cmd) {  	case BNEPCONNADD:  		if (!capable(CAP_NET_ADMIN)) -			return -EACCES; +			return -EPERM;  		if (copy_from_user(&ca, argp, sizeof(ca)))  			return -EFAULT; @@ -84,7 +84,7 @@ static int bnep_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long  	case BNEPCONNDEL:  		if (!capable(CAP_NET_ADMIN)) -			return -EACCES; +			return -EPERM;  		if (copy_from_user(&cd, argp, sizeof(cd)))  			return -EFAULT; diff --git a/net/bluetooth/cmtp/sock.c b/net/bluetooth/cmtp/sock.c index 311668d1457..32dc83dcb6b 100644 --- a/net/bluetooth/cmtp/sock.c +++ b/net/bluetooth/cmtp/sock.c @@ -72,7 +72,7 @@ static int cmtp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long  	switch (cmd) {  	case CMTPCONNADD:  		if (!capable(CAP_NET_ADMIN)) -			return -EACCES; +			return -EPERM;  		if (copy_from_user(&ca, argp, sizeof(ca)))  			return -EFAULT; @@ -97,7 +97,7 @@ static int cmtp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long  	case CMTPCONNDEL:  		if (!capable(CAP_NET_ADMIN)) -			return -EACCES; +			return -EPERM;  		if (copy_from_user(&cd, argp, sizeof(cd)))  			return -EFAULT; diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index d4de5db18d5..0b997c8f965 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -734,6 +734,8 @@ static int hci_dev_do_close(struct hci_dev *hdev)  	cancel_work_sync(&hdev->le_scan); +	cancel_delayed_work(&hdev->power_off); +  	hci_req_cancel(hdev, ENODEV);  	hci_req_lock(hdev); diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index 19fdac78e55..d5ace1eda3e 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -490,7 +490,7 @@ static int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd,  	switch (cmd) {  	case HCISETRAW:  		if (!capable(CAP_NET_ADMIN)) -			return -EACCES; +			return -EPERM;  		if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))  			return -EPERM; @@ -510,12 +510,12 @@ static int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd,  	case HCIBLOCKADDR:  		if (!capable(CAP_NET_ADMIN)) -			return -EACCES; +			return -EPERM;  		return hci_sock_blacklist_add(hdev, (void __user *) arg);  	case HCIUNBLOCKADDR:  		if (!capable(CAP_NET_ADMIN)) -			return -EACCES; +			return -EPERM;  		return hci_sock_blacklist_del(hdev, (void __user *) arg);  	default: @@ -546,22 +546,22 @@ static int hci_sock_ioctl(struct socket *sock, unsigned int cmd,  	case HCIDEVUP:  		if (!capable(CAP_NET_ADMIN)) -			return -EACCES; +			return -EPERM;  		return hci_dev_open(arg);  	case HCIDEVDOWN:  		if (!capable(CAP_NET_ADMIN)) -			return -EACCES; +			return -EPERM;  		return hci_dev_close(arg);  	case HCIDEVRESET:  		if (!capable(CAP_NET_ADMIN)) -			return -EACCES; +			return -EPERM;  		return hci_dev_reset(arg);  	case HCIDEVRESTAT:  		if (!capable(CAP_NET_ADMIN)) -			return -EACCES; +			return -EPERM;  		return hci_dev_reset_stat(arg);  	case HCISETSCAN: @@ -573,7 +573,7 @@ static int hci_sock_ioctl(struct socket *sock, unsigned int cmd,  	case HCISETACLMTU:  	case HCISETSCOMTU:  		if (!capable(CAP_NET_ADMIN)) -			return -EACCES; +			return -EPERM;  		return hci_dev_cmd(cmd, argp);  	case HCIINQUIRY: diff --git a/net/bluetooth/hidp/sock.c b/net/bluetooth/hidp/sock.c index 18b3f6892a3..b24fb3bd862 100644 --- a/net/bluetooth/hidp/sock.c +++ b/net/bluetooth/hidp/sock.c @@ -56,7 +56,7 @@ static int hidp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long  	switch (cmd) {  	case HIDPCONNADD:  		if (!capable(CAP_NET_ADMIN)) -			return -EACCES; +			return -EPERM;  		if (copy_from_user(&ca, argp, sizeof(ca)))  			return -EFAULT; @@ -91,7 +91,7 @@ static int hidp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long  	case HIDPCONNDEL:  		if (!capable(CAP_NET_ADMIN)) -			return -EACCES; +			return -EPERM;  		if (copy_from_user(&cd, argp, sizeof(cd)))  			return -EFAULT; diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 4ea1710a478..38c00f14220 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -1008,7 +1008,7 @@ static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *c  	if (!conn)  		return; -	if (chan->mode == L2CAP_MODE_ERTM) { +	if (chan->mode == L2CAP_MODE_ERTM && chan->state == BT_CONNECTED) {  		__clear_retrans_timer(chan);  		__clear_monitor_timer(chan);  		__clear_ack_timer(chan); diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index ad6613d17ca..eba022de3c2 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -2875,6 +2875,22 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered)  		if (scan)  			hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); +		if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) { +			u8 ssp = 1; + +			hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &ssp); +		} + +		if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { +			struct hci_cp_write_le_host_supported cp; + +			cp.le = 1; +			cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR); + +			hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, +				     sizeof(cp), &cp); +		} +  		update_class(hdev);  		update_name(hdev, hdev->dev_name);  		update_eir(hdev); diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 24c5eea8c45..159aa8bef9e 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -1073,16 +1073,13 @@ static int write_partial_msg_pages(struct ceph_connection *con)  			BUG_ON(kaddr == NULL);  			base = kaddr + con->out_msg_pos.page_pos + bio_offset;  			crc = crc32c(crc, base, len); +			kunmap(page);  			msg->footer.data_crc = cpu_to_le32(crc);  			con->out_msg_pos.did_page_crc = true;  		}  		ret = ceph_tcp_sendpage(con->sock, page,  				      con->out_msg_pos.page_pos + bio_offset,  				      len, 1); - -		if (do_datacrc) -			kunmap(page); -  		if (ret <= 0)  			goto out; diff --git a/net/core/dev.c b/net/core/dev.c index d7fe32c946c..89e33a5d4d9 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2134,7 +2134,8 @@ static bool can_checksum_protocol(netdev_features_t features, __be16 protocol)  static netdev_features_t harmonize_features(struct sk_buff *skb,  	__be16 protocol, netdev_features_t features)  { -	if (!can_checksum_protocol(features, protocol)) { +	if (skb->ip_summed != CHECKSUM_NONE && +	    !can_checksum_protocol(features, protocol)) {  		features &= ~NETIF_F_ALL_CSUM;  		features &= ~NETIF_F_SG;  	} else if (illegal_highdma(skb->dev, skb)) { @@ -3322,7 +3323,7 @@ ncls:  	if (pt_prev) {  		if (unlikely(skb_orphan_frags(skb, GFP_ATOMIC))) -			ret = -ENOMEM; +			goto drop;  		else  			ret = pt_prev->func(skb, skb->dev, pt_prev, orig_dev);  	} else { diff --git a/net/core/skbuff.c b/net/core/skbuff.c index fe00d120816..e33ebae519c 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -3502,7 +3502,9 @@ bool skb_try_coalesce(struct sk_buff *to, struct sk_buff *from,  	if (!skb_cloned(from))  		skb_shinfo(from)->nr_frags = 0; -	/* if the skb is cloned this does nothing since we set nr_frags to 0 */ +	/* if the skb is not cloned this does nothing +	 * since we set nr_frags to 0. +	 */  	for (i = 0; i < skb_shinfo(from)->nr_frags; i++)  		skb_frag_ref(from, i); diff --git a/net/core/sock.c b/net/core/sock.c index 30579207612..a6000fbad29 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -691,7 +691,8 @@ set_rcvbuf:  	case SO_KEEPALIVE:  #ifdef CONFIG_INET -		if (sk->sk_protocol == IPPROTO_TCP) +		if (sk->sk_protocol == IPPROTO_TCP && +		    sk->sk_type == SOCK_STREAM)  			tcp_set_keepalive(sk, valbool);  #endif  		sock_valbool_flag(sk, SOCK_KEEPOPEN, valbool); diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 77e87aff419..47800459e4c 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -1225,7 +1225,7 @@ static int arp_netdev_event(struct notifier_block *this, unsigned long event,  	switch (event) {  	case NETDEV_CHANGEADDR:  		neigh_changeaddr(&arp_tbl, dev); -		rt_cache_flush(dev_net(dev), 0); +		rt_cache_flush(dev_net(dev));  		break;  	default:  		break; diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 44bf82e3aef..e12fad77385 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -725,7 +725,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)  		break;  	case SIOCSIFFLAGS: -		ret = -EACCES; +		ret = -EPERM;  		if (!capable(CAP_NET_ADMIN))  			goto out;  		break; @@ -733,7 +733,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)  	case SIOCSIFBRDADDR:	/* Set the broadcast address */  	case SIOCSIFDSTADDR:	/* Set the destination address */  	case SIOCSIFNETMASK: 	/* Set the netmask for the interface */ -		ret = -EACCES; +		ret = -EPERM;  		if (!capable(CAP_NET_ADMIN))  			goto out;  		ret = -EINVAL; @@ -1503,7 +1503,7 @@ static int devinet_conf_proc(ctl_table *ctl, int write,  		if (i == IPV4_DEVCONF_ACCEPT_LOCAL - 1 ||  		    i == IPV4_DEVCONF_ROUTE_LOCALNET - 1)  			if ((new_value == 0) && (old_value != 0)) -				rt_cache_flush(net, 0); +				rt_cache_flush(net);  	}  	return ret; @@ -1537,7 +1537,7 @@ static int devinet_sysctl_forward(ctl_table *ctl, int write,  				dev_disable_lro(idev->dev);  			}  			rtnl_unlock(); -			rt_cache_flush(net, 0); +			rt_cache_flush(net);  		}  	} @@ -1554,7 +1554,7 @@ static int ipv4_doint_and_flush(ctl_table *ctl, int write,  	struct net *net = ctl->extra2;  	if (write && *valp != val) -		rt_cache_flush(net, 0); +		rt_cache_flush(net);  	return ret;  } diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index c43ae3fba79..8e2b475da9f 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -148,7 +148,7 @@ static void fib_flush(struct net *net)  	}  	if (flushed) -		rt_cache_flush(net, -1); +		rt_cache_flush(net);  }  /* @@ -999,11 +999,11 @@ static void nl_fib_lookup_exit(struct net *net)  	net->ipv4.fibnl = NULL;  } -static void fib_disable_ip(struct net_device *dev, int force, int delay) +static void fib_disable_ip(struct net_device *dev, int force)  {  	if (fib_sync_down_dev(dev, force))  		fib_flush(dev_net(dev)); -	rt_cache_flush(dev_net(dev), delay); +	rt_cache_flush(dev_net(dev));  	arp_ifdown(dev);  } @@ -1020,7 +1020,7 @@ static int fib_inetaddr_event(struct notifier_block *this, unsigned long event,  		fib_sync_up(dev);  #endif  		atomic_inc(&net->ipv4.dev_addr_genid); -		rt_cache_flush(dev_net(dev), -1); +		rt_cache_flush(dev_net(dev));  		break;  	case NETDEV_DOWN:  		fib_del_ifaddr(ifa, NULL); @@ -1029,9 +1029,9 @@ static int fib_inetaddr_event(struct notifier_block *this, unsigned long event,  			/* Last address was deleted from this interface.  			 * Disable IP.  			 */ -			fib_disable_ip(dev, 1, 0); +			fib_disable_ip(dev, 1);  		} else { -			rt_cache_flush(dev_net(dev), -1); +			rt_cache_flush(dev_net(dev));  		}  		break;  	} @@ -1045,7 +1045,7 @@ static int fib_netdev_event(struct notifier_block *this, unsigned long event, vo  	struct net *net = dev_net(dev);  	if (event == NETDEV_UNREGISTER) { -		fib_disable_ip(dev, 2, -1); +		fib_disable_ip(dev, 2);  		rt_flush_dev(dev);  		return NOTIFY_DONE;  	} @@ -1062,14 +1062,14 @@ static int fib_netdev_event(struct notifier_block *this, unsigned long event, vo  		fib_sync_up(dev);  #endif  		atomic_inc(&net->ipv4.dev_addr_genid); -		rt_cache_flush(dev_net(dev), -1); +		rt_cache_flush(dev_net(dev));  		break;  	case NETDEV_DOWN: -		fib_disable_ip(dev, 0, 0); +		fib_disable_ip(dev, 0);  		break;  	case NETDEV_CHANGEMTU:  	case NETDEV_CHANGE: -		rt_cache_flush(dev_net(dev), 0); +		rt_cache_flush(dev_net(dev));  		break;  	case NETDEV_UNREGISTER_BATCH:  		break; diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c index a83d74e498d..274309d3ade 100644 --- a/net/ipv4/fib_rules.c +++ b/net/ipv4/fib_rules.c @@ -259,7 +259,7 @@ static size_t fib4_rule_nlmsg_payload(struct fib_rule *rule)  static void fib4_rule_flush_cache(struct fib_rules_ops *ops)  { -	rt_cache_flush(ops->fro_net, -1); +	rt_cache_flush(ops->fro_net);  }  static const struct fib_rules_ops __net_initdata fib4_rules_ops_template = { diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 57bd978483e..d1b93595b4a 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c @@ -1286,7 +1286,7 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg)  			fib_release_info(fi_drop);  			if (state & FA_S_ACCESSED) -				rt_cache_flush(cfg->fc_nlinfo.nl_net, -1); +				rt_cache_flush(cfg->fc_nlinfo.nl_net);  			rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen,  				tb->tb_id, &cfg->fc_nlinfo, NLM_F_REPLACE); @@ -1333,7 +1333,7 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg)  	list_add_tail_rcu(&new_fa->fa_list,  			  (fa ? &fa->fa_list : fa_head)); -	rt_cache_flush(cfg->fc_nlinfo.nl_net, -1); +	rt_cache_flush(cfg->fc_nlinfo.nl_net);  	rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen, tb->tb_id,  		  &cfg->fc_nlinfo, 0);  succeeded: @@ -1708,7 +1708,7 @@ int fib_table_delete(struct fib_table *tb, struct fib_config *cfg)  		trie_leaf_remove(t, l);  	if (fa->fa_state & FA_S_ACCESSED) -		rt_cache_flush(cfg->fc_nlinfo.nl_net, -1); +		rt_cache_flush(cfg->fc_nlinfo.nl_net);  	fib_release_info(fa->fa_info);  	alias_free_mem_rcu(fa); diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index ff0f071969e..d23c6571ba1 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -131,18 +131,20 @@ found:   *	0 - deliver   *	1 - block   */ -static __inline__ int icmp_filter(struct sock *sk, struct sk_buff *skb) +static int icmp_filter(const struct sock *sk, const struct sk_buff *skb)  { -	int type; +	struct icmphdr _hdr; +	const struct icmphdr *hdr; -	if (!pskb_may_pull(skb, sizeof(struct icmphdr))) +	hdr = skb_header_pointer(skb, skb_transport_offset(skb), +				 sizeof(_hdr), &_hdr); +	if (!hdr)  		return 1; -	type = icmp_hdr(skb)->type; -	if (type < 32) { +	if (hdr->type < 32) {  		__u32 data = raw_sk(sk)->filter.data; -		return ((1 << type) & data) != 0; +		return ((1U << hdr->type) & data) != 0;  	}  	/* Do not block unknown ICMP types */ diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 82cf2a722b2..fd9af60397b 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -202,11 +202,6 @@ EXPORT_SYMBOL(ip_tos2prio);  static DEFINE_PER_CPU(struct rt_cache_stat, rt_cache_stat);  #define RT_CACHE_STAT_INC(field) __this_cpu_inc(rt_cache_stat.field) -static inline int rt_genid(struct net *net) -{ -	return atomic_read(&net->ipv4.rt_genid); -} -  #ifdef CONFIG_PROC_FS  static void *rt_cache_seq_start(struct seq_file *seq, loff_t *pos)  { @@ -447,27 +442,9 @@ static inline bool rt_is_expired(const struct rtable *rth)  	return rth->rt_genid != rt_genid(dev_net(rth->dst.dev));  } -/* - * Perturbation of rt_genid by a small quantity [1..256] - * Using 8 bits of shuffling ensure we can call rt_cache_invalidate() - * many times (2^24) without giving recent rt_genid. - * Jenkins hash is strong enough that litle changes of rt_genid are OK. - */ -static void rt_cache_invalidate(struct net *net) +void rt_cache_flush(struct net *net)  { -	unsigned char shuffle; - -	get_random_bytes(&shuffle, sizeof(shuffle)); -	atomic_add(shuffle + 1U, &net->ipv4.rt_genid); -} - -/* - * delay < 0  : invalidate cache (fast : entries will be deleted later) - * delay >= 0 : invalidate & flush cache (can be long) - */ -void rt_cache_flush(struct net *net, int delay) -{ -	rt_cache_invalidate(net); +	rt_genid_bump(net);  }  static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, @@ -2345,7 +2322,7 @@ int ip_rt_dump(struct sk_buff *skb,  struct netlink_callback *cb)  void ip_rt_multicast_event(struct in_device *in_dev)  { -	rt_cache_flush(dev_net(in_dev->dev), 0); +	rt_cache_flush(dev_net(in_dev->dev));  }  #ifdef CONFIG_SYSCTL @@ -2354,16 +2331,7 @@ static int ipv4_sysctl_rtcache_flush(ctl_table *__ctl, int write,  					size_t *lenp, loff_t *ppos)  {  	if (write) { -		int flush_delay; -		ctl_table ctl; -		struct net *net; - -		memcpy(&ctl, __ctl, sizeof(ctl)); -		ctl.data = &flush_delay; -		proc_dointvec(&ctl, write, buffer, lenp, ppos); - -		net = (struct net *)__ctl->extra1; -		rt_cache_flush(net, flush_delay); +		rt_cache_flush((struct net *)__ctl->extra1);  		return 0;  	} @@ -2533,8 +2501,7 @@ static __net_initdata struct pernet_operations sysctl_route_ops = {  static __net_init int rt_genid_init(struct net *net)  { -	get_random_bytes(&net->ipv4.rt_genid, -			 sizeof(net->ipv4.rt_genid)); +	atomic_set(&net->rt_genid, 0);  	get_random_bytes(&net->ipv4.dev_addr_genid,  			 sizeof(net->ipv4.dev_addr_genid));  	return 0; diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 2109ff4a1da..5f641934182 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -1762,8 +1762,14 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,  		}  #ifdef CONFIG_NET_DMA -		if (tp->ucopy.dma_chan) -			dma_async_memcpy_issue_pending(tp->ucopy.dma_chan); +		if (tp->ucopy.dma_chan) { +			if (tp->rcv_wnd == 0 && +			    !skb_queue_empty(&sk->sk_async_wait_queue)) { +				tcp_service_net_dma(sk, true); +				tcp_cleanup_rbuf(sk, copied); +			} else +				dma_async_memcpy_issue_pending(tp->ucopy.dma_chan); +		}  #endif  		if (copied >= target) {  			/* Do not sleep, just process backlog. */ @@ -2325,10 +2331,17 @@ static int tcp_repair_options_est(struct tcp_sock *tp,  			tp->rx_opt.mss_clamp = opt.opt_val;  			break;  		case TCPOPT_WINDOW: -			if (opt.opt_val > 14) -				return -EFBIG; +			{ +				u16 snd_wscale = opt.opt_val & 0xFFFF; +				u16 rcv_wscale = opt.opt_val >> 16; + +				if (snd_wscale > 14 || rcv_wscale > 14) +					return -EFBIG; -			tp->rx_opt.snd_wscale = opt.opt_val; +				tp->rx_opt.snd_wscale = snd_wscale; +				tp->rx_opt.rcv_wscale = rcv_wscale; +				tp->rx_opt.wscale_ok = 1; +			}  			break;  		case TCPOPT_SACK_PERM:  			if (opt.opt_val != 0) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 6e38c6c23ca..d377f4854cb 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -4661,7 +4661,7 @@ queue_and_out:  		if (eaten > 0)  			kfree_skb_partial(skb, fragstolen); -		else if (!sock_flag(sk, SOCK_DEAD)) +		if (!sock_flag(sk, SOCK_DEAD))  			sk->sk_data_ready(sk, 0);  		return;  	} @@ -5556,8 +5556,7 @@ no_ack:  #endif  			if (eaten)  				kfree_skb_partial(skb, fragstolen); -			else -				sk->sk_data_ready(sk, 0); +			sk->sk_data_ready(sk, 0);  			return 0;  		}  	} diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c index 0251a6005be..c4f934176ca 100644 --- a/net/ipv6/inet6_connection_sock.c +++ b/net/ipv6/inet6_connection_sock.c @@ -175,33 +175,12 @@ void __inet6_csk_dst_store(struct sock *sk, struct dst_entry *dst,  			   const struct in6_addr *saddr)  {  	__ip6_dst_store(sk, dst, daddr, saddr); - -#ifdef CONFIG_XFRM -	{ -		struct rt6_info *rt = (struct rt6_info  *)dst; -		rt->rt6i_flow_cache_genid = atomic_read(&flow_cache_genid); -	} -#endif  }  static inline  struct dst_entry *__inet6_csk_dst_check(struct sock *sk, u32 cookie)  { -	struct dst_entry *dst; - -	dst = __sk_dst_check(sk, cookie); - -#ifdef CONFIG_XFRM -	if (dst) { -		struct rt6_info *rt = (struct rt6_info *)dst; -		if (rt->rt6i_flow_cache_genid != atomic_read(&flow_cache_genid)) { -			__sk_dst_reset(sk); -			dst = NULL; -		} -	} -#endif - -	return dst; +	return __sk_dst_check(sk, cookie);  }  static struct dst_entry *inet6_csk_route_socket(struct sock *sk, diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 13690d650c3..286acfc2125 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -819,6 +819,10 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info)  					offsetof(struct rt6_info, rt6i_src),  					allow_create, replace_required); +			if (IS_ERR(sn)) { +				err = PTR_ERR(sn); +				sn = NULL; +			}  			if (!sn) {  				/* If it is failed, discard just allocated  				   root, and then (in st_failure) stale node diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c index 5b087c31d87..0f9bdc5ee9f 100644 --- a/net/ipv6/mip6.c +++ b/net/ipv6/mip6.c @@ -86,28 +86,30 @@ static int mip6_mh_len(int type)  static int mip6_mh_filter(struct sock *sk, struct sk_buff *skb)  { -	struct ip6_mh *mh; +	struct ip6_mh _hdr; +	const struct ip6_mh *mh; -	if (!pskb_may_pull(skb, (skb_transport_offset(skb)) + 8) || -	    !pskb_may_pull(skb, (skb_transport_offset(skb) + -				 ((skb_transport_header(skb)[1] + 1) << 3)))) +	mh = skb_header_pointer(skb, skb_transport_offset(skb), +				sizeof(_hdr), &_hdr); +	if (!mh)  		return -1; -	mh = (struct ip6_mh *)skb_transport_header(skb); +	if (((mh->ip6mh_hdrlen + 1) << 3) > skb->len) +		return -1;  	if (mh->ip6mh_hdrlen < mip6_mh_len(mh->ip6mh_type)) {  		LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH message too short: %d vs >=%d\n",  			       mh->ip6mh_hdrlen, mip6_mh_len(mh->ip6mh_type)); -		mip6_param_prob(skb, 0, ((&mh->ip6mh_hdrlen) - -					 skb_network_header(skb))); +		mip6_param_prob(skb, 0, offsetof(struct ip6_mh, ip6mh_hdrlen) + +				skb_network_header_len(skb));  		return -1;  	}  	if (mh->ip6mh_proto != IPPROTO_NONE) {  		LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH invalid payload proto = %d\n",  			       mh->ip6mh_proto); -		mip6_param_prob(skb, 0, ((&mh->ip6mh_proto) - -					 skb_network_header(skb))); +		mip6_param_prob(skb, 0, offsetof(struct ip6_mh, ip6mh_proto) + +				skb_network_header_len(skb));  		return -1;  	} diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index ef0579d5bca..4a5f78b5049 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -107,21 +107,20 @@ found:   *	0 - deliver   *	1 - block   */ -static __inline__ int icmpv6_filter(struct sock *sk, struct sk_buff *skb) +static int icmpv6_filter(const struct sock *sk, const struct sk_buff *skb)  { -	struct icmp6hdr *icmph; -	struct raw6_sock *rp = raw6_sk(sk); - -	if (pskb_may_pull(skb, sizeof(struct icmp6hdr))) { -		__u32 *data = &rp->filter.data[0]; -		int bit_nr; +	struct icmp6hdr *_hdr; +	const struct icmp6hdr *hdr; -		icmph = (struct icmp6hdr *) skb->data; -		bit_nr = icmph->icmp6_type; +	hdr = skb_header_pointer(skb, skb_transport_offset(skb), +				 sizeof(_hdr), &_hdr); +	if (hdr) { +		const __u32 *data = &raw6_sk(sk)->filter.data[0]; +		unsigned int type = hdr->icmp6_type; -		return (data[bit_nr >> 5] & (1 << (bit_nr & 31))) != 0; +		return (data[type >> 5] & (1U << (type & 31))) != 0;  	} -	return 0; +	return 1;  }  #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 8e80fd27910..854e4018d20 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -226,7 +226,7 @@ static struct rt6_info ip6_null_entry_template = {  	.dst = {  		.__refcnt	= ATOMIC_INIT(1),  		.__use		= 1, -		.obsolete	= -1, +		.obsolete	= DST_OBSOLETE_FORCE_CHK,  		.error		= -ENETUNREACH,  		.input		= ip6_pkt_discard,  		.output		= ip6_pkt_discard_out, @@ -246,7 +246,7 @@ static struct rt6_info ip6_prohibit_entry_template = {  	.dst = {  		.__refcnt	= ATOMIC_INIT(1),  		.__use		= 1, -		.obsolete	= -1, +		.obsolete	= DST_OBSOLETE_FORCE_CHK,  		.error		= -EACCES,  		.input		= ip6_pkt_prohibit,  		.output		= ip6_pkt_prohibit_out, @@ -261,7 +261,7 @@ static struct rt6_info ip6_blk_hole_entry_template = {  	.dst = {  		.__refcnt	= ATOMIC_INIT(1),  		.__use		= 1, -		.obsolete	= -1, +		.obsolete	= DST_OBSOLETE_FORCE_CHK,  		.error		= -EINVAL,  		.input		= dst_discard,  		.output		= dst_discard, @@ -281,13 +281,14 @@ static inline struct rt6_info *ip6_dst_alloc(struct net *net,  					     struct fib6_table *table)  {  	struct rt6_info *rt = dst_alloc(&net->ipv6.ip6_dst_ops, dev, -					0, DST_OBSOLETE_NONE, flags); +					0, DST_OBSOLETE_FORCE_CHK, flags);  	if (rt) {  		struct dst_entry *dst = &rt->dst;  		memset(dst + 1, 0, sizeof(*rt) - sizeof(*dst));  		rt6_init_peer(rt, table ? &table->tb6_peers : net->ipv6.peers); +		rt->rt6i_genid = rt_genid(net);  	}  	return rt;  } @@ -1031,6 +1032,13 @@ static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie)  	rt = (struct rt6_info *) dst; +	/* All IPV6 dsts are created with ->obsolete set to the value +	 * DST_OBSOLETE_FORCE_CHK which forces validation calls down +	 * into this function always. +	 */ +	if (rt->rt6i_genid != rt_genid(dev_net(rt->dst.dev))) +		return NULL; +  	if (rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie)) {  		if (rt->rt6i_peer_genid != rt6_peer_genid()) {  			if (!rt6_has_peer(rt)) @@ -1397,8 +1405,6 @@ int ip6_route_add(struct fib6_config *cfg)  		goto out;  	} -	rt->dst.obsolete = -1; -  	if (cfg->fc_flags & RTF_EXPIRES)  		rt6_set_expires(rt, jiffies +  				clock_t_to_jiffies(cfg->fc_expires)); @@ -2080,7 +2086,6 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,  	rt->dst.input = ip6_input;  	rt->dst.output = ip6_output;  	rt->rt6i_idev = idev; -	rt->dst.obsolete = -1;  	rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP;  	if (anycast) diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index 1b9024ee963..7261eb81974 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c @@ -601,7 +601,7 @@ static int nr_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)  		if (!capable(CAP_NET_BIND_SERVICE)) {  			dev_put(dev);  			release_sock(sk); -			return -EACCES; +			return -EPERM;  		}  		nr->user_addr   = addr->fsa_digipeater[0];  		nr->source_addr = addr->fsa_ax25.sax25_call; diff --git a/net/sched/sch_qfq.c b/net/sched/sch_qfq.c index e4723d31fdd..211a2121704 100644 --- a/net/sched/sch_qfq.c +++ b/net/sched/sch_qfq.c @@ -865,7 +865,10 @@ static void qfq_update_start(struct qfq_sched *q, struct qfq_class *cl)  		if (mask) {  			struct qfq_group *next = qfq_ffs(q, mask);  			if (qfq_gt(roundedF, next->F)) { -				cl->S = next->F; +				if (qfq_gt(limit, next->F)) +					cl->S = next->F; +				else /* preserve timestamp correctness */ +					cl->S = limit;  				return;  			}  		} diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 2ded3c7fad0..72d170ca340 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -350,6 +350,9 @@ static void reg_regdb_search(struct work_struct *work)  	struct reg_regdb_search_request *request;  	const struct ieee80211_regdomain *curdom, *regdom;  	int i, r; +	bool set_reg = false; + +	mutex_lock(&cfg80211_mutex);  	mutex_lock(®_regdb_search_mutex);  	while (!list_empty(®_regdb_search_list)) { @@ -365,9 +368,7 @@ static void reg_regdb_search(struct work_struct *work)  				r = reg_copy_regd(®dom, curdom);  				if (r)  					break; -				mutex_lock(&cfg80211_mutex); -				set_regdom(regdom); -				mutex_unlock(&cfg80211_mutex); +				set_reg = true;  				break;  			}  		} @@ -375,6 +376,11 @@ static void reg_regdb_search(struct work_struct *work)  		kfree(request);  	}  	mutex_unlock(®_regdb_search_mutex); + +	if (set_reg) +		set_regdom(regdom); + +	mutex_unlock(&cfg80211_mutex);  }  static DECLARE_WORK(reg_regdb_work, reg_regdb_search); diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 5a2aa17e4d3..387848e9007 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -585,6 +585,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)  	xfrm_pol_hold(policy);  	net->xfrm.policy_count[dir]++;  	atomic_inc(&flow_cache_genid); +	rt_genid_bump(net);  	if (delpol)  		__xfrm_policy_unlink(delpol, dir);  	policy->index = delpol ? delpol->index : xfrm_gen_index(net, dir); @@ -1763,7 +1764,7 @@ static struct dst_entry *make_blackhole(struct net *net, u16 family,  	if (!afinfo) {  		dst_release(dst_orig); -		ret = ERR_PTR(-EINVAL); +		return ERR_PTR(-EINVAL);  	} else {  		ret = afinfo->blackhole_route(net, dst_orig);  	} diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index e75d8e47f35..289f4bf18ff 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -123,9 +123,21 @@ static inline int verify_replay(struct xfrm_usersa_info *p,  				struct nlattr **attrs)  {  	struct nlattr *rt = attrs[XFRMA_REPLAY_ESN_VAL]; +	struct xfrm_replay_state_esn *rs; -	if ((p->flags & XFRM_STATE_ESN) && !rt) -		return -EINVAL; +	if (p->flags & XFRM_STATE_ESN) { +		if (!rt) +			return -EINVAL; + +		rs = nla_data(rt); + +		if (rs->bmp_len > XFRMA_REPLAY_ESN_MAX / sizeof(rs->bmp[0]) / 8) +			return -EINVAL; + +		if (nla_len(rt) < xfrm_replay_state_esn_len(rs) && +		    nla_len(rt) != sizeof(*rs)) +			return -EINVAL; +	}  	if (!rt)  		return 0; @@ -370,14 +382,15 @@ static inline int xfrm_replay_verify_len(struct xfrm_replay_state_esn *replay_es  					 struct nlattr *rp)  {  	struct xfrm_replay_state_esn *up; +	int ulen;  	if (!replay_esn || !rp)  		return 0;  	up = nla_data(rp); +	ulen = xfrm_replay_state_esn_len(up); -	if (xfrm_replay_state_esn_len(replay_esn) != -			xfrm_replay_state_esn_len(up)) +	if (nla_len(rp) < ulen || xfrm_replay_state_esn_len(replay_esn) != ulen)  		return -EINVAL;  	return 0; @@ -388,22 +401,28 @@ static int xfrm_alloc_replay_state_esn(struct xfrm_replay_state_esn **replay_esn  				       struct nlattr *rta)  {  	struct xfrm_replay_state_esn *p, *pp, *up; +	int klen, ulen;  	if (!rta)  		return 0;  	up = nla_data(rta); +	klen = xfrm_replay_state_esn_len(up); +	ulen = nla_len(rta) >= klen ? klen : sizeof(*up); -	p = kmemdup(up, xfrm_replay_state_esn_len(up), GFP_KERNEL); +	p = kzalloc(klen, GFP_KERNEL);  	if (!p)  		return -ENOMEM; -	pp = kmemdup(up, xfrm_replay_state_esn_len(up), GFP_KERNEL); +	pp = kzalloc(klen, GFP_KERNEL);  	if (!pp) {  		kfree(p);  		return -ENOMEM;  	} +	memcpy(p, up, ulen); +	memcpy(pp, up, ulen); +  	*replay_esn = p;  	*preplay_esn = pp; @@ -442,10 +461,11 @@ static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info *   * somehow made shareable and move it to xfrm_state.c - JHS   *  */ -static void xfrm_update_ae_params(struct xfrm_state *x, struct nlattr **attrs) +static void xfrm_update_ae_params(struct xfrm_state *x, struct nlattr **attrs, +				  int update_esn)  {  	struct nlattr *rp = attrs[XFRMA_REPLAY_VAL]; -	struct nlattr *re = attrs[XFRMA_REPLAY_ESN_VAL]; +	struct nlattr *re = update_esn ? attrs[XFRMA_REPLAY_ESN_VAL] : NULL;  	struct nlattr *lt = attrs[XFRMA_LTIME_VAL];  	struct nlattr *et = attrs[XFRMA_ETIMER_THRESH];  	struct nlattr *rt = attrs[XFRMA_REPLAY_THRESH]; @@ -555,7 +575,7 @@ static struct xfrm_state *xfrm_state_construct(struct net *net,  		goto error;  	/* override default values from above */ -	xfrm_update_ae_params(x, attrs); +	xfrm_update_ae_params(x, attrs, 0);  	return x; @@ -689,6 +709,7 @@ out:  static void copy_to_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p)  { +	memset(p, 0, sizeof(*p));  	memcpy(&p->id, &x->id, sizeof(p->id));  	memcpy(&p->sel, &x->sel, sizeof(p->sel));  	memcpy(&p->lft, &x->lft, sizeof(p->lft)); @@ -742,7 +763,7 @@ static int copy_to_user_auth(struct xfrm_algo_auth *auth, struct sk_buff *skb)  		return -EMSGSIZE;  	algo = nla_data(nla); -	strcpy(algo->alg_name, auth->alg_name); +	strncpy(algo->alg_name, auth->alg_name, sizeof(algo->alg_name));  	memcpy(algo->alg_key, auth->alg_key, (auth->alg_key_len + 7) / 8);  	algo->alg_key_len = auth->alg_key_len; @@ -878,6 +899,7 @@ static struct sk_buff *xfrm_state_netlink(struct sk_buff *in_skb,  {  	struct xfrm_dump_info info;  	struct sk_buff *skb; +	int err;  	skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);  	if (!skb) @@ -888,9 +910,10 @@ static struct sk_buff *xfrm_state_netlink(struct sk_buff *in_skb,  	info.nlmsg_seq = seq;  	info.nlmsg_flags = 0; -	if (dump_one_state(x, 0, &info)) { +	err = dump_one_state(x, 0, &info); +	if (err) {  		kfree_skb(skb); -		return NULL; +		return ERR_PTR(err);  	}  	return skb; @@ -1317,6 +1340,7 @@ static void copy_from_user_policy(struct xfrm_policy *xp, struct xfrm_userpolicy  static void copy_to_user_policy(struct xfrm_policy *xp, struct xfrm_userpolicy_info *p, int dir)  { +	memset(p, 0, sizeof(*p));  	memcpy(&p->sel, &xp->selector, sizeof(p->sel));  	memcpy(&p->lft, &xp->lft, sizeof(p->lft));  	memcpy(&p->curlft, &xp->curlft, sizeof(p->curlft)); @@ -1421,6 +1445,7 @@ static int copy_to_user_tmpl(struct xfrm_policy *xp, struct sk_buff *skb)  		struct xfrm_user_tmpl *up = &vec[i];  		struct xfrm_tmpl *kp = &xp->xfrm_vec[i]; +		memset(up, 0, sizeof(*up));  		memcpy(&up->id, &kp->id, sizeof(up->id));  		up->family = kp->encap_family;  		memcpy(&up->saddr, &kp->saddr, sizeof(up->saddr)); @@ -1546,6 +1571,7 @@ static struct sk_buff *xfrm_policy_netlink(struct sk_buff *in_skb,  {  	struct xfrm_dump_info info;  	struct sk_buff *skb; +	int err;  	skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);  	if (!skb) @@ -1556,9 +1582,10 @@ static struct sk_buff *xfrm_policy_netlink(struct sk_buff *in_skb,  	info.nlmsg_seq = seq;  	info.nlmsg_flags = 0; -	if (dump_one_policy(xp, dir, 0, &info) < 0) { +	err = dump_one_policy(xp, dir, 0, &info); +	if (err) {  		kfree_skb(skb); -		return NULL; +		return ERR_PTR(err);  	}  	return skb; @@ -1822,7 +1849,7 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh,  		goto out;  	spin_lock_bh(&x->lock); -	xfrm_update_ae_params(x, attrs); +	xfrm_update_ae_params(x, attrs, 1);  	spin_unlock_bh(&x->lock);  	c.event = nlh->nlmsg_type;  |