diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-05-26 21:40:19 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-05-26 21:40:19 -0400 |
commit | f35c69b736e4f910d7447346980145212c283570 (patch) | |
tree | 824b90cd870e6de07bbba19d761c1c74cf1fb4a7 /net | |
parent | cd4373984a5903276f52777a6003425e023eaa7e (diff) | |
parent | e4aa937ec75df0eea0bee03bffa3303ad36c986b (diff) |
Merge 3.10-rc3 into char-misc-next
We want the changes in here.
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'net')
49 files changed, 431 insertions, 182 deletions
diff --git a/net/802/mrp.c b/net/802/mrp.c index e085bcc754f6..1eb05d80b07b 100644 --- a/net/802/mrp.c +++ b/net/802/mrp.c | |||
@@ -871,10 +871,10 @@ void mrp_uninit_applicant(struct net_device *dev, struct mrp_application *appl) | |||
871 | */ | 871 | */ |
872 | del_timer_sync(&app->join_timer); | 872 | del_timer_sync(&app->join_timer); |
873 | 873 | ||
874 | spin_lock(&app->lock); | 874 | spin_lock_bh(&app->lock); |
875 | mrp_mad_event(app, MRP_EVENT_TX); | 875 | mrp_mad_event(app, MRP_EVENT_TX); |
876 | mrp_pdu_queue(app); | 876 | mrp_pdu_queue(app); |
877 | spin_unlock(&app->lock); | 877 | spin_unlock_bh(&app->lock); |
878 | 878 | ||
879 | mrp_queue_xmit(app); | 879 | mrp_queue_xmit(app); |
880 | 880 | ||
diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c index 8e15d966d9b0..239992021b1d 100644 --- a/net/batman-adv/distributed-arp-table.c +++ b/net/batman-adv/distributed-arp-table.c | |||
@@ -837,6 +837,19 @@ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv, | |||
837 | 837 | ||
838 | dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst); | 838 | dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst); |
839 | if (dat_entry) { | 839 | if (dat_entry) { |
840 | /* If the ARP request is destined for a local client the local | ||
841 | * client will answer itself. DAT would only generate a | ||
842 | * duplicate packet. | ||
843 | * | ||
844 | * Moreover, if the soft-interface is enslaved into a bridge, an | ||
845 | * additional DAT answer may trigger kernel warnings about | ||
846 | * a packet coming from the wrong port. | ||
847 | */ | ||
848 | if (batadv_is_my_client(bat_priv, dat_entry->mac_addr)) { | ||
849 | ret = true; | ||
850 | goto out; | ||
851 | } | ||
852 | |||
840 | skb_new = arp_create(ARPOP_REPLY, ETH_P_ARP, ip_src, | 853 | skb_new = arp_create(ARPOP_REPLY, ETH_P_ARP, ip_src, |
841 | bat_priv->soft_iface, ip_dst, hw_src, | 854 | bat_priv->soft_iface, ip_dst, hw_src, |
842 | dat_entry->mac_addr, hw_src); | 855 | dat_entry->mac_addr, hw_src); |
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c index 3e30a0f1b908..51aafd669cbb 100644 --- a/net/batman-adv/main.c +++ b/net/batman-adv/main.c | |||
@@ -163,16 +163,25 @@ void batadv_mesh_free(struct net_device *soft_iface) | |||
163 | batadv_vis_quit(bat_priv); | 163 | batadv_vis_quit(bat_priv); |
164 | 164 | ||
165 | batadv_gw_node_purge(bat_priv); | 165 | batadv_gw_node_purge(bat_priv); |
166 | batadv_originator_free(bat_priv); | ||
167 | batadv_nc_free(bat_priv); | 166 | batadv_nc_free(bat_priv); |
167 | batadv_dat_free(bat_priv); | ||
168 | batadv_bla_free(bat_priv); | ||
168 | 169 | ||
170 | /* Free the TT and the originator tables only after having terminated | ||
171 | * all the other depending components which may use these structures for | ||
172 | * their purposes. | ||
173 | */ | ||
169 | batadv_tt_free(bat_priv); | 174 | batadv_tt_free(bat_priv); |
170 | 175 | ||
171 | batadv_bla_free(bat_priv); | 176 | /* Since the originator table clean up routine is accessing the TT |
172 | 177 | * tables as well, it has to be invoked after the TT tables have been | |
173 | batadv_dat_free(bat_priv); | 178 | * freed and marked as empty. This ensures that no cleanup RCU callbacks |
179 | * accessing the TT data are scheduled for later execution. | ||
180 | */ | ||
181 | batadv_originator_free(bat_priv); | ||
174 | 182 | ||
175 | free_percpu(bat_priv->bat_counters); | 183 | free_percpu(bat_priv->bat_counters); |
184 | bat_priv->bat_counters = NULL; | ||
176 | 185 | ||
177 | atomic_set(&bat_priv->mesh_state, BATADV_MESH_INACTIVE); | 186 | atomic_set(&bat_priv->mesh_state, BATADV_MESH_INACTIVE); |
178 | } | 187 | } |
@@ -475,7 +484,7 @@ static int batadv_param_set_ra(const char *val, const struct kernel_param *kp) | |||
475 | char *algo_name = (char *)val; | 484 | char *algo_name = (char *)val; |
476 | size_t name_len = strlen(algo_name); | 485 | size_t name_len = strlen(algo_name); |
477 | 486 | ||
478 | if (algo_name[name_len - 1] == '\n') | 487 | if (name_len > 0 && algo_name[name_len - 1] == '\n') |
479 | algo_name[name_len - 1] = '\0'; | 488 | algo_name[name_len - 1] = '\0'; |
480 | 489 | ||
481 | bat_algo_ops = batadv_algo_get(algo_name); | 490 | bat_algo_ops = batadv_algo_get(algo_name); |
diff --git a/net/batman-adv/network-coding.c b/net/batman-adv/network-coding.c index f7c54305a918..e84629ece9b7 100644 --- a/net/batman-adv/network-coding.c +++ b/net/batman-adv/network-coding.c | |||
@@ -1514,6 +1514,7 @@ batadv_nc_skb_decode_packet(struct batadv_priv *bat_priv, struct sk_buff *skb, | |||
1514 | struct ethhdr *ethhdr, ethhdr_tmp; | 1514 | struct ethhdr *ethhdr, ethhdr_tmp; |
1515 | uint8_t *orig_dest, ttl, ttvn; | 1515 | uint8_t *orig_dest, ttl, ttvn; |
1516 | unsigned int coding_len; | 1516 | unsigned int coding_len; |
1517 | int err; | ||
1517 | 1518 | ||
1518 | /* Save headers temporarily */ | 1519 | /* Save headers temporarily */ |
1519 | memcpy(&coded_packet_tmp, skb->data, sizeof(coded_packet_tmp)); | 1520 | memcpy(&coded_packet_tmp, skb->data, sizeof(coded_packet_tmp)); |
@@ -1568,8 +1569,11 @@ batadv_nc_skb_decode_packet(struct batadv_priv *bat_priv, struct sk_buff *skb, | |||
1568 | coding_len); | 1569 | coding_len); |
1569 | 1570 | ||
1570 | /* Resize decoded skb if decoded with larger packet */ | 1571 | /* Resize decoded skb if decoded with larger packet */ |
1571 | if (nc_packet->skb->len > coding_len + h_size) | 1572 | if (nc_packet->skb->len > coding_len + h_size) { |
1572 | pskb_trim_rcsum(skb, coding_len + h_size); | 1573 | err = pskb_trim_rcsum(skb, coding_len + h_size); |
1574 | if (err) | ||
1575 | return NULL; | ||
1576 | } | ||
1573 | 1577 | ||
1574 | /* Create decoded unicast packet */ | 1578 | /* Create decoded unicast packet */ |
1575 | unicast_packet = (struct batadv_unicast_packet *)skb->data; | 1579 | unicast_packet = (struct batadv_unicast_packet *)skb->data; |
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index 2f3452546636..fad1a2093e15 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c | |||
@@ -156,12 +156,28 @@ static void batadv_orig_node_free_rcu(struct rcu_head *rcu) | |||
156 | kfree(orig_node); | 156 | kfree(orig_node); |
157 | } | 157 | } |
158 | 158 | ||
159 | /** | ||
160 | * batadv_orig_node_free_ref - decrement the orig node refcounter and possibly | ||
161 | * schedule an rcu callback for freeing it | ||
162 | * @orig_node: the orig node to free | ||
163 | */ | ||
159 | void batadv_orig_node_free_ref(struct batadv_orig_node *orig_node) | 164 | void batadv_orig_node_free_ref(struct batadv_orig_node *orig_node) |
160 | { | 165 | { |
161 | if (atomic_dec_and_test(&orig_node->refcount)) | 166 | if (atomic_dec_and_test(&orig_node->refcount)) |
162 | call_rcu(&orig_node->rcu, batadv_orig_node_free_rcu); | 167 | call_rcu(&orig_node->rcu, batadv_orig_node_free_rcu); |
163 | } | 168 | } |
164 | 169 | ||
170 | /** | ||
171 | * batadv_orig_node_free_ref_now - decrement the orig node refcounter and | ||
172 | * possibly free it (without rcu callback) | ||
173 | * @orig_node: the orig node to free | ||
174 | */ | ||
175 | void batadv_orig_node_free_ref_now(struct batadv_orig_node *orig_node) | ||
176 | { | ||
177 | if (atomic_dec_and_test(&orig_node->refcount)) | ||
178 | batadv_orig_node_free_rcu(&orig_node->rcu); | ||
179 | } | ||
180 | |||
165 | void batadv_originator_free(struct batadv_priv *bat_priv) | 181 | void batadv_originator_free(struct batadv_priv *bat_priv) |
166 | { | 182 | { |
167 | struct batadv_hashtable *hash = bat_priv->orig_hash; | 183 | struct batadv_hashtable *hash = bat_priv->orig_hash; |
diff --git a/net/batman-adv/originator.h b/net/batman-adv/originator.h index 7df48fa7669d..734e5a3d8a5b 100644 --- a/net/batman-adv/originator.h +++ b/net/batman-adv/originator.h | |||
@@ -26,6 +26,7 @@ int batadv_originator_init(struct batadv_priv *bat_priv); | |||
26 | void batadv_originator_free(struct batadv_priv *bat_priv); | 26 | void batadv_originator_free(struct batadv_priv *bat_priv); |
27 | void batadv_purge_orig_ref(struct batadv_priv *bat_priv); | 27 | void batadv_purge_orig_ref(struct batadv_priv *bat_priv); |
28 | void batadv_orig_node_free_ref(struct batadv_orig_node *orig_node); | 28 | void batadv_orig_node_free_ref(struct batadv_orig_node *orig_node); |
29 | void batadv_orig_node_free_ref_now(struct batadv_orig_node *orig_node); | ||
29 | struct batadv_orig_node *batadv_get_orig_node(struct batadv_priv *bat_priv, | 30 | struct batadv_orig_node *batadv_get_orig_node(struct batadv_priv *bat_priv, |
30 | const uint8_t *addr); | 31 | const uint8_t *addr); |
31 | struct batadv_neigh_node * | 32 | struct batadv_neigh_node * |
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index 6f20d339e33a..819dfb006cdf 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c | |||
@@ -505,6 +505,7 @@ unreg_debugfs: | |||
505 | batadv_debugfs_del_meshif(dev); | 505 | batadv_debugfs_del_meshif(dev); |
506 | free_bat_counters: | 506 | free_bat_counters: |
507 | free_percpu(bat_priv->bat_counters); | 507 | free_percpu(bat_priv->bat_counters); |
508 | bat_priv->bat_counters = NULL; | ||
508 | 509 | ||
509 | return ret; | 510 | return ret; |
510 | } | 511 | } |
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index 5e89deeb9542..9e8748575845 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c | |||
@@ -144,7 +144,12 @@ static void batadv_tt_orig_list_entry_free_rcu(struct rcu_head *rcu) | |||
144 | struct batadv_tt_orig_list_entry *orig_entry; | 144 | struct batadv_tt_orig_list_entry *orig_entry; |
145 | 145 | ||
146 | orig_entry = container_of(rcu, struct batadv_tt_orig_list_entry, rcu); | 146 | orig_entry = container_of(rcu, struct batadv_tt_orig_list_entry, rcu); |
147 | batadv_orig_node_free_ref(orig_entry->orig_node); | 147 | |
148 | /* We are in an rcu callback here, therefore we cannot use | ||
149 | * batadv_orig_node_free_ref() and its call_rcu(): | ||
150 | * An rcu_barrier() wouldn't wait for that to finish | ||
151 | */ | ||
152 | batadv_orig_node_free_ref_now(orig_entry->orig_node); | ||
148 | kfree(orig_entry); | 153 | kfree(orig_entry); |
149 | } | 154 | } |
150 | 155 | ||
diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c index 9878eb8204c5..19c37a4929bc 100644 --- a/net/bridge/netfilter/ebt_log.c +++ b/net/bridge/netfilter/ebt_log.c | |||
@@ -72,13 +72,12 @@ print_ports(const struct sk_buff *skb, uint8_t protocol, int offset) | |||
72 | } | 72 | } |
73 | 73 | ||
74 | static void | 74 | static void |
75 | ebt_log_packet(u_int8_t pf, unsigned int hooknum, | 75 | ebt_log_packet(struct net *net, u_int8_t pf, unsigned int hooknum, |
76 | const struct sk_buff *skb, const struct net_device *in, | 76 | const struct sk_buff *skb, const struct net_device *in, |
77 | const struct net_device *out, const struct nf_loginfo *loginfo, | 77 | const struct net_device *out, const struct nf_loginfo *loginfo, |
78 | const char *prefix) | 78 | const char *prefix) |
79 | { | 79 | { |
80 | unsigned int bitmask; | 80 | unsigned int bitmask; |
81 | struct net *net = dev_net(in ? in : out); | ||
82 | 81 | ||
83 | /* FIXME: Disabled from containers until syslog ns is supported */ | 82 | /* FIXME: Disabled from containers until syslog ns is supported */ |
84 | if (!net_eq(net, &init_net)) | 83 | if (!net_eq(net, &init_net)) |
@@ -191,7 +190,7 @@ ebt_log_tg(struct sk_buff *skb, const struct xt_action_param *par) | |||
191 | nf_log_packet(net, NFPROTO_BRIDGE, par->hooknum, skb, | 190 | nf_log_packet(net, NFPROTO_BRIDGE, par->hooknum, skb, |
192 | par->in, par->out, &li, "%s", info->prefix); | 191 | par->in, par->out, &li, "%s", info->prefix); |
193 | else | 192 | else |
194 | ebt_log_packet(NFPROTO_BRIDGE, par->hooknum, skb, par->in, | 193 | ebt_log_packet(net, NFPROTO_BRIDGE, par->hooknum, skb, par->in, |
195 | par->out, &li, info->prefix); | 194 | par->out, &li, info->prefix); |
196 | return EBT_CONTINUE; | 195 | return EBT_CONTINUE; |
197 | } | 196 | } |
diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c index fc1905c51417..df0364aa12d5 100644 --- a/net/bridge/netfilter/ebt_ulog.c +++ b/net/bridge/netfilter/ebt_ulog.c | |||
@@ -131,14 +131,16 @@ static struct sk_buff *ulog_alloc_skb(unsigned int size) | |||
131 | return skb; | 131 | return skb; |
132 | } | 132 | } |
133 | 133 | ||
134 | static void ebt_ulog_packet(unsigned int hooknr, const struct sk_buff *skb, | 134 | static void ebt_ulog_packet(struct net *net, unsigned int hooknr, |
135 | const struct net_device *in, const struct net_device *out, | 135 | const struct sk_buff *skb, |
136 | const struct ebt_ulog_info *uloginfo, const char *prefix) | 136 | const struct net_device *in, |
137 | const struct net_device *out, | ||
138 | const struct ebt_ulog_info *uloginfo, | ||
139 | const char *prefix) | ||
137 | { | 140 | { |
138 | ebt_ulog_packet_msg_t *pm; | 141 | ebt_ulog_packet_msg_t *pm; |
139 | size_t size, copy_len; | 142 | size_t size, copy_len; |
140 | struct nlmsghdr *nlh; | 143 | struct nlmsghdr *nlh; |
141 | struct net *net = dev_net(in ? in : out); | ||
142 | struct ebt_ulog_net *ebt = ebt_ulog_pernet(net); | 144 | struct ebt_ulog_net *ebt = ebt_ulog_pernet(net); |
143 | unsigned int group = uloginfo->nlgroup; | 145 | unsigned int group = uloginfo->nlgroup; |
144 | ebt_ulog_buff_t *ub = &ebt->ulog_buffers[group]; | 146 | ebt_ulog_buff_t *ub = &ebt->ulog_buffers[group]; |
@@ -233,7 +235,7 @@ unlock: | |||
233 | } | 235 | } |
234 | 236 | ||
235 | /* this function is registered with the netfilter core */ | 237 | /* this function is registered with the netfilter core */ |
236 | static void ebt_log_packet(u_int8_t pf, unsigned int hooknum, | 238 | static void ebt_log_packet(struct net *net, u_int8_t pf, unsigned int hooknum, |
237 | const struct sk_buff *skb, const struct net_device *in, | 239 | const struct sk_buff *skb, const struct net_device *in, |
238 | const struct net_device *out, const struct nf_loginfo *li, | 240 | const struct net_device *out, const struct nf_loginfo *li, |
239 | const char *prefix) | 241 | const char *prefix) |
@@ -252,13 +254,15 @@ static void ebt_log_packet(u_int8_t pf, unsigned int hooknum, | |||
252 | strlcpy(loginfo.prefix, prefix, sizeof(loginfo.prefix)); | 254 | strlcpy(loginfo.prefix, prefix, sizeof(loginfo.prefix)); |
253 | } | 255 | } |
254 | 256 | ||
255 | ebt_ulog_packet(hooknum, skb, in, out, &loginfo, prefix); | 257 | ebt_ulog_packet(net, hooknum, skb, in, out, &loginfo, prefix); |
256 | } | 258 | } |
257 | 259 | ||
258 | static unsigned int | 260 | static unsigned int |
259 | ebt_ulog_tg(struct sk_buff *skb, const struct xt_action_param *par) | 261 | ebt_ulog_tg(struct sk_buff *skb, const struct xt_action_param *par) |
260 | { | 262 | { |
261 | ebt_ulog_packet(par->hooknum, skb, par->in, par->out, | 263 | struct net *net = dev_net(par->in ? par->in : par->out); |
264 | |||
265 | ebt_ulog_packet(net, par->hooknum, skb, par->in, par->out, | ||
262 | par->targinfo, NULL); | 266 | par->targinfo, NULL); |
263 | return EBT_CONTINUE; | 267 | return EBT_CONTINUE; |
264 | } | 268 | } |
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index a3395fdfbd4f..d5953b87918c 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c | |||
@@ -1204,6 +1204,7 @@ void ceph_osdc_unregister_linger_request(struct ceph_osd_client *osdc, | |||
1204 | mutex_lock(&osdc->request_mutex); | 1204 | mutex_lock(&osdc->request_mutex); |
1205 | if (req->r_linger) { | 1205 | if (req->r_linger) { |
1206 | __unregister_linger_request(osdc, req); | 1206 | __unregister_linger_request(osdc, req); |
1207 | req->r_linger = 0; | ||
1207 | ceph_osdc_put_request(req); | 1208 | ceph_osdc_put_request(req); |
1208 | } | 1209 | } |
1209 | mutex_unlock(&osdc->request_mutex); | 1210 | mutex_unlock(&osdc->request_mutex); |
@@ -2120,7 +2121,9 @@ int ceph_osdc_start_request(struct ceph_osd_client *osdc, | |||
2120 | down_read(&osdc->map_sem); | 2121 | down_read(&osdc->map_sem); |
2121 | mutex_lock(&osdc->request_mutex); | 2122 | mutex_lock(&osdc->request_mutex); |
2122 | __register_request(osdc, req); | 2123 | __register_request(osdc, req); |
2123 | WARN_ON(req->r_sent); | 2124 | req->r_sent = 0; |
2125 | req->r_got_reply = 0; | ||
2126 | req->r_completed = 0; | ||
2124 | rc = __map_request(osdc, req, 0); | 2127 | rc = __map_request(osdc, req, 0); |
2125 | if (rc < 0) { | 2128 | if (rc < 0) { |
2126 | if (nofail) { | 2129 | if (nofail) { |
diff --git a/net/core/iovec.c b/net/core/iovec.c index 7e7aeb01de45..de178e462682 100644 --- a/net/core/iovec.c +++ b/net/core/iovec.c | |||
@@ -75,31 +75,6 @@ int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr_storage *a | |||
75 | 75 | ||
76 | /* | 76 | /* |
77 | * Copy kernel to iovec. Returns -EFAULT on error. | 77 | * Copy kernel to iovec. Returns -EFAULT on error. |
78 | * | ||
79 | * Note: this modifies the original iovec. | ||
80 | */ | ||
81 | |||
82 | int memcpy_toiovec(struct iovec *iov, unsigned char *kdata, int len) | ||
83 | { | ||
84 | while (len > 0) { | ||
85 | if (iov->iov_len) { | ||
86 | int copy = min_t(unsigned int, iov->iov_len, len); | ||
87 | if (copy_to_user(iov->iov_base, kdata, copy)) | ||
88 | return -EFAULT; | ||
89 | kdata += copy; | ||
90 | len -= copy; | ||
91 | iov->iov_len -= copy; | ||
92 | iov->iov_base += copy; | ||
93 | } | ||
94 | iov++; | ||
95 | } | ||
96 | |||
97 | return 0; | ||
98 | } | ||
99 | EXPORT_SYMBOL(memcpy_toiovec); | ||
100 | |||
101 | /* | ||
102 | * Copy kernel to iovec. Returns -EFAULT on error. | ||
103 | */ | 78 | */ |
104 | 79 | ||
105 | int memcpy_toiovecend(const struct iovec *iov, unsigned char *kdata, | 80 | int memcpy_toiovecend(const struct iovec *iov, unsigned char *kdata, |
@@ -125,31 +100,6 @@ int memcpy_toiovecend(const struct iovec *iov, unsigned char *kdata, | |||
125 | EXPORT_SYMBOL(memcpy_toiovecend); | 100 | EXPORT_SYMBOL(memcpy_toiovecend); |
126 | 101 | ||
127 | /* | 102 | /* |
128 | * Copy iovec to kernel. Returns -EFAULT on error. | ||
129 | * | ||
130 | * Note: this modifies the original iovec. | ||
131 | */ | ||
132 | |||
133 | int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len) | ||
134 | { | ||
135 | while (len > 0) { | ||
136 | if (iov->iov_len) { | ||
137 | int copy = min_t(unsigned int, len, iov->iov_len); | ||
138 | if (copy_from_user(kdata, iov->iov_base, copy)) | ||
139 | return -EFAULT; | ||
140 | len -= copy; | ||
141 | kdata += copy; | ||
142 | iov->iov_base += copy; | ||
143 | iov->iov_len -= copy; | ||
144 | } | ||
145 | iov++; | ||
146 | } | ||
147 | |||
148 | return 0; | ||
149 | } | ||
150 | EXPORT_SYMBOL(memcpy_fromiovec); | ||
151 | |||
152 | /* | ||
153 | * Copy iovec from kernel. Returns -EFAULT on error. | 103 | * Copy iovec from kernel. Returns -EFAULT on error. |
154 | */ | 104 | */ |
155 | 105 | ||
diff --git a/net/core/sock.c b/net/core/sock.c index d4f4cea726e7..6ba327da79e1 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -1217,18 +1217,6 @@ static void sock_copy(struct sock *nsk, const struct sock *osk) | |||
1217 | #endif | 1217 | #endif |
1218 | } | 1218 | } |
1219 | 1219 | ||
1220 | /* | ||
1221 | * caches using SLAB_DESTROY_BY_RCU should let .next pointer from nulls nodes | ||
1222 | * un-modified. Special care is taken when initializing object to zero. | ||
1223 | */ | ||
1224 | static inline void sk_prot_clear_nulls(struct sock *sk, int size) | ||
1225 | { | ||
1226 | if (offsetof(struct sock, sk_node.next) != 0) | ||
1227 | memset(sk, 0, offsetof(struct sock, sk_node.next)); | ||
1228 | memset(&sk->sk_node.pprev, 0, | ||
1229 | size - offsetof(struct sock, sk_node.pprev)); | ||
1230 | } | ||
1231 | |||
1232 | void sk_prot_clear_portaddr_nulls(struct sock *sk, int size) | 1220 | void sk_prot_clear_portaddr_nulls(struct sock *sk, int size) |
1233 | { | 1221 | { |
1234 | unsigned long nulls1, nulls2; | 1222 | unsigned long nulls1, nulls2; |
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index c625e4dad4b0..2a83591492dd 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c | |||
@@ -235,7 +235,7 @@ static void ipgre_err(struct sk_buff *skb, u32 info) | |||
235 | */ | 235 | */ |
236 | struct net *net = dev_net(skb->dev); | 236 | struct net *net = dev_net(skb->dev); |
237 | struct ip_tunnel_net *itn; | 237 | struct ip_tunnel_net *itn; |
238 | const struct iphdr *iph = (const struct iphdr *)skb->data; | 238 | const struct iphdr *iph; |
239 | const int type = icmp_hdr(skb)->type; | 239 | const int type = icmp_hdr(skb)->type; |
240 | const int code = icmp_hdr(skb)->code; | 240 | const int code = icmp_hdr(skb)->code; |
241 | struct ip_tunnel *t; | 241 | struct ip_tunnel *t; |
@@ -281,6 +281,7 @@ static void ipgre_err(struct sk_buff *skb, u32 info) | |||
281 | else | 281 | else |
282 | itn = net_generic(net, ipgre_net_id); | 282 | itn = net_generic(net, ipgre_net_id); |
283 | 283 | ||
284 | iph = (const struct iphdr *)skb->data; | ||
284 | t = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi.flags, | 285 | t = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi.flags, |
285 | iph->daddr, iph->saddr, tpi.key); | 286 | iph->daddr, iph->saddr, tpi.key); |
286 | 287 | ||
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 147abf5275aa..4bcabf3ab4ca 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
@@ -84,7 +84,7 @@ int sysctl_ip_default_ttl __read_mostly = IPDEFTTL; | |||
84 | EXPORT_SYMBOL(sysctl_ip_default_ttl); | 84 | EXPORT_SYMBOL(sysctl_ip_default_ttl); |
85 | 85 | ||
86 | /* Generate a checksum for an outgoing IP datagram. */ | 86 | /* Generate a checksum for an outgoing IP datagram. */ |
87 | __inline__ void ip_send_check(struct iphdr *iph) | 87 | void ip_send_check(struct iphdr *iph) |
88 | { | 88 | { |
89 | iph->check = 0; | 89 | iph->check = 0; |
90 | iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); | 90 | iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); |
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c index f8a222cb6448..cf08218ddbcf 100644 --- a/net/ipv4/netfilter/ipt_ULOG.c +++ b/net/ipv4/netfilter/ipt_ULOG.c | |||
@@ -162,7 +162,8 @@ static struct sk_buff *ulog_alloc_skb(unsigned int size) | |||
162 | return skb; | 162 | return skb; |
163 | } | 163 | } |
164 | 164 | ||
165 | static void ipt_ulog_packet(unsigned int hooknum, | 165 | static void ipt_ulog_packet(struct net *net, |
166 | unsigned int hooknum, | ||
166 | const struct sk_buff *skb, | 167 | const struct sk_buff *skb, |
167 | const struct net_device *in, | 168 | const struct net_device *in, |
168 | const struct net_device *out, | 169 | const struct net_device *out, |
@@ -174,7 +175,6 @@ static void ipt_ulog_packet(unsigned int hooknum, | |||
174 | size_t size, copy_len; | 175 | size_t size, copy_len; |
175 | struct nlmsghdr *nlh; | 176 | struct nlmsghdr *nlh; |
176 | struct timeval tv; | 177 | struct timeval tv; |
177 | struct net *net = dev_net(in ? in : out); | ||
178 | struct ulog_net *ulog = ulog_pernet(net); | 178 | struct ulog_net *ulog = ulog_pernet(net); |
179 | 179 | ||
180 | /* ffs == find first bit set, necessary because userspace | 180 | /* ffs == find first bit set, necessary because userspace |
@@ -291,12 +291,15 @@ alloc_failure: | |||
291 | static unsigned int | 291 | static unsigned int |
292 | ulog_tg(struct sk_buff *skb, const struct xt_action_param *par) | 292 | ulog_tg(struct sk_buff *skb, const struct xt_action_param *par) |
293 | { | 293 | { |
294 | ipt_ulog_packet(par->hooknum, skb, par->in, par->out, | 294 | struct net *net = dev_net(par->in ? par->in : par->out); |
295 | |||
296 | ipt_ulog_packet(net, par->hooknum, skb, par->in, par->out, | ||
295 | par->targinfo, NULL); | 297 | par->targinfo, NULL); |
296 | return XT_CONTINUE; | 298 | return XT_CONTINUE; |
297 | } | 299 | } |
298 | 300 | ||
299 | static void ipt_logfn(u_int8_t pf, | 301 | static void ipt_logfn(struct net *net, |
302 | u_int8_t pf, | ||
300 | unsigned int hooknum, | 303 | unsigned int hooknum, |
301 | const struct sk_buff *skb, | 304 | const struct sk_buff *skb, |
302 | const struct net_device *in, | 305 | const struct net_device *in, |
@@ -318,7 +321,7 @@ static void ipt_logfn(u_int8_t pf, | |||
318 | strlcpy(loginfo.prefix, prefix, sizeof(loginfo.prefix)); | 321 | strlcpy(loginfo.prefix, prefix, sizeof(loginfo.prefix)); |
319 | } | 322 | } |
320 | 323 | ||
321 | ipt_ulog_packet(hooknum, skb, in, out, &loginfo, prefix); | 324 | ipt_ulog_packet(net, hooknum, skb, in, out, &loginfo, prefix); |
322 | } | 325 | } |
323 | 326 | ||
324 | static int ulog_tg_check(const struct xt_tgchk_param *par) | 327 | static int ulog_tg_check(const struct xt_tgchk_param *par) |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index dcb116dde216..ab450c099aa4 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -2887,6 +2887,7 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, | |||
2887 | unsigned int mss; | 2887 | unsigned int mss; |
2888 | struct sk_buff *gso_skb = skb; | 2888 | struct sk_buff *gso_skb = skb; |
2889 | __sum16 newcheck; | 2889 | __sum16 newcheck; |
2890 | bool ooo_okay, copy_destructor; | ||
2890 | 2891 | ||
2891 | if (!pskb_may_pull(skb, sizeof(*th))) | 2892 | if (!pskb_may_pull(skb, sizeof(*th))) |
2892 | goto out; | 2893 | goto out; |
@@ -2927,10 +2928,18 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, | |||
2927 | goto out; | 2928 | goto out; |
2928 | } | 2929 | } |
2929 | 2930 | ||
2931 | copy_destructor = gso_skb->destructor == tcp_wfree; | ||
2932 | ooo_okay = gso_skb->ooo_okay; | ||
2933 | /* All segments but the first should have ooo_okay cleared */ | ||
2934 | skb->ooo_okay = 0; | ||
2935 | |||
2930 | segs = skb_segment(skb, features); | 2936 | segs = skb_segment(skb, features); |
2931 | if (IS_ERR(segs)) | 2937 | if (IS_ERR(segs)) |
2932 | goto out; | 2938 | goto out; |
2933 | 2939 | ||
2940 | /* Only first segment might have ooo_okay set */ | ||
2941 | segs->ooo_okay = ooo_okay; | ||
2942 | |||
2934 | delta = htonl(oldlen + (thlen + mss)); | 2943 | delta = htonl(oldlen + (thlen + mss)); |
2935 | 2944 | ||
2936 | skb = segs; | 2945 | skb = segs; |
@@ -2950,6 +2959,17 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, | |||
2950 | thlen, skb->csum)); | 2959 | thlen, skb->csum)); |
2951 | 2960 | ||
2952 | seq += mss; | 2961 | seq += mss; |
2962 | if (copy_destructor) { | ||
2963 | skb->destructor = gso_skb->destructor; | ||
2964 | skb->sk = gso_skb->sk; | ||
2965 | /* {tcp|sock}_wfree() use exact truesize accounting : | ||
2966 | * sum(skb->truesize) MUST be exactly be gso_skb->truesize | ||
2967 | * So we account mss bytes of 'true size' for each segment. | ||
2968 | * The last segment will contain the remaining. | ||
2969 | */ | ||
2970 | skb->truesize = mss; | ||
2971 | gso_skb->truesize -= mss; | ||
2972 | } | ||
2953 | skb = skb->next; | 2973 | skb = skb->next; |
2954 | th = tcp_hdr(skb); | 2974 | th = tcp_hdr(skb); |
2955 | 2975 | ||
@@ -2962,7 +2982,7 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, | |||
2962 | * is freed at TX completion, and not right now when gso_skb | 2982 | * is freed at TX completion, and not right now when gso_skb |
2963 | * is freed by GSO engine | 2983 | * is freed by GSO engine |
2964 | */ | 2984 | */ |
2965 | if (gso_skb->destructor == tcp_wfree) { | 2985 | if (copy_destructor) { |
2966 | swap(gso_skb->sk, skb->sk); | 2986 | swap(gso_skb->sk, skb->sk); |
2967 | swap(gso_skb->destructor, skb->destructor); | 2987 | swap(gso_skb->destructor, skb->destructor); |
2968 | swap(gso_skb->truesize, skb->truesize); | 2988 | swap(gso_skb->truesize, skb->truesize); |
@@ -3269,8 +3289,11 @@ int tcp_md5_hash_skb_data(struct tcp_md5sig_pool *hp, | |||
3269 | 3289 | ||
3270 | for (i = 0; i < shi->nr_frags; ++i) { | 3290 | for (i = 0; i < shi->nr_frags; ++i) { |
3271 | const struct skb_frag_struct *f = &shi->frags[i]; | 3291 | const struct skb_frag_struct *f = &shi->frags[i]; |
3272 | struct page *page = skb_frag_page(f); | 3292 | unsigned int offset = f->page_offset; |
3273 | sg_set_page(&sg, page, skb_frag_size(f), f->page_offset); | 3293 | struct page *page = skb_frag_page(f) + (offset >> PAGE_SHIFT); |
3294 | |||
3295 | sg_set_page(&sg, page, skb_frag_size(f), | ||
3296 | offset_in_page(offset)); | ||
3274 | if (crypto_hash_update(desc, &sg, skb_frag_size(f))) | 3297 | if (crypto_hash_update(desc, &sg, skb_frag_size(f))) |
3275 | return 1; | 3298 | return 1; |
3276 | } | 3299 | } |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 08bbe6096528..9c6225780bd5 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -2743,8 +2743,8 @@ static void tcp_process_loss(struct sock *sk, int flag, bool is_dupack) | |||
2743 | * tcp_xmit_retransmit_queue(). | 2743 | * tcp_xmit_retransmit_queue(). |
2744 | */ | 2744 | */ |
2745 | static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked, | 2745 | static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked, |
2746 | int prior_sacked, bool is_dupack, | 2746 | int prior_sacked, int prior_packets, |
2747 | int flag) | 2747 | bool is_dupack, int flag) |
2748 | { | 2748 | { |
2749 | struct inet_connection_sock *icsk = inet_csk(sk); | 2749 | struct inet_connection_sock *icsk = inet_csk(sk); |
2750 | struct tcp_sock *tp = tcp_sk(sk); | 2750 | struct tcp_sock *tp = tcp_sk(sk); |
@@ -2804,7 +2804,8 @@ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked, | |||
2804 | tcp_add_reno_sack(sk); | 2804 | tcp_add_reno_sack(sk); |
2805 | } else | 2805 | } else |
2806 | do_lost = tcp_try_undo_partial(sk, pkts_acked); | 2806 | do_lost = tcp_try_undo_partial(sk, pkts_acked); |
2807 | newly_acked_sacked = pkts_acked + tp->sacked_out - prior_sacked; | 2807 | newly_acked_sacked = prior_packets - tp->packets_out + |
2808 | tp->sacked_out - prior_sacked; | ||
2808 | break; | 2809 | break; |
2809 | case TCP_CA_Loss: | 2810 | case TCP_CA_Loss: |
2810 | tcp_process_loss(sk, flag, is_dupack); | 2811 | tcp_process_loss(sk, flag, is_dupack); |
@@ -2818,7 +2819,8 @@ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked, | |||
2818 | if (is_dupack) | 2819 | if (is_dupack) |
2819 | tcp_add_reno_sack(sk); | 2820 | tcp_add_reno_sack(sk); |
2820 | } | 2821 | } |
2821 | newly_acked_sacked = pkts_acked + tp->sacked_out - prior_sacked; | 2822 | newly_acked_sacked = prior_packets - tp->packets_out + |
2823 | tp->sacked_out - prior_sacked; | ||
2822 | 2824 | ||
2823 | if (icsk->icsk_ca_state <= TCP_CA_Disorder) | 2825 | if (icsk->icsk_ca_state <= TCP_CA_Disorder) |
2824 | tcp_try_undo_dsack(sk); | 2826 | tcp_try_undo_dsack(sk); |
@@ -3330,9 +3332,10 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) | |||
3330 | bool is_dupack = false; | 3332 | bool is_dupack = false; |
3331 | u32 prior_in_flight; | 3333 | u32 prior_in_flight; |
3332 | u32 prior_fackets; | 3334 | u32 prior_fackets; |
3333 | int prior_packets; | 3335 | int prior_packets = tp->packets_out; |
3334 | int prior_sacked = tp->sacked_out; | 3336 | int prior_sacked = tp->sacked_out; |
3335 | int pkts_acked = 0; | 3337 | int pkts_acked = 0; |
3338 | int previous_packets_out = 0; | ||
3336 | 3339 | ||
3337 | /* If the ack is older than previous acks | 3340 | /* If the ack is older than previous acks |
3338 | * then we can probably ignore it. | 3341 | * then we can probably ignore it. |
@@ -3403,14 +3406,14 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) | |||
3403 | sk->sk_err_soft = 0; | 3406 | sk->sk_err_soft = 0; |
3404 | icsk->icsk_probes_out = 0; | 3407 | icsk->icsk_probes_out = 0; |
3405 | tp->rcv_tstamp = tcp_time_stamp; | 3408 | tp->rcv_tstamp = tcp_time_stamp; |
3406 | prior_packets = tp->packets_out; | ||
3407 | if (!prior_packets) | 3409 | if (!prior_packets) |
3408 | goto no_queue; | 3410 | goto no_queue; |
3409 | 3411 | ||
3410 | /* See if we can take anything off of the retransmit queue. */ | 3412 | /* See if we can take anything off of the retransmit queue. */ |
3413 | previous_packets_out = tp->packets_out; | ||
3411 | flag |= tcp_clean_rtx_queue(sk, prior_fackets, prior_snd_una); | 3414 | flag |= tcp_clean_rtx_queue(sk, prior_fackets, prior_snd_una); |
3412 | 3415 | ||
3413 | pkts_acked = prior_packets - tp->packets_out; | 3416 | pkts_acked = previous_packets_out - tp->packets_out; |
3414 | 3417 | ||
3415 | if (tcp_ack_is_dubious(sk, flag)) { | 3418 | if (tcp_ack_is_dubious(sk, flag)) { |
3416 | /* Advance CWND, if state allows this. */ | 3419 | /* Advance CWND, if state allows this. */ |
@@ -3418,7 +3421,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) | |||
3418 | tcp_cong_avoid(sk, ack, prior_in_flight); | 3421 | tcp_cong_avoid(sk, ack, prior_in_flight); |
3419 | is_dupack = !(flag & (FLAG_SND_UNA_ADVANCED | FLAG_NOT_DUP)); | 3422 | is_dupack = !(flag & (FLAG_SND_UNA_ADVANCED | FLAG_NOT_DUP)); |
3420 | tcp_fastretrans_alert(sk, pkts_acked, prior_sacked, | 3423 | tcp_fastretrans_alert(sk, pkts_acked, prior_sacked, |
3421 | is_dupack, flag); | 3424 | prior_packets, is_dupack, flag); |
3422 | } else { | 3425 | } else { |
3423 | if (flag & FLAG_DATA_ACKED) | 3426 | if (flag & FLAG_DATA_ACKED) |
3424 | tcp_cong_avoid(sk, ack, prior_in_flight); | 3427 | tcp_cong_avoid(sk, ack, prior_in_flight); |
@@ -3441,7 +3444,7 @@ no_queue: | |||
3441 | /* If data was DSACKed, see if we can undo a cwnd reduction. */ | 3444 | /* If data was DSACKed, see if we can undo a cwnd reduction. */ |
3442 | if (flag & FLAG_DSACKING_ACK) | 3445 | if (flag & FLAG_DSACKING_ACK) |
3443 | tcp_fastretrans_alert(sk, pkts_acked, prior_sacked, | 3446 | tcp_fastretrans_alert(sk, pkts_acked, prior_sacked, |
3444 | is_dupack, flag); | 3447 | prior_packets, is_dupack, flag); |
3445 | /* If this ack opens up a zero window, clear backoff. It was | 3448 | /* If this ack opens up a zero window, clear backoff. It was |
3446 | * being used to time the probes, and is probably far higher than | 3449 | * being used to time the probes, and is probably far higher than |
3447 | * it needs to be for normal retransmission. | 3450 | * it needs to be for normal retransmission. |
@@ -3464,7 +3467,7 @@ old_ack: | |||
3464 | if (TCP_SKB_CB(skb)->sacked) { | 3467 | if (TCP_SKB_CB(skb)->sacked) { |
3465 | flag |= tcp_sacktag_write_queue(sk, skb, prior_snd_una); | 3468 | flag |= tcp_sacktag_write_queue(sk, skb, prior_snd_una); |
3466 | tcp_fastretrans_alert(sk, pkts_acked, prior_sacked, | 3469 | tcp_fastretrans_alert(sk, pkts_acked, prior_sacked, |
3467 | is_dupack, flag); | 3470 | prior_packets, is_dupack, flag); |
3468 | } | 3471 | } |
3469 | 3472 | ||
3470 | SOCK_DEBUG(sk, "Ack %u before %u:%u\n", ack, tp->snd_una, tp->snd_nxt); | 3473 | SOCK_DEBUG(sk, "Ack %u before %u:%u\n", ack, tp->snd_una, tp->snd_nxt); |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 536d40929ba6..ec335fabd5cc 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -874,11 +874,13 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, | |||
874 | &md5); | 874 | &md5); |
875 | tcp_header_size = tcp_options_size + sizeof(struct tcphdr); | 875 | tcp_header_size = tcp_options_size + sizeof(struct tcphdr); |
876 | 876 | ||
877 | if (tcp_packets_in_flight(tp) == 0) { | 877 | if (tcp_packets_in_flight(tp) == 0) |
878 | tcp_ca_event(sk, CA_EVENT_TX_START); | 878 | tcp_ca_event(sk, CA_EVENT_TX_START); |
879 | skb->ooo_okay = 1; | 879 | |
880 | } else | 880 | /* if no packet is in qdisc/device queue, then allow XPS to select |
881 | skb->ooo_okay = 0; | 881 | * another queue. |
882 | */ | ||
883 | skb->ooo_okay = sk_wmem_alloc_get(sk) == 0; | ||
882 | 884 | ||
883 | skb_push(skb, tcp_header_size); | 885 | skb_push(skb, tcp_header_size); |
884 | skb_reset_transport_header(skb); | 886 | skb_reset_transport_header(skb); |
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index d3ddd8400354..ecd60733e5e2 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c | |||
@@ -1081,6 +1081,7 @@ static int ip6gre_tunnel_ioctl(struct net_device *dev, | |||
1081 | } | 1081 | } |
1082 | if (t == NULL) | 1082 | if (t == NULL) |
1083 | t = netdev_priv(dev); | 1083 | t = netdev_priv(dev); |
1084 | memset(&p, 0, sizeof(p)); | ||
1084 | ip6gre_tnl_parm_to_user(&p, &t->parms); | 1085 | ip6gre_tnl_parm_to_user(&p, &t->parms); |
1085 | if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p))) | 1086 | if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p))) |
1086 | err = -EFAULT; | 1087 | err = -EFAULT; |
@@ -1128,6 +1129,7 @@ static int ip6gre_tunnel_ioctl(struct net_device *dev, | |||
1128 | if (t) { | 1129 | if (t) { |
1129 | err = 0; | 1130 | err = 0; |
1130 | 1131 | ||
1132 | memset(&p, 0, sizeof(p)); | ||
1131 | ip6gre_tnl_parm_to_user(&p, &t->parms); | 1133 | ip6gre_tnl_parm_to_user(&p, &t->parms); |
1132 | if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p))) | 1134 | if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p))) |
1133 | err = -EFAULT; | 1135 | err = -EFAULT; |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index d2eedf192330..dae1949019d7 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -1147,7 +1147,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1147 | if (WARN_ON(np->cork.opt)) | 1147 | if (WARN_ON(np->cork.opt)) |
1148 | return -EINVAL; | 1148 | return -EINVAL; |
1149 | 1149 | ||
1150 | np->cork.opt = kmalloc(opt->tot_len, sk->sk_allocation); | 1150 | np->cork.opt = kzalloc(opt->tot_len, sk->sk_allocation); |
1151 | if (unlikely(np->cork.opt == NULL)) | 1151 | if (unlikely(np->cork.opt == NULL)) |
1152 | return -ENOBUFS; | 1152 | return -ENOBUFS; |
1153 | 1153 | ||
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 71167069b394..0a17ed9eaf39 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -1890,6 +1890,17 @@ void tcp6_proc_exit(struct net *net) | |||
1890 | } | 1890 | } |
1891 | #endif | 1891 | #endif |
1892 | 1892 | ||
1893 | static void tcp_v6_clear_sk(struct sock *sk, int size) | ||
1894 | { | ||
1895 | struct inet_sock *inet = inet_sk(sk); | ||
1896 | |||
1897 | /* we do not want to clear pinet6 field, because of RCU lookups */ | ||
1898 | sk_prot_clear_nulls(sk, offsetof(struct inet_sock, pinet6)); | ||
1899 | |||
1900 | size -= offsetof(struct inet_sock, pinet6) + sizeof(inet->pinet6); | ||
1901 | memset(&inet->pinet6 + 1, 0, size); | ||
1902 | } | ||
1903 | |||
1893 | struct proto tcpv6_prot = { | 1904 | struct proto tcpv6_prot = { |
1894 | .name = "TCPv6", | 1905 | .name = "TCPv6", |
1895 | .owner = THIS_MODULE, | 1906 | .owner = THIS_MODULE, |
@@ -1933,6 +1944,7 @@ struct proto tcpv6_prot = { | |||
1933 | #ifdef CONFIG_MEMCG_KMEM | 1944 | #ifdef CONFIG_MEMCG_KMEM |
1934 | .proto_cgroup = tcp_proto_cgroup, | 1945 | .proto_cgroup = tcp_proto_cgroup, |
1935 | #endif | 1946 | #endif |
1947 | .clear_sk = tcp_v6_clear_sk, | ||
1936 | }; | 1948 | }; |
1937 | 1949 | ||
1938 | static const struct inet6_protocol tcpv6_protocol = { | 1950 | static const struct inet6_protocol tcpv6_protocol = { |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index d4defdd44937..42923b14dfa6 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -1432,6 +1432,17 @@ void udp6_proc_exit(struct net *net) { | |||
1432 | } | 1432 | } |
1433 | #endif /* CONFIG_PROC_FS */ | 1433 | #endif /* CONFIG_PROC_FS */ |
1434 | 1434 | ||
1435 | void udp_v6_clear_sk(struct sock *sk, int size) | ||
1436 | { | ||
1437 | struct inet_sock *inet = inet_sk(sk); | ||
1438 | |||
1439 | /* we do not want to clear pinet6 field, because of RCU lookups */ | ||
1440 | sk_prot_clear_portaddr_nulls(sk, offsetof(struct inet_sock, pinet6)); | ||
1441 | |||
1442 | size -= offsetof(struct inet_sock, pinet6) + sizeof(inet->pinet6); | ||
1443 | memset(&inet->pinet6 + 1, 0, size); | ||
1444 | } | ||
1445 | |||
1435 | /* ------------------------------------------------------------------------ */ | 1446 | /* ------------------------------------------------------------------------ */ |
1436 | 1447 | ||
1437 | struct proto udpv6_prot = { | 1448 | struct proto udpv6_prot = { |
@@ -1462,7 +1473,7 @@ struct proto udpv6_prot = { | |||
1462 | .compat_setsockopt = compat_udpv6_setsockopt, | 1473 | .compat_setsockopt = compat_udpv6_setsockopt, |
1463 | .compat_getsockopt = compat_udpv6_getsockopt, | 1474 | .compat_getsockopt = compat_udpv6_getsockopt, |
1464 | #endif | 1475 | #endif |
1465 | .clear_sk = sk_prot_clear_portaddr_nulls, | 1476 | .clear_sk = udp_v6_clear_sk, |
1466 | }; | 1477 | }; |
1467 | 1478 | ||
1468 | static struct inet_protosw udpv6_protosw = { | 1479 | static struct inet_protosw udpv6_protosw = { |
diff --git a/net/ipv6/udp_impl.h b/net/ipv6/udp_impl.h index d7571046bfc4..4691ed50a928 100644 --- a/net/ipv6/udp_impl.h +++ b/net/ipv6/udp_impl.h | |||
@@ -31,6 +31,8 @@ extern int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk, | |||
31 | extern int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb); | 31 | extern int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb); |
32 | extern void udpv6_destroy_sock(struct sock *sk); | 32 | extern void udpv6_destroy_sock(struct sock *sk); |
33 | 33 | ||
34 | extern void udp_v6_clear_sk(struct sock *sk, int size); | ||
35 | |||
34 | #ifdef CONFIG_PROC_FS | 36 | #ifdef CONFIG_PROC_FS |
35 | extern int udp6_seq_show(struct seq_file *seq, void *v); | 37 | extern int udp6_seq_show(struct seq_file *seq, void *v); |
36 | #endif | 38 | #endif |
diff --git a/net/ipv6/udplite.c b/net/ipv6/udplite.c index 1d08e21d9f69..dfcc4be46898 100644 --- a/net/ipv6/udplite.c +++ b/net/ipv6/udplite.c | |||
@@ -56,7 +56,7 @@ struct proto udplitev6_prot = { | |||
56 | .compat_setsockopt = compat_udpv6_setsockopt, | 56 | .compat_setsockopt = compat_udpv6_setsockopt, |
57 | .compat_getsockopt = compat_udpv6_getsockopt, | 57 | .compat_getsockopt = compat_udpv6_getsockopt, |
58 | #endif | 58 | #endif |
59 | .clear_sk = sk_prot_clear_portaddr_nulls, | 59 | .clear_sk = udp_v6_clear_sk, |
60 | }; | 60 | }; |
61 | 61 | ||
62 | static struct inet_protosw udplite6_protosw = { | 62 | static struct inet_protosw udplite6_protosw = { |
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index 4ef7bdb65440..23ed03d786c8 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c | |||
@@ -103,8 +103,10 @@ static int xfrm6_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, | |||
103 | dev_hold(dev); | 103 | dev_hold(dev); |
104 | 104 | ||
105 | xdst->u.rt6.rt6i_idev = in6_dev_get(dev); | 105 | xdst->u.rt6.rt6i_idev = in6_dev_get(dev); |
106 | if (!xdst->u.rt6.rt6i_idev) | 106 | if (!xdst->u.rt6.rt6i_idev) { |
107 | dev_put(dev); | ||
107 | return -ENODEV; | 108 | return -ENODEV; |
109 | } | ||
108 | 110 | ||
109 | rt6_transfer_peer(&xdst->u.rt6, rt); | 111 | rt6_transfer_peer(&xdst->u.rt6, rt); |
110 | 112 | ||
diff --git a/net/irda/irlap_frame.c b/net/irda/irlap_frame.c index 8c004161a843..9ea0c933b9ff 100644 --- a/net/irda/irlap_frame.c +++ b/net/irda/irlap_frame.c | |||
@@ -544,7 +544,7 @@ static void irlap_recv_discovery_xid_cmd(struct irlap_cb *self, | |||
544 | /* | 544 | /* |
545 | * We now have some discovery info to deliver! | 545 | * We now have some discovery info to deliver! |
546 | */ | 546 | */ |
547 | discovery = kmalloc(sizeof(discovery_t), GFP_ATOMIC); | 547 | discovery = kzalloc(sizeof(discovery_t), GFP_ATOMIC); |
548 | if (!discovery) { | 548 | if (!discovery) { |
549 | IRDA_WARNING("%s: unable to malloc!\n", __func__); | 549 | IRDA_WARNING("%s: unable to malloc!\n", __func__); |
550 | return; | 550 | return; |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 158e6eb188d3..44be28cfc6c4 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -1267,6 +1267,7 @@ void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata); | |||
1267 | void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata); | 1267 | void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata); |
1268 | void ieee80211_mgd_conn_tx_status(struct ieee80211_sub_if_data *sdata, | 1268 | void ieee80211_mgd_conn_tx_status(struct ieee80211_sub_if_data *sdata, |
1269 | __le16 fc, bool acked); | 1269 | __le16 fc, bool acked); |
1270 | void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata); | ||
1270 | 1271 | ||
1271 | /* IBSS code */ | 1272 | /* IBSS code */ |
1272 | void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local); | 1273 | void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local); |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 29620bfc7a69..a46e490f20dd 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -1015,7 +1015,8 @@ static void ieee80211_chswitch_timer(unsigned long data) | |||
1015 | 1015 | ||
1016 | static void | 1016 | static void |
1017 | ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | 1017 | ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, |
1018 | u64 timestamp, struct ieee802_11_elems *elems) | 1018 | u64 timestamp, struct ieee802_11_elems *elems, |
1019 | bool beacon) | ||
1019 | { | 1020 | { |
1020 | struct ieee80211_local *local = sdata->local; | 1021 | struct ieee80211_local *local = sdata->local; |
1021 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 1022 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
@@ -1032,6 +1033,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
1032 | struct cfg80211_chan_def new_vht_chandef = {}; | 1033 | struct cfg80211_chan_def new_vht_chandef = {}; |
1033 | const struct ieee80211_sec_chan_offs_ie *sec_chan_offs; | 1034 | const struct ieee80211_sec_chan_offs_ie *sec_chan_offs; |
1034 | const struct ieee80211_wide_bw_chansw_ie *wide_bw_chansw_ie; | 1035 | const struct ieee80211_wide_bw_chansw_ie *wide_bw_chansw_ie; |
1036 | const struct ieee80211_ht_operation *ht_oper; | ||
1035 | int secondary_channel_offset = -1; | 1037 | int secondary_channel_offset = -1; |
1036 | 1038 | ||
1037 | ASSERT_MGD_MTX(ifmgd); | 1039 | ASSERT_MGD_MTX(ifmgd); |
@@ -1048,11 +1050,14 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
1048 | 1050 | ||
1049 | sec_chan_offs = elems->sec_chan_offs; | 1051 | sec_chan_offs = elems->sec_chan_offs; |
1050 | wide_bw_chansw_ie = elems->wide_bw_chansw_ie; | 1052 | wide_bw_chansw_ie = elems->wide_bw_chansw_ie; |
1053 | ht_oper = elems->ht_operation; | ||
1051 | 1054 | ||
1052 | if (ifmgd->flags & (IEEE80211_STA_DISABLE_HT | | 1055 | if (ifmgd->flags & (IEEE80211_STA_DISABLE_HT | |
1053 | IEEE80211_STA_DISABLE_40MHZ)) { | 1056 | IEEE80211_STA_DISABLE_40MHZ)) { |
1054 | sec_chan_offs = NULL; | 1057 | sec_chan_offs = NULL; |
1055 | wide_bw_chansw_ie = NULL; | 1058 | wide_bw_chansw_ie = NULL; |
1059 | /* only used for bandwidth here */ | ||
1060 | ht_oper = NULL; | ||
1056 | } | 1061 | } |
1057 | 1062 | ||
1058 | if (ifmgd->flags & IEEE80211_STA_DISABLE_VHT) | 1063 | if (ifmgd->flags & IEEE80211_STA_DISABLE_VHT) |
@@ -1094,10 +1099,20 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
1094 | return; | 1099 | return; |
1095 | } | 1100 | } |
1096 | 1101 | ||
1097 | if (sec_chan_offs) { | 1102 | if (!beacon && sec_chan_offs) { |
1098 | secondary_channel_offset = sec_chan_offs->sec_chan_offs; | 1103 | secondary_channel_offset = sec_chan_offs->sec_chan_offs; |
1104 | } else if (beacon && ht_oper) { | ||
1105 | secondary_channel_offset = | ||
1106 | ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET; | ||
1099 | } else if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) { | 1107 | } else if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) { |
1100 | /* if HT is enabled and the IE not present, it's still HT */ | 1108 | /* |
1109 | * If it's not a beacon, HT is enabled and the IE not present, | ||
1110 | * it's 20 MHz, 802.11-2012 8.5.2.6: | ||
1111 | * This element [the Secondary Channel Offset Element] is | ||
1112 | * present when switching to a 40 MHz channel. It may be | ||
1113 | * present when switching to a 20 MHz channel (in which | ||
1114 | * case the secondary channel offset is set to SCN). | ||
1115 | */ | ||
1101 | secondary_channel_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE; | 1116 | secondary_channel_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE; |
1102 | } | 1117 | } |
1103 | 1118 | ||
@@ -2796,7 +2811,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
2796 | mutex_unlock(&local->iflist_mtx); | 2811 | mutex_unlock(&local->iflist_mtx); |
2797 | } | 2812 | } |
2798 | 2813 | ||
2799 | ieee80211_sta_process_chanswitch(sdata, rx_status->mactime, elems); | 2814 | ieee80211_sta_process_chanswitch(sdata, rx_status->mactime, |
2815 | elems, true); | ||
2800 | 2816 | ||
2801 | } | 2817 | } |
2802 | 2818 | ||
@@ -3210,7 +3226,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
3210 | 3226 | ||
3211 | ieee80211_sta_process_chanswitch(sdata, | 3227 | ieee80211_sta_process_chanswitch(sdata, |
3212 | rx_status->mactime, | 3228 | rx_status->mactime, |
3213 | &elems); | 3229 | &elems, false); |
3214 | } else if (mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) { | 3230 | } else if (mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) { |
3215 | ies_len = skb->len - | 3231 | ies_len = skb->len - |
3216 | offsetof(struct ieee80211_mgmt, | 3232 | offsetof(struct ieee80211_mgmt, |
@@ -3232,7 +3248,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
3232 | 3248 | ||
3233 | ieee80211_sta_process_chanswitch(sdata, | 3249 | ieee80211_sta_process_chanswitch(sdata, |
3234 | rx_status->mactime, | 3250 | rx_status->mactime, |
3235 | &elems); | 3251 | &elems, false); |
3236 | } | 3252 | } |
3237 | break; | 3253 | break; |
3238 | } | 3254 | } |
@@ -3623,6 +3639,31 @@ static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata) | |||
3623 | } | 3639 | } |
3624 | } | 3640 | } |
3625 | 3641 | ||
3642 | #ifdef CONFIG_PM | ||
3643 | void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata) | ||
3644 | { | ||
3645 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
3646 | |||
3647 | mutex_lock(&ifmgd->mtx); | ||
3648 | if (!ifmgd->associated) { | ||
3649 | mutex_unlock(&ifmgd->mtx); | ||
3650 | return; | ||
3651 | } | ||
3652 | |||
3653 | if (sdata->flags & IEEE80211_SDATA_DISCONNECT_RESUME) { | ||
3654 | sdata->flags &= ~IEEE80211_SDATA_DISCONNECT_RESUME; | ||
3655 | mlme_dbg(sdata, "driver requested disconnect after resume\n"); | ||
3656 | ieee80211_sta_connection_lost(sdata, | ||
3657 | ifmgd->associated->bssid, | ||
3658 | WLAN_REASON_UNSPECIFIED, | ||
3659 | true); | ||
3660 | mutex_unlock(&ifmgd->mtx); | ||
3661 | return; | ||
3662 | } | ||
3663 | mutex_unlock(&ifmgd->mtx); | ||
3664 | } | ||
3665 | #endif | ||
3666 | |||
3626 | /* interface setup */ | 3667 | /* interface setup */ |
3627 | void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) | 3668 | void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) |
3628 | { | 3669 | { |
@@ -4329,7 +4370,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
4329 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 4370 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
4330 | u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; | 4371 | u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; |
4331 | bool tx = !req->local_state_change; | 4372 | bool tx = !req->local_state_change; |
4332 | bool sent_frame = false; | 4373 | bool report_frame = false; |
4333 | 4374 | ||
4334 | mutex_lock(&ifmgd->mtx); | 4375 | mutex_lock(&ifmgd->mtx); |
4335 | 4376 | ||
@@ -4346,7 +4387,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
4346 | ieee80211_destroy_auth_data(sdata, false); | 4387 | ieee80211_destroy_auth_data(sdata, false); |
4347 | mutex_unlock(&ifmgd->mtx); | 4388 | mutex_unlock(&ifmgd->mtx); |
4348 | 4389 | ||
4349 | sent_frame = tx; | 4390 | report_frame = true; |
4350 | goto out; | 4391 | goto out; |
4351 | } | 4392 | } |
4352 | 4393 | ||
@@ -4354,12 +4395,12 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
4354 | ether_addr_equal(ifmgd->associated->bssid, req->bssid)) { | 4395 | ether_addr_equal(ifmgd->associated->bssid, req->bssid)) { |
4355 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, | 4396 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, |
4356 | req->reason_code, tx, frame_buf); | 4397 | req->reason_code, tx, frame_buf); |
4357 | sent_frame = tx; | 4398 | report_frame = true; |
4358 | } | 4399 | } |
4359 | mutex_unlock(&ifmgd->mtx); | 4400 | mutex_unlock(&ifmgd->mtx); |
4360 | 4401 | ||
4361 | out: | 4402 | out: |
4362 | if (sent_frame) | 4403 | if (report_frame) |
4363 | __cfg80211_send_deauth(sdata->dev, frame_buf, | 4404 | __cfg80211_send_deauth(sdata->dev, frame_buf, |
4364 | IEEE80211_DEAUTH_FRAME_LEN); | 4405 | IEEE80211_DEAUTH_FRAME_LEN); |
4365 | 4406 | ||
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 0d51877efdb7..d3f414fe67e0 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c | |||
@@ -688,8 +688,15 @@ int rate_control_set_rates(struct ieee80211_hw *hw, | |||
688 | struct ieee80211_sta *pubsta, | 688 | struct ieee80211_sta *pubsta, |
689 | struct ieee80211_sta_rates *rates) | 689 | struct ieee80211_sta_rates *rates) |
690 | { | 690 | { |
691 | struct ieee80211_sta_rates *old = rcu_dereference(pubsta->rates); | 691 | struct ieee80211_sta_rates *old; |
692 | 692 | ||
693 | /* | ||
694 | * mac80211 guarantees that this function will not be called | ||
695 | * concurrently, so the following RCU access is safe, even without | ||
696 | * extra locking. This can not be checked easily, so we just set | ||
697 | * the condition to true. | ||
698 | */ | ||
699 | old = rcu_dereference_protected(pubsta->rates, true); | ||
693 | rcu_assign_pointer(pubsta->rates, rates); | 700 | rcu_assign_pointer(pubsta->rates, rates); |
694 | if (old) | 701 | if (old) |
695 | kfree_rcu(old, rcu_head); | 702 | kfree_rcu(old, rcu_head); |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index c8447af76ead..8e2952620256 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -3036,6 +3036,9 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx, | |||
3036 | * and location updates. Note that mac80211 | 3036 | * and location updates. Note that mac80211 |
3037 | * itself never looks at these frames. | 3037 | * itself never looks at these frames. |
3038 | */ | 3038 | */ |
3039 | if (!multicast && | ||
3040 | !ether_addr_equal(sdata->vif.addr, hdr->addr1)) | ||
3041 | return 0; | ||
3039 | if (ieee80211_is_public_action(hdr, skb->len)) | 3042 | if (ieee80211_is_public_action(hdr, skb->len)) |
3040 | return 1; | 3043 | return 1; |
3041 | if (!ieee80211_is_beacon(hdr->frame_control)) | 3044 | if (!ieee80211_is_beacon(hdr->frame_control)) |
diff --git a/net/mac80211/tkip.c b/net/mac80211/tkip.c index 3ed801d90f1e..124b1fdc20d0 100644 --- a/net/mac80211/tkip.c +++ b/net/mac80211/tkip.c | |||
@@ -208,10 +208,10 @@ void ieee80211_get_tkip_p2k(struct ieee80211_key_conf *keyconf, | |||
208 | u32 iv32 = get_unaligned_le32(&data[4]); | 208 | u32 iv32 = get_unaligned_le32(&data[4]); |
209 | u16 iv16 = data[2] | (data[0] << 8); | 209 | u16 iv16 = data[2] | (data[0] << 8); |
210 | 210 | ||
211 | spin_lock_bh(&key->u.tkip.txlock); | 211 | spin_lock(&key->u.tkip.txlock); |
212 | ieee80211_compute_tkip_p1k(key, iv32); | 212 | ieee80211_compute_tkip_p1k(key, iv32); |
213 | tkip_mixing_phase2(tk, ctx, iv16, p2k); | 213 | tkip_mixing_phase2(tk, ctx, iv16, p2k); |
214 | spin_unlock_bh(&key->u.tkip.txlock); | 214 | spin_unlock(&key->u.tkip.txlock); |
215 | } | 215 | } |
216 | EXPORT_SYMBOL(ieee80211_get_tkip_p2k); | 216 | EXPORT_SYMBOL(ieee80211_get_tkip_p2k); |
217 | 217 | ||
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 3f87fa468b1f..27e07150eb46 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -1740,6 +1740,13 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1740 | mb(); | 1740 | mb(); |
1741 | local->resuming = false; | 1741 | local->resuming = false; |
1742 | 1742 | ||
1743 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
1744 | if (!ieee80211_sdata_running(sdata)) | ||
1745 | continue; | ||
1746 | if (sdata->vif.type == NL80211_IFTYPE_STATION) | ||
1747 | ieee80211_sta_restart(sdata); | ||
1748 | } | ||
1749 | |||
1743 | mod_timer(&local->sta_cleanup, jiffies + 1); | 1750 | mod_timer(&local->sta_cleanup, jiffies + 1); |
1744 | #else | 1751 | #else |
1745 | WARN_ON(1); | 1752 | WARN_ON(1); |
diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c index 388656d5a9ec..3b18dd1be7d9 100644 --- a/net/netfilter/nf_log.c +++ b/net/netfilter/nf_log.c | |||
@@ -148,7 +148,7 @@ void nf_log_packet(struct net *net, | |||
148 | va_start(args, fmt); | 148 | va_start(args, fmt); |
149 | vsnprintf(prefix, sizeof(prefix), fmt, args); | 149 | vsnprintf(prefix, sizeof(prefix), fmt, args); |
150 | va_end(args); | 150 | va_end(args); |
151 | logger->logfn(pf, hooknum, skb, in, out, loginfo, prefix); | 151 | logger->logfn(net, pf, hooknum, skb, in, out, loginfo, prefix); |
152 | } | 152 | } |
153 | rcu_read_unlock(); | 153 | rcu_read_unlock(); |
154 | } | 154 | } |
@@ -368,17 +368,20 @@ static int __net_init nf_log_net_init(struct net *net) | |||
368 | return 0; | 368 | return 0; |
369 | 369 | ||
370 | out_sysctl: | 370 | out_sysctl: |
371 | #ifdef CONFIG_PROC_FS | ||
371 | /* For init_net: errors will trigger panic, don't unroll on error. */ | 372 | /* For init_net: errors will trigger panic, don't unroll on error. */ |
372 | if (!net_eq(net, &init_net)) | 373 | if (!net_eq(net, &init_net)) |
373 | remove_proc_entry("nf_log", net->nf.proc_netfilter); | 374 | remove_proc_entry("nf_log", net->nf.proc_netfilter); |
374 | 375 | #endif | |
375 | return ret; | 376 | return ret; |
376 | } | 377 | } |
377 | 378 | ||
378 | static void __net_exit nf_log_net_exit(struct net *net) | 379 | static void __net_exit nf_log_net_exit(struct net *net) |
379 | { | 380 | { |
380 | netfilter_log_sysctl_exit(net); | 381 | netfilter_log_sysctl_exit(net); |
382 | #ifdef CONFIG_PROC_FS | ||
381 | remove_proc_entry("nf_log", net->nf.proc_netfilter); | 383 | remove_proc_entry("nf_log", net->nf.proc_netfilter); |
384 | #endif | ||
382 | } | 385 | } |
383 | 386 | ||
384 | static struct pernet_operations nf_log_net_ops = { | 387 | static struct pernet_operations nf_log_net_ops = { |
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index faf1e9300d8a..962e9792e317 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c | |||
@@ -602,7 +602,8 @@ static struct nf_loginfo default_loginfo = { | |||
602 | 602 | ||
603 | /* log handler for internal netfilter logging api */ | 603 | /* log handler for internal netfilter logging api */ |
604 | void | 604 | void |
605 | nfulnl_log_packet(u_int8_t pf, | 605 | nfulnl_log_packet(struct net *net, |
606 | u_int8_t pf, | ||
606 | unsigned int hooknum, | 607 | unsigned int hooknum, |
607 | const struct sk_buff *skb, | 608 | const struct sk_buff *skb, |
608 | const struct net_device *in, | 609 | const struct net_device *in, |
@@ -615,7 +616,6 @@ nfulnl_log_packet(u_int8_t pf, | |||
615 | const struct nf_loginfo *li; | 616 | const struct nf_loginfo *li; |
616 | unsigned int qthreshold; | 617 | unsigned int qthreshold; |
617 | unsigned int plen; | 618 | unsigned int plen; |
618 | struct net *net = dev_net(in ? in : out); | ||
619 | struct nfnl_log_net *log = nfnl_log_pernet(net); | 619 | struct nfnl_log_net *log = nfnl_log_pernet(net); |
620 | 620 | ||
621 | if (li_user && li_user->type == NF_LOG_TYPE_ULOG) | 621 | if (li_user && li_user->type == NF_LOG_TYPE_ULOG) |
@@ -1045,7 +1045,9 @@ static int __net_init nfnl_log_net_init(struct net *net) | |||
1045 | 1045 | ||
1046 | static void __net_exit nfnl_log_net_exit(struct net *net) | 1046 | static void __net_exit nfnl_log_net_exit(struct net *net) |
1047 | { | 1047 | { |
1048 | #ifdef CONFIG_PROC_FS | ||
1048 | remove_proc_entry("nfnetlink_log", net->nf.proc_netfilter); | 1049 | remove_proc_entry("nfnetlink_log", net->nf.proc_netfilter); |
1050 | #endif | ||
1049 | } | 1051 | } |
1050 | 1052 | ||
1051 | static struct pernet_operations nfnl_log_net_ops = { | 1053 | static struct pernet_operations nfnl_log_net_ops = { |
diff --git a/net/netfilter/nfnetlink_queue_core.c b/net/netfilter/nfnetlink_queue_core.c index 2e0e835baf72..4e27fa035814 100644 --- a/net/netfilter/nfnetlink_queue_core.c +++ b/net/netfilter/nfnetlink_queue_core.c | |||
@@ -1285,7 +1285,9 @@ static int __net_init nfnl_queue_net_init(struct net *net) | |||
1285 | 1285 | ||
1286 | static void __net_exit nfnl_queue_net_exit(struct net *net) | 1286 | static void __net_exit nfnl_queue_net_exit(struct net *net) |
1287 | { | 1287 | { |
1288 | #ifdef CONFIG_PROC_FS | ||
1288 | remove_proc_entry("nfnetlink_queue", net->nf.proc_netfilter); | 1289 | remove_proc_entry("nfnetlink_queue", net->nf.proc_netfilter); |
1290 | #endif | ||
1289 | } | 1291 | } |
1290 | 1292 | ||
1291 | static struct pernet_operations nfnl_queue_net_ops = { | 1293 | static struct pernet_operations nfnl_queue_net_ops = { |
diff --git a/net/netfilter/xt_LOG.c b/net/netfilter/xt_LOG.c index fe573f6c9e91..491c7d821a0b 100644 --- a/net/netfilter/xt_LOG.c +++ b/net/netfilter/xt_LOG.c | |||
@@ -466,7 +466,8 @@ log_packet_common(struct sbuff *m, | |||
466 | 466 | ||
467 | 467 | ||
468 | static void | 468 | static void |
469 | ipt_log_packet(u_int8_t pf, | 469 | ipt_log_packet(struct net *net, |
470 | u_int8_t pf, | ||
470 | unsigned int hooknum, | 471 | unsigned int hooknum, |
471 | const struct sk_buff *skb, | 472 | const struct sk_buff *skb, |
472 | const struct net_device *in, | 473 | const struct net_device *in, |
@@ -475,7 +476,6 @@ ipt_log_packet(u_int8_t pf, | |||
475 | const char *prefix) | 476 | const char *prefix) |
476 | { | 477 | { |
477 | struct sbuff *m; | 478 | struct sbuff *m; |
478 | struct net *net = dev_net(in ? in : out); | ||
479 | 479 | ||
480 | /* FIXME: Disabled from containers until syslog ns is supported */ | 480 | /* FIXME: Disabled from containers until syslog ns is supported */ |
481 | if (!net_eq(net, &init_net)) | 481 | if (!net_eq(net, &init_net)) |
@@ -797,7 +797,8 @@ fallback: | |||
797 | } | 797 | } |
798 | 798 | ||
799 | static void | 799 | static void |
800 | ip6t_log_packet(u_int8_t pf, | 800 | ip6t_log_packet(struct net *net, |
801 | u_int8_t pf, | ||
801 | unsigned int hooknum, | 802 | unsigned int hooknum, |
802 | const struct sk_buff *skb, | 803 | const struct sk_buff *skb, |
803 | const struct net_device *in, | 804 | const struct net_device *in, |
@@ -806,7 +807,6 @@ ip6t_log_packet(u_int8_t pf, | |||
806 | const char *prefix) | 807 | const char *prefix) |
807 | { | 808 | { |
808 | struct sbuff *m; | 809 | struct sbuff *m; |
809 | struct net *net = dev_net(in ? in : out); | ||
810 | 810 | ||
811 | /* FIXME: Disabled from containers until syslog ns is supported */ | 811 | /* FIXME: Disabled from containers until syslog ns is supported */ |
812 | if (!net_eq(net, &init_net)) | 812 | if (!net_eq(net, &init_net)) |
@@ -833,17 +833,18 @@ log_tg(struct sk_buff *skb, const struct xt_action_param *par) | |||
833 | { | 833 | { |
834 | const struct xt_log_info *loginfo = par->targinfo; | 834 | const struct xt_log_info *loginfo = par->targinfo; |
835 | struct nf_loginfo li; | 835 | struct nf_loginfo li; |
836 | struct net *net = dev_net(par->in ? par->in : par->out); | ||
836 | 837 | ||
837 | li.type = NF_LOG_TYPE_LOG; | 838 | li.type = NF_LOG_TYPE_LOG; |
838 | li.u.log.level = loginfo->level; | 839 | li.u.log.level = loginfo->level; |
839 | li.u.log.logflags = loginfo->logflags; | 840 | li.u.log.logflags = loginfo->logflags; |
840 | 841 | ||
841 | if (par->family == NFPROTO_IPV4) | 842 | if (par->family == NFPROTO_IPV4) |
842 | ipt_log_packet(NFPROTO_IPV4, par->hooknum, skb, par->in, | 843 | ipt_log_packet(net, NFPROTO_IPV4, par->hooknum, skb, par->in, |
843 | par->out, &li, loginfo->prefix); | 844 | par->out, &li, loginfo->prefix); |
844 | #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) | 845 | #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) |
845 | else if (par->family == NFPROTO_IPV6) | 846 | else if (par->family == NFPROTO_IPV6) |
846 | ip6t_log_packet(NFPROTO_IPV6, par->hooknum, skb, par->in, | 847 | ip6t_log_packet(net, NFPROTO_IPV6, par->hooknum, skb, par->in, |
847 | par->out, &li, loginfo->prefix); | 848 | par->out, &li, loginfo->prefix); |
848 | #endif | 849 | #endif |
849 | else | 850 | else |
diff --git a/net/netfilter/xt_NFLOG.c b/net/netfilter/xt_NFLOG.c index a17dd0f589b2..fb7497c928a0 100644 --- a/net/netfilter/xt_NFLOG.c +++ b/net/netfilter/xt_NFLOG.c | |||
@@ -26,13 +26,14 @@ nflog_tg(struct sk_buff *skb, const struct xt_action_param *par) | |||
26 | { | 26 | { |
27 | const struct xt_nflog_info *info = par->targinfo; | 27 | const struct xt_nflog_info *info = par->targinfo; |
28 | struct nf_loginfo li; | 28 | struct nf_loginfo li; |
29 | struct net *net = dev_net(par->in ? par->in : par->out); | ||
29 | 30 | ||
30 | li.type = NF_LOG_TYPE_ULOG; | 31 | li.type = NF_LOG_TYPE_ULOG; |
31 | li.u.ulog.copy_len = info->len; | 32 | li.u.ulog.copy_len = info->len; |
32 | li.u.ulog.group = info->group; | 33 | li.u.ulog.group = info->group; |
33 | li.u.ulog.qthreshold = info->threshold; | 34 | li.u.ulog.qthreshold = info->threshold; |
34 | 35 | ||
35 | nfulnl_log_packet(par->family, par->hooknum, skb, par->in, | 36 | nfulnl_log_packet(net, par->family, par->hooknum, skb, par->in, |
36 | par->out, &li, info->prefix); | 37 | par->out, &li, info->prefix); |
37 | return XT_CONTINUE; | 38 | return XT_CONTINUE; |
38 | } | 39 | } |
diff --git a/net/netfilter/xt_TCPOPTSTRIP.c b/net/netfilter/xt_TCPOPTSTRIP.c index 25fd1c4e1eec..1eb1a44bfd3d 100644 --- a/net/netfilter/xt_TCPOPTSTRIP.c +++ b/net/netfilter/xt_TCPOPTSTRIP.c | |||
@@ -30,17 +30,28 @@ static inline unsigned int optlen(const u_int8_t *opt, unsigned int offset) | |||
30 | 30 | ||
31 | static unsigned int | 31 | static unsigned int |
32 | tcpoptstrip_mangle_packet(struct sk_buff *skb, | 32 | tcpoptstrip_mangle_packet(struct sk_buff *skb, |
33 | const struct xt_tcpoptstrip_target_info *info, | 33 | const struct xt_action_param *par, |
34 | unsigned int tcphoff, unsigned int minlen) | 34 | unsigned int tcphoff, unsigned int minlen) |
35 | { | 35 | { |
36 | const struct xt_tcpoptstrip_target_info *info = par->targinfo; | ||
36 | unsigned int optl, i, j; | 37 | unsigned int optl, i, j; |
37 | struct tcphdr *tcph; | 38 | struct tcphdr *tcph; |
38 | u_int16_t n, o; | 39 | u_int16_t n, o; |
39 | u_int8_t *opt; | 40 | u_int8_t *opt; |
41 | int len; | ||
42 | |||
43 | /* This is a fragment, no TCP header is available */ | ||
44 | if (par->fragoff != 0) | ||
45 | return XT_CONTINUE; | ||
40 | 46 | ||
41 | if (!skb_make_writable(skb, skb->len)) | 47 | if (!skb_make_writable(skb, skb->len)) |
42 | return NF_DROP; | 48 | return NF_DROP; |
43 | 49 | ||
50 | len = skb->len - tcphoff; | ||
51 | if (len < (int)sizeof(struct tcphdr) || | ||
52 | tcp_hdr(skb)->doff * 4 > len) | ||
53 | return NF_DROP; | ||
54 | |||
44 | tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff); | 55 | tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff); |
45 | opt = (u_int8_t *)tcph; | 56 | opt = (u_int8_t *)tcph; |
46 | 57 | ||
@@ -76,7 +87,7 @@ tcpoptstrip_mangle_packet(struct sk_buff *skb, | |||
76 | static unsigned int | 87 | static unsigned int |
77 | tcpoptstrip_tg4(struct sk_buff *skb, const struct xt_action_param *par) | 88 | tcpoptstrip_tg4(struct sk_buff *skb, const struct xt_action_param *par) |
78 | { | 89 | { |
79 | return tcpoptstrip_mangle_packet(skb, par->targinfo, ip_hdrlen(skb), | 90 | return tcpoptstrip_mangle_packet(skb, par, ip_hdrlen(skb), |
80 | sizeof(struct iphdr) + sizeof(struct tcphdr)); | 91 | sizeof(struct iphdr) + sizeof(struct tcphdr)); |
81 | } | 92 | } |
82 | 93 | ||
@@ -94,7 +105,7 @@ tcpoptstrip_tg6(struct sk_buff *skb, const struct xt_action_param *par) | |||
94 | if (tcphoff < 0) | 105 | if (tcphoff < 0) |
95 | return NF_DROP; | 106 | return NF_DROP; |
96 | 107 | ||
97 | return tcpoptstrip_mangle_packet(skb, par->targinfo, tcphoff, | 108 | return tcpoptstrip_mangle_packet(skb, par, tcphoff, |
98 | sizeof(*ipv6h) + sizeof(struct tcphdr)); | 109 | sizeof(*ipv6h) + sizeof(struct tcphdr)); |
99 | } | 110 | } |
100 | #endif | 111 | #endif |
diff --git a/net/netlabel/netlabel_domainhash.c b/net/netlabel/netlabel_domainhash.c index d8d424337550..6bb1d42f0fac 100644 --- a/net/netlabel/netlabel_domainhash.c +++ b/net/netlabel/netlabel_domainhash.c | |||
@@ -245,6 +245,71 @@ static void netlbl_domhsh_audit_add(struct netlbl_dom_map *entry, | |||
245 | } | 245 | } |
246 | } | 246 | } |
247 | 247 | ||
248 | /** | ||
249 | * netlbl_domhsh_validate - Validate a new domain mapping entry | ||
250 | * @entry: the entry to validate | ||
251 | * | ||
252 | * This function validates the new domain mapping entry to ensure that it is | ||
253 | * a valid entry. Returns zero on success, negative values on failure. | ||
254 | * | ||
255 | */ | ||
256 | static int netlbl_domhsh_validate(const struct netlbl_dom_map *entry) | ||
257 | { | ||
258 | struct netlbl_af4list *iter4; | ||
259 | struct netlbl_domaddr4_map *map4; | ||
260 | #if IS_ENABLED(CONFIG_IPV6) | ||
261 | struct netlbl_af6list *iter6; | ||
262 | struct netlbl_domaddr6_map *map6; | ||
263 | #endif /* IPv6 */ | ||
264 | |||
265 | if (entry == NULL) | ||
266 | return -EINVAL; | ||
267 | |||
268 | switch (entry->type) { | ||
269 | case NETLBL_NLTYPE_UNLABELED: | ||
270 | if (entry->type_def.cipsov4 != NULL || | ||
271 | entry->type_def.addrsel != NULL) | ||
272 | return -EINVAL; | ||
273 | break; | ||
274 | case NETLBL_NLTYPE_CIPSOV4: | ||
275 | if (entry->type_def.cipsov4 == NULL) | ||
276 | return -EINVAL; | ||
277 | break; | ||
278 | case NETLBL_NLTYPE_ADDRSELECT: | ||
279 | netlbl_af4list_foreach(iter4, &entry->type_def.addrsel->list4) { | ||
280 | map4 = netlbl_domhsh_addr4_entry(iter4); | ||
281 | switch (map4->type) { | ||
282 | case NETLBL_NLTYPE_UNLABELED: | ||
283 | if (map4->type_def.cipsov4 != NULL) | ||
284 | return -EINVAL; | ||
285 | break; | ||
286 | case NETLBL_NLTYPE_CIPSOV4: | ||
287 | if (map4->type_def.cipsov4 == NULL) | ||
288 | return -EINVAL; | ||
289 | break; | ||
290 | default: | ||
291 | return -EINVAL; | ||
292 | } | ||
293 | } | ||
294 | #if IS_ENABLED(CONFIG_IPV6) | ||
295 | netlbl_af6list_foreach(iter6, &entry->type_def.addrsel->list6) { | ||
296 | map6 = netlbl_domhsh_addr6_entry(iter6); | ||
297 | switch (map6->type) { | ||
298 | case NETLBL_NLTYPE_UNLABELED: | ||
299 | break; | ||
300 | default: | ||
301 | return -EINVAL; | ||
302 | } | ||
303 | } | ||
304 | #endif /* IPv6 */ | ||
305 | break; | ||
306 | default: | ||
307 | return -EINVAL; | ||
308 | } | ||
309 | |||
310 | return 0; | ||
311 | } | ||
312 | |||
248 | /* | 313 | /* |
249 | * Domain Hash Table Functions | 314 | * Domain Hash Table Functions |
250 | */ | 315 | */ |
@@ -311,6 +376,10 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry, | |||
311 | struct netlbl_af6list *tmp6; | 376 | struct netlbl_af6list *tmp6; |
312 | #endif /* IPv6 */ | 377 | #endif /* IPv6 */ |
313 | 378 | ||
379 | ret_val = netlbl_domhsh_validate(entry); | ||
380 | if (ret_val != 0) | ||
381 | return ret_val; | ||
382 | |||
314 | /* XXX - we can remove this RCU read lock as the spinlock protects the | 383 | /* XXX - we can remove this RCU read lock as the spinlock protects the |
315 | * entire function, but before we do we need to fixup the | 384 | * entire function, but before we do we need to fixup the |
316 | * netlbl_af[4,6]list RCU functions to do "the right thing" with | 385 | * netlbl_af[4,6]list RCU functions to do "the right thing" with |
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 7da6b457f66a..fc2f78d6a9b4 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
@@ -52,6 +52,8 @@ | |||
52 | #include <linux/sunrpc/gss_api.h> | 52 | #include <linux/sunrpc/gss_api.h> |
53 | #include <asm/uaccess.h> | 53 | #include <asm/uaccess.h> |
54 | 54 | ||
55 | #include "../netns.h" | ||
56 | |||
55 | static const struct rpc_authops authgss_ops; | 57 | static const struct rpc_authops authgss_ops; |
56 | 58 | ||
57 | static const struct rpc_credops gss_credops; | 59 | static const struct rpc_credops gss_credops; |
@@ -85,8 +87,6 @@ struct gss_auth { | |||
85 | }; | 87 | }; |
86 | 88 | ||
87 | /* pipe_version >= 0 if and only if someone has a pipe open. */ | 89 | /* pipe_version >= 0 if and only if someone has a pipe open. */ |
88 | static int pipe_version = -1; | ||
89 | static atomic_t pipe_users = ATOMIC_INIT(0); | ||
90 | static DEFINE_SPINLOCK(pipe_version_lock); | 90 | static DEFINE_SPINLOCK(pipe_version_lock); |
91 | static struct rpc_wait_queue pipe_version_rpc_waitqueue; | 91 | static struct rpc_wait_queue pipe_version_rpc_waitqueue; |
92 | static DECLARE_WAIT_QUEUE_HEAD(pipe_version_waitqueue); | 92 | static DECLARE_WAIT_QUEUE_HEAD(pipe_version_waitqueue); |
@@ -266,24 +266,27 @@ struct gss_upcall_msg { | |||
266 | char databuf[UPCALL_BUF_LEN]; | 266 | char databuf[UPCALL_BUF_LEN]; |
267 | }; | 267 | }; |
268 | 268 | ||
269 | static int get_pipe_version(void) | 269 | static int get_pipe_version(struct net *net) |
270 | { | 270 | { |
271 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
271 | int ret; | 272 | int ret; |
272 | 273 | ||
273 | spin_lock(&pipe_version_lock); | 274 | spin_lock(&pipe_version_lock); |
274 | if (pipe_version >= 0) { | 275 | if (sn->pipe_version >= 0) { |
275 | atomic_inc(&pipe_users); | 276 | atomic_inc(&sn->pipe_users); |
276 | ret = pipe_version; | 277 | ret = sn->pipe_version; |
277 | } else | 278 | } else |
278 | ret = -EAGAIN; | 279 | ret = -EAGAIN; |
279 | spin_unlock(&pipe_version_lock); | 280 | spin_unlock(&pipe_version_lock); |
280 | return ret; | 281 | return ret; |
281 | } | 282 | } |
282 | 283 | ||
283 | static void put_pipe_version(void) | 284 | static void put_pipe_version(struct net *net) |
284 | { | 285 | { |
285 | if (atomic_dec_and_lock(&pipe_users, &pipe_version_lock)) { | 286 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); |
286 | pipe_version = -1; | 287 | |
288 | if (atomic_dec_and_lock(&sn->pipe_users, &pipe_version_lock)) { | ||
289 | sn->pipe_version = -1; | ||
287 | spin_unlock(&pipe_version_lock); | 290 | spin_unlock(&pipe_version_lock); |
288 | } | 291 | } |
289 | } | 292 | } |
@@ -291,9 +294,10 @@ static void put_pipe_version(void) | |||
291 | static void | 294 | static void |
292 | gss_release_msg(struct gss_upcall_msg *gss_msg) | 295 | gss_release_msg(struct gss_upcall_msg *gss_msg) |
293 | { | 296 | { |
297 | struct net *net = rpc_net_ns(gss_msg->auth->client); | ||
294 | if (!atomic_dec_and_test(&gss_msg->count)) | 298 | if (!atomic_dec_and_test(&gss_msg->count)) |
295 | return; | 299 | return; |
296 | put_pipe_version(); | 300 | put_pipe_version(net); |
297 | BUG_ON(!list_empty(&gss_msg->list)); | 301 | BUG_ON(!list_empty(&gss_msg->list)); |
298 | if (gss_msg->ctx != NULL) | 302 | if (gss_msg->ctx != NULL) |
299 | gss_put_ctx(gss_msg->ctx); | 303 | gss_put_ctx(gss_msg->ctx); |
@@ -439,7 +443,10 @@ static void gss_encode_msg(struct gss_upcall_msg *gss_msg, | |||
439 | struct rpc_clnt *clnt, | 443 | struct rpc_clnt *clnt, |
440 | const char *service_name) | 444 | const char *service_name) |
441 | { | 445 | { |
442 | if (pipe_version == 0) | 446 | struct net *net = rpc_net_ns(clnt); |
447 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
448 | |||
449 | if (sn->pipe_version == 0) | ||
443 | gss_encode_v0_msg(gss_msg); | 450 | gss_encode_v0_msg(gss_msg); |
444 | else /* pipe_version == 1 */ | 451 | else /* pipe_version == 1 */ |
445 | gss_encode_v1_msg(gss_msg, clnt, service_name); | 452 | gss_encode_v1_msg(gss_msg, clnt, service_name); |
@@ -455,7 +462,7 @@ gss_alloc_msg(struct gss_auth *gss_auth, struct rpc_clnt *clnt, | |||
455 | gss_msg = kzalloc(sizeof(*gss_msg), GFP_NOFS); | 462 | gss_msg = kzalloc(sizeof(*gss_msg), GFP_NOFS); |
456 | if (gss_msg == NULL) | 463 | if (gss_msg == NULL) |
457 | return ERR_PTR(-ENOMEM); | 464 | return ERR_PTR(-ENOMEM); |
458 | vers = get_pipe_version(); | 465 | vers = get_pipe_version(rpc_net_ns(clnt)); |
459 | if (vers < 0) { | 466 | if (vers < 0) { |
460 | kfree(gss_msg); | 467 | kfree(gss_msg); |
461 | return ERR_PTR(vers); | 468 | return ERR_PTR(vers); |
@@ -559,24 +566,34 @@ out: | |||
559 | static inline int | 566 | static inline int |
560 | gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred) | 567 | gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred) |
561 | { | 568 | { |
569 | struct net *net = rpc_net_ns(gss_auth->client); | ||
570 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
562 | struct rpc_pipe *pipe; | 571 | struct rpc_pipe *pipe; |
563 | struct rpc_cred *cred = &gss_cred->gc_base; | 572 | struct rpc_cred *cred = &gss_cred->gc_base; |
564 | struct gss_upcall_msg *gss_msg; | 573 | struct gss_upcall_msg *gss_msg; |
574 | unsigned long timeout; | ||
565 | DEFINE_WAIT(wait); | 575 | DEFINE_WAIT(wait); |
566 | int err = 0; | 576 | int err; |
567 | 577 | ||
568 | dprintk("RPC: %s for uid %u\n", | 578 | dprintk("RPC: %s for uid %u\n", |
569 | __func__, from_kuid(&init_user_ns, cred->cr_uid)); | 579 | __func__, from_kuid(&init_user_ns, cred->cr_uid)); |
570 | retry: | 580 | retry: |
581 | err = 0; | ||
582 | /* Default timeout is 15s unless we know that gssd is not running */ | ||
583 | timeout = 15 * HZ; | ||
584 | if (!sn->gssd_running) | ||
585 | timeout = HZ >> 2; | ||
571 | gss_msg = gss_setup_upcall(gss_auth->client, gss_auth, cred); | 586 | gss_msg = gss_setup_upcall(gss_auth->client, gss_auth, cred); |
572 | if (PTR_ERR(gss_msg) == -EAGAIN) { | 587 | if (PTR_ERR(gss_msg) == -EAGAIN) { |
573 | err = wait_event_interruptible_timeout(pipe_version_waitqueue, | 588 | err = wait_event_interruptible_timeout(pipe_version_waitqueue, |
574 | pipe_version >= 0, 15*HZ); | 589 | sn->pipe_version >= 0, timeout); |
575 | if (pipe_version < 0) { | 590 | if (sn->pipe_version < 0) { |
591 | if (err == 0) | ||
592 | sn->gssd_running = 0; | ||
576 | warn_gssd(); | 593 | warn_gssd(); |
577 | err = -EACCES; | 594 | err = -EACCES; |
578 | } | 595 | } |
579 | if (err) | 596 | if (err < 0) |
580 | goto out; | 597 | goto out; |
581 | goto retry; | 598 | goto retry; |
582 | } | 599 | } |
@@ -707,20 +724,22 @@ out: | |||
707 | 724 | ||
708 | static int gss_pipe_open(struct inode *inode, int new_version) | 725 | static int gss_pipe_open(struct inode *inode, int new_version) |
709 | { | 726 | { |
727 | struct net *net = inode->i_sb->s_fs_info; | ||
728 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
710 | int ret = 0; | 729 | int ret = 0; |
711 | 730 | ||
712 | spin_lock(&pipe_version_lock); | 731 | spin_lock(&pipe_version_lock); |
713 | if (pipe_version < 0) { | 732 | if (sn->pipe_version < 0) { |
714 | /* First open of any gss pipe determines the version: */ | 733 | /* First open of any gss pipe determines the version: */ |
715 | pipe_version = new_version; | 734 | sn->pipe_version = new_version; |
716 | rpc_wake_up(&pipe_version_rpc_waitqueue); | 735 | rpc_wake_up(&pipe_version_rpc_waitqueue); |
717 | wake_up(&pipe_version_waitqueue); | 736 | wake_up(&pipe_version_waitqueue); |
718 | } else if (pipe_version != new_version) { | 737 | } else if (sn->pipe_version != new_version) { |
719 | /* Trying to open a pipe of a different version */ | 738 | /* Trying to open a pipe of a different version */ |
720 | ret = -EBUSY; | 739 | ret = -EBUSY; |
721 | goto out; | 740 | goto out; |
722 | } | 741 | } |
723 | atomic_inc(&pipe_users); | 742 | atomic_inc(&sn->pipe_users); |
724 | out: | 743 | out: |
725 | spin_unlock(&pipe_version_lock); | 744 | spin_unlock(&pipe_version_lock); |
726 | return ret; | 745 | return ret; |
@@ -740,6 +759,7 @@ static int gss_pipe_open_v1(struct inode *inode) | |||
740 | static void | 759 | static void |
741 | gss_pipe_release(struct inode *inode) | 760 | gss_pipe_release(struct inode *inode) |
742 | { | 761 | { |
762 | struct net *net = inode->i_sb->s_fs_info; | ||
743 | struct rpc_pipe *pipe = RPC_I(inode)->pipe; | 763 | struct rpc_pipe *pipe = RPC_I(inode)->pipe; |
744 | struct gss_upcall_msg *gss_msg; | 764 | struct gss_upcall_msg *gss_msg; |
745 | 765 | ||
@@ -758,7 +778,7 @@ restart: | |||
758 | } | 778 | } |
759 | spin_unlock(&pipe->lock); | 779 | spin_unlock(&pipe->lock); |
760 | 780 | ||
761 | put_pipe_version(); | 781 | put_pipe_version(net); |
762 | } | 782 | } |
763 | 783 | ||
764 | static void | 784 | static void |
diff --git a/net/sunrpc/netns.h b/net/sunrpc/netns.h index 7111a4c9113b..74d948f5d5a1 100644 --- a/net/sunrpc/netns.h +++ b/net/sunrpc/netns.h | |||
@@ -28,7 +28,11 @@ struct sunrpc_net { | |||
28 | wait_queue_head_t gssp_wq; | 28 | wait_queue_head_t gssp_wq; |
29 | struct rpc_clnt *gssp_clnt; | 29 | struct rpc_clnt *gssp_clnt; |
30 | int use_gss_proxy; | 30 | int use_gss_proxy; |
31 | int pipe_version; | ||
32 | atomic_t pipe_users; | ||
31 | struct proc_dir_entry *use_gssp_proc; | 33 | struct proc_dir_entry *use_gssp_proc; |
34 | |||
35 | unsigned int gssd_running; | ||
32 | }; | 36 | }; |
33 | 37 | ||
34 | extern int sunrpc_net_id; | 38 | extern int sunrpc_net_id; |
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index a9129f8d7070..e7ce4b3eb0bd 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c | |||
@@ -216,11 +216,14 @@ rpc_destroy_inode(struct inode *inode) | |||
216 | static int | 216 | static int |
217 | rpc_pipe_open(struct inode *inode, struct file *filp) | 217 | rpc_pipe_open(struct inode *inode, struct file *filp) |
218 | { | 218 | { |
219 | struct net *net = inode->i_sb->s_fs_info; | ||
220 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
219 | struct rpc_pipe *pipe; | 221 | struct rpc_pipe *pipe; |
220 | int first_open; | 222 | int first_open; |
221 | int res = -ENXIO; | 223 | int res = -ENXIO; |
222 | 224 | ||
223 | mutex_lock(&inode->i_mutex); | 225 | mutex_lock(&inode->i_mutex); |
226 | sn->gssd_running = 1; | ||
224 | pipe = RPC_I(inode)->pipe; | 227 | pipe = RPC_I(inode)->pipe; |
225 | if (pipe == NULL) | 228 | if (pipe == NULL) |
226 | goto out; | 229 | goto out; |
@@ -1069,6 +1072,8 @@ void rpc_pipefs_init_net(struct net *net) | |||
1069 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | 1072 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); |
1070 | 1073 | ||
1071 | mutex_init(&sn->pipefs_sb_lock); | 1074 | mutex_init(&sn->pipefs_sb_lock); |
1075 | sn->gssd_running = 1; | ||
1076 | sn->pipe_version = -1; | ||
1072 | } | 1077 | } |
1073 | 1078 | ||
1074 | /* | 1079 | /* |
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index f8529fc8e542..5356b120dbf8 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c | |||
@@ -324,11 +324,17 @@ EXPORT_SYMBOL_GPL(__rpc_wait_for_completion_task); | |||
324 | * Note: If the task is ASYNC, and is being made runnable after sitting on an | 324 | * Note: If the task is ASYNC, and is being made runnable after sitting on an |
325 | * rpc_wait_queue, this must be called with the queue spinlock held to protect | 325 | * rpc_wait_queue, this must be called with the queue spinlock held to protect |
326 | * the wait queue operation. | 326 | * the wait queue operation. |
327 | * Note the ordering of rpc_test_and_set_running() and rpc_clear_queued(), | ||
328 | * which is needed to ensure that __rpc_execute() doesn't loop (due to the | ||
329 | * lockless RPC_IS_QUEUED() test) before we've had a chance to test | ||
330 | * the RPC_TASK_RUNNING flag. | ||
327 | */ | 331 | */ |
328 | static void rpc_make_runnable(struct rpc_task *task) | 332 | static void rpc_make_runnable(struct rpc_task *task) |
329 | { | 333 | { |
334 | bool need_wakeup = !rpc_test_and_set_running(task); | ||
335 | |||
330 | rpc_clear_queued(task); | 336 | rpc_clear_queued(task); |
331 | if (rpc_test_and_set_running(task)) | 337 | if (!need_wakeup) |
332 | return; | 338 | return; |
333 | if (RPC_IS_ASYNC(task)) { | 339 | if (RPC_IS_ASYNC(task)) { |
334 | INIT_WORK(&task->u.tk_work, rpc_async_schedule); | 340 | INIT_WORK(&task->u.tk_work, rpc_async_schedule); |
diff --git a/net/wireless/core.c b/net/wireless/core.c index 84c9ad7e1dca..73405e00c800 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -638,17 +638,21 @@ int wiphy_register(struct wiphy *wiphy) | |||
638 | * cfg80211_mutex lock | 638 | * cfg80211_mutex lock |
639 | */ | 639 | */ |
640 | res = rfkill_register(rdev->rfkill); | 640 | res = rfkill_register(rdev->rfkill); |
641 | if (res) | 641 | if (res) { |
642 | goto out_rm_dev; | 642 | device_del(&rdev->wiphy.dev); |
643 | |||
644 | mutex_lock(&cfg80211_mutex); | ||
645 | debugfs_remove_recursive(rdev->wiphy.debugfsdir); | ||
646 | list_del_rcu(&rdev->list); | ||
647 | wiphy_regulatory_deregister(wiphy); | ||
648 | mutex_unlock(&cfg80211_mutex); | ||
649 | return res; | ||
650 | } | ||
643 | 651 | ||
644 | rtnl_lock(); | 652 | rtnl_lock(); |
645 | rdev->wiphy.registered = true; | 653 | rdev->wiphy.registered = true; |
646 | rtnl_unlock(); | 654 | rtnl_unlock(); |
647 | return 0; | 655 | return 0; |
648 | |||
649 | out_rm_dev: | ||
650 | device_del(&rdev->wiphy.dev); | ||
651 | return res; | ||
652 | } | 656 | } |
653 | EXPORT_SYMBOL(wiphy_register); | 657 | EXPORT_SYMBOL(wiphy_register); |
654 | 658 | ||
@@ -866,7 +870,6 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev, | |||
866 | #endif | 870 | #endif |
867 | __cfg80211_disconnect(rdev, dev, | 871 | __cfg80211_disconnect(rdev, dev, |
868 | WLAN_REASON_DEAUTH_LEAVING, true); | 872 | WLAN_REASON_DEAUTH_LEAVING, true); |
869 | cfg80211_mlme_down(rdev, dev); | ||
870 | wdev_unlock(wdev); | 873 | wdev_unlock(wdev); |
871 | break; | 874 | break; |
872 | case NL80211_IFTYPE_MESH_POINT: | 875 | case NL80211_IFTYPE_MESH_POINT: |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index afa283841e8c..dfdb5e643211 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -7577,6 +7577,8 @@ static int nl80211_send_wowlan_tcp(struct sk_buff *msg, | |||
7577 | &tcp->payload_tok)) | 7577 | &tcp->payload_tok)) |
7578 | return -ENOBUFS; | 7578 | return -ENOBUFS; |
7579 | 7579 | ||
7580 | nla_nest_end(msg, nl_tcp); | ||
7581 | |||
7580 | return 0; | 7582 | return 0; |
7581 | } | 7583 | } |
7582 | 7584 | ||
@@ -9970,6 +9972,7 @@ int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, | |||
9970 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || | 9972 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || |
9971 | (netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX, | 9973 | (netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX, |
9972 | netdev->ifindex)) || | 9974 | netdev->ifindex)) || |
9975 | nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)) || | ||
9973 | nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq) || | 9976 | nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq) || |
9974 | (sig_dbm && | 9977 | (sig_dbm && |
9975 | nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)) || | 9978 | nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)) || |
@@ -10010,6 +10013,7 @@ void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie, | |||
10010 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || | 10013 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || |
10011 | (netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX, | 10014 | (netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX, |
10012 | netdev->ifindex)) || | 10015 | netdev->ifindex)) || |
10016 | nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)) || | ||
10013 | nla_put(msg, NL80211_ATTR_FRAME, len, buf) || | 10017 | nla_put(msg, NL80211_ATTR_FRAME, len, buf) || |
10014 | nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie) || | 10018 | nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie) || |
10015 | (ack && nla_put_flag(msg, NL80211_ATTR_ACK))) | 10019 | (ack && nla_put_flag(msg, NL80211_ATTR_ACK))) |
diff --git a/net/wireless/sme.c b/net/wireless/sme.c index a9dc5c736df0..8b5eddfba1e5 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c | |||
@@ -961,7 +961,7 @@ int __cfg80211_disconnect(struct cfg80211_registered_device *rdev, | |||
961 | /* was it connected by userspace SME? */ | 961 | /* was it connected by userspace SME? */ |
962 | if (!wdev->conn) { | 962 | if (!wdev->conn) { |
963 | cfg80211_mlme_down(rdev, dev); | 963 | cfg80211_mlme_down(rdev, dev); |
964 | return 0; | 964 | goto disconnect; |
965 | } | 965 | } |
966 | 966 | ||
967 | if (wdev->sme_state == CFG80211_SME_CONNECTING && | 967 | if (wdev->sme_state == CFG80211_SME_CONNECTING && |
@@ -987,6 +987,7 @@ int __cfg80211_disconnect(struct cfg80211_registered_device *rdev, | |||
987 | return err; | 987 | return err; |
988 | } | 988 | } |
989 | 989 | ||
990 | disconnect: | ||
990 | if (wdev->sme_state == CFG80211_SME_CONNECTED) | 991 | if (wdev->sme_state == CFG80211_SME_CONNECTED) |
991 | __cfg80211_disconnected(dev, NULL, 0, 0, false); | 992 | __cfg80211_disconnected(dev, NULL, 0, 0, false); |
992 | else if (wdev->sme_state == CFG80211_SME_CONNECTING) | 993 | else if (wdev->sme_state == CFG80211_SME_CONNECTING) |
diff --git a/net/wireless/trace.h b/net/wireless/trace.h index ecd4fcec3c94..5755bc14abbd 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h | |||
@@ -2441,6 +2441,7 @@ TRACE_EVENT(cfg80211_report_wowlan_wakeup, | |||
2441 | TP_STRUCT__entry( | 2441 | TP_STRUCT__entry( |
2442 | WIPHY_ENTRY | 2442 | WIPHY_ENTRY |
2443 | WDEV_ENTRY | 2443 | WDEV_ENTRY |
2444 | __field(bool, non_wireless) | ||
2444 | __field(bool, disconnect) | 2445 | __field(bool, disconnect) |
2445 | __field(bool, magic_pkt) | 2446 | __field(bool, magic_pkt) |
2446 | __field(bool, gtk_rekey_failure) | 2447 | __field(bool, gtk_rekey_failure) |
@@ -2449,20 +2450,22 @@ TRACE_EVENT(cfg80211_report_wowlan_wakeup, | |||
2449 | __field(bool, rfkill_release) | 2450 | __field(bool, rfkill_release) |
2450 | __field(s32, pattern_idx) | 2451 | __field(s32, pattern_idx) |
2451 | __field(u32, packet_len) | 2452 | __field(u32, packet_len) |
2452 | __dynamic_array(u8, packet, wakeup->packet_present_len) | 2453 | __dynamic_array(u8, packet, |
2454 | wakeup ? wakeup->packet_present_len : 0) | ||
2453 | ), | 2455 | ), |
2454 | TP_fast_assign( | 2456 | TP_fast_assign( |
2455 | WIPHY_ASSIGN; | 2457 | WIPHY_ASSIGN; |
2456 | WDEV_ASSIGN; | 2458 | WDEV_ASSIGN; |
2457 | __entry->disconnect = wakeup->disconnect; | 2459 | __entry->non_wireless = !wakeup; |
2458 | __entry->magic_pkt = wakeup->magic_pkt; | 2460 | __entry->disconnect = wakeup ? wakeup->disconnect : false; |
2459 | __entry->gtk_rekey_failure = wakeup->gtk_rekey_failure; | 2461 | __entry->magic_pkt = wakeup ? wakeup->magic_pkt : false; |
2460 | __entry->eap_identity_req = wakeup->eap_identity_req; | 2462 | __entry->gtk_rekey_failure = wakeup ? wakeup->gtk_rekey_failure : false; |
2461 | __entry->four_way_handshake = wakeup->four_way_handshake; | 2463 | __entry->eap_identity_req = wakeup ? wakeup->eap_identity_req : false; |
2462 | __entry->rfkill_release = wakeup->rfkill_release; | 2464 | __entry->four_way_handshake = wakeup ? wakeup->four_way_handshake : false; |
2463 | __entry->pattern_idx = wakeup->pattern_idx; | 2465 | __entry->rfkill_release = wakeup ? wakeup->rfkill_release : false; |
2464 | __entry->packet_len = wakeup->packet_len; | 2466 | __entry->pattern_idx = wakeup ? wakeup->pattern_idx : false; |
2465 | if (wakeup->packet && wakeup->packet_present_len) | 2467 | __entry->packet_len = wakeup ? wakeup->packet_len : false; |
2468 | if (wakeup && wakeup->packet && wakeup->packet_present_len) | ||
2466 | memcpy(__get_dynamic_array(packet), wakeup->packet, | 2469 | memcpy(__get_dynamic_array(packet), wakeup->packet, |
2467 | wakeup->packet_present_len); | 2470 | wakeup->packet_present_len); |
2468 | ), | 2471 | ), |
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c index bcfda8921b5b..0cf003dfa8fc 100644 --- a/net/xfrm/xfrm_output.c +++ b/net/xfrm/xfrm_output.c | |||
@@ -64,6 +64,7 @@ static int xfrm_output_one(struct sk_buff *skb, int err) | |||
64 | 64 | ||
65 | if (unlikely(x->km.state != XFRM_STATE_VALID)) { | 65 | if (unlikely(x->km.state != XFRM_STATE_VALID)) { |
66 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTSTATEINVALID); | 66 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTSTATEINVALID); |
67 | err = -EINVAL; | ||
67 | goto error; | 68 | goto error; |
68 | } | 69 | } |
69 | 70 | ||