diff options
Diffstat (limited to 'net')
38 files changed, 430 insertions, 216 deletions
diff --git a/net/9p/client.c b/net/9p/client.c index 8eb75425e6e6..addc116cecf0 100644 --- a/net/9p/client.c +++ b/net/9p/client.c | |||
| @@ -562,36 +562,19 @@ static int p9_check_zc_errors(struct p9_client *c, struct p9_req_t *req, | |||
| 562 | 562 | ||
| 563 | if (!p9_is_proto_dotl(c)) { | 563 | if (!p9_is_proto_dotl(c)) { |
| 564 | /* Error is reported in string format */ | 564 | /* Error is reported in string format */ |
| 565 | uint16_t len; | 565 | int len; |
| 566 | /* 7 = header size for RERROR, 2 is the size of string len; */ | 566 | /* 7 = header size for RERROR; */ |
| 567 | int inline_len = in_hdrlen - (7 + 2); | 567 | int inline_len = in_hdrlen - 7; |
| 568 | 568 | ||
| 569 | /* Read the size of error string */ | 569 | len = req->rc->size - req->rc->offset; |
| 570 | err = p9pdu_readf(req->rc, c->proto_version, "w", &len); | 570 | if (len > (P9_ZC_HDR_SZ - 7)) { |
| 571 | if (err) | 571 | err = -EFAULT; |
| 572 | goto out_err; | ||
| 573 | |||
| 574 | ename = kmalloc(len + 1, GFP_NOFS); | ||
| 575 | if (!ename) { | ||
| 576 | err = -ENOMEM; | ||
| 577 | goto out_err; | 572 | goto out_err; |
| 578 | } | 573 | } |
| 579 | if (len <= inline_len) { | ||
| 580 | /* We have error in protocol buffer itself */ | ||
| 581 | if (pdu_read(req->rc, ename, len)) { | ||
| 582 | err = -EFAULT; | ||
| 583 | goto out_free; | ||
| 584 | 574 | ||
| 585 | } | 575 | ename = &req->rc->sdata[req->rc->offset]; |
| 586 | } else { | 576 | if (len > inline_len) { |
| 587 | /* | 577 | /* We have error in external buffer */ |
| 588 | * Part of the data is in user space buffer. | ||
| 589 | */ | ||
| 590 | if (pdu_read(req->rc, ename, inline_len)) { | ||
| 591 | err = -EFAULT; | ||
| 592 | goto out_free; | ||
| 593 | |||
| 594 | } | ||
| 595 | if (kern_buf) { | 578 | if (kern_buf) { |
| 596 | memcpy(ename + inline_len, uidata, | 579 | memcpy(ename + inline_len, uidata, |
| 597 | len - inline_len); | 580 | len - inline_len); |
| @@ -600,19 +583,19 @@ static int p9_check_zc_errors(struct p9_client *c, struct p9_req_t *req, | |||
| 600 | uidata, len - inline_len); | 583 | uidata, len - inline_len); |
| 601 | if (err) { | 584 | if (err) { |
| 602 | err = -EFAULT; | 585 | err = -EFAULT; |
| 603 | goto out_free; | 586 | goto out_err; |
| 604 | } | 587 | } |
| 605 | } | 588 | } |
| 606 | } | 589 | } |
| 607 | ename[len] = 0; | 590 | ename = NULL; |
| 608 | if (p9_is_proto_dotu(c)) { | 591 | err = p9pdu_readf(req->rc, c->proto_version, "s?d", |
| 609 | /* For dotu we also have error code */ | 592 | &ename, &ecode); |
| 610 | err = p9pdu_readf(req->rc, | 593 | if (err) |
| 611 | c->proto_version, "d", &ecode); | 594 | goto out_err; |
| 612 | if (err) | 595 | |
| 613 | goto out_free; | 596 | if (p9_is_proto_dotu(c)) |
| 614 | err = -ecode; | 597 | err = -ecode; |
| 615 | } | 598 | |
| 616 | if (!err || !IS_ERR_VALUE(err)) { | 599 | if (!err || !IS_ERR_VALUE(err)) { |
| 617 | err = p9_errstr2errno(ename, strlen(ename)); | 600 | err = p9_errstr2errno(ename, strlen(ename)); |
| 618 | 601 | ||
| @@ -628,8 +611,6 @@ static int p9_check_zc_errors(struct p9_client *c, struct p9_req_t *req, | |||
| 628 | } | 611 | } |
| 629 | return err; | 612 | return err; |
| 630 | 613 | ||
| 631 | out_free: | ||
| 632 | kfree(ename); | ||
| 633 | out_err: | 614 | out_err: |
| 634 | p9_debug(P9_DEBUG_ERROR, "couldn't parse error%d\n", err); | 615 | p9_debug(P9_DEBUG_ERROR, "couldn't parse error%d\n", err); |
| 635 | return err; | 616 | return err; |
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index 071f288b77a8..f680ee101878 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c | |||
| @@ -29,6 +29,21 @@ | |||
| 29 | #include "bat_algo.h" | 29 | #include "bat_algo.h" |
| 30 | #include "network-coding.h" | 30 | #include "network-coding.h" |
| 31 | 31 | ||
| 32 | /** | ||
| 33 | * batadv_dup_status - duplicate status | ||
| 34 | * @BATADV_NO_DUP: the packet is a duplicate | ||
| 35 | * @BATADV_ORIG_DUP: OGM is a duplicate in the originator (but not for the | ||
| 36 | * neighbor) | ||
| 37 | * @BATADV_NEIGH_DUP: OGM is a duplicate for the neighbor | ||
| 38 | * @BATADV_PROTECTED: originator is currently protected (after reboot) | ||
| 39 | */ | ||
| 40 | enum batadv_dup_status { | ||
| 41 | BATADV_NO_DUP = 0, | ||
| 42 | BATADV_ORIG_DUP, | ||
| 43 | BATADV_NEIGH_DUP, | ||
| 44 | BATADV_PROTECTED, | ||
| 45 | }; | ||
| 46 | |||
| 32 | static struct batadv_neigh_node * | 47 | static struct batadv_neigh_node * |
| 33 | batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface, | 48 | batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface, |
| 34 | const uint8_t *neigh_addr, | 49 | const uint8_t *neigh_addr, |
| @@ -650,7 +665,7 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv, | |||
| 650 | const struct batadv_ogm_packet *batadv_ogm_packet, | 665 | const struct batadv_ogm_packet *batadv_ogm_packet, |
| 651 | struct batadv_hard_iface *if_incoming, | 666 | struct batadv_hard_iface *if_incoming, |
| 652 | const unsigned char *tt_buff, | 667 | const unsigned char *tt_buff, |
| 653 | int is_duplicate) | 668 | enum batadv_dup_status dup_status) |
| 654 | { | 669 | { |
| 655 | struct batadv_neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL; | 670 | struct batadv_neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL; |
| 656 | struct batadv_neigh_node *router = NULL; | 671 | struct batadv_neigh_node *router = NULL; |
| @@ -676,7 +691,7 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv, | |||
| 676 | continue; | 691 | continue; |
| 677 | } | 692 | } |
| 678 | 693 | ||
| 679 | if (is_duplicate) | 694 | if (dup_status != BATADV_NO_DUP) |
| 680 | continue; | 695 | continue; |
| 681 | 696 | ||
| 682 | spin_lock_bh(&tmp_neigh_node->lq_update_lock); | 697 | spin_lock_bh(&tmp_neigh_node->lq_update_lock); |
| @@ -718,7 +733,7 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv, | |||
| 718 | neigh_node->tq_avg = batadv_ring_buffer_avg(neigh_node->tq_recv); | 733 | neigh_node->tq_avg = batadv_ring_buffer_avg(neigh_node->tq_recv); |
| 719 | spin_unlock_bh(&neigh_node->lq_update_lock); | 734 | spin_unlock_bh(&neigh_node->lq_update_lock); |
| 720 | 735 | ||
| 721 | if (!is_duplicate) { | 736 | if (dup_status == BATADV_NO_DUP) { |
| 722 | orig_node->last_ttl = batadv_ogm_packet->header.ttl; | 737 | orig_node->last_ttl = batadv_ogm_packet->header.ttl; |
| 723 | neigh_node->last_ttl = batadv_ogm_packet->header.ttl; | 738 | neigh_node->last_ttl = batadv_ogm_packet->header.ttl; |
| 724 | } | 739 | } |
| @@ -902,15 +917,16 @@ out: | |||
| 902 | return ret; | 917 | return ret; |
| 903 | } | 918 | } |
| 904 | 919 | ||
| 905 | /* processes a batman packet for all interfaces, adjusts the sequence number and | 920 | /** |
| 906 | * finds out whether it is a duplicate. | 921 | * batadv_iv_ogm_update_seqnos - process a batman packet for all interfaces, |
| 907 | * returns: | 922 | * adjust the sequence number and find out whether it is a duplicate |
| 908 | * 1 the packet is a duplicate | 923 | * @ethhdr: ethernet header of the packet |
| 909 | * 0 the packet has not yet been received | 924 | * @batadv_ogm_packet: OGM packet to be considered |
| 910 | * -1 the packet is old and has been received while the seqno window | 925 | * @if_incoming: interface on which the OGM packet was received |
| 911 | * was protected. Caller should drop it. | 926 | * |
| 927 | * Returns duplicate status as enum batadv_dup_status | ||
| 912 | */ | 928 | */ |
| 913 | static int | 929 | static enum batadv_dup_status |
| 914 | batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr, | 930 | batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr, |
| 915 | const struct batadv_ogm_packet *batadv_ogm_packet, | 931 | const struct batadv_ogm_packet *batadv_ogm_packet, |
| 916 | const struct batadv_hard_iface *if_incoming) | 932 | const struct batadv_hard_iface *if_incoming) |
| @@ -918,17 +934,18 @@ batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr, | |||
| 918 | struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface); | 934 | struct batadv_priv *bat_priv = netdev_priv(if_incoming->soft_iface); |
| 919 | struct batadv_orig_node *orig_node; | 935 | struct batadv_orig_node *orig_node; |
| 920 | struct batadv_neigh_node *tmp_neigh_node; | 936 | struct batadv_neigh_node *tmp_neigh_node; |
| 921 | int is_duplicate = 0; | 937 | int is_dup; |
| 922 | int32_t seq_diff; | 938 | int32_t seq_diff; |
| 923 | int need_update = 0; | 939 | int need_update = 0; |
| 924 | int set_mark, ret = -1; | 940 | int set_mark; |
| 941 | enum batadv_dup_status ret = BATADV_NO_DUP; | ||
| 925 | uint32_t seqno = ntohl(batadv_ogm_packet->seqno); | 942 | uint32_t seqno = ntohl(batadv_ogm_packet->seqno); |
| 926 | uint8_t *neigh_addr; | 943 | uint8_t *neigh_addr; |
| 927 | uint8_t packet_count; | 944 | uint8_t packet_count; |
| 928 | 945 | ||
| 929 | orig_node = batadv_get_orig_node(bat_priv, batadv_ogm_packet->orig); | 946 | orig_node = batadv_get_orig_node(bat_priv, batadv_ogm_packet->orig); |
| 930 | if (!orig_node) | 947 | if (!orig_node) |
| 931 | return 0; | 948 | return BATADV_NO_DUP; |
| 932 | 949 | ||
| 933 | spin_lock_bh(&orig_node->ogm_cnt_lock); | 950 | spin_lock_bh(&orig_node->ogm_cnt_lock); |
| 934 | seq_diff = seqno - orig_node->last_real_seqno; | 951 | seq_diff = seqno - orig_node->last_real_seqno; |
| @@ -936,22 +953,29 @@ batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr, | |||
| 936 | /* signalize caller that the packet is to be dropped. */ | 953 | /* signalize caller that the packet is to be dropped. */ |
| 937 | if (!hlist_empty(&orig_node->neigh_list) && | 954 | if (!hlist_empty(&orig_node->neigh_list) && |
| 938 | batadv_window_protected(bat_priv, seq_diff, | 955 | batadv_window_protected(bat_priv, seq_diff, |
| 939 | &orig_node->batman_seqno_reset)) | 956 | &orig_node->batman_seqno_reset)) { |
| 957 | ret = BATADV_PROTECTED; | ||
| 940 | goto out; | 958 | goto out; |
| 959 | } | ||
| 941 | 960 | ||
| 942 | rcu_read_lock(); | 961 | rcu_read_lock(); |
| 943 | hlist_for_each_entry_rcu(tmp_neigh_node, | 962 | hlist_for_each_entry_rcu(tmp_neigh_node, |
| 944 | &orig_node->neigh_list, list) { | 963 | &orig_node->neigh_list, list) { |
| 945 | is_duplicate |= batadv_test_bit(tmp_neigh_node->real_bits, | ||
| 946 | orig_node->last_real_seqno, | ||
| 947 | seqno); | ||
| 948 | |||
| 949 | neigh_addr = tmp_neigh_node->addr; | 964 | neigh_addr = tmp_neigh_node->addr; |
| 965 | is_dup = batadv_test_bit(tmp_neigh_node->real_bits, | ||
| 966 | orig_node->last_real_seqno, | ||
| 967 | seqno); | ||
| 968 | |||
| 950 | if (batadv_compare_eth(neigh_addr, ethhdr->h_source) && | 969 | if (batadv_compare_eth(neigh_addr, ethhdr->h_source) && |
| 951 | tmp_neigh_node->if_incoming == if_incoming) | 970 | tmp_neigh_node->if_incoming == if_incoming) { |
| 952 | set_mark = 1; | 971 | set_mark = 1; |
| 953 | else | 972 | if (is_dup) |
| 973 | ret = BATADV_NEIGH_DUP; | ||
| 974 | } else { | ||
| 954 | set_mark = 0; | 975 | set_mark = 0; |
| 976 | if (is_dup && (ret != BATADV_NEIGH_DUP)) | ||
| 977 | ret = BATADV_ORIG_DUP; | ||
| 978 | } | ||
| 955 | 979 | ||
| 956 | /* if the window moved, set the update flag. */ | 980 | /* if the window moved, set the update flag. */ |
| 957 | need_update |= batadv_bit_get_packet(bat_priv, | 981 | need_update |= batadv_bit_get_packet(bat_priv, |
| @@ -971,8 +995,6 @@ batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr, | |||
| 971 | orig_node->last_real_seqno = seqno; | 995 | orig_node->last_real_seqno = seqno; |
| 972 | } | 996 | } |
| 973 | 997 | ||
| 974 | ret = is_duplicate; | ||
| 975 | |||
| 976 | out: | 998 | out: |
| 977 | spin_unlock_bh(&orig_node->ogm_cnt_lock); | 999 | spin_unlock_bh(&orig_node->ogm_cnt_lock); |
| 978 | batadv_orig_node_free_ref(orig_node); | 1000 | batadv_orig_node_free_ref(orig_node); |
| @@ -994,7 +1016,8 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr, | |||
| 994 | int is_broadcast = 0, is_bidirect; | 1016 | int is_broadcast = 0, is_bidirect; |
| 995 | bool is_single_hop_neigh = false; | 1017 | bool is_single_hop_neigh = false; |
| 996 | bool is_from_best_next_hop = false; | 1018 | bool is_from_best_next_hop = false; |
| 997 | int is_duplicate, sameseq, simlar_ttl; | 1019 | int sameseq, similar_ttl; |
| 1020 | enum batadv_dup_status dup_status; | ||
| 998 | uint32_t if_incoming_seqno; | 1021 | uint32_t if_incoming_seqno; |
| 999 | uint8_t *prev_sender; | 1022 | uint8_t *prev_sender; |
| 1000 | 1023 | ||
| @@ -1138,10 +1161,10 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr, | |||
| 1138 | if (!orig_node) | 1161 | if (!orig_node) |
| 1139 | return; | 1162 | return; |
| 1140 | 1163 | ||
| 1141 | is_duplicate = batadv_iv_ogm_update_seqnos(ethhdr, batadv_ogm_packet, | 1164 | dup_status = batadv_iv_ogm_update_seqnos(ethhdr, batadv_ogm_packet, |
| 1142 | if_incoming); | 1165 | if_incoming); |
| 1143 | 1166 | ||
| 1144 | if (is_duplicate == -1) { | 1167 | if (dup_status == BATADV_PROTECTED) { |
| 1145 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | 1168 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, |
| 1146 | "Drop packet: packet within seqno protection time (sender: %pM)\n", | 1169 | "Drop packet: packet within seqno protection time (sender: %pM)\n", |
| 1147 | ethhdr->h_source); | 1170 | ethhdr->h_source); |
| @@ -1211,11 +1234,12 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr, | |||
| 1211 | * seqno and similar ttl as the non-duplicate | 1234 | * seqno and similar ttl as the non-duplicate |
| 1212 | */ | 1235 | */ |
| 1213 | sameseq = orig_node->last_real_seqno == ntohl(batadv_ogm_packet->seqno); | 1236 | sameseq = orig_node->last_real_seqno == ntohl(batadv_ogm_packet->seqno); |
| 1214 | simlar_ttl = orig_node->last_ttl - 3 <= batadv_ogm_packet->header.ttl; | 1237 | similar_ttl = orig_node->last_ttl - 3 <= batadv_ogm_packet->header.ttl; |
| 1215 | if (is_bidirect && (!is_duplicate || (sameseq && simlar_ttl))) | 1238 | if (is_bidirect && ((dup_status == BATADV_NO_DUP) || |
| 1239 | (sameseq && similar_ttl))) | ||
| 1216 | batadv_iv_ogm_orig_update(bat_priv, orig_node, ethhdr, | 1240 | batadv_iv_ogm_orig_update(bat_priv, orig_node, ethhdr, |
| 1217 | batadv_ogm_packet, if_incoming, | 1241 | batadv_ogm_packet, if_incoming, |
| 1218 | tt_buff, is_duplicate); | 1242 | tt_buff, dup_status); |
| 1219 | 1243 | ||
| 1220 | /* is single hop (direct) neighbor */ | 1244 | /* is single hop (direct) neighbor */ |
| 1221 | if (is_single_hop_neigh) { | 1245 | if (is_single_hop_neigh) { |
| @@ -1236,7 +1260,7 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr, | |||
| 1236 | goto out_neigh; | 1260 | goto out_neigh; |
| 1237 | } | 1261 | } |
| 1238 | 1262 | ||
| 1239 | if (is_duplicate) { | 1263 | if (dup_status == BATADV_NEIGH_DUP) { |
| 1240 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | 1264 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, |
| 1241 | "Drop packet: duplicate packet received\n"); | 1265 | "Drop packet: duplicate packet received\n"); |
| 1242 | goto out_neigh; | 1266 | goto out_neigh; |
diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c index 379061c72549..de27b3175cfd 100644 --- a/net/batman-adv/bridge_loop_avoidance.c +++ b/net/batman-adv/bridge_loop_avoidance.c | |||
| @@ -1067,6 +1067,10 @@ void batadv_bla_update_orig_address(struct batadv_priv *bat_priv, | |||
| 1067 | group = htons(crc16(0, primary_if->net_dev->dev_addr, ETH_ALEN)); | 1067 | group = htons(crc16(0, primary_if->net_dev->dev_addr, ETH_ALEN)); |
| 1068 | bat_priv->bla.claim_dest.group = group; | 1068 | bat_priv->bla.claim_dest.group = group; |
| 1069 | 1069 | ||
| 1070 | /* purge everything when bridge loop avoidance is turned off */ | ||
| 1071 | if (!atomic_read(&bat_priv->bridge_loop_avoidance)) | ||
| 1072 | oldif = NULL; | ||
| 1073 | |||
| 1070 | if (!oldif) { | 1074 | if (!oldif) { |
| 1071 | batadv_bla_purge_claims(bat_priv, NULL, 1); | 1075 | batadv_bla_purge_claims(bat_priv, NULL, 1); |
| 1072 | batadv_bla_purge_backbone_gw(bat_priv, 1); | 1076 | batadv_bla_purge_backbone_gw(bat_priv, 1); |
diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c index 15a22efa9a67..929e304dacb2 100644 --- a/net/batman-adv/sysfs.c +++ b/net/batman-adv/sysfs.c | |||
| @@ -582,10 +582,7 @@ static ssize_t batadv_store_mesh_iface(struct kobject *kobj, | |||
| 582 | (strncmp(hard_iface->soft_iface->name, buff, IFNAMSIZ) == 0)) | 582 | (strncmp(hard_iface->soft_iface->name, buff, IFNAMSIZ) == 0)) |
| 583 | goto out; | 583 | goto out; |
| 584 | 584 | ||
| 585 | if (!rtnl_trylock()) { | 585 | rtnl_lock(); |
| 586 | ret = -ERESTARTSYS; | ||
| 587 | goto out; | ||
| 588 | } | ||
| 589 | 586 | ||
| 590 | if (status_tmp == BATADV_IF_NOT_IN_USE) { | 587 | if (status_tmp == BATADV_IF_NOT_IN_USE) { |
| 591 | batadv_hardif_disable_interface(hard_iface, | 588 | batadv_hardif_disable_interface(hard_iface, |
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 33843c5c4939..ace5e55fe5a3 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
| @@ -341,7 +341,6 @@ static void hci_init1_req(struct hci_request *req, unsigned long opt) | |||
| 341 | 341 | ||
| 342 | static void bredr_setup(struct hci_request *req) | 342 | static void bredr_setup(struct hci_request *req) |
| 343 | { | 343 | { |
| 344 | struct hci_cp_delete_stored_link_key cp; | ||
| 345 | __le16 param; | 344 | __le16 param; |
| 346 | __u8 flt_type; | 345 | __u8 flt_type; |
| 347 | 346 | ||
| @@ -365,10 +364,6 @@ static void bredr_setup(struct hci_request *req) | |||
| 365 | param = __constant_cpu_to_le16(0x7d00); | 364 | param = __constant_cpu_to_le16(0x7d00); |
| 366 | hci_req_add(req, HCI_OP_WRITE_CA_TIMEOUT, 2, ¶m); | 365 | hci_req_add(req, HCI_OP_WRITE_CA_TIMEOUT, 2, ¶m); |
| 367 | 366 | ||
| 368 | bacpy(&cp.bdaddr, BDADDR_ANY); | ||
| 369 | cp.delete_all = 0x01; | ||
| 370 | hci_req_add(req, HCI_OP_DELETE_STORED_LINK_KEY, sizeof(cp), &cp); | ||
| 371 | |||
| 372 | /* Read page scan parameters */ | 367 | /* Read page scan parameters */ |
| 373 | if (req->hdev->hci_ver > BLUETOOTH_VER_1_1) { | 368 | if (req->hdev->hci_ver > BLUETOOTH_VER_1_1) { |
| 374 | hci_req_add(req, HCI_OP_READ_PAGE_SCAN_ACTIVITY, 0, NULL); | 369 | hci_req_add(req, HCI_OP_READ_PAGE_SCAN_ACTIVITY, 0, NULL); |
| @@ -602,6 +597,16 @@ static void hci_init3_req(struct hci_request *req, unsigned long opt) | |||
| 602 | struct hci_dev *hdev = req->hdev; | 597 | struct hci_dev *hdev = req->hdev; |
| 603 | u8 p; | 598 | u8 p; |
| 604 | 599 | ||
| 600 | /* Only send HCI_Delete_Stored_Link_Key if it is supported */ | ||
| 601 | if (hdev->commands[6] & 0x80) { | ||
| 602 | struct hci_cp_delete_stored_link_key cp; | ||
| 603 | |||
| 604 | bacpy(&cp.bdaddr, BDADDR_ANY); | ||
| 605 | cp.delete_all = 0x01; | ||
| 606 | hci_req_add(req, HCI_OP_DELETE_STORED_LINK_KEY, | ||
| 607 | sizeof(cp), &cp); | ||
| 608 | } | ||
| 609 | |||
| 605 | if (hdev->commands[5] & 0x10) | 610 | if (hdev->commands[5] & 0x10) |
| 606 | hci_setup_link_policy(req); | 611 | hci_setup_link_policy(req); |
| 607 | 612 | ||
| @@ -1555,11 +1560,15 @@ static const struct rfkill_ops hci_rfkill_ops = { | |||
| 1555 | static void hci_power_on(struct work_struct *work) | 1560 | static void hci_power_on(struct work_struct *work) |
| 1556 | { | 1561 | { |
| 1557 | struct hci_dev *hdev = container_of(work, struct hci_dev, power_on); | 1562 | struct hci_dev *hdev = container_of(work, struct hci_dev, power_on); |
| 1563 | int err; | ||
| 1558 | 1564 | ||
| 1559 | BT_DBG("%s", hdev->name); | 1565 | BT_DBG("%s", hdev->name); |
| 1560 | 1566 | ||
| 1561 | if (hci_dev_open(hdev->id) < 0) | 1567 | err = hci_dev_open(hdev->id); |
| 1568 | if (err < 0) { | ||
| 1569 | mgmt_set_powered_failed(hdev, err); | ||
| 1562 | return; | 1570 | return; |
| 1571 | } | ||
| 1563 | 1572 | ||
| 1564 | if (test_bit(HCI_AUTO_OFF, &hdev->dev_flags)) | 1573 | if (test_bit(HCI_AUTO_OFF, &hdev->dev_flags)) |
| 1565 | queue_delayed_work(hdev->req_workqueue, &hdev->power_off, | 1574 | queue_delayed_work(hdev->req_workqueue, &hdev->power_off, |
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index a76d1ac0321b..4be6a264b475 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
| @@ -2852,6 +2852,9 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code, | |||
| 2852 | BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %u", | 2852 | BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %u", |
| 2853 | conn, code, ident, dlen); | 2853 | conn, code, ident, dlen); |
| 2854 | 2854 | ||
| 2855 | if (conn->mtu < L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE) | ||
| 2856 | return NULL; | ||
| 2857 | |||
| 2855 | len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen; | 2858 | len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen; |
| 2856 | count = min_t(unsigned int, conn->mtu, len); | 2859 | count = min_t(unsigned int, conn->mtu, len); |
| 2857 | 2860 | ||
| @@ -3677,10 +3680,14 @@ static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len) | |||
| 3677 | } | 3680 | } |
| 3678 | 3681 | ||
| 3679 | static inline int l2cap_command_rej(struct l2cap_conn *conn, | 3682 | static inline int l2cap_command_rej(struct l2cap_conn *conn, |
| 3680 | struct l2cap_cmd_hdr *cmd, u8 *data) | 3683 | struct l2cap_cmd_hdr *cmd, u16 cmd_len, |
| 3684 | u8 *data) | ||
| 3681 | { | 3685 | { |
| 3682 | struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data; | 3686 | struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data; |
| 3683 | 3687 | ||
| 3688 | if (cmd_len < sizeof(*rej)) | ||
| 3689 | return -EPROTO; | ||
| 3690 | |||
| 3684 | if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD) | 3691 | if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD) |
| 3685 | return 0; | 3692 | return 0; |
| 3686 | 3693 | ||
| @@ -3829,11 +3836,14 @@ sendresp: | |||
| 3829 | } | 3836 | } |
| 3830 | 3837 | ||
| 3831 | static int l2cap_connect_req(struct l2cap_conn *conn, | 3838 | static int l2cap_connect_req(struct l2cap_conn *conn, |
| 3832 | struct l2cap_cmd_hdr *cmd, u8 *data) | 3839 | struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) |
| 3833 | { | 3840 | { |
| 3834 | struct hci_dev *hdev = conn->hcon->hdev; | 3841 | struct hci_dev *hdev = conn->hcon->hdev; |
| 3835 | struct hci_conn *hcon = conn->hcon; | 3842 | struct hci_conn *hcon = conn->hcon; |
| 3836 | 3843 | ||
| 3844 | if (cmd_len < sizeof(struct l2cap_conn_req)) | ||
| 3845 | return -EPROTO; | ||
| 3846 | |||
| 3837 | hci_dev_lock(hdev); | 3847 | hci_dev_lock(hdev); |
| 3838 | if (test_bit(HCI_MGMT, &hdev->dev_flags) && | 3848 | if (test_bit(HCI_MGMT, &hdev->dev_flags) && |
| 3839 | !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &hcon->flags)) | 3849 | !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &hcon->flags)) |
| @@ -3847,7 +3857,8 @@ static int l2cap_connect_req(struct l2cap_conn *conn, | |||
| 3847 | } | 3857 | } |
| 3848 | 3858 | ||
| 3849 | static int l2cap_connect_create_rsp(struct l2cap_conn *conn, | 3859 | static int l2cap_connect_create_rsp(struct l2cap_conn *conn, |
| 3850 | struct l2cap_cmd_hdr *cmd, u8 *data) | 3860 | struct l2cap_cmd_hdr *cmd, u16 cmd_len, |
| 3861 | u8 *data) | ||
| 3851 | { | 3862 | { |
| 3852 | struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data; | 3863 | struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data; |
| 3853 | u16 scid, dcid, result, status; | 3864 | u16 scid, dcid, result, status; |
| @@ -3855,6 +3866,9 @@ static int l2cap_connect_create_rsp(struct l2cap_conn *conn, | |||
| 3855 | u8 req[128]; | 3866 | u8 req[128]; |
| 3856 | int err; | 3867 | int err; |
| 3857 | 3868 | ||
| 3869 | if (cmd_len < sizeof(*rsp)) | ||
| 3870 | return -EPROTO; | ||
| 3871 | |||
| 3858 | scid = __le16_to_cpu(rsp->scid); | 3872 | scid = __le16_to_cpu(rsp->scid); |
| 3859 | dcid = __le16_to_cpu(rsp->dcid); | 3873 | dcid = __le16_to_cpu(rsp->dcid); |
| 3860 | result = __le16_to_cpu(rsp->result); | 3874 | result = __le16_to_cpu(rsp->result); |
| @@ -3952,6 +3966,9 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, | |||
| 3952 | struct l2cap_chan *chan; | 3966 | struct l2cap_chan *chan; |
| 3953 | int len, err = 0; | 3967 | int len, err = 0; |
| 3954 | 3968 | ||
| 3969 | if (cmd_len < sizeof(*req)) | ||
| 3970 | return -EPROTO; | ||
| 3971 | |||
| 3955 | dcid = __le16_to_cpu(req->dcid); | 3972 | dcid = __le16_to_cpu(req->dcid); |
| 3956 | flags = __le16_to_cpu(req->flags); | 3973 | flags = __le16_to_cpu(req->flags); |
| 3957 | 3974 | ||
| @@ -3975,7 +3992,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, | |||
| 3975 | 3992 | ||
| 3976 | /* Reject if config buffer is too small. */ | 3993 | /* Reject if config buffer is too small. */ |
| 3977 | len = cmd_len - sizeof(*req); | 3994 | len = cmd_len - sizeof(*req); |
| 3978 | if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) { | 3995 | if (chan->conf_len + len > sizeof(chan->conf_req)) { |
| 3979 | l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, | 3996 | l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, |
| 3980 | l2cap_build_conf_rsp(chan, rsp, | 3997 | l2cap_build_conf_rsp(chan, rsp, |
| 3981 | L2CAP_CONF_REJECT, flags), rsp); | 3998 | L2CAP_CONF_REJECT, flags), rsp); |
| @@ -4053,14 +4070,18 @@ unlock: | |||
| 4053 | } | 4070 | } |
| 4054 | 4071 | ||
| 4055 | static inline int l2cap_config_rsp(struct l2cap_conn *conn, | 4072 | static inline int l2cap_config_rsp(struct l2cap_conn *conn, |
| 4056 | struct l2cap_cmd_hdr *cmd, u8 *data) | 4073 | struct l2cap_cmd_hdr *cmd, u16 cmd_len, |
| 4074 | u8 *data) | ||
| 4057 | { | 4075 | { |
| 4058 | struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data; | 4076 | struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data; |
| 4059 | u16 scid, flags, result; | 4077 | u16 scid, flags, result; |
| 4060 | struct l2cap_chan *chan; | 4078 | struct l2cap_chan *chan; |
| 4061 | int len = le16_to_cpu(cmd->len) - sizeof(*rsp); | 4079 | int len = cmd_len - sizeof(*rsp); |
| 4062 | int err = 0; | 4080 | int err = 0; |
| 4063 | 4081 | ||
| 4082 | if (cmd_len < sizeof(*rsp)) | ||
| 4083 | return -EPROTO; | ||
| 4084 | |||
| 4064 | scid = __le16_to_cpu(rsp->scid); | 4085 | scid = __le16_to_cpu(rsp->scid); |
| 4065 | flags = __le16_to_cpu(rsp->flags); | 4086 | flags = __le16_to_cpu(rsp->flags); |
| 4066 | result = __le16_to_cpu(rsp->result); | 4087 | result = __le16_to_cpu(rsp->result); |
| @@ -4161,7 +4182,8 @@ done: | |||
| 4161 | } | 4182 | } |
| 4162 | 4183 | ||
| 4163 | static inline int l2cap_disconnect_req(struct l2cap_conn *conn, | 4184 | static inline int l2cap_disconnect_req(struct l2cap_conn *conn, |
| 4164 | struct l2cap_cmd_hdr *cmd, u8 *data) | 4185 | struct l2cap_cmd_hdr *cmd, u16 cmd_len, |
| 4186 | u8 *data) | ||
| 4165 | { | 4187 | { |
| 4166 | struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data; | 4188 | struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data; |
| 4167 | struct l2cap_disconn_rsp rsp; | 4189 | struct l2cap_disconn_rsp rsp; |
| @@ -4169,6 +4191,9 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, | |||
| 4169 | struct l2cap_chan *chan; | 4191 | struct l2cap_chan *chan; |
| 4170 | struct sock *sk; | 4192 | struct sock *sk; |
| 4171 | 4193 | ||
| 4194 | if (cmd_len != sizeof(*req)) | ||
| 4195 | return -EPROTO; | ||
| 4196 | |||
| 4172 | scid = __le16_to_cpu(req->scid); | 4197 | scid = __le16_to_cpu(req->scid); |
| 4173 | dcid = __le16_to_cpu(req->dcid); | 4198 | dcid = __le16_to_cpu(req->dcid); |
| 4174 | 4199 | ||
| @@ -4208,12 +4233,16 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, | |||
| 4208 | } | 4233 | } |
| 4209 | 4234 | ||
| 4210 | static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, | 4235 | static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, |
| 4211 | struct l2cap_cmd_hdr *cmd, u8 *data) | 4236 | struct l2cap_cmd_hdr *cmd, u16 cmd_len, |
| 4237 | u8 *data) | ||
| 4212 | { | 4238 | { |
| 4213 | struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data; | 4239 | struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data; |
| 4214 | u16 dcid, scid; | 4240 | u16 dcid, scid; |
| 4215 | struct l2cap_chan *chan; | 4241 | struct l2cap_chan *chan; |
| 4216 | 4242 | ||
| 4243 | if (cmd_len != sizeof(*rsp)) | ||
| 4244 | return -EPROTO; | ||
| 4245 | |||
| 4217 | scid = __le16_to_cpu(rsp->scid); | 4246 | scid = __le16_to_cpu(rsp->scid); |
| 4218 | dcid = __le16_to_cpu(rsp->dcid); | 4247 | dcid = __le16_to_cpu(rsp->dcid); |
| 4219 | 4248 | ||
| @@ -4243,11 +4272,15 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, | |||
| 4243 | } | 4272 | } |
| 4244 | 4273 | ||
| 4245 | static inline int l2cap_information_req(struct l2cap_conn *conn, | 4274 | static inline int l2cap_information_req(struct l2cap_conn *conn, |
| 4246 | struct l2cap_cmd_hdr *cmd, u8 *data) | 4275 | struct l2cap_cmd_hdr *cmd, u16 cmd_len, |
| 4276 | u8 *data) | ||
| 4247 | { | 4277 | { |
| 4248 | struct l2cap_info_req *req = (struct l2cap_info_req *) data; | 4278 | struct l2cap_info_req *req = (struct l2cap_info_req *) data; |
| 4249 | u16 type; | 4279 | u16 type; |
| 4250 | 4280 | ||
| 4281 | if (cmd_len != sizeof(*req)) | ||
| 4282 | return -EPROTO; | ||
| 4283 | |||
| 4251 | type = __le16_to_cpu(req->type); | 4284 | type = __le16_to_cpu(req->type); |
| 4252 | 4285 | ||
| 4253 | BT_DBG("type 0x%4.4x", type); | 4286 | BT_DBG("type 0x%4.4x", type); |
| @@ -4294,11 +4327,15 @@ static inline int l2cap_information_req(struct l2cap_conn *conn, | |||
| 4294 | } | 4327 | } |
| 4295 | 4328 | ||
| 4296 | static inline int l2cap_information_rsp(struct l2cap_conn *conn, | 4329 | static inline int l2cap_information_rsp(struct l2cap_conn *conn, |
| 4297 | struct l2cap_cmd_hdr *cmd, u8 *data) | 4330 | struct l2cap_cmd_hdr *cmd, u16 cmd_len, |
| 4331 | u8 *data) | ||
| 4298 | { | 4332 | { |
| 4299 | struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data; | 4333 | struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data; |
| 4300 | u16 type, result; | 4334 | u16 type, result; |
| 4301 | 4335 | ||
| 4336 | if (cmd_len != sizeof(*rsp)) | ||
| 4337 | return -EPROTO; | ||
| 4338 | |||
| 4302 | type = __le16_to_cpu(rsp->type); | 4339 | type = __le16_to_cpu(rsp->type); |
| 4303 | result = __le16_to_cpu(rsp->result); | 4340 | result = __le16_to_cpu(rsp->result); |
| 4304 | 4341 | ||
| @@ -5164,16 +5201,16 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn, | |||
| 5164 | 5201 | ||
| 5165 | switch (cmd->code) { | 5202 | switch (cmd->code) { |
| 5166 | case L2CAP_COMMAND_REJ: | 5203 | case L2CAP_COMMAND_REJ: |
| 5167 | l2cap_command_rej(conn, cmd, data); | 5204 | l2cap_command_rej(conn, cmd, cmd_len, data); |
| 5168 | break; | 5205 | break; |
| 5169 | 5206 | ||
| 5170 | case L2CAP_CONN_REQ: | 5207 | case L2CAP_CONN_REQ: |
| 5171 | err = l2cap_connect_req(conn, cmd, data); | 5208 | err = l2cap_connect_req(conn, cmd, cmd_len, data); |
| 5172 | break; | 5209 | break; |
| 5173 | 5210 | ||
| 5174 | case L2CAP_CONN_RSP: | 5211 | case L2CAP_CONN_RSP: |
| 5175 | case L2CAP_CREATE_CHAN_RSP: | 5212 | case L2CAP_CREATE_CHAN_RSP: |
| 5176 | err = l2cap_connect_create_rsp(conn, cmd, data); | 5213 | err = l2cap_connect_create_rsp(conn, cmd, cmd_len, data); |
| 5177 | break; | 5214 | break; |
| 5178 | 5215 | ||
| 5179 | case L2CAP_CONF_REQ: | 5216 | case L2CAP_CONF_REQ: |
| @@ -5181,15 +5218,15 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn, | |||
| 5181 | break; | 5218 | break; |
| 5182 | 5219 | ||
| 5183 | case L2CAP_CONF_RSP: | 5220 | case L2CAP_CONF_RSP: |
| 5184 | err = l2cap_config_rsp(conn, cmd, data); | 5221 | err = l2cap_config_rsp(conn, cmd, cmd_len, data); |
| 5185 | break; | 5222 | break; |
| 5186 | 5223 | ||
| 5187 | case L2CAP_DISCONN_REQ: | 5224 | case L2CAP_DISCONN_REQ: |
| 5188 | err = l2cap_disconnect_req(conn, cmd, data); | 5225 | err = l2cap_disconnect_req(conn, cmd, cmd_len, data); |
| 5189 | break; | 5226 | break; |
| 5190 | 5227 | ||
| 5191 | case L2CAP_DISCONN_RSP: | 5228 | case L2CAP_DISCONN_RSP: |
| 5192 | err = l2cap_disconnect_rsp(conn, cmd, data); | 5229 | err = l2cap_disconnect_rsp(conn, cmd, cmd_len, data); |
| 5193 | break; | 5230 | break; |
| 5194 | 5231 | ||
| 5195 | case L2CAP_ECHO_REQ: | 5232 | case L2CAP_ECHO_REQ: |
| @@ -5200,11 +5237,11 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn, | |||
| 5200 | break; | 5237 | break; |
| 5201 | 5238 | ||
| 5202 | case L2CAP_INFO_REQ: | 5239 | case L2CAP_INFO_REQ: |
| 5203 | err = l2cap_information_req(conn, cmd, data); | 5240 | err = l2cap_information_req(conn, cmd, cmd_len, data); |
| 5204 | break; | 5241 | break; |
| 5205 | 5242 | ||
| 5206 | case L2CAP_INFO_RSP: | 5243 | case L2CAP_INFO_RSP: |
| 5207 | err = l2cap_information_rsp(conn, cmd, data); | 5244 | err = l2cap_information_rsp(conn, cmd, cmd_len, data); |
| 5208 | break; | 5245 | break; |
| 5209 | 5246 | ||
| 5210 | case L2CAP_CREATE_CHAN_REQ: | 5247 | case L2CAP_CREATE_CHAN_REQ: |
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 35fef22703e9..f8ecbc70293d 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
| @@ -2700,7 +2700,7 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, | |||
| 2700 | break; | 2700 | break; |
| 2701 | 2701 | ||
| 2702 | case DISCOV_TYPE_LE: | 2702 | case DISCOV_TYPE_LE: |
| 2703 | if (!lmp_host_le_capable(hdev)) { | 2703 | if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { |
| 2704 | err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, | 2704 | err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, |
| 2705 | MGMT_STATUS_NOT_SUPPORTED); | 2705 | MGMT_STATUS_NOT_SUPPORTED); |
| 2706 | mgmt_pending_remove(cmd); | 2706 | mgmt_pending_remove(cmd); |
| @@ -3418,6 +3418,27 @@ new_settings: | |||
| 3418 | return err; | 3418 | return err; |
| 3419 | } | 3419 | } |
| 3420 | 3420 | ||
| 3421 | int mgmt_set_powered_failed(struct hci_dev *hdev, int err) | ||
| 3422 | { | ||
| 3423 | struct pending_cmd *cmd; | ||
| 3424 | u8 status; | ||
| 3425 | |||
| 3426 | cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev); | ||
| 3427 | if (!cmd) | ||
| 3428 | return -ENOENT; | ||
| 3429 | |||
| 3430 | if (err == -ERFKILL) | ||
| 3431 | status = MGMT_STATUS_RFKILLED; | ||
| 3432 | else | ||
| 3433 | status = MGMT_STATUS_FAILED; | ||
| 3434 | |||
| 3435 | err = cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status); | ||
| 3436 | |||
| 3437 | mgmt_pending_remove(cmd); | ||
| 3438 | |||
| 3439 | return err; | ||
| 3440 | } | ||
| 3441 | |||
| 3421 | int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable) | 3442 | int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable) |
| 3422 | { | 3443 | { |
| 3423 | struct cmd_lookup match = { NULL, hdev }; | 3444 | struct cmd_lookup match = { NULL, hdev }; |
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index b2296d3857a0..b5562abdd6e0 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c | |||
| @@ -770,7 +770,7 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level) | |||
| 770 | 770 | ||
| 771 | BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level); | 771 | BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level); |
| 772 | 772 | ||
| 773 | if (!lmp_host_le_capable(hcon->hdev)) | 773 | if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags)) |
| 774 | return 1; | 774 | return 1; |
| 775 | 775 | ||
| 776 | if (sec_level == BT_SECURITY_LOW) | 776 | if (sec_level == BT_SECURITY_LOW) |
| @@ -851,7 +851,7 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb) | |||
| 851 | __u8 reason; | 851 | __u8 reason; |
| 852 | int err = 0; | 852 | int err = 0; |
| 853 | 853 | ||
| 854 | if (!lmp_host_le_capable(conn->hcon->hdev)) { | 854 | if (!test_bit(HCI_LE_ENABLED, &conn->hcon->hdev->dev_flags)) { |
| 855 | err = -ENOTSUPP; | 855 | err = -ENOTSUPP; |
| 856 | reason = SMP_PAIRING_NOTSUPP; | 856 | reason = SMP_PAIRING_NOTSUPP; |
| 857 | goto done; | 857 | goto done; |
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 81f2389f78eb..d6448e35e027 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c | |||
| @@ -465,8 +465,9 @@ static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge *br, | |||
| 465 | skb_set_transport_header(skb, skb->len); | 465 | skb_set_transport_header(skb, skb->len); |
| 466 | mldq = (struct mld_msg *) icmp6_hdr(skb); | 466 | mldq = (struct mld_msg *) icmp6_hdr(skb); |
| 467 | 467 | ||
| 468 | interval = ipv6_addr_any(group) ? br->multicast_last_member_interval : | 468 | interval = ipv6_addr_any(group) ? |
| 469 | br->multicast_query_response_interval; | 469 | br->multicast_query_response_interval : |
| 470 | br->multicast_last_member_interval; | ||
| 470 | 471 | ||
| 471 | mldq->mld_type = ICMPV6_MGM_QUERY; | 472 | mldq->mld_type = ICMPV6_MGM_QUERY; |
| 472 | mldq->mld_code = 0; | 473 | mldq->mld_code = 0; |
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index d5953b87918c..3a246a6cab47 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c | |||
| @@ -1675,13 +1675,13 @@ static void kick_requests(struct ceph_osd_client *osdc, int force_resend) | |||
| 1675 | __register_request(osdc, req); | 1675 | __register_request(osdc, req); |
| 1676 | __unregister_linger_request(osdc, req); | 1676 | __unregister_linger_request(osdc, req); |
| 1677 | } | 1677 | } |
| 1678 | reset_changed_osds(osdc); | ||
| 1678 | mutex_unlock(&osdc->request_mutex); | 1679 | mutex_unlock(&osdc->request_mutex); |
| 1679 | 1680 | ||
| 1680 | if (needmap) { | 1681 | if (needmap) { |
| 1681 | dout("%d requests for down osds, need new map\n", needmap); | 1682 | dout("%d requests for down osds, need new map\n", needmap); |
| 1682 | ceph_monc_request_next_osdmap(&osdc->client->monc); | 1683 | ceph_monc_request_next_osdmap(&osdc->client->monc); |
| 1683 | } | 1684 | } |
| 1684 | reset_changed_osds(osdc); | ||
| 1685 | } | 1685 | } |
| 1686 | 1686 | ||
| 1687 | 1687 | ||
diff --git a/net/compat.c b/net/compat.c index 79ae88485001..f0a1ba6c8086 100644 --- a/net/compat.c +++ b/net/compat.c | |||
| @@ -734,19 +734,25 @@ static unsigned char nas[21] = { | |||
| 734 | 734 | ||
| 735 | asmlinkage long compat_sys_sendmsg(int fd, struct compat_msghdr __user *msg, unsigned int flags) | 735 | asmlinkage long compat_sys_sendmsg(int fd, struct compat_msghdr __user *msg, unsigned int flags) |
| 736 | { | 736 | { |
| 737 | return sys_sendmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT); | 737 | if (flags & MSG_CMSG_COMPAT) |
| 738 | return -EINVAL; | ||
| 739 | return __sys_sendmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT); | ||
| 738 | } | 740 | } |
| 739 | 741 | ||
| 740 | asmlinkage long compat_sys_sendmmsg(int fd, struct compat_mmsghdr __user *mmsg, | 742 | asmlinkage long compat_sys_sendmmsg(int fd, struct compat_mmsghdr __user *mmsg, |
| 741 | unsigned int vlen, unsigned int flags) | 743 | unsigned int vlen, unsigned int flags) |
| 742 | { | 744 | { |
| 745 | if (flags & MSG_CMSG_COMPAT) | ||
| 746 | return -EINVAL; | ||
| 743 | return __sys_sendmmsg(fd, (struct mmsghdr __user *)mmsg, vlen, | 747 | return __sys_sendmmsg(fd, (struct mmsghdr __user *)mmsg, vlen, |
| 744 | flags | MSG_CMSG_COMPAT); | 748 | flags | MSG_CMSG_COMPAT); |
| 745 | } | 749 | } |
| 746 | 750 | ||
| 747 | asmlinkage long compat_sys_recvmsg(int fd, struct compat_msghdr __user *msg, unsigned int flags) | 751 | asmlinkage long compat_sys_recvmsg(int fd, struct compat_msghdr __user *msg, unsigned int flags) |
| 748 | { | 752 | { |
| 749 | return sys_recvmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT); | 753 | if (flags & MSG_CMSG_COMPAT) |
| 754 | return -EINVAL; | ||
| 755 | return __sys_recvmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT); | ||
| 750 | } | 756 | } |
| 751 | 757 | ||
| 752 | asmlinkage long compat_sys_recv(int fd, void __user *buf, size_t len, unsigned int flags) | 758 | asmlinkage long compat_sys_recv(int fd, void __user *buf, size_t len, unsigned int flags) |
| @@ -768,6 +774,9 @@ asmlinkage long compat_sys_recvmmsg(int fd, struct compat_mmsghdr __user *mmsg, | |||
| 768 | int datagrams; | 774 | int datagrams; |
| 769 | struct timespec ktspec; | 775 | struct timespec ktspec; |
| 770 | 776 | ||
| 777 | if (flags & MSG_CMSG_COMPAT) | ||
| 778 | return -EINVAL; | ||
| 779 | |||
| 771 | if (COMPAT_USE_64BIT_TIME) | 780 | if (COMPAT_USE_64BIT_TIME) |
| 772 | return __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen, | 781 | return __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen, |
| 773 | flags | MSG_CMSG_COMPAT, | 782 | flags | MSG_CMSG_COMPAT, |
diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 22efdaa76ebf..ce91766eeca9 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c | |||
| @@ -60,10 +60,10 @@ static const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN] | |||
| 60 | [NETIF_F_IPV6_CSUM_BIT] = "tx-checksum-ipv6", | 60 | [NETIF_F_IPV6_CSUM_BIT] = "tx-checksum-ipv6", |
| 61 | [NETIF_F_HIGHDMA_BIT] = "highdma", | 61 | [NETIF_F_HIGHDMA_BIT] = "highdma", |
| 62 | [NETIF_F_FRAGLIST_BIT] = "tx-scatter-gather-fraglist", | 62 | [NETIF_F_FRAGLIST_BIT] = "tx-scatter-gather-fraglist", |
| 63 | [NETIF_F_HW_VLAN_CTAG_TX_BIT] = "tx-vlan-ctag-hw-insert", | 63 | [NETIF_F_HW_VLAN_CTAG_TX_BIT] = "tx-vlan-hw-insert", |
| 64 | 64 | ||
| 65 | [NETIF_F_HW_VLAN_CTAG_RX_BIT] = "rx-vlan-ctag-hw-parse", | 65 | [NETIF_F_HW_VLAN_CTAG_RX_BIT] = "rx-vlan-hw-parse", |
| 66 | [NETIF_F_HW_VLAN_CTAG_FILTER_BIT] = "rx-vlan-ctag-filter", | 66 | [NETIF_F_HW_VLAN_CTAG_FILTER_BIT] = "rx-vlan-filter", |
| 67 | [NETIF_F_HW_VLAN_STAG_TX_BIT] = "tx-vlan-stag-hw-insert", | 67 | [NETIF_F_HW_VLAN_STAG_TX_BIT] = "tx-vlan-stag-hw-insert", |
| 68 | [NETIF_F_HW_VLAN_STAG_RX_BIT] = "rx-vlan-stag-hw-parse", | 68 | [NETIF_F_HW_VLAN_STAG_RX_BIT] = "rx-vlan-stag-hw-parse", |
| 69 | [NETIF_F_HW_VLAN_STAG_FILTER_BIT] = "rx-vlan-stag-filter", | 69 | [NETIF_F_HW_VLAN_STAG_FILTER_BIT] = "rx-vlan-stag-filter", |
diff --git a/net/core/filter.c b/net/core/filter.c index dad2a178f9f8..6438f29ff266 100644 --- a/net/core/filter.c +++ b/net/core/filter.c | |||
| @@ -778,7 +778,7 @@ int sk_detach_filter(struct sock *sk) | |||
| 778 | } | 778 | } |
| 779 | EXPORT_SYMBOL_GPL(sk_detach_filter); | 779 | EXPORT_SYMBOL_GPL(sk_detach_filter); |
| 780 | 780 | ||
| 781 | static void sk_decode_filter(struct sock_filter *filt, struct sock_filter *to) | 781 | void sk_decode_filter(struct sock_filter *filt, struct sock_filter *to) |
| 782 | { | 782 | { |
| 783 | static const u16 decodes[] = { | 783 | static const u16 decodes[] = { |
| 784 | [BPF_S_ALU_ADD_K] = BPF_ALU|BPF_ADD|BPF_K, | 784 | [BPF_S_ALU_ADD_K] = BPF_ALU|BPF_ADD|BPF_K, |
diff --git a/net/core/sock_diag.c b/net/core/sock_diag.c index d5bef0b0f639..a0e9cf6379de 100644 --- a/net/core/sock_diag.c +++ b/net/core/sock_diag.c | |||
| @@ -73,8 +73,13 @@ int sock_diag_put_filterinfo(struct user_namespace *user_ns, struct sock *sk, | |||
| 73 | goto out; | 73 | goto out; |
| 74 | } | 74 | } |
| 75 | 75 | ||
| 76 | if (filter) | 76 | if (filter) { |
| 77 | memcpy(nla_data(attr), filter->insns, len); | 77 | struct sock_filter *fb = (struct sock_filter *)nla_data(attr); |
| 78 | int i; | ||
| 79 | |||
| 80 | for (i = 0; i < filter->len; i++, fb++) | ||
| 81 | sk_decode_filter(&filter->insns[i], fb); | ||
| 82 | } | ||
| 78 | 83 | ||
| 79 | out: | 84 | out: |
| 80 | rcu_read_unlock(); | 85 | rcu_read_unlock(); |
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index be2f8da0ae8e..7fa8f08fa7ae 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c | |||
| @@ -853,7 +853,7 @@ void ip_tunnel_dellink(struct net_device *dev, struct list_head *head) | |||
| 853 | } | 853 | } |
| 854 | EXPORT_SYMBOL_GPL(ip_tunnel_dellink); | 854 | EXPORT_SYMBOL_GPL(ip_tunnel_dellink); |
| 855 | 855 | ||
| 856 | int __net_init ip_tunnel_init_net(struct net *net, int ip_tnl_net_id, | 856 | int ip_tunnel_init_net(struct net *net, int ip_tnl_net_id, |
| 857 | struct rtnl_link_ops *ops, char *devname) | 857 | struct rtnl_link_ops *ops, char *devname) |
| 858 | { | 858 | { |
| 859 | struct ip_tunnel_net *itn = net_generic(net, ip_tnl_net_id); | 859 | struct ip_tunnel_net *itn = net_generic(net, ip_tnl_net_id); |
| @@ -899,7 +899,7 @@ static void ip_tunnel_destroy(struct ip_tunnel_net *itn, struct list_head *head) | |||
| 899 | unregister_netdevice_queue(itn->fb_tunnel_dev, head); | 899 | unregister_netdevice_queue(itn->fb_tunnel_dev, head); |
| 900 | } | 900 | } |
| 901 | 901 | ||
| 902 | void __net_exit ip_tunnel_delete_net(struct ip_tunnel_net *itn) | 902 | void ip_tunnel_delete_net(struct ip_tunnel_net *itn) |
| 903 | { | 903 | { |
| 904 | LIST_HEAD(list); | 904 | LIST_HEAD(list); |
| 905 | 905 | ||
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c index 9d2bdb2c1d3f..c118f6b576bb 100644 --- a/net/ipv4/ip_vti.c +++ b/net/ipv4/ip_vti.c | |||
| @@ -361,8 +361,7 @@ static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 361 | tunnel->err_count = 0; | 361 | tunnel->err_count = 0; |
| 362 | } | 362 | } |
| 363 | 363 | ||
| 364 | IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | | 364 | memset(IPCB(skb), 0, sizeof(*IPCB(skb))); |
| 365 | IPSKB_REROUTED); | ||
| 366 | skb_dst_drop(skb); | 365 | skb_dst_drop(skb); |
| 367 | skb_dst_set(skb, &rt->dst); | 366 | skb_dst_set(skb, &rt->dst); |
| 368 | nf_reset(skb); | 367 | nf_reset(skb); |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 719652305a29..7999fc55c83b 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
| @@ -1003,7 +1003,7 @@ int tcp_md5_do_add(struct sock *sk, const union tcp_md5_addr *addr, | |||
| 1003 | struct tcp_sock *tp = tcp_sk(sk); | 1003 | struct tcp_sock *tp = tcp_sk(sk); |
| 1004 | struct tcp_md5sig_info *md5sig; | 1004 | struct tcp_md5sig_info *md5sig; |
| 1005 | 1005 | ||
| 1006 | key = tcp_md5_do_lookup(sk, (union tcp_md5_addr *)&addr, AF_INET); | 1006 | key = tcp_md5_do_lookup(sk, addr, family); |
| 1007 | if (key) { | 1007 | if (key) { |
| 1008 | /* Pre-existing entry - just update that one. */ | 1008 | /* Pre-existing entry - just update that one. */ |
| 1009 | memcpy(key->key, newkey, newkeylen); | 1009 | memcpy(key->key, newkey, newkeylen); |
| @@ -1048,7 +1048,7 @@ int tcp_md5_do_del(struct sock *sk, const union tcp_md5_addr *addr, int family) | |||
| 1048 | struct tcp_md5sig_key *key; | 1048 | struct tcp_md5sig_key *key; |
| 1049 | struct tcp_md5sig_info *md5sig; | 1049 | struct tcp_md5sig_info *md5sig; |
| 1050 | 1050 | ||
| 1051 | key = tcp_md5_do_lookup(sk, (union tcp_md5_addr *)&addr, AF_INET); | 1051 | key = tcp_md5_do_lookup(sk, addr, family); |
| 1052 | if (!key) | 1052 | if (!key) |
| 1053 | return -ENOENT; | 1053 | return -ENOENT; |
| 1054 | hlist_del_rcu(&key->node); | 1054 | hlist_del_rcu(&key->node); |
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 1bbf744c2cc3..77b626136c23 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
| @@ -2655,6 +2655,9 @@ static void init_loopback(struct net_device *dev) | |||
| 2655 | if (sp_ifa->flags & (IFA_F_DADFAILED | IFA_F_TENTATIVE)) | 2655 | if (sp_ifa->flags & (IFA_F_DADFAILED | IFA_F_TENTATIVE)) |
| 2656 | continue; | 2656 | continue; |
| 2657 | 2657 | ||
| 2658 | if (sp_ifa->rt) | ||
| 2659 | continue; | ||
| 2660 | |||
| 2658 | sp_rt = addrconf_dst_alloc(idev, &sp_ifa->addr, 0); | 2661 | sp_rt = addrconf_dst_alloc(idev, &sp_ifa->addr, 0); |
| 2659 | 2662 | ||
| 2660 | /* Failure cases are ignored */ | 2663 | /* Failure cases are ignored */ |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 2712ab22a174..ca4ffcc287f1 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
| @@ -1493,7 +1493,7 @@ void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target) | |||
| 1493 | */ | 1493 | */ |
| 1494 | 1494 | ||
| 1495 | if (ha) | 1495 | if (ha) |
| 1496 | ndisc_fill_addr_option(skb, ND_OPT_TARGET_LL_ADDR, ha); | 1496 | ndisc_fill_addr_option(buff, ND_OPT_TARGET_LL_ADDR, ha); |
| 1497 | 1497 | ||
| 1498 | /* | 1498 | /* |
| 1499 | * build redirect option and copy skb over to the new packet. | 1499 | * build redirect option and copy skb over to the new packet. |
diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c index 637a341c1e2d..8dec6876dc50 100644 --- a/net/l2tp/l2tp_ppp.c +++ b/net/l2tp/l2tp_ppp.c | |||
| @@ -346,19 +346,19 @@ static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msgh | |||
| 346 | skb_put(skb, 2); | 346 | skb_put(skb, 2); |
| 347 | 347 | ||
| 348 | /* Copy user data into skb */ | 348 | /* Copy user data into skb */ |
| 349 | error = memcpy_fromiovec(skb->data, m->msg_iov, total_len); | 349 | error = memcpy_fromiovec(skb_put(skb, total_len), m->msg_iov, |
| 350 | total_len); | ||
| 350 | if (error < 0) { | 351 | if (error < 0) { |
| 351 | kfree_skb(skb); | 352 | kfree_skb(skb); |
| 352 | goto error_put_sess_tun; | 353 | goto error_put_sess_tun; |
| 353 | } | 354 | } |
| 354 | skb_put(skb, total_len); | ||
| 355 | 355 | ||
| 356 | l2tp_xmit_skb(session, skb, session->hdr_len); | 356 | l2tp_xmit_skb(session, skb, session->hdr_len); |
| 357 | 357 | ||
| 358 | sock_put(ps->tunnel_sock); | 358 | sock_put(ps->tunnel_sock); |
| 359 | sock_put(sk); | 359 | sock_put(sk); |
| 360 | 360 | ||
| 361 | return error; | 361 | return total_len; |
| 362 | 362 | ||
| 363 | error_put_sess_tun: | 363 | error_put_sess_tun: |
| 364 | sock_put(ps->tunnel_sock); | 364 | sock_put(ps->tunnel_sock); |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 1a89c80e6407..4fdb306e42e0 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
| @@ -1057,6 +1057,12 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) | |||
| 1057 | clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state); | 1057 | clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state); |
| 1058 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); | 1058 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); |
| 1059 | 1059 | ||
| 1060 | if (sdata->wdev.cac_started) { | ||
| 1061 | cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); | ||
| 1062 | cfg80211_cac_event(sdata->dev, NL80211_RADAR_CAC_ABORTED, | ||
| 1063 | GFP_KERNEL); | ||
| 1064 | } | ||
| 1065 | |||
| 1060 | drv_stop_ap(sdata->local, sdata); | 1066 | drv_stop_ap(sdata->local, sdata); |
| 1061 | 1067 | ||
| 1062 | /* free all potentially still buffered bcast frames */ | 1068 | /* free all potentially still buffered bcast frames */ |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 44be28cfc6c4..9ca8e3278cc0 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
| @@ -1497,10 +1497,11 @@ static inline void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, | |||
| 1497 | ieee80211_tx_skb_tid(sdata, skb, 7); | 1497 | ieee80211_tx_skb_tid(sdata, skb, 7); |
| 1498 | } | 1498 | } |
| 1499 | 1499 | ||
| 1500 | u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, bool action, | 1500 | u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, |
| 1501 | struct ieee802_11_elems *elems, | 1501 | struct ieee802_11_elems *elems, |
| 1502 | u64 filter, u32 crc); | 1502 | u64 filter, u32 crc); |
| 1503 | static inline void ieee802_11_parse_elems(u8 *start, size_t len, bool action, | 1503 | static inline void ieee802_11_parse_elems(const u8 *start, size_t len, |
| 1504 | bool action, | ||
| 1504 | struct ieee802_11_elems *elems) | 1505 | struct ieee802_11_elems *elems) |
| 1505 | { | 1506 | { |
| 1506 | ieee802_11_parse_elems_crc(start, len, action, elems, 0, 0); | 1507 | ieee802_11_parse_elems_crc(start, len, action, elems, 0, 0); |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index a8c2130c8ba4..741448b30825 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
| @@ -2522,8 +2522,11 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | |||
| 2522 | u16 capab_info, aid; | 2522 | u16 capab_info, aid; |
| 2523 | struct ieee802_11_elems elems; | 2523 | struct ieee802_11_elems elems; |
| 2524 | struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; | 2524 | struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; |
| 2525 | const struct cfg80211_bss_ies *bss_ies = NULL; | ||
| 2526 | struct ieee80211_mgd_assoc_data *assoc_data = ifmgd->assoc_data; | ||
| 2525 | u32 changed = 0; | 2527 | u32 changed = 0; |
| 2526 | int err; | 2528 | int err; |
| 2529 | bool ret; | ||
| 2527 | 2530 | ||
| 2528 | /* AssocResp and ReassocResp have identical structure */ | 2531 | /* AssocResp and ReassocResp have identical structure */ |
| 2529 | 2532 | ||
| @@ -2555,21 +2558,86 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | |||
| 2555 | ifmgd->aid = aid; | 2558 | ifmgd->aid = aid; |
| 2556 | 2559 | ||
| 2557 | /* | 2560 | /* |
| 2561 | * Some APs are erroneously not including some information in their | ||
| 2562 | * (re)association response frames. Try to recover by using the data | ||
| 2563 | * from the beacon or probe response. This seems to afflict mobile | ||
| 2564 | * 2G/3G/4G wifi routers, reported models include the "Onda PN51T", | ||
| 2565 | * "Vodafone PocketWiFi 2", "ZTE MF60" and a similar T-Mobile device. | ||
| 2566 | */ | ||
| 2567 | if ((assoc_data->wmm && !elems.wmm_param) || | ||
| 2568 | (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) && | ||
| 2569 | (!elems.ht_cap_elem || !elems.ht_operation)) || | ||
| 2570 | (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT) && | ||
| 2571 | (!elems.vht_cap_elem || !elems.vht_operation))) { | ||
| 2572 | const struct cfg80211_bss_ies *ies; | ||
| 2573 | struct ieee802_11_elems bss_elems; | ||
| 2574 | |||
| 2575 | rcu_read_lock(); | ||
| 2576 | ies = rcu_dereference(cbss->ies); | ||
| 2577 | if (ies) | ||
| 2578 | bss_ies = kmemdup(ies, sizeof(*ies) + ies->len, | ||
| 2579 | GFP_ATOMIC); | ||
| 2580 | rcu_read_unlock(); | ||
| 2581 | if (!bss_ies) | ||
| 2582 | return false; | ||
| 2583 | |||
| 2584 | ieee802_11_parse_elems(bss_ies->data, bss_ies->len, | ||
| 2585 | false, &bss_elems); | ||
| 2586 | if (assoc_data->wmm && | ||
| 2587 | !elems.wmm_param && bss_elems.wmm_param) { | ||
| 2588 | elems.wmm_param = bss_elems.wmm_param; | ||
| 2589 | sdata_info(sdata, | ||
| 2590 | "AP bug: WMM param missing from AssocResp\n"); | ||
| 2591 | } | ||
| 2592 | |||
| 2593 | /* | ||
| 2594 | * Also check if we requested HT/VHT, otherwise the AP doesn't | ||
| 2595 | * have to include the IEs in the (re)association response. | ||
| 2596 | */ | ||
| 2597 | if (!elems.ht_cap_elem && bss_elems.ht_cap_elem && | ||
| 2598 | !(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) { | ||
| 2599 | elems.ht_cap_elem = bss_elems.ht_cap_elem; | ||
| 2600 | sdata_info(sdata, | ||
| 2601 | "AP bug: HT capability missing from AssocResp\n"); | ||
| 2602 | } | ||
| 2603 | if (!elems.ht_operation && bss_elems.ht_operation && | ||
| 2604 | !(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) { | ||
| 2605 | elems.ht_operation = bss_elems.ht_operation; | ||
| 2606 | sdata_info(sdata, | ||
| 2607 | "AP bug: HT operation missing from AssocResp\n"); | ||
| 2608 | } | ||
| 2609 | if (!elems.vht_cap_elem && bss_elems.vht_cap_elem && | ||
| 2610 | !(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) { | ||
| 2611 | elems.vht_cap_elem = bss_elems.vht_cap_elem; | ||
| 2612 | sdata_info(sdata, | ||
| 2613 | "AP bug: VHT capa missing from AssocResp\n"); | ||
| 2614 | } | ||
| 2615 | if (!elems.vht_operation && bss_elems.vht_operation && | ||
| 2616 | !(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) { | ||
| 2617 | elems.vht_operation = bss_elems.vht_operation; | ||
| 2618 | sdata_info(sdata, | ||
| 2619 | "AP bug: VHT operation missing from AssocResp\n"); | ||
| 2620 | } | ||
| 2621 | } | ||
| 2622 | |||
| 2623 | /* | ||
| 2558 | * We previously checked these in the beacon/probe response, so | 2624 | * We previously checked these in the beacon/probe response, so |
| 2559 | * they should be present here. This is just a safety net. | 2625 | * they should be present here. This is just a safety net. |
| 2560 | */ | 2626 | */ |
| 2561 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) && | 2627 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) && |
| 2562 | (!elems.wmm_param || !elems.ht_cap_elem || !elems.ht_operation)) { | 2628 | (!elems.wmm_param || !elems.ht_cap_elem || !elems.ht_operation)) { |
| 2563 | sdata_info(sdata, | 2629 | sdata_info(sdata, |
| 2564 | "HT AP is missing WMM params or HT capability/operation in AssocResp\n"); | 2630 | "HT AP is missing WMM params or HT capability/operation\n"); |
| 2565 | return false; | 2631 | ret = false; |
| 2632 | goto out; | ||
| 2566 | } | 2633 | } |
| 2567 | 2634 | ||
| 2568 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT) && | 2635 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT) && |
| 2569 | (!elems.vht_cap_elem || !elems.vht_operation)) { | 2636 | (!elems.vht_cap_elem || !elems.vht_operation)) { |
| 2570 | sdata_info(sdata, | 2637 | sdata_info(sdata, |
| 2571 | "VHT AP is missing VHT capability/operation in AssocResp\n"); | 2638 | "VHT AP is missing VHT capability/operation\n"); |
| 2572 | return false; | 2639 | ret = false; |
| 2640 | goto out; | ||
| 2573 | } | 2641 | } |
| 2574 | 2642 | ||
| 2575 | mutex_lock(&sdata->local->sta_mtx); | 2643 | mutex_lock(&sdata->local->sta_mtx); |
| @@ -2580,7 +2648,8 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | |||
| 2580 | sta = sta_info_get(sdata, cbss->bssid); | 2648 | sta = sta_info_get(sdata, cbss->bssid); |
| 2581 | if (WARN_ON(!sta)) { | 2649 | if (WARN_ON(!sta)) { |
| 2582 | mutex_unlock(&sdata->local->sta_mtx); | 2650 | mutex_unlock(&sdata->local->sta_mtx); |
| 2583 | return false; | 2651 | ret = false; |
| 2652 | goto out; | ||
| 2584 | } | 2653 | } |
| 2585 | 2654 | ||
| 2586 | sband = local->hw.wiphy->bands[ieee80211_get_sdata_band(sdata)]; | 2655 | sband = local->hw.wiphy->bands[ieee80211_get_sdata_band(sdata)]; |
| @@ -2633,7 +2702,8 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | |||
| 2633 | sta->sta.addr); | 2702 | sta->sta.addr); |
| 2634 | WARN_ON(__sta_info_destroy(sta)); | 2703 | WARN_ON(__sta_info_destroy(sta)); |
| 2635 | mutex_unlock(&sdata->local->sta_mtx); | 2704 | mutex_unlock(&sdata->local->sta_mtx); |
| 2636 | return false; | 2705 | ret = false; |
| 2706 | goto out; | ||
| 2637 | } | 2707 | } |
| 2638 | 2708 | ||
| 2639 | mutex_unlock(&sdata->local->sta_mtx); | 2709 | mutex_unlock(&sdata->local->sta_mtx); |
| @@ -2673,7 +2743,10 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | |||
| 2673 | ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt); | 2743 | ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt); |
| 2674 | ieee80211_sta_reset_beacon_monitor(sdata); | 2744 | ieee80211_sta_reset_beacon_monitor(sdata); |
| 2675 | 2745 | ||
| 2676 | return true; | 2746 | ret = true; |
| 2747 | out: | ||
| 2748 | kfree(bss_ies); | ||
| 2749 | return ret; | ||
| 2677 | } | 2750 | } |
| 2678 | 2751 | ||
| 2679 | static enum rx_mgmt_action __must_check | 2752 | static enum rx_mgmt_action __must_check |
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index d3f414fe67e0..a02bef35b134 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c | |||
| @@ -615,7 +615,7 @@ static void rate_control_apply_mask(struct ieee80211_sub_if_data *sdata, | |||
| 615 | if (rates[i].idx < 0) | 615 | if (rates[i].idx < 0) |
| 616 | break; | 616 | break; |
| 617 | 617 | ||
| 618 | rate_idx_match_mask(&rates[i], sband, mask, chan_width, | 618 | rate_idx_match_mask(&rates[i], sband, chan_width, mask, |
| 619 | mcs_mask); | 619 | mcs_mask); |
| 620 | } | 620 | } |
| 621 | } | 621 | } |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 27e07150eb46..72e6292955bb 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
| @@ -661,12 +661,12 @@ void ieee80211_queue_delayed_work(struct ieee80211_hw *hw, | |||
| 661 | } | 661 | } |
| 662 | EXPORT_SYMBOL(ieee80211_queue_delayed_work); | 662 | EXPORT_SYMBOL(ieee80211_queue_delayed_work); |
| 663 | 663 | ||
| 664 | u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, bool action, | 664 | u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, |
| 665 | struct ieee802_11_elems *elems, | 665 | struct ieee802_11_elems *elems, |
| 666 | u64 filter, u32 crc) | 666 | u64 filter, u32 crc) |
| 667 | { | 667 | { |
| 668 | size_t left = len; | 668 | size_t left = len; |
| 669 | u8 *pos = start; | 669 | const u8 *pos = start; |
| 670 | bool calc_crc = filter != 0; | 670 | bool calc_crc = filter != 0; |
| 671 | DECLARE_BITMAP(seen_elems, 256); | 671 | DECLARE_BITMAP(seen_elems, 256); |
| 672 | const u8 *ie; | 672 | const u8 *ie; |
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index d0b3dd60d386..57ee84d21470 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
| @@ -371,7 +371,7 @@ static int netlink_mmap(struct file *file, struct socket *sock, | |||
| 371 | err = 0; | 371 | err = 0; |
| 372 | out: | 372 | out: |
| 373 | mutex_unlock(&nlk->pg_vec_lock); | 373 | mutex_unlock(&nlk->pg_vec_lock); |
| 374 | return 0; | 374 | return err; |
| 375 | } | 375 | } |
| 376 | 376 | ||
| 377 | static void netlink_frame_flush_dcache(const struct nl_mmap_hdr *hdr) | 377 | static void netlink_frame_flush_dcache(const struct nl_mmap_hdr *hdr) |
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 8ec1bca7f859..20a1bd0e6549 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
| @@ -2851,12 +2851,11 @@ static int packet_getname_spkt(struct socket *sock, struct sockaddr *uaddr, | |||
| 2851 | return -EOPNOTSUPP; | 2851 | return -EOPNOTSUPP; |
| 2852 | 2852 | ||
| 2853 | uaddr->sa_family = AF_PACKET; | 2853 | uaddr->sa_family = AF_PACKET; |
| 2854 | memset(uaddr->sa_data, 0, sizeof(uaddr->sa_data)); | ||
| 2854 | rcu_read_lock(); | 2855 | rcu_read_lock(); |
| 2855 | dev = dev_get_by_index_rcu(sock_net(sk), pkt_sk(sk)->ifindex); | 2856 | dev = dev_get_by_index_rcu(sock_net(sk), pkt_sk(sk)->ifindex); |
| 2856 | if (dev) | 2857 | if (dev) |
| 2857 | strncpy(uaddr->sa_data, dev->name, 14); | 2858 | strlcpy(uaddr->sa_data, dev->name, sizeof(uaddr->sa_data)); |
| 2858 | else | ||
| 2859 | memset(uaddr->sa_data, 0, 14); | ||
| 2860 | rcu_read_unlock(); | 2859 | rcu_read_unlock(); |
| 2861 | *uaddr_len = sizeof(*uaddr); | 2860 | *uaddr_len = sizeof(*uaddr); |
| 2862 | 2861 | ||
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 2b935e7cfe7b..281c1bded1f6 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c | |||
| @@ -291,17 +291,18 @@ struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r, struct nlattr *ta | |||
| 291 | { | 291 | { |
| 292 | struct qdisc_rate_table *rtab; | 292 | struct qdisc_rate_table *rtab; |
| 293 | 293 | ||
| 294 | if (tab == NULL || r->rate == 0 || r->cell_log == 0 || | ||
| 295 | nla_len(tab) != TC_RTAB_SIZE) | ||
| 296 | return NULL; | ||
| 297 | |||
| 294 | for (rtab = qdisc_rtab_list; rtab; rtab = rtab->next) { | 298 | for (rtab = qdisc_rtab_list; rtab; rtab = rtab->next) { |
| 295 | if (memcmp(&rtab->rate, r, sizeof(struct tc_ratespec)) == 0) { | 299 | if (!memcmp(&rtab->rate, r, sizeof(struct tc_ratespec)) && |
| 300 | !memcmp(&rtab->data, nla_data(tab), 1024)) { | ||
| 296 | rtab->refcnt++; | 301 | rtab->refcnt++; |
| 297 | return rtab; | 302 | return rtab; |
| 298 | } | 303 | } |
| 299 | } | 304 | } |
| 300 | 305 | ||
| 301 | if (tab == NULL || r->rate == 0 || r->cell_log == 0 || | ||
| 302 | nla_len(tab) != TC_RTAB_SIZE) | ||
| 303 | return NULL; | ||
| 304 | |||
| 305 | rtab = kmalloc(sizeof(*rtab), GFP_KERNEL); | 306 | rtab = kmalloc(sizeof(*rtab), GFP_KERNEL); |
| 306 | if (rtab) { | 307 | if (rtab) { |
| 307 | rtab->rate = *r; | 308 | rtab->rate = *r; |
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index 32a4625fef77..be35e2dbcc9a 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c | |||
| @@ -206,6 +206,8 @@ static inline int sctp_cacc_skip(struct sctp_transport *primary, | |||
| 206 | */ | 206 | */ |
| 207 | void sctp_outq_init(struct sctp_association *asoc, struct sctp_outq *q) | 207 | void sctp_outq_init(struct sctp_association *asoc, struct sctp_outq *q) |
| 208 | { | 208 | { |
| 209 | memset(q, 0, sizeof(struct sctp_outq)); | ||
| 210 | |||
| 209 | q->asoc = asoc; | 211 | q->asoc = asoc; |
| 210 | INIT_LIST_HEAD(&q->out_chunk_list); | 212 | INIT_LIST_HEAD(&q->out_chunk_list); |
| 211 | INIT_LIST_HEAD(&q->control_chunk_list); | 213 | INIT_LIST_HEAD(&q->control_chunk_list); |
| @@ -213,11 +215,7 @@ void sctp_outq_init(struct sctp_association *asoc, struct sctp_outq *q) | |||
| 213 | INIT_LIST_HEAD(&q->sacked); | 215 | INIT_LIST_HEAD(&q->sacked); |
| 214 | INIT_LIST_HEAD(&q->abandoned); | 216 | INIT_LIST_HEAD(&q->abandoned); |
| 215 | 217 | ||
| 216 | q->fast_rtx = 0; | ||
| 217 | q->outstanding_bytes = 0; | ||
| 218 | q->empty = 1; | 218 | q->empty = 1; |
| 219 | q->cork = 0; | ||
| 220 | q->out_qlen = 0; | ||
| 221 | } | 219 | } |
| 222 | 220 | ||
| 223 | /* Free the outqueue structure and any related pending chunks. | 221 | /* Free the outqueue structure and any related pending chunks. |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index f631c5ff4dbf..6abb1caf9836 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
| @@ -4003,6 +4003,12 @@ SCTP_STATIC void sctp_destroy_sock(struct sock *sk) | |||
| 4003 | 4003 | ||
| 4004 | /* Release our hold on the endpoint. */ | 4004 | /* Release our hold on the endpoint. */ |
| 4005 | sp = sctp_sk(sk); | 4005 | sp = sctp_sk(sk); |
| 4006 | /* This could happen during socket init, thus we bail out | ||
| 4007 | * early, since the rest of the below is not setup either. | ||
| 4008 | */ | ||
| 4009 | if (sp->ep == NULL) | ||
| 4010 | return; | ||
| 4011 | |||
| 4006 | if (sp->do_auto_asconf) { | 4012 | if (sp->do_auto_asconf) { |
| 4007 | sp->do_auto_asconf = 0; | 4013 | sp->do_auto_asconf = 0; |
| 4008 | list_del(&sp->auto_asconf_list); | 4014 | list_del(&sp->auto_asconf_list); |
diff --git a/net/socket.c b/net/socket.c index 9ff6366fee13..4ca1526db756 100644 --- a/net/socket.c +++ b/net/socket.c | |||
| @@ -1956,7 +1956,7 @@ struct used_address { | |||
| 1956 | unsigned int name_len; | 1956 | unsigned int name_len; |
| 1957 | }; | 1957 | }; |
| 1958 | 1958 | ||
| 1959 | static int __sys_sendmsg(struct socket *sock, struct msghdr __user *msg, | 1959 | static int ___sys_sendmsg(struct socket *sock, struct msghdr __user *msg, |
| 1960 | struct msghdr *msg_sys, unsigned int flags, | 1960 | struct msghdr *msg_sys, unsigned int flags, |
| 1961 | struct used_address *used_address) | 1961 | struct used_address *used_address) |
| 1962 | { | 1962 | { |
| @@ -2071,26 +2071,30 @@ out: | |||
| 2071 | * BSD sendmsg interface | 2071 | * BSD sendmsg interface |
| 2072 | */ | 2072 | */ |
| 2073 | 2073 | ||
| 2074 | SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned int, flags) | 2074 | long __sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags) |
| 2075 | { | 2075 | { |
| 2076 | int fput_needed, err; | 2076 | int fput_needed, err; |
| 2077 | struct msghdr msg_sys; | 2077 | struct msghdr msg_sys; |
| 2078 | struct socket *sock; | 2078 | struct socket *sock; |
| 2079 | 2079 | ||
| 2080 | if (flags & MSG_CMSG_COMPAT) | ||
| 2081 | return -EINVAL; | ||
| 2082 | |||
| 2083 | sock = sockfd_lookup_light(fd, &err, &fput_needed); | 2080 | sock = sockfd_lookup_light(fd, &err, &fput_needed); |
| 2084 | if (!sock) | 2081 | if (!sock) |
| 2085 | goto out; | 2082 | goto out; |
| 2086 | 2083 | ||
| 2087 | err = __sys_sendmsg(sock, msg, &msg_sys, flags, NULL); | 2084 | err = ___sys_sendmsg(sock, msg, &msg_sys, flags, NULL); |
| 2088 | 2085 | ||
| 2089 | fput_light(sock->file, fput_needed); | 2086 | fput_light(sock->file, fput_needed); |
| 2090 | out: | 2087 | out: |
| 2091 | return err; | 2088 | return err; |
| 2092 | } | 2089 | } |
| 2093 | 2090 | ||
| 2091 | SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned int, flags) | ||
| 2092 | { | ||
| 2093 | if (flags & MSG_CMSG_COMPAT) | ||
| 2094 | return -EINVAL; | ||
| 2095 | return __sys_sendmsg(fd, msg, flags); | ||
| 2096 | } | ||
| 2097 | |||
| 2094 | /* | 2098 | /* |
| 2095 | * Linux sendmmsg interface | 2099 | * Linux sendmmsg interface |
| 2096 | */ | 2100 | */ |
| @@ -2121,15 +2125,16 @@ int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, | |||
| 2121 | 2125 | ||
| 2122 | while (datagrams < vlen) { | 2126 | while (datagrams < vlen) { |
| 2123 | if (MSG_CMSG_COMPAT & flags) { | 2127 | if (MSG_CMSG_COMPAT & flags) { |
| 2124 | err = __sys_sendmsg(sock, (struct msghdr __user *)compat_entry, | 2128 | err = ___sys_sendmsg(sock, (struct msghdr __user *)compat_entry, |
| 2125 | &msg_sys, flags, &used_address); | 2129 | &msg_sys, flags, &used_address); |
| 2126 | if (err < 0) | 2130 | if (err < 0) |
| 2127 | break; | 2131 | break; |
| 2128 | err = __put_user(err, &compat_entry->msg_len); | 2132 | err = __put_user(err, &compat_entry->msg_len); |
| 2129 | ++compat_entry; | 2133 | ++compat_entry; |
| 2130 | } else { | 2134 | } else { |
| 2131 | err = __sys_sendmsg(sock, (struct msghdr __user *)entry, | 2135 | err = ___sys_sendmsg(sock, |
| 2132 | &msg_sys, flags, &used_address); | 2136 | (struct msghdr __user *)entry, |
| 2137 | &msg_sys, flags, &used_address); | ||
| 2133 | if (err < 0) | 2138 | if (err < 0) |
| 2134 | break; | 2139 | break; |
| 2135 | err = put_user(err, &entry->msg_len); | 2140 | err = put_user(err, &entry->msg_len); |
| @@ -2158,7 +2163,7 @@ SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg, | |||
| 2158 | return __sys_sendmmsg(fd, mmsg, vlen, flags); | 2163 | return __sys_sendmmsg(fd, mmsg, vlen, flags); |
| 2159 | } | 2164 | } |
| 2160 | 2165 | ||
| 2161 | static int __sys_recvmsg(struct socket *sock, struct msghdr __user *msg, | 2166 | static int ___sys_recvmsg(struct socket *sock, struct msghdr __user *msg, |
| 2162 | struct msghdr *msg_sys, unsigned int flags, int nosec) | 2167 | struct msghdr *msg_sys, unsigned int flags, int nosec) |
| 2163 | { | 2168 | { |
| 2164 | struct compat_msghdr __user *msg_compat = | 2169 | struct compat_msghdr __user *msg_compat = |
| @@ -2250,27 +2255,31 @@ out: | |||
| 2250 | * BSD recvmsg interface | 2255 | * BSD recvmsg interface |
| 2251 | */ | 2256 | */ |
| 2252 | 2257 | ||
| 2253 | SYSCALL_DEFINE3(recvmsg, int, fd, struct msghdr __user *, msg, | 2258 | long __sys_recvmsg(int fd, struct msghdr __user *msg, unsigned flags) |
| 2254 | unsigned int, flags) | ||
| 2255 | { | 2259 | { |
| 2256 | int fput_needed, err; | 2260 | int fput_needed, err; |
| 2257 | struct msghdr msg_sys; | 2261 | struct msghdr msg_sys; |
| 2258 | struct socket *sock; | 2262 | struct socket *sock; |
| 2259 | 2263 | ||
| 2260 | if (flags & MSG_CMSG_COMPAT) | ||
| 2261 | return -EINVAL; | ||
| 2262 | |||
| 2263 | sock = sockfd_lookup_light(fd, &err, &fput_needed); | 2264 | sock = sockfd_lookup_light(fd, &err, &fput_needed); |
| 2264 | if (!sock) | 2265 | if (!sock) |
| 2265 | goto out; | 2266 | goto out; |
| 2266 | 2267 | ||
| 2267 | err = __sys_recvmsg(sock, msg, &msg_sys, flags, 0); | 2268 | err = ___sys_recvmsg(sock, msg, &msg_sys, flags, 0); |
| 2268 | 2269 | ||
| 2269 | fput_light(sock->file, fput_needed); | 2270 | fput_light(sock->file, fput_needed); |
| 2270 | out: | 2271 | out: |
| 2271 | return err; | 2272 | return err; |
| 2272 | } | 2273 | } |
| 2273 | 2274 | ||
| 2275 | SYSCALL_DEFINE3(recvmsg, int, fd, struct msghdr __user *, msg, | ||
| 2276 | unsigned int, flags) | ||
| 2277 | { | ||
| 2278 | if (flags & MSG_CMSG_COMPAT) | ||
| 2279 | return -EINVAL; | ||
| 2280 | return __sys_recvmsg(fd, msg, flags); | ||
| 2281 | } | ||
| 2282 | |||
| 2274 | /* | 2283 | /* |
| 2275 | * Linux recvmmsg interface | 2284 | * Linux recvmmsg interface |
| 2276 | */ | 2285 | */ |
| @@ -2308,17 +2317,18 @@ int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, | |||
| 2308 | * No need to ask LSM for more than the first datagram. | 2317 | * No need to ask LSM for more than the first datagram. |
| 2309 | */ | 2318 | */ |
| 2310 | if (MSG_CMSG_COMPAT & flags) { | 2319 | if (MSG_CMSG_COMPAT & flags) { |
| 2311 | err = __sys_recvmsg(sock, (struct msghdr __user *)compat_entry, | 2320 | err = ___sys_recvmsg(sock, (struct msghdr __user *)compat_entry, |
| 2312 | &msg_sys, flags & ~MSG_WAITFORONE, | 2321 | &msg_sys, flags & ~MSG_WAITFORONE, |
| 2313 | datagrams); | 2322 | datagrams); |
| 2314 | if (err < 0) | 2323 | if (err < 0) |
| 2315 | break; | 2324 | break; |
| 2316 | err = __put_user(err, &compat_entry->msg_len); | 2325 | err = __put_user(err, &compat_entry->msg_len); |
| 2317 | ++compat_entry; | 2326 | ++compat_entry; |
| 2318 | } else { | 2327 | } else { |
| 2319 | err = __sys_recvmsg(sock, (struct msghdr __user *)entry, | 2328 | err = ___sys_recvmsg(sock, |
| 2320 | &msg_sys, flags & ~MSG_WAITFORONE, | 2329 | (struct msghdr __user *)entry, |
| 2321 | datagrams); | 2330 | &msg_sys, flags & ~MSG_WAITFORONE, |
| 2331 | datagrams); | ||
| 2322 | if (err < 0) | 2332 | if (err < 0) |
| 2323 | break; | 2333 | break; |
| 2324 | err = put_user(err, &entry->msg_len); | 2334 | err = put_user(err, &entry->msg_len); |
| @@ -2505,31 +2515,15 @@ SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args) | |||
| 2505 | (int __user *)a[4]); | 2515 | (int __user *)a[4]); |
| 2506 | break; | 2516 | break; |
| 2507 | case SYS_SENDMSG: | 2517 | case SYS_SENDMSG: |
| 2508 | if (a[2] & MSG_CMSG_COMPAT) { | ||
| 2509 | err = -EINVAL; | ||
| 2510 | break; | ||
| 2511 | } | ||
| 2512 | err = sys_sendmsg(a0, (struct msghdr __user *)a1, a[2]); | 2518 | err = sys_sendmsg(a0, (struct msghdr __user *)a1, a[2]); |
| 2513 | break; | 2519 | break; |
| 2514 | case SYS_SENDMMSG: | 2520 | case SYS_SENDMMSG: |
| 2515 | if (a[3] & MSG_CMSG_COMPAT) { | ||
| 2516 | err = -EINVAL; | ||
| 2517 | break; | ||
| 2518 | } | ||
| 2519 | err = sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3]); | 2521 | err = sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3]); |
| 2520 | break; | 2522 | break; |
| 2521 | case SYS_RECVMSG: | 2523 | case SYS_RECVMSG: |
| 2522 | if (a[2] & MSG_CMSG_COMPAT) { | ||
| 2523 | err = -EINVAL; | ||
| 2524 | break; | ||
| 2525 | } | ||
| 2526 | err = sys_recvmsg(a0, (struct msghdr __user *)a1, a[2]); | 2524 | err = sys_recvmsg(a0, (struct msghdr __user *)a1, a[2]); |
| 2527 | break; | 2525 | break; |
| 2528 | case SYS_RECVMMSG: | 2526 | case SYS_RECVMMSG: |
| 2529 | if (a[3] & MSG_CMSG_COMPAT) { | ||
| 2530 | err = -EINVAL; | ||
| 2531 | break; | ||
| 2532 | } | ||
| 2533 | err = sys_recvmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3], | 2527 | err = sys_recvmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3], |
| 2534 | (struct timespec __user *)a[4]); | 2528 | (struct timespec __user *)a[4]); |
| 2535 | break; | 2529 | break; |
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/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index 871c73c92165..29b4ba93ab3c 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c | |||
| @@ -1287,7 +1287,7 @@ static bool use_gss_proxy(struct net *net) | |||
| 1287 | 1287 | ||
| 1288 | #ifdef CONFIG_PROC_FS | 1288 | #ifdef CONFIG_PROC_FS |
| 1289 | 1289 | ||
| 1290 | static bool set_gss_proxy(struct net *net, int type) | 1290 | static int set_gss_proxy(struct net *net, int type) |
| 1291 | { | 1291 | { |
| 1292 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | 1292 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); |
| 1293 | int ret = 0; | 1293 | int ret = 0; |
| @@ -1317,10 +1317,12 @@ static inline bool gssp_ready(struct sunrpc_net *sn) | |||
| 1317 | return false; | 1317 | return false; |
| 1318 | } | 1318 | } |
| 1319 | 1319 | ||
| 1320 | static int wait_for_gss_proxy(struct net *net) | 1320 | static int wait_for_gss_proxy(struct net *net, struct file *file) |
| 1321 | { | 1321 | { |
| 1322 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | 1322 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); |
| 1323 | 1323 | ||
| 1324 | if (file->f_flags & O_NONBLOCK && !gssp_ready(sn)) | ||
| 1325 | return -EAGAIN; | ||
| 1324 | return wait_event_interruptible(sn->gssp_wq, gssp_ready(sn)); | 1326 | return wait_event_interruptible(sn->gssp_wq, gssp_ready(sn)); |
| 1325 | } | 1327 | } |
| 1326 | 1328 | ||
| @@ -1362,7 +1364,7 @@ static ssize_t read_gssp(struct file *file, char __user *buf, | |||
| 1362 | size_t len; | 1364 | size_t len; |
| 1363 | int ret; | 1365 | int ret; |
| 1364 | 1366 | ||
| 1365 | ret = wait_for_gss_proxy(net); | 1367 | ret = wait_for_gss_proxy(net, file); |
| 1366 | if (ret) | 1368 | if (ret) |
| 1367 | return ret; | 1369 | return ret; |
| 1368 | 1370 | ||
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/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index c3f9e1ef7f53..06bdf5a1082c 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c | |||
| @@ -810,11 +810,15 @@ svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
| 810 | goto badcred; | 810 | goto badcred; |
| 811 | argv->iov_base = (void*)((__be32*)argv->iov_base + slen); /* skip machname */ | 811 | argv->iov_base = (void*)((__be32*)argv->iov_base + slen); /* skip machname */ |
| 812 | argv->iov_len -= slen*4; | 812 | argv->iov_len -= slen*4; |
| 813 | 813 | /* | |
| 814 | * Note: we skip uid_valid()/gid_valid() checks here for | ||
| 815 | * backwards compatibility with clients that use -1 id's. | ||
| 816 | * Instead, -1 uid or gid is later mapped to the | ||
| 817 | * (export-specific) anonymous id by nfsd_setuser. | ||
| 818 | * Supplementary gid's will be left alone. | ||
| 819 | */ | ||
| 814 | cred->cr_uid = make_kuid(&init_user_ns, svc_getnl(argv)); /* uid */ | 820 | cred->cr_uid = make_kuid(&init_user_ns, svc_getnl(argv)); /* uid */ |
| 815 | cred->cr_gid = make_kgid(&init_user_ns, svc_getnl(argv)); /* gid */ | 821 | cred->cr_gid = make_kgid(&init_user_ns, svc_getnl(argv)); /* gid */ |
| 816 | if (!uid_valid(cred->cr_uid) || !gid_valid(cred->cr_gid)) | ||
| 817 | goto badcred; | ||
| 818 | slen = svc_getnl(argv); /* gids length */ | 822 | slen = svc_getnl(argv); /* gids length */ |
| 819 | if (slen > 16 || (len -= (slen + 2)*4) < 0) | 823 | if (slen > 16 || (len -= (slen + 2)*4) < 0) |
| 820 | goto badcred; | 824 | goto badcred; |
| @@ -823,8 +827,6 @@ svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
| 823 | return SVC_CLOSE; | 827 | return SVC_CLOSE; |
| 824 | for (i = 0; i < slen; i++) { | 828 | for (i = 0; i < slen; i++) { |
| 825 | kgid_t kgid = make_kgid(&init_user_ns, svc_getnl(argv)); | 829 | kgid_t kgid = make_kgid(&init_user_ns, svc_getnl(argv)); |
| 826 | if (!gid_valid(kgid)) | ||
| 827 | goto badcred; | ||
| 828 | GROUP_AT(cred->cr_group_info, i) = kgid; | 830 | GROUP_AT(cred->cr_group_info, i) = kgid; |
| 829 | } | 831 | } |
| 830 | if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) { | 832 | if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) { |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index d5aed3bb3945..b14b7e3cb6e6 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
| @@ -1564,12 +1564,17 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 1564 | struct cfg80211_registered_device *dev; | 1564 | struct cfg80211_registered_device *dev; |
| 1565 | s64 filter_wiphy = -1; | 1565 | s64 filter_wiphy = -1; |
| 1566 | bool split = false; | 1566 | bool split = false; |
| 1567 | struct nlattr **tb = nl80211_fam.attrbuf; | 1567 | struct nlattr **tb; |
| 1568 | int res; | 1568 | int res; |
| 1569 | 1569 | ||
| 1570 | /* will be zeroed in nlmsg_parse() */ | ||
| 1571 | tb = kmalloc(sizeof(*tb) * (NL80211_ATTR_MAX + 1), GFP_KERNEL); | ||
| 1572 | if (!tb) | ||
| 1573 | return -ENOMEM; | ||
| 1574 | |||
| 1570 | mutex_lock(&cfg80211_mutex); | 1575 | mutex_lock(&cfg80211_mutex); |
| 1571 | res = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, | 1576 | res = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, |
| 1572 | tb, nl80211_fam.maxattr, nl80211_policy); | 1577 | tb, NL80211_ATTR_MAX, nl80211_policy); |
| 1573 | if (res == 0) { | 1578 | if (res == 0) { |
| 1574 | split = tb[NL80211_ATTR_SPLIT_WIPHY_DUMP]; | 1579 | split = tb[NL80211_ATTR_SPLIT_WIPHY_DUMP]; |
| 1575 | if (tb[NL80211_ATTR_WIPHY]) | 1580 | if (tb[NL80211_ATTR_WIPHY]) |
| @@ -1583,6 +1588,7 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 1583 | netdev = dev_get_by_index(sock_net(skb->sk), ifidx); | 1588 | netdev = dev_get_by_index(sock_net(skb->sk), ifidx); |
| 1584 | if (!netdev) { | 1589 | if (!netdev) { |
| 1585 | mutex_unlock(&cfg80211_mutex); | 1590 | mutex_unlock(&cfg80211_mutex); |
| 1591 | kfree(tb); | ||
| 1586 | return -ENODEV; | 1592 | return -ENODEV; |
| 1587 | } | 1593 | } |
| 1588 | if (netdev->ieee80211_ptr) { | 1594 | if (netdev->ieee80211_ptr) { |
| @@ -1593,6 +1599,7 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 1593 | dev_put(netdev); | 1599 | dev_put(netdev); |
| 1594 | } | 1600 | } |
| 1595 | } | 1601 | } |
| 1602 | kfree(tb); | ||
| 1596 | 1603 | ||
| 1597 | list_for_each_entry(dev, &cfg80211_rdev_list, list) { | 1604 | list_for_each_entry(dev, &cfg80211_rdev_list, list) { |
| 1598 | if (!net_eq(wiphy_net(&dev->wiphy), sock_net(skb->sk))) | 1605 | if (!net_eq(wiphy_net(&dev->wiphy), sock_net(skb->sk))) |
