diff options
Diffstat (limited to 'net')
| -rw-r--r-- | net/core/dev.c | 20 | ||||
| -rw-r--r-- | net/dsa/slave.c | 1 | ||||
| -rw-r--r-- | net/ipv4/ip_forward.c | 3 | ||||
| -rw-r--r-- | net/ipv4/ip_sockglue.c | 8 | ||||
| -rw-r--r-- | net/ipv4/ping.c | 5 | ||||
| -rw-r--r-- | net/ipv4/route.c | 9 | ||||
| -rw-r--r-- | net/ipv4/udp_diag.c | 4 | ||||
| -rw-r--r-- | net/ipv6/datagram.c | 10 | ||||
| -rw-r--r-- | net/ipv6/ip6_fib.c | 45 | ||||
| -rw-r--r-- | net/ipv6/route.c | 13 | ||||
| -rw-r--r-- | net/ipv6/xfrm6_policy.c | 10 | ||||
| -rw-r--r-- | net/llc/sysctl_net_llc.c | 8 | ||||
| -rw-r--r-- | net/mac80211/mlme.c | 2 | ||||
| -rw-r--r-- | net/mac80211/pm.c | 29 | ||||
| -rw-r--r-- | net/mac80211/rx.c | 2 | ||||
| -rw-r--r-- | net/netlink/af_netlink.c | 24 | ||||
| -rw-r--r-- | net/netlink/af_netlink.h | 1 | ||||
| -rw-r--r-- | net/netlink/genetlink.c | 18 | ||||
| -rw-r--r-- | net/sched/cls_bpf.c | 15 | ||||
| -rw-r--r-- | net/sctp/associola.c | 1 | ||||
| -rw-r--r-- | net/sctp/socket.c | 8 | ||||
| -rw-r--r-- | net/socket.c | 3 | ||||
| -rw-r--r-- | net/wireless/nl80211.c | 9 | ||||
| -rw-r--r-- | net/wireless/reg.c | 56 | ||||
| -rw-r--r-- | net/wireless/util.c | 6 |
25 files changed, 189 insertions, 121 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index 683d493aa1bf..171420e75b03 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
| @@ -7072,10 +7072,20 @@ static int dev_cpu_callback(struct notifier_block *nfb, | |||
| 7072 | oldsd->output_queue = NULL; | 7072 | oldsd->output_queue = NULL; |
| 7073 | oldsd->output_queue_tailp = &oldsd->output_queue; | 7073 | oldsd->output_queue_tailp = &oldsd->output_queue; |
| 7074 | } | 7074 | } |
| 7075 | /* Append NAPI poll list from offline CPU. */ | 7075 | /* Append NAPI poll list from offline CPU, with one exception : |
| 7076 | if (!list_empty(&oldsd->poll_list)) { | 7076 | * process_backlog() must be called by cpu owning percpu backlog. |
| 7077 | list_splice_init(&oldsd->poll_list, &sd->poll_list); | 7077 | * We properly handle process_queue & input_pkt_queue later. |
| 7078 | raise_softirq_irqoff(NET_RX_SOFTIRQ); | 7078 | */ |
| 7079 | while (!list_empty(&oldsd->poll_list)) { | ||
| 7080 | struct napi_struct *napi = list_first_entry(&oldsd->poll_list, | ||
| 7081 | struct napi_struct, | ||
| 7082 | poll_list); | ||
| 7083 | |||
| 7084 | list_del_init(&napi->poll_list); | ||
| 7085 | if (napi->poll == process_backlog) | ||
| 7086 | napi->state = 0; | ||
| 7087 | else | ||
| 7088 | ____napi_schedule(sd, napi); | ||
| 7079 | } | 7089 | } |
| 7080 | 7090 | ||
| 7081 | raise_softirq_irqoff(NET_TX_SOFTIRQ); | 7091 | raise_softirq_irqoff(NET_TX_SOFTIRQ); |
| @@ -7086,7 +7096,7 @@ static int dev_cpu_callback(struct notifier_block *nfb, | |||
| 7086 | netif_rx_internal(skb); | 7096 | netif_rx_internal(skb); |
| 7087 | input_queue_head_incr(oldsd); | 7097 | input_queue_head_incr(oldsd); |
| 7088 | } | 7098 | } |
| 7089 | while ((skb = __skb_dequeue(&oldsd->input_pkt_queue))) { | 7099 | while ((skb = skb_dequeue(&oldsd->input_pkt_queue))) { |
| 7090 | netif_rx_internal(skb); | 7100 | netif_rx_internal(skb); |
| 7091 | input_queue_head_incr(oldsd); | 7101 | input_queue_head_incr(oldsd); |
| 7092 | } | 7102 | } |
diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 515569ffde8a..589aafd01fc5 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c | |||
| @@ -46,6 +46,7 @@ void dsa_slave_mii_bus_init(struct dsa_switch *ds) | |||
| 46 | snprintf(ds->slave_mii_bus->id, MII_BUS_ID_SIZE, "dsa-%d:%.2x", | 46 | snprintf(ds->slave_mii_bus->id, MII_BUS_ID_SIZE, "dsa-%d:%.2x", |
| 47 | ds->index, ds->pd->sw_addr); | 47 | ds->index, ds->pd->sw_addr); |
| 48 | ds->slave_mii_bus->parent = ds->master_dev; | 48 | ds->slave_mii_bus->parent = ds->master_dev; |
| 49 | ds->slave_mii_bus->phy_mask = ~ds->phys_mii_mask; | ||
| 49 | } | 50 | } |
| 50 | 51 | ||
| 51 | 52 | ||
diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c index 3a83ce5efa80..787b3c294ce6 100644 --- a/net/ipv4/ip_forward.c +++ b/net/ipv4/ip_forward.c | |||
| @@ -129,7 +129,8 @@ int ip_forward(struct sk_buff *skb) | |||
| 129 | * We now generate an ICMP HOST REDIRECT giving the route | 129 | * We now generate an ICMP HOST REDIRECT giving the route |
| 130 | * we calculated. | 130 | * we calculated. |
| 131 | */ | 131 | */ |
| 132 | if (rt->rt_flags&RTCF_DOREDIRECT && !opt->srr && !skb_sec_path(skb)) | 132 | if (IPCB(skb)->flags & IPSKB_DOREDIRECT && !opt->srr && |
| 133 | !skb_sec_path(skb)) | ||
| 133 | ip_rt_send_redirect(skb); | 134 | ip_rt_send_redirect(skb); |
| 134 | 135 | ||
| 135 | skb->priority = rt_tos2priority(iph->tos); | 136 | skb->priority = rt_tos2priority(iph->tos); |
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 8a89c738b7a3..6b85adb05003 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c | |||
| @@ -461,17 +461,13 @@ int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) | |||
| 461 | 461 | ||
| 462 | memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err)); | 462 | memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err)); |
| 463 | sin = &errhdr.offender; | 463 | sin = &errhdr.offender; |
| 464 | sin->sin_family = AF_UNSPEC; | 464 | memset(sin, 0, sizeof(*sin)); |
| 465 | 465 | ||
| 466 | if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP || | 466 | if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP || |
| 467 | ipv4_pktinfo_prepare_errqueue(sk, skb, serr->ee.ee_origin)) { | 467 | ipv4_pktinfo_prepare_errqueue(sk, skb, serr->ee.ee_origin)) { |
| 468 | struct inet_sock *inet = inet_sk(sk); | ||
| 469 | |||
| 470 | sin->sin_family = AF_INET; | 468 | sin->sin_family = AF_INET; |
| 471 | sin->sin_addr.s_addr = ip_hdr(skb)->saddr; | 469 | sin->sin_addr.s_addr = ip_hdr(skb)->saddr; |
| 472 | sin->sin_port = 0; | 470 | if (inet_sk(sk)->cmsg_flags) |
| 473 | memset(&sin->sin_zero, 0, sizeof(sin->sin_zero)); | ||
| 474 | if (inet->cmsg_flags) | ||
| 475 | ip_cmsg_recv(msg, skb); | 471 | ip_cmsg_recv(msg, skb); |
| 476 | } | 472 | } |
| 477 | 473 | ||
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index c0d82f78d364..2a3720fb5a5f 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c | |||
| @@ -966,8 +966,11 @@ bool ping_rcv(struct sk_buff *skb) | |||
| 966 | 966 | ||
| 967 | sk = ping_lookup(net, skb, ntohs(icmph->un.echo.id)); | 967 | sk = ping_lookup(net, skb, ntohs(icmph->un.echo.id)); |
| 968 | if (sk != NULL) { | 968 | if (sk != NULL) { |
| 969 | struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); | ||
| 970 | |||
| 969 | pr_debug("rcv on socket %p\n", sk); | 971 | pr_debug("rcv on socket %p\n", sk); |
| 970 | ping_queue_rcv_skb(sk, skb_get(skb)); | 972 | if (skb2) |
| 973 | ping_queue_rcv_skb(sk, skb2); | ||
| 971 | sock_put(sk); | 974 | sock_put(sk); |
| 972 | return true; | 975 | return true; |
| 973 | } | 976 | } |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 6a2155b02602..d58dd0ec3e53 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
| @@ -1554,11 +1554,10 @@ static int __mkroute_input(struct sk_buff *skb, | |||
| 1554 | 1554 | ||
| 1555 | do_cache = res->fi && !itag; | 1555 | do_cache = res->fi && !itag; |
| 1556 | if (out_dev == in_dev && err && IN_DEV_TX_REDIRECTS(out_dev) && | 1556 | if (out_dev == in_dev && err && IN_DEV_TX_REDIRECTS(out_dev) && |
| 1557 | skb->protocol == htons(ETH_P_IP) && | ||
| 1557 | (IN_DEV_SHARED_MEDIA(out_dev) || | 1558 | (IN_DEV_SHARED_MEDIA(out_dev) || |
| 1558 | inet_addr_onlink(out_dev, saddr, FIB_RES_GW(*res)))) { | 1559 | inet_addr_onlink(out_dev, saddr, FIB_RES_GW(*res)))) |
| 1559 | flags |= RTCF_DOREDIRECT; | 1560 | IPCB(skb)->flags |= IPSKB_DOREDIRECT; |
| 1560 | do_cache = false; | ||
| 1561 | } | ||
| 1562 | 1561 | ||
| 1563 | if (skb->protocol != htons(ETH_P_IP)) { | 1562 | if (skb->protocol != htons(ETH_P_IP)) { |
| 1564 | /* Not IP (i.e. ARP). Do not create route, if it is | 1563 | /* Not IP (i.e. ARP). Do not create route, if it is |
| @@ -2303,6 +2302,8 @@ static int rt_fill_info(struct net *net, __be32 dst, __be32 src, | |||
| 2303 | r->rtm_flags = (rt->rt_flags & ~0xFFFF) | RTM_F_CLONED; | 2302 | r->rtm_flags = (rt->rt_flags & ~0xFFFF) | RTM_F_CLONED; |
| 2304 | if (rt->rt_flags & RTCF_NOTIFY) | 2303 | if (rt->rt_flags & RTCF_NOTIFY) |
| 2305 | r->rtm_flags |= RTM_F_NOTIFY; | 2304 | r->rtm_flags |= RTM_F_NOTIFY; |
| 2305 | if (IPCB(skb)->flags & IPSKB_DOREDIRECT) | ||
| 2306 | r->rtm_flags |= RTCF_DOREDIRECT; | ||
| 2306 | 2307 | ||
| 2307 | if (nla_put_be32(skb, RTA_DST, dst)) | 2308 | if (nla_put_be32(skb, RTA_DST, dst)) |
| 2308 | goto nla_put_failure; | 2309 | goto nla_put_failure; |
diff --git a/net/ipv4/udp_diag.c b/net/ipv4/udp_diag.c index 7927db0a9279..4a000f1dd757 100644 --- a/net/ipv4/udp_diag.c +++ b/net/ipv4/udp_diag.c | |||
| @@ -99,11 +99,13 @@ static void udp_dump(struct udp_table *table, struct sk_buff *skb, struct netlin | |||
| 99 | s_slot = cb->args[0]; | 99 | s_slot = cb->args[0]; |
| 100 | num = s_num = cb->args[1]; | 100 | num = s_num = cb->args[1]; |
| 101 | 101 | ||
| 102 | for (slot = s_slot; slot <= table->mask; num = s_num = 0, slot++) { | 102 | for (slot = s_slot; slot <= table->mask; s_num = 0, slot++) { |
| 103 | struct sock *sk; | 103 | struct sock *sk; |
| 104 | struct hlist_nulls_node *node; | 104 | struct hlist_nulls_node *node; |
| 105 | struct udp_hslot *hslot = &table->hash[slot]; | 105 | struct udp_hslot *hslot = &table->hash[slot]; |
| 106 | 106 | ||
| 107 | num = 0; | ||
| 108 | |||
| 107 | if (hlist_nulls_empty(&hslot->head)) | 109 | if (hlist_nulls_empty(&hslot->head)) |
| 108 | continue; | 110 | continue; |
| 109 | 111 | ||
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 100c589a2a6c..49f5e73db122 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c | |||
| @@ -393,11 +393,10 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) | |||
| 393 | 393 | ||
| 394 | memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err)); | 394 | memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err)); |
| 395 | sin = &errhdr.offender; | 395 | sin = &errhdr.offender; |
| 396 | sin->sin6_family = AF_UNSPEC; | 396 | memset(sin, 0, sizeof(*sin)); |
| 397 | |||
| 397 | if (serr->ee.ee_origin != SO_EE_ORIGIN_LOCAL) { | 398 | if (serr->ee.ee_origin != SO_EE_ORIGIN_LOCAL) { |
| 398 | sin->sin6_family = AF_INET6; | 399 | sin->sin6_family = AF_INET6; |
| 399 | sin->sin6_flowinfo = 0; | ||
| 400 | sin->sin6_port = 0; | ||
| 401 | if (np->rxopt.all) { | 400 | if (np->rxopt.all) { |
| 402 | if (serr->ee.ee_origin != SO_EE_ORIGIN_ICMP && | 401 | if (serr->ee.ee_origin != SO_EE_ORIGIN_ICMP && |
| 403 | serr->ee.ee_origin != SO_EE_ORIGIN_ICMP6) | 402 | serr->ee.ee_origin != SO_EE_ORIGIN_ICMP6) |
| @@ -412,12 +411,9 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) | |||
| 412 | ipv6_iface_scope_id(&sin->sin6_addr, | 411 | ipv6_iface_scope_id(&sin->sin6_addr, |
| 413 | IP6CB(skb)->iif); | 412 | IP6CB(skb)->iif); |
| 414 | } else { | 413 | } else { |
| 415 | struct inet_sock *inet = inet_sk(sk); | ||
| 416 | |||
| 417 | ipv6_addr_set_v4mapped(ip_hdr(skb)->saddr, | 414 | ipv6_addr_set_v4mapped(ip_hdr(skb)->saddr, |
| 418 | &sin->sin6_addr); | 415 | &sin->sin6_addr); |
| 419 | sin->sin6_scope_id = 0; | 416 | if (inet_sk(sk)->cmsg_flags) |
| 420 | if (inet->cmsg_flags) | ||
| 421 | ip_cmsg_recv(msg, skb); | 417 | ip_cmsg_recv(msg, skb); |
| 422 | } | 418 | } |
| 423 | } | 419 | } |
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index b2d1838897c9..f1c6d5e98322 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c | |||
| @@ -659,6 +659,29 @@ static int fib6_commit_metrics(struct dst_entry *dst, | |||
| 659 | return 0; | 659 | return 0; |
| 660 | } | 660 | } |
| 661 | 661 | ||
| 662 | static void fib6_purge_rt(struct rt6_info *rt, struct fib6_node *fn, | ||
| 663 | struct net *net) | ||
| 664 | { | ||
| 665 | if (atomic_read(&rt->rt6i_ref) != 1) { | ||
| 666 | /* This route is used as dummy address holder in some split | ||
| 667 | * nodes. It is not leaked, but it still holds other resources, | ||
| 668 | * which must be released in time. So, scan ascendant nodes | ||
| 669 | * and replace dummy references to this route with references | ||
| 670 | * to still alive ones. | ||
| 671 | */ | ||
| 672 | while (fn) { | ||
| 673 | if (!(fn->fn_flags & RTN_RTINFO) && fn->leaf == rt) { | ||
| 674 | fn->leaf = fib6_find_prefix(net, fn); | ||
| 675 | atomic_inc(&fn->leaf->rt6i_ref); | ||
| 676 | rt6_release(rt); | ||
| 677 | } | ||
| 678 | fn = fn->parent; | ||
| 679 | } | ||
| 680 | /* No more references are possible at this point. */ | ||
| 681 | BUG_ON(atomic_read(&rt->rt6i_ref) != 1); | ||
| 682 | } | ||
| 683 | } | ||
| 684 | |||
| 662 | /* | 685 | /* |
| 663 | * Insert routing information in a node. | 686 | * Insert routing information in a node. |
| 664 | */ | 687 | */ |
| @@ -807,11 +830,12 @@ add: | |||
| 807 | rt->dst.rt6_next = iter->dst.rt6_next; | 830 | rt->dst.rt6_next = iter->dst.rt6_next; |
| 808 | atomic_inc(&rt->rt6i_ref); | 831 | atomic_inc(&rt->rt6i_ref); |
| 809 | inet6_rt_notify(RTM_NEWROUTE, rt, info); | 832 | inet6_rt_notify(RTM_NEWROUTE, rt, info); |
| 810 | rt6_release(iter); | ||
| 811 | if (!(fn->fn_flags & RTN_RTINFO)) { | 833 | if (!(fn->fn_flags & RTN_RTINFO)) { |
| 812 | info->nl_net->ipv6.rt6_stats->fib_route_nodes++; | 834 | info->nl_net->ipv6.rt6_stats->fib_route_nodes++; |
| 813 | fn->fn_flags |= RTN_RTINFO; | 835 | fn->fn_flags |= RTN_RTINFO; |
| 814 | } | 836 | } |
| 837 | fib6_purge_rt(iter, fn, info->nl_net); | ||
| 838 | rt6_release(iter); | ||
| 815 | } | 839 | } |
| 816 | 840 | ||
| 817 | return 0; | 841 | return 0; |
| @@ -1322,24 +1346,7 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp, | |||
| 1322 | fn = fib6_repair_tree(net, fn); | 1346 | fn = fib6_repair_tree(net, fn); |
| 1323 | } | 1347 | } |
| 1324 | 1348 | ||
| 1325 | if (atomic_read(&rt->rt6i_ref) != 1) { | 1349 | fib6_purge_rt(rt, fn, net); |
| 1326 | /* This route is used as dummy address holder in some split | ||
| 1327 | * nodes. It is not leaked, but it still holds other resources, | ||
| 1328 | * which must be released in time. So, scan ascendant nodes | ||
| 1329 | * and replace dummy references to this route with references | ||
| 1330 | * to still alive ones. | ||
| 1331 | */ | ||
| 1332 | while (fn) { | ||
| 1333 | if (!(fn->fn_flags & RTN_RTINFO) && fn->leaf == rt) { | ||
| 1334 | fn->leaf = fib6_find_prefix(net, fn); | ||
| 1335 | atomic_inc(&fn->leaf->rt6i_ref); | ||
| 1336 | rt6_release(rt); | ||
| 1337 | } | ||
| 1338 | fn = fn->parent; | ||
| 1339 | } | ||
| 1340 | /* No more references are possible at this point. */ | ||
| 1341 | BUG_ON(atomic_read(&rt->rt6i_ref) != 1); | ||
| 1342 | } | ||
| 1343 | 1350 | ||
| 1344 | inet6_rt_notify(RTM_DELROUTE, rt, info); | 1351 | inet6_rt_notify(RTM_DELROUTE, rt, info); |
| 1345 | rt6_release(rt); | 1352 | rt6_release(rt); |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index c91083156edb..495965358d22 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
| @@ -1160,12 +1160,9 @@ static void ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, | |||
| 1160 | struct net *net = dev_net(dst->dev); | 1160 | struct net *net = dev_net(dst->dev); |
| 1161 | 1161 | ||
| 1162 | rt6->rt6i_flags |= RTF_MODIFIED; | 1162 | rt6->rt6i_flags |= RTF_MODIFIED; |
| 1163 | if (mtu < IPV6_MIN_MTU) { | 1163 | if (mtu < IPV6_MIN_MTU) |
| 1164 | u32 features = dst_metric(dst, RTAX_FEATURES); | ||
| 1165 | mtu = IPV6_MIN_MTU; | 1164 | mtu = IPV6_MIN_MTU; |
| 1166 | features |= RTAX_FEATURE_ALLFRAG; | 1165 | |
| 1167 | dst_metric_set(dst, RTAX_FEATURES, features); | ||
| 1168 | } | ||
| 1169 | dst_metric_set(dst, RTAX_MTU, mtu); | 1166 | dst_metric_set(dst, RTAX_MTU, mtu); |
| 1170 | rt6_update_expires(rt6, net->ipv6.sysctl.ip6_rt_mtu_expires); | 1167 | rt6_update_expires(rt6, net->ipv6.sysctl.ip6_rt_mtu_expires); |
| 1171 | } | 1168 | } |
| @@ -1245,12 +1242,16 @@ restart: | |||
| 1245 | rt = net->ipv6.ip6_null_entry; | 1242 | rt = net->ipv6.ip6_null_entry; |
| 1246 | else if (rt->dst.error) { | 1243 | else if (rt->dst.error) { |
| 1247 | rt = net->ipv6.ip6_null_entry; | 1244 | rt = net->ipv6.ip6_null_entry; |
| 1248 | } else if (rt == net->ipv6.ip6_null_entry) { | 1245 | goto out; |
| 1246 | } | ||
| 1247 | |||
| 1248 | if (rt == net->ipv6.ip6_null_entry) { | ||
| 1249 | fn = fib6_backtrack(fn, &fl6->saddr); | 1249 | fn = fib6_backtrack(fn, &fl6->saddr); |
| 1250 | if (fn) | 1250 | if (fn) |
| 1251 | goto restart; | 1251 | goto restart; |
| 1252 | } | 1252 | } |
| 1253 | 1253 | ||
| 1254 | out: | ||
| 1254 | dst_hold(&rt->dst); | 1255 | dst_hold(&rt->dst); |
| 1255 | 1256 | ||
| 1256 | read_unlock_bh(&table->tb6_lock); | 1257 | read_unlock_bh(&table->tb6_lock); |
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index 5f983644373a..48bf5a06847b 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c | |||
| @@ -130,12 +130,18 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) | |||
| 130 | { | 130 | { |
| 131 | struct flowi6 *fl6 = &fl->u.ip6; | 131 | struct flowi6 *fl6 = &fl->u.ip6; |
| 132 | int onlyproto = 0; | 132 | int onlyproto = 0; |
| 133 | u16 offset = skb_network_header_len(skb); | ||
| 134 | const struct ipv6hdr *hdr = ipv6_hdr(skb); | 133 | const struct ipv6hdr *hdr = ipv6_hdr(skb); |
| 134 | u16 offset = sizeof(*hdr); | ||
| 135 | struct ipv6_opt_hdr *exthdr; | 135 | struct ipv6_opt_hdr *exthdr; |
| 136 | const unsigned char *nh = skb_network_header(skb); | 136 | const unsigned char *nh = skb_network_header(skb); |
| 137 | u8 nexthdr = nh[IP6CB(skb)->nhoff]; | 137 | u16 nhoff = IP6CB(skb)->nhoff; |
| 138 | int oif = 0; | 138 | int oif = 0; |
| 139 | u8 nexthdr; | ||
| 140 | |||
| 141 | if (!nhoff) | ||
| 142 | nhoff = offsetof(struct ipv6hdr, nexthdr); | ||
| 143 | |||
| 144 | nexthdr = nh[nhoff]; | ||
| 139 | 145 | ||
| 140 | if (skb_dst(skb)) | 146 | if (skb_dst(skb)) |
| 141 | oif = skb_dst(skb)->dev->ifindex; | 147 | oif = skb_dst(skb)->dev->ifindex; |
diff --git a/net/llc/sysctl_net_llc.c b/net/llc/sysctl_net_llc.c index 612a5ddaf93b..799bafc2af39 100644 --- a/net/llc/sysctl_net_llc.c +++ b/net/llc/sysctl_net_llc.c | |||
| @@ -18,28 +18,28 @@ static struct ctl_table llc2_timeout_table[] = { | |||
| 18 | { | 18 | { |
| 19 | .procname = "ack", | 19 | .procname = "ack", |
| 20 | .data = &sysctl_llc2_ack_timeout, | 20 | .data = &sysctl_llc2_ack_timeout, |
| 21 | .maxlen = sizeof(long), | 21 | .maxlen = sizeof(sysctl_llc2_ack_timeout), |
| 22 | .mode = 0644, | 22 | .mode = 0644, |
| 23 | .proc_handler = proc_dointvec_jiffies, | 23 | .proc_handler = proc_dointvec_jiffies, |
| 24 | }, | 24 | }, |
| 25 | { | 25 | { |
| 26 | .procname = "busy", | 26 | .procname = "busy", |
| 27 | .data = &sysctl_llc2_busy_timeout, | 27 | .data = &sysctl_llc2_busy_timeout, |
| 28 | .maxlen = sizeof(long), | 28 | .maxlen = sizeof(sysctl_llc2_busy_timeout), |
| 29 | .mode = 0644, | 29 | .mode = 0644, |
| 30 | .proc_handler = proc_dointvec_jiffies, | 30 | .proc_handler = proc_dointvec_jiffies, |
| 31 | }, | 31 | }, |
| 32 | { | 32 | { |
| 33 | .procname = "p", | 33 | .procname = "p", |
| 34 | .data = &sysctl_llc2_p_timeout, | 34 | .data = &sysctl_llc2_p_timeout, |
| 35 | .maxlen = sizeof(long), | 35 | .maxlen = sizeof(sysctl_llc2_p_timeout), |
| 36 | .mode = 0644, | 36 | .mode = 0644, |
| 37 | .proc_handler = proc_dointvec_jiffies, | 37 | .proc_handler = proc_dointvec_jiffies, |
| 38 | }, | 38 | }, |
| 39 | { | 39 | { |
| 40 | .procname = "rej", | 40 | .procname = "rej", |
| 41 | .data = &sysctl_llc2_rej_timeout, | 41 | .data = &sysctl_llc2_rej_timeout, |
| 42 | .maxlen = sizeof(long), | 42 | .maxlen = sizeof(sysctl_llc2_rej_timeout), |
| 43 | .mode = 0644, | 43 | .mode = 0644, |
| 44 | .proc_handler = proc_dointvec_jiffies, | 44 | .proc_handler = proc_dointvec_jiffies, |
| 45 | }, | 45 | }, |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 2c36c4765f47..837a406a9dd6 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
| @@ -1643,7 +1643,7 @@ __ieee80211_sta_handle_tspec_ac_params(struct ieee80211_sub_if_data *sdata) | |||
| 1643 | { | 1643 | { |
| 1644 | struct ieee80211_local *local = sdata->local; | 1644 | struct ieee80211_local *local = sdata->local; |
| 1645 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 1645 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
| 1646 | bool ret; | 1646 | bool ret = false; |
| 1647 | int ac; | 1647 | int ac; |
| 1648 | 1648 | ||
| 1649 | if (local->hw.queues < IEEE80211_NUM_ACS) | 1649 | if (local->hw.queues < IEEE80211_NUM_ACS) |
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 4c5192e0d66c..4a95fe3cffbc 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c | |||
| @@ -86,20 +86,6 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
| 86 | } | 86 | } |
| 87 | } | 87 | } |
| 88 | 88 | ||
| 89 | /* tear down aggregation sessions and remove STAs */ | ||
| 90 | mutex_lock(&local->sta_mtx); | ||
| 91 | list_for_each_entry(sta, &local->sta_list, list) { | ||
| 92 | if (sta->uploaded) { | ||
| 93 | enum ieee80211_sta_state state; | ||
| 94 | |||
| 95 | state = sta->sta_state; | ||
| 96 | for (; state > IEEE80211_STA_NOTEXIST; state--) | ||
| 97 | WARN_ON(drv_sta_state(local, sta->sdata, sta, | ||
| 98 | state, state - 1)); | ||
| 99 | } | ||
| 100 | } | ||
| 101 | mutex_unlock(&local->sta_mtx); | ||
| 102 | |||
| 103 | /* remove all interfaces that were created in the driver */ | 89 | /* remove all interfaces that were created in the driver */ |
| 104 | list_for_each_entry(sdata, &local->interfaces, list) { | 90 | list_for_each_entry(sdata, &local->interfaces, list) { |
| 105 | if (!ieee80211_sdata_running(sdata)) | 91 | if (!ieee80211_sdata_running(sdata)) |
| @@ -111,6 +97,21 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
| 111 | case NL80211_IFTYPE_STATION: | 97 | case NL80211_IFTYPE_STATION: |
| 112 | ieee80211_mgd_quiesce(sdata); | 98 | ieee80211_mgd_quiesce(sdata); |
| 113 | break; | 99 | break; |
| 100 | case NL80211_IFTYPE_WDS: | ||
| 101 | /* tear down aggregation sessions and remove STAs */ | ||
| 102 | mutex_lock(&local->sta_mtx); | ||
| 103 | sta = sdata->u.wds.sta; | ||
| 104 | if (sta && sta->uploaded) { | ||
| 105 | enum ieee80211_sta_state state; | ||
| 106 | |||
| 107 | state = sta->sta_state; | ||
| 108 | for (; state > IEEE80211_STA_NOTEXIST; state--) | ||
| 109 | WARN_ON(drv_sta_state(local, sta->sdata, | ||
| 110 | sta, state, | ||
| 111 | state - 1)); | ||
| 112 | } | ||
| 113 | mutex_unlock(&local->sta_mtx); | ||
| 114 | break; | ||
| 114 | default: | 115 | default: |
| 115 | break; | 116 | break; |
| 116 | } | 117 | } |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 683b10f46505..d69ca513848e 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
| @@ -272,7 +272,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
| 272 | else if (rate && rate->flags & IEEE80211_RATE_ERP_G) | 272 | else if (rate && rate->flags & IEEE80211_RATE_ERP_G) |
| 273 | channel_flags |= IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ; | 273 | channel_flags |= IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ; |
| 274 | else if (rate) | 274 | else if (rate) |
| 275 | channel_flags |= IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ; | 275 | channel_flags |= IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ; |
| 276 | else | 276 | else |
| 277 | channel_flags |= IEEE80211_CHAN_2GHZ; | 277 | channel_flags |= IEEE80211_CHAN_2GHZ; |
| 278 | put_unaligned_le16(channel_flags, pos); | 278 | put_unaligned_le16(channel_flags, pos); |
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 84ea76ca3f1f..02fdde28dada 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
| @@ -61,6 +61,7 @@ | |||
| 61 | #include <linux/rhashtable.h> | 61 | #include <linux/rhashtable.h> |
| 62 | #include <asm/cacheflush.h> | 62 | #include <asm/cacheflush.h> |
| 63 | #include <linux/hash.h> | 63 | #include <linux/hash.h> |
| 64 | #include <linux/genetlink.h> | ||
| 64 | 65 | ||
| 65 | #include <net/net_namespace.h> | 66 | #include <net/net_namespace.h> |
| 66 | #include <net/sock.h> | 67 | #include <net/sock.h> |
| @@ -1095,6 +1096,8 @@ static void netlink_remove(struct sock *sk) | |||
| 1095 | __sk_del_bind_node(sk); | 1096 | __sk_del_bind_node(sk); |
| 1096 | netlink_update_listeners(sk); | 1097 | netlink_update_listeners(sk); |
| 1097 | } | 1098 | } |
| 1099 | if (sk->sk_protocol == NETLINK_GENERIC) | ||
| 1100 | atomic_inc(&genl_sk_destructing_cnt); | ||
| 1098 | netlink_table_ungrab(); | 1101 | netlink_table_ungrab(); |
| 1099 | } | 1102 | } |
| 1100 | 1103 | ||
| @@ -1211,6 +1214,20 @@ static int netlink_release(struct socket *sock) | |||
| 1211 | * will be purged. | 1214 | * will be purged. |
| 1212 | */ | 1215 | */ |
| 1213 | 1216 | ||
| 1217 | /* must not acquire netlink_table_lock in any way again before unbind | ||
| 1218 | * and notifying genetlink is done as otherwise it might deadlock | ||
| 1219 | */ | ||
| 1220 | if (nlk->netlink_unbind) { | ||
| 1221 | int i; | ||
| 1222 | |||
| 1223 | for (i = 0; i < nlk->ngroups; i++) | ||
| 1224 | if (test_bit(i, nlk->groups)) | ||
| 1225 | nlk->netlink_unbind(sock_net(sk), i + 1); | ||
| 1226 | } | ||
| 1227 | if (sk->sk_protocol == NETLINK_GENERIC && | ||
| 1228 | atomic_dec_return(&genl_sk_destructing_cnt) == 0) | ||
| 1229 | wake_up(&genl_sk_destructing_waitq); | ||
| 1230 | |||
| 1214 | sock->sk = NULL; | 1231 | sock->sk = NULL; |
| 1215 | wake_up_interruptible_all(&nlk->wait); | 1232 | wake_up_interruptible_all(&nlk->wait); |
| 1216 | 1233 | ||
| @@ -1246,13 +1263,6 @@ static int netlink_release(struct socket *sock) | |||
| 1246 | netlink_table_ungrab(); | 1263 | netlink_table_ungrab(); |
| 1247 | } | 1264 | } |
| 1248 | 1265 | ||
| 1249 | if (nlk->netlink_unbind) { | ||
| 1250 | int i; | ||
| 1251 | |||
| 1252 | for (i = 0; i < nlk->ngroups; i++) | ||
| 1253 | if (test_bit(i, nlk->groups)) | ||
| 1254 | nlk->netlink_unbind(sock_net(sk), i + 1); | ||
| 1255 | } | ||
| 1256 | kfree(nlk->groups); | 1266 | kfree(nlk->groups); |
| 1257 | nlk->groups = NULL; | 1267 | nlk->groups = NULL; |
| 1258 | 1268 | ||
diff --git a/net/netlink/af_netlink.h b/net/netlink/af_netlink.h index f123a88496f8..f1c31b39aa3e 100644 --- a/net/netlink/af_netlink.h +++ b/net/netlink/af_netlink.h | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | #define _AF_NETLINK_H | 2 | #define _AF_NETLINK_H |
| 3 | 3 | ||
| 4 | #include <linux/rhashtable.h> | 4 | #include <linux/rhashtable.h> |
| 5 | #include <linux/atomic.h> | ||
| 5 | #include <net/sock.h> | 6 | #include <net/sock.h> |
| 6 | 7 | ||
| 7 | #define NLGRPSZ(x) (ALIGN(x, sizeof(unsigned long) * 8) / 8) | 8 | #define NLGRPSZ(x) (ALIGN(x, sizeof(unsigned long) * 8) / 8) |
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 2e11061ef885..ee57459fc258 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c | |||
| @@ -23,6 +23,9 @@ | |||
| 23 | static DEFINE_MUTEX(genl_mutex); /* serialization of message processing */ | 23 | static DEFINE_MUTEX(genl_mutex); /* serialization of message processing */ |
| 24 | static DECLARE_RWSEM(cb_lock); | 24 | static DECLARE_RWSEM(cb_lock); |
| 25 | 25 | ||
| 26 | atomic_t genl_sk_destructing_cnt = ATOMIC_INIT(0); | ||
| 27 | DECLARE_WAIT_QUEUE_HEAD(genl_sk_destructing_waitq); | ||
| 28 | |||
| 26 | void genl_lock(void) | 29 | void genl_lock(void) |
| 27 | { | 30 | { |
| 28 | mutex_lock(&genl_mutex); | 31 | mutex_lock(&genl_mutex); |
| @@ -435,15 +438,18 @@ int genl_unregister_family(struct genl_family *family) | |||
| 435 | 438 | ||
| 436 | genl_lock_all(); | 439 | genl_lock_all(); |
| 437 | 440 | ||
| 438 | genl_unregister_mc_groups(family); | ||
| 439 | |||
| 440 | list_for_each_entry(rc, genl_family_chain(family->id), family_list) { | 441 | list_for_each_entry(rc, genl_family_chain(family->id), family_list) { |
| 441 | if (family->id != rc->id || strcmp(rc->name, family->name)) | 442 | if (family->id != rc->id || strcmp(rc->name, family->name)) |
| 442 | continue; | 443 | continue; |
| 443 | 444 | ||
| 445 | genl_unregister_mc_groups(family); | ||
| 446 | |||
| 444 | list_del(&rc->family_list); | 447 | list_del(&rc->family_list); |
| 445 | family->n_ops = 0; | 448 | family->n_ops = 0; |
| 446 | genl_unlock_all(); | 449 | up_write(&cb_lock); |
| 450 | wait_event(genl_sk_destructing_waitq, | ||
| 451 | atomic_read(&genl_sk_destructing_cnt) == 0); | ||
| 452 | genl_unlock(); | ||
| 447 | 453 | ||
| 448 | kfree(family->attrbuf); | 454 | kfree(family->attrbuf); |
| 449 | genl_ctrl_event(CTRL_CMD_DELFAMILY, family, NULL, 0); | 455 | genl_ctrl_event(CTRL_CMD_DELFAMILY, family, NULL, 0); |
| @@ -985,7 +991,7 @@ static struct genl_multicast_group genl_ctrl_groups[] = { | |||
| 985 | 991 | ||
| 986 | static int genl_bind(struct net *net, int group) | 992 | static int genl_bind(struct net *net, int group) |
| 987 | { | 993 | { |
| 988 | int i, err = 0; | 994 | int i, err = -ENOENT; |
| 989 | 995 | ||
| 990 | down_read(&cb_lock); | 996 | down_read(&cb_lock); |
| 991 | for (i = 0; i < GENL_FAM_TAB_SIZE; i++) { | 997 | for (i = 0; i < GENL_FAM_TAB_SIZE; i++) { |
| @@ -1014,7 +1020,6 @@ static int genl_bind(struct net *net, int group) | |||
| 1014 | static void genl_unbind(struct net *net, int group) | 1020 | static void genl_unbind(struct net *net, int group) |
| 1015 | { | 1021 | { |
| 1016 | int i; | 1022 | int i; |
| 1017 | bool found = false; | ||
| 1018 | 1023 | ||
| 1019 | down_read(&cb_lock); | 1024 | down_read(&cb_lock); |
| 1020 | for (i = 0; i < GENL_FAM_TAB_SIZE; i++) { | 1025 | for (i = 0; i < GENL_FAM_TAB_SIZE; i++) { |
| @@ -1027,14 +1032,11 @@ static void genl_unbind(struct net *net, int group) | |||
| 1027 | 1032 | ||
| 1028 | if (f->mcast_unbind) | 1033 | if (f->mcast_unbind) |
| 1029 | f->mcast_unbind(net, fam_grp); | 1034 | f->mcast_unbind(net, fam_grp); |
| 1030 | found = true; | ||
| 1031 | break; | 1035 | break; |
| 1032 | } | 1036 | } |
| 1033 | } | 1037 | } |
| 1034 | } | 1038 | } |
| 1035 | up_read(&cb_lock); | 1039 | up_read(&cb_lock); |
| 1036 | |||
| 1037 | WARN_ON(!found); | ||
| 1038 | } | 1040 | } |
| 1039 | 1041 | ||
| 1040 | static int __net_init genl_pernet_init(struct net *net) | 1042 | static int __net_init genl_pernet_init(struct net *net) |
diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c index 84c8219c3e1c..f59adf8a4cd7 100644 --- a/net/sched/cls_bpf.c +++ b/net/sched/cls_bpf.c | |||
| @@ -180,6 +180,11 @@ static int cls_bpf_modify_existing(struct net *net, struct tcf_proto *tp, | |||
| 180 | } | 180 | } |
| 181 | 181 | ||
| 182 | bpf_size = bpf_len * sizeof(*bpf_ops); | 182 | bpf_size = bpf_len * sizeof(*bpf_ops); |
| 183 | if (bpf_size != nla_len(tb[TCA_BPF_OPS])) { | ||
| 184 | ret = -EINVAL; | ||
| 185 | goto errout; | ||
| 186 | } | ||
| 187 | |||
| 183 | bpf_ops = kzalloc(bpf_size, GFP_KERNEL); | 188 | bpf_ops = kzalloc(bpf_size, GFP_KERNEL); |
| 184 | if (bpf_ops == NULL) { | 189 | if (bpf_ops == NULL) { |
| 185 | ret = -ENOMEM; | 190 | ret = -ENOMEM; |
| @@ -215,15 +220,21 @@ static u32 cls_bpf_grab_new_handle(struct tcf_proto *tp, | |||
| 215 | struct cls_bpf_head *head) | 220 | struct cls_bpf_head *head) |
| 216 | { | 221 | { |
| 217 | unsigned int i = 0x80000000; | 222 | unsigned int i = 0x80000000; |
| 223 | u32 handle; | ||
| 218 | 224 | ||
| 219 | do { | 225 | do { |
| 220 | if (++head->hgen == 0x7FFFFFFF) | 226 | if (++head->hgen == 0x7FFFFFFF) |
| 221 | head->hgen = 1; | 227 | head->hgen = 1; |
| 222 | } while (--i > 0 && cls_bpf_get(tp, head->hgen)); | 228 | } while (--i > 0 && cls_bpf_get(tp, head->hgen)); |
| 223 | if (i == 0) | 229 | |
| 230 | if (unlikely(i == 0)) { | ||
| 224 | pr_err("Insufficient number of handles\n"); | 231 | pr_err("Insufficient number of handles\n"); |
| 232 | handle = 0; | ||
| 233 | } else { | ||
| 234 | handle = head->hgen; | ||
| 235 | } | ||
| 225 | 236 | ||
| 226 | return i; | 237 | return handle; |
| 227 | } | 238 | } |
| 228 | 239 | ||
| 229 | static int cls_bpf_change(struct net *net, struct sk_buff *in_skb, | 240 | static int cls_bpf_change(struct net *net, struct sk_buff *in_skb, |
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index f791edd64d6c..26d06dbcc1c8 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c | |||
| @@ -1182,7 +1182,6 @@ void sctp_assoc_update(struct sctp_association *asoc, | |||
| 1182 | asoc->peer.peer_hmacs = new->peer.peer_hmacs; | 1182 | asoc->peer.peer_hmacs = new->peer.peer_hmacs; |
| 1183 | new->peer.peer_hmacs = NULL; | 1183 | new->peer.peer_hmacs = NULL; |
| 1184 | 1184 | ||
| 1185 | sctp_auth_key_put(asoc->asoc_shared_key); | ||
| 1186 | sctp_auth_asoc_init_active_key(asoc, GFP_ATOMIC); | 1185 | sctp_auth_asoc_init_active_key(asoc, GFP_ATOMIC); |
| 1187 | } | 1186 | } |
| 1188 | 1187 | ||
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 2625eccb77d5..aafe94bf292e 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
| @@ -1603,7 +1603,7 @@ static int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
| 1603 | sctp_assoc_t associd = 0; | 1603 | sctp_assoc_t associd = 0; |
| 1604 | sctp_cmsgs_t cmsgs = { NULL }; | 1604 | sctp_cmsgs_t cmsgs = { NULL }; |
| 1605 | sctp_scope_t scope; | 1605 | sctp_scope_t scope; |
| 1606 | bool fill_sinfo_ttl = false; | 1606 | bool fill_sinfo_ttl = false, wait_connect = false; |
| 1607 | struct sctp_datamsg *datamsg; | 1607 | struct sctp_datamsg *datamsg; |
| 1608 | int msg_flags = msg->msg_flags; | 1608 | int msg_flags = msg->msg_flags; |
| 1609 | __u16 sinfo_flags = 0; | 1609 | __u16 sinfo_flags = 0; |
| @@ -1943,6 +1943,7 @@ static int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
| 1943 | if (err < 0) | 1943 | if (err < 0) |
| 1944 | goto out_free; | 1944 | goto out_free; |
| 1945 | 1945 | ||
| 1946 | wait_connect = true; | ||
| 1946 | pr_debug("%s: we associated primitively\n", __func__); | 1947 | pr_debug("%s: we associated primitively\n", __func__); |
| 1947 | } | 1948 | } |
| 1948 | 1949 | ||
| @@ -1980,6 +1981,11 @@ static int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
| 1980 | sctp_datamsg_put(datamsg); | 1981 | sctp_datamsg_put(datamsg); |
| 1981 | err = msg_len; | 1982 | err = msg_len; |
| 1982 | 1983 | ||
| 1984 | if (unlikely(wait_connect)) { | ||
| 1985 | timeo = sock_sndtimeo(sk, msg_flags & MSG_DONTWAIT); | ||
| 1986 | sctp_wait_for_connect(asoc, &timeo); | ||
| 1987 | } | ||
| 1988 | |||
| 1983 | /* If we are already past ASSOCIATE, the lower | 1989 | /* If we are already past ASSOCIATE, the lower |
| 1984 | * layers are responsible for association cleanup. | 1990 | * layers are responsible for association cleanup. |
| 1985 | */ | 1991 | */ |
diff --git a/net/socket.c b/net/socket.c index a2c33a4dc7ba..418795caa897 100644 --- a/net/socket.c +++ b/net/socket.c | |||
| @@ -869,9 +869,6 @@ static ssize_t sock_splice_read(struct file *file, loff_t *ppos, | |||
| 869 | static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb, | 869 | static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb, |
| 870 | struct sock_iocb *siocb) | 870 | struct sock_iocb *siocb) |
| 871 | { | 871 | { |
| 872 | if (!is_sync_kiocb(iocb)) | ||
| 873 | BUG(); | ||
| 874 | |||
| 875 | siocb->kiocb = iocb; | 872 | siocb->kiocb = iocb; |
| 876 | iocb->private = siocb; | 873 | iocb->private = siocb; |
| 877 | return siocb; | 874 | return siocb; |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 7ca4b5133123..8887c6e5fca8 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
| @@ -2854,6 +2854,9 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info) | |||
| 2854 | if (!rdev->ops->get_key) | 2854 | if (!rdev->ops->get_key) |
| 2855 | return -EOPNOTSUPP; | 2855 | return -EOPNOTSUPP; |
| 2856 | 2856 | ||
| 2857 | if (!pairwise && mac_addr && !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN)) | ||
| 2858 | return -ENOENT; | ||
| 2859 | |||
| 2857 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | 2860 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); |
| 2858 | if (!msg) | 2861 | if (!msg) |
| 2859 | return -ENOMEM; | 2862 | return -ENOMEM; |
| @@ -2873,10 +2876,6 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info) | |||
| 2873 | nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr)) | 2876 | nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr)) |
| 2874 | goto nla_put_failure; | 2877 | goto nla_put_failure; |
| 2875 | 2878 | ||
| 2876 | if (pairwise && mac_addr && | ||
| 2877 | !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN)) | ||
| 2878 | return -ENOENT; | ||
| 2879 | |||
| 2880 | err = rdev_get_key(rdev, dev, key_idx, pairwise, mac_addr, &cookie, | 2879 | err = rdev_get_key(rdev, dev, key_idx, pairwise, mac_addr, &cookie, |
| 2881 | get_key_callback); | 2880 | get_key_callback); |
| 2882 | 2881 | ||
| @@ -3047,7 +3046,7 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info) | |||
| 3047 | wdev_lock(dev->ieee80211_ptr); | 3046 | wdev_lock(dev->ieee80211_ptr); |
| 3048 | err = nl80211_key_allowed(dev->ieee80211_ptr); | 3047 | err = nl80211_key_allowed(dev->ieee80211_ptr); |
| 3049 | 3048 | ||
| 3050 | if (key.type == NL80211_KEYTYPE_PAIRWISE && mac_addr && | 3049 | if (key.type == NL80211_KEYTYPE_GROUP && mac_addr && |
| 3051 | !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN)) | 3050 | !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN)) |
| 3052 | err = -ENOENT; | 3051 | err = -ENOENT; |
| 3053 | 3052 | ||
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 7b8309840d4e..d39d1cbc86b1 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
| @@ -1530,45 +1530,40 @@ static void reg_call_notifier(struct wiphy *wiphy, | |||
| 1530 | 1530 | ||
| 1531 | static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev) | 1531 | static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev) |
| 1532 | { | 1532 | { |
| 1533 | struct ieee80211_channel *ch; | ||
| 1534 | struct cfg80211_chan_def chandef; | 1533 | struct cfg80211_chan_def chandef; |
| 1535 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); | 1534 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); |
| 1536 | bool ret = true; | 1535 | enum nl80211_iftype iftype; |
| 1537 | 1536 | ||
| 1538 | wdev_lock(wdev); | 1537 | wdev_lock(wdev); |
| 1538 | iftype = wdev->iftype; | ||
| 1539 | 1539 | ||
| 1540 | /* make sure the interface is active */ | ||
| 1540 | if (!wdev->netdev || !netif_running(wdev->netdev)) | 1541 | if (!wdev->netdev || !netif_running(wdev->netdev)) |
| 1541 | goto out; | 1542 | goto wdev_inactive_unlock; |
| 1542 | 1543 | ||
| 1543 | switch (wdev->iftype) { | 1544 | switch (iftype) { |
| 1544 | case NL80211_IFTYPE_AP: | 1545 | case NL80211_IFTYPE_AP: |
| 1545 | case NL80211_IFTYPE_P2P_GO: | 1546 | case NL80211_IFTYPE_P2P_GO: |
| 1546 | if (!wdev->beacon_interval) | 1547 | if (!wdev->beacon_interval) |
| 1547 | goto out; | 1548 | goto wdev_inactive_unlock; |
| 1548 | 1549 | chandef = wdev->chandef; | |
| 1549 | ret = cfg80211_reg_can_beacon(wiphy, | ||
| 1550 | &wdev->chandef, wdev->iftype); | ||
| 1551 | break; | 1550 | break; |
| 1552 | case NL80211_IFTYPE_ADHOC: | 1551 | case NL80211_IFTYPE_ADHOC: |
| 1553 | if (!wdev->ssid_len) | 1552 | if (!wdev->ssid_len) |
| 1554 | goto out; | 1553 | goto wdev_inactive_unlock; |
| 1555 | 1554 | chandef = wdev->chandef; | |
| 1556 | ret = cfg80211_reg_can_beacon(wiphy, | ||
| 1557 | &wdev->chandef, wdev->iftype); | ||
| 1558 | break; | 1555 | break; |
| 1559 | case NL80211_IFTYPE_STATION: | 1556 | case NL80211_IFTYPE_STATION: |
| 1560 | case NL80211_IFTYPE_P2P_CLIENT: | 1557 | case NL80211_IFTYPE_P2P_CLIENT: |
| 1561 | if (!wdev->current_bss || | 1558 | if (!wdev->current_bss || |
| 1562 | !wdev->current_bss->pub.channel) | 1559 | !wdev->current_bss->pub.channel) |
| 1563 | goto out; | 1560 | goto wdev_inactive_unlock; |
| 1564 | 1561 | ||
| 1565 | ch = wdev->current_bss->pub.channel; | 1562 | if (!rdev->ops->get_channel || |
| 1566 | if (rdev->ops->get_channel && | 1563 | rdev_get_channel(rdev, wdev, &chandef)) |
| 1567 | !rdev_get_channel(rdev, wdev, &chandef)) | 1564 | cfg80211_chandef_create(&chandef, |
| 1568 | ret = cfg80211_chandef_usable(wiphy, &chandef, | 1565 | wdev->current_bss->pub.channel, |
| 1569 | IEEE80211_CHAN_DISABLED); | 1566 | NL80211_CHAN_NO_HT); |
| 1570 | else | ||
| 1571 | ret = !(ch->flags & IEEE80211_CHAN_DISABLED); | ||
| 1572 | break; | 1567 | break; |
| 1573 | case NL80211_IFTYPE_MONITOR: | 1568 | case NL80211_IFTYPE_MONITOR: |
| 1574 | case NL80211_IFTYPE_AP_VLAN: | 1569 | case NL80211_IFTYPE_AP_VLAN: |
| @@ -1581,9 +1576,26 @@ static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev) | |||
| 1581 | break; | 1576 | break; |
| 1582 | } | 1577 | } |
| 1583 | 1578 | ||
| 1584 | out: | ||
| 1585 | wdev_unlock(wdev); | 1579 | wdev_unlock(wdev); |
| 1586 | return ret; | 1580 | |
| 1581 | switch (iftype) { | ||
| 1582 | case NL80211_IFTYPE_AP: | ||
| 1583 | case NL80211_IFTYPE_P2P_GO: | ||
| 1584 | case NL80211_IFTYPE_ADHOC: | ||
| 1585 | return cfg80211_reg_can_beacon(wiphy, &chandef, iftype); | ||
| 1586 | case NL80211_IFTYPE_STATION: | ||
| 1587 | case NL80211_IFTYPE_P2P_CLIENT: | ||
| 1588 | return cfg80211_chandef_usable(wiphy, &chandef, | ||
| 1589 | IEEE80211_CHAN_DISABLED); | ||
| 1590 | default: | ||
| 1591 | break; | ||
| 1592 | } | ||
| 1593 | |||
| 1594 | return true; | ||
| 1595 | |||
| 1596 | wdev_inactive_unlock: | ||
| 1597 | wdev_unlock(wdev); | ||
| 1598 | return true; | ||
| 1587 | } | 1599 | } |
| 1588 | 1600 | ||
| 1589 | static void reg_leave_invalid_chans(struct wiphy *wiphy) | 1601 | static void reg_leave_invalid_chans(struct wiphy *wiphy) |
diff --git a/net/wireless/util.c b/net/wireless/util.c index d0ac795445b7..5488c3662f7d 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
| @@ -308,6 +308,12 @@ unsigned int __attribute_const__ ieee80211_hdrlen(__le16 fc) | |||
| 308 | goto out; | 308 | goto out; |
| 309 | } | 309 | } |
| 310 | 310 | ||
| 311 | if (ieee80211_is_mgmt(fc)) { | ||
| 312 | if (ieee80211_has_order(fc)) | ||
| 313 | hdrlen += IEEE80211_HT_CTL_LEN; | ||
| 314 | goto out; | ||
| 315 | } | ||
| 316 | |||
| 311 | if (ieee80211_is_ctl(fc)) { | 317 | if (ieee80211_is_ctl(fc)) { |
| 312 | /* | 318 | /* |
| 313 | * ACK and CTS are 10 bytes, all others 16. To see how | 319 | * ACK and CTS are 10 bytes, all others 16. To see how |
