diff options
Diffstat (limited to 'net')
| -rw-r--r-- | net/bridge/br_multicast.c | 2 | ||||
| -rw-r--r-- | net/ipv4/udp.c | 4 | ||||
| -rw-r--r-- | net/ipv6/udp.c | 4 | ||||
| -rw-r--r-- | net/mac80211/main.c | 4 | ||||
| -rw-r--r-- | net/mac80211/mesh.c | 3 | ||||
| -rw-r--r-- | net/mac80211/rx.c | 5 | ||||
| -rw-r--r-- | net/mac80211/sta_info.c | 20 | ||||
| -rw-r--r-- | net/x25/af_x25.c | 67 | ||||
| -rw-r--r-- | net/x25/x25_facilities.c | 27 | ||||
| -rw-r--r-- | net/x25/x25_in.c | 15 |
10 files changed, 124 insertions, 27 deletions
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 6980625537ca..f29ada827a6a 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c | |||
| @@ -723,7 +723,7 @@ static int br_multicast_igmp3_report(struct net_bridge *br, | |||
| 723 | if (!pskb_may_pull(skb, len)) | 723 | if (!pskb_may_pull(skb, len)) |
| 724 | return -EINVAL; | 724 | return -EINVAL; |
| 725 | 725 | ||
| 726 | grec = (void *)(skb->data + len); | 726 | grec = (void *)(skb->data + len - sizeof(*grec)); |
| 727 | group = grec->grec_mca; | 727 | group = grec->grec_mca; |
| 728 | type = grec->grec_type; | 728 | type = grec->grec_type; |
| 729 | 729 | ||
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 954bbfb39dff..8fef859db35d 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
| @@ -472,8 +472,8 @@ static struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, | |||
| 472 | if (hslot->count < hslot2->count) | 472 | if (hslot->count < hslot2->count) |
| 473 | goto begin; | 473 | goto begin; |
| 474 | 474 | ||
| 475 | result = udp4_lib_lookup2(net, INADDR_ANY, sport, | 475 | result = udp4_lib_lookup2(net, saddr, sport, |
| 476 | daddr, hnum, dif, | 476 | INADDR_ANY, hnum, dif, |
| 477 | hslot2, slot2); | 477 | hslot2, slot2); |
| 478 | } | 478 | } |
| 479 | rcu_read_unlock(); | 479 | rcu_read_unlock(); |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index c177aea88c0b..90824852f598 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
| @@ -259,8 +259,8 @@ static struct sock *__udp6_lib_lookup(struct net *net, | |||
| 259 | if (hslot->count < hslot2->count) | 259 | if (hslot->count < hslot2->count) |
| 260 | goto begin; | 260 | goto begin; |
| 261 | 261 | ||
| 262 | result = udp6_lib_lookup2(net, &in6addr_any, sport, | 262 | result = udp6_lib_lookup2(net, saddr, sport, |
| 263 | daddr, hnum, dif, | 263 | &in6addr_any, hnum, dif, |
| 264 | hslot2, slot2); | 264 | hslot2, slot2); |
| 265 | } | 265 | } |
| 266 | rcu_read_unlock(); | 266 | rcu_read_unlock(); |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 06c33b68d8e5..b887e484ae04 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
| @@ -225,11 +225,11 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | |||
| 225 | switch (sdata->vif.type) { | 225 | switch (sdata->vif.type) { |
| 226 | case NL80211_IFTYPE_AP: | 226 | case NL80211_IFTYPE_AP: |
| 227 | sdata->vif.bss_conf.enable_beacon = | 227 | sdata->vif.bss_conf.enable_beacon = |
| 228 | !!rcu_dereference(sdata->u.ap.beacon); | 228 | !!sdata->u.ap.beacon; |
| 229 | break; | 229 | break; |
| 230 | case NL80211_IFTYPE_ADHOC: | 230 | case NL80211_IFTYPE_ADHOC: |
| 231 | sdata->vif.bss_conf.enable_beacon = | 231 | sdata->vif.bss_conf.enable_beacon = |
| 232 | !!rcu_dereference(sdata->u.ibss.presp); | 232 | !!sdata->u.ibss.presp; |
| 233 | break; | 233 | break; |
| 234 | case NL80211_IFTYPE_MESH_POINT: | 234 | case NL80211_IFTYPE_MESH_POINT: |
| 235 | sdata->vif.bss_conf.enable_beacon = true; | 235 | sdata->vif.bss_conf.enable_beacon = true; |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 58e3e3a61d99..859ee5f3d941 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
| @@ -750,9 +750,6 @@ ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) | |||
| 750 | 750 | ||
| 751 | switch (fc & IEEE80211_FCTL_STYPE) { | 751 | switch (fc & IEEE80211_FCTL_STYPE) { |
| 752 | case IEEE80211_STYPE_ACTION: | 752 | case IEEE80211_STYPE_ACTION: |
| 753 | if (skb->len < IEEE80211_MIN_ACTION_SIZE) | ||
| 754 | return RX_DROP_MONITOR; | ||
| 755 | /* fall through */ | ||
| 756 | case IEEE80211_STYPE_PROBE_RESP: | 753 | case IEEE80211_STYPE_PROBE_RESP: |
| 757 | case IEEE80211_STYPE_BEACON: | 754 | case IEEE80211_STYPE_BEACON: |
| 758 | skb_queue_tail(&ifmsh->skb_queue, skb); | 755 | skb_queue_tail(&ifmsh->skb_queue, skb); |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index f0accf622cd7..04ea07f0e78a 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
| @@ -1974,6 +1974,11 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
| 1974 | goto handled; | 1974 | goto handled; |
| 1975 | } | 1975 | } |
| 1976 | break; | 1976 | break; |
| 1977 | case MESH_PLINK_CATEGORY: | ||
| 1978 | case MESH_PATH_SEL_CATEGORY: | ||
| 1979 | if (ieee80211_vif_is_mesh(&sdata->vif)) | ||
| 1980 | return ieee80211_mesh_rx_mgmt(sdata, rx->skb); | ||
| 1981 | break; | ||
| 1977 | } | 1982 | } |
| 1978 | 1983 | ||
| 1979 | /* | 1984 | /* |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 56422d894351..fb12cec4d333 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
| @@ -93,12 +93,18 @@ struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata, | |||
| 93 | struct ieee80211_local *local = sdata->local; | 93 | struct ieee80211_local *local = sdata->local; |
| 94 | struct sta_info *sta; | 94 | struct sta_info *sta; |
| 95 | 95 | ||
| 96 | sta = rcu_dereference(local->sta_hash[STA_HASH(addr)]); | 96 | sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], |
| 97 | rcu_read_lock_held() || | ||
| 98 | lockdep_is_held(&local->sta_lock) || | ||
| 99 | lockdep_is_held(&local->sta_mtx)); | ||
| 97 | while (sta) { | 100 | while (sta) { |
| 98 | if (sta->sdata == sdata && | 101 | if (sta->sdata == sdata && |
| 99 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) | 102 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) |
| 100 | break; | 103 | break; |
| 101 | sta = rcu_dereference(sta->hnext); | 104 | sta = rcu_dereference_check(sta->hnext, |
| 105 | rcu_read_lock_held() || | ||
| 106 | lockdep_is_held(&local->sta_lock) || | ||
| 107 | lockdep_is_held(&local->sta_mtx)); | ||
| 102 | } | 108 | } |
| 103 | return sta; | 109 | return sta; |
| 104 | } | 110 | } |
| @@ -113,13 +119,19 @@ struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata, | |||
| 113 | struct ieee80211_local *local = sdata->local; | 119 | struct ieee80211_local *local = sdata->local; |
| 114 | struct sta_info *sta; | 120 | struct sta_info *sta; |
| 115 | 121 | ||
| 116 | sta = rcu_dereference(local->sta_hash[STA_HASH(addr)]); | 122 | sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], |
| 123 | rcu_read_lock_held() || | ||
| 124 | lockdep_is_held(&local->sta_lock) || | ||
| 125 | lockdep_is_held(&local->sta_mtx)); | ||
| 117 | while (sta) { | 126 | while (sta) { |
| 118 | if ((sta->sdata == sdata || | 127 | if ((sta->sdata == sdata || |
| 119 | sta->sdata->bss == sdata->bss) && | 128 | sta->sdata->bss == sdata->bss) && |
| 120 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) | 129 | memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) |
| 121 | break; | 130 | break; |
| 122 | sta = rcu_dereference(sta->hnext); | 131 | sta = rcu_dereference_check(sta->hnext, |
| 132 | rcu_read_lock_held() || | ||
| 133 | lockdep_is_held(&local->sta_lock) || | ||
| 134 | lockdep_is_held(&local->sta_mtx)); | ||
| 123 | } | 135 | } |
| 124 | return sta; | 136 | return sta; |
| 125 | } | 137 | } |
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index e56f711baccc..cbddd0cb83f1 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c | |||
| @@ -83,6 +83,41 @@ struct compat_x25_subscrip_struct { | |||
| 83 | }; | 83 | }; |
| 84 | #endif | 84 | #endif |
| 85 | 85 | ||
| 86 | |||
| 87 | int x25_parse_address_block(struct sk_buff *skb, | ||
| 88 | struct x25_address *called_addr, | ||
| 89 | struct x25_address *calling_addr) | ||
| 90 | { | ||
| 91 | unsigned char len; | ||
| 92 | int needed; | ||
| 93 | int rc; | ||
| 94 | |||
| 95 | if (skb->len < 1) { | ||
| 96 | /* packet has no address block */ | ||
| 97 | rc = 0; | ||
| 98 | goto empty; | ||
| 99 | } | ||
| 100 | |||
| 101 | len = *skb->data; | ||
| 102 | needed = 1 + (len >> 4) + (len & 0x0f); | ||
| 103 | |||
| 104 | if (skb->len < needed) { | ||
| 105 | /* packet is too short to hold the addresses it claims | ||
| 106 | to hold */ | ||
| 107 | rc = -1; | ||
| 108 | goto empty; | ||
| 109 | } | ||
| 110 | |||
| 111 | return x25_addr_ntoa(skb->data, called_addr, calling_addr); | ||
| 112 | |||
| 113 | empty: | ||
| 114 | *called_addr->x25_addr = 0; | ||
| 115 | *calling_addr->x25_addr = 0; | ||
| 116 | |||
| 117 | return rc; | ||
| 118 | } | ||
| 119 | |||
| 120 | |||
| 86 | int x25_addr_ntoa(unsigned char *p, struct x25_address *called_addr, | 121 | int x25_addr_ntoa(unsigned char *p, struct x25_address *called_addr, |
| 87 | struct x25_address *calling_addr) | 122 | struct x25_address *calling_addr) |
| 88 | { | 123 | { |
| @@ -554,7 +589,8 @@ static int x25_create(struct net *net, struct socket *sock, int protocol, | |||
| 554 | x25->facilities.winsize_out = X25_DEFAULT_WINDOW_SIZE; | 589 | x25->facilities.winsize_out = X25_DEFAULT_WINDOW_SIZE; |
| 555 | x25->facilities.pacsize_in = X25_DEFAULT_PACKET_SIZE; | 590 | x25->facilities.pacsize_in = X25_DEFAULT_PACKET_SIZE; |
| 556 | x25->facilities.pacsize_out = X25_DEFAULT_PACKET_SIZE; | 591 | x25->facilities.pacsize_out = X25_DEFAULT_PACKET_SIZE; |
| 557 | x25->facilities.throughput = X25_DEFAULT_THROUGHPUT; | 592 | x25->facilities.throughput = 0; /* by default don't negotiate |
| 593 | throughput */ | ||
| 558 | x25->facilities.reverse = X25_DEFAULT_REVERSE; | 594 | x25->facilities.reverse = X25_DEFAULT_REVERSE; |
| 559 | x25->dte_facilities.calling_len = 0; | 595 | x25->dte_facilities.calling_len = 0; |
| 560 | x25->dte_facilities.called_len = 0; | 596 | x25->dte_facilities.called_len = 0; |
| @@ -922,16 +958,26 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, | |||
| 922 | /* | 958 | /* |
| 923 | * Extract the X.25 addresses and convert them to ASCII strings, | 959 | * Extract the X.25 addresses and convert them to ASCII strings, |
| 924 | * and remove them. | 960 | * and remove them. |
| 961 | * | ||
| 962 | * Address block is mandatory in call request packets | ||
| 925 | */ | 963 | */ |
| 926 | addr_len = x25_addr_ntoa(skb->data, &source_addr, &dest_addr); | 964 | addr_len = x25_parse_address_block(skb, &source_addr, &dest_addr); |
| 965 | if (addr_len <= 0) | ||
| 966 | goto out_clear_request; | ||
| 927 | skb_pull(skb, addr_len); | 967 | skb_pull(skb, addr_len); |
| 928 | 968 | ||
| 929 | /* | 969 | /* |
| 930 | * Get the length of the facilities, skip past them for the moment | 970 | * Get the length of the facilities, skip past them for the moment |
| 931 | * get the call user data because this is needed to determine | 971 | * get the call user data because this is needed to determine |
| 932 | * the correct listener | 972 | * the correct listener |
| 973 | * | ||
| 974 | * Facilities length is mandatory in call request packets | ||
| 933 | */ | 975 | */ |
| 976 | if (skb->len < 1) | ||
| 977 | goto out_clear_request; | ||
| 934 | len = skb->data[0] + 1; | 978 | len = skb->data[0] + 1; |
| 979 | if (skb->len < len) | ||
| 980 | goto out_clear_request; | ||
| 935 | skb_pull(skb,len); | 981 | skb_pull(skb,len); |
| 936 | 982 | ||
| 937 | /* | 983 | /* |
| @@ -1415,9 +1461,20 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
| 1415 | if (facilities.winsize_in < 1 || | 1461 | if (facilities.winsize_in < 1 || |
| 1416 | facilities.winsize_in > 127) | 1462 | facilities.winsize_in > 127) |
| 1417 | break; | 1463 | break; |
| 1418 | if (facilities.throughput < 0x03 || | 1464 | if (facilities.throughput) { |
| 1419 | facilities.throughput > 0xDD) | 1465 | int out = facilities.throughput & 0xf0; |
| 1420 | break; | 1466 | int in = facilities.throughput & 0x0f; |
| 1467 | if (!out) | ||
| 1468 | facilities.throughput |= | ||
| 1469 | X25_DEFAULT_THROUGHPUT << 4; | ||
| 1470 | else if (out < 0x30 || out > 0xD0) | ||
| 1471 | break; | ||
| 1472 | if (!in) | ||
| 1473 | facilities.throughput |= | ||
| 1474 | X25_DEFAULT_THROUGHPUT; | ||
| 1475 | else if (in < 0x03 || in > 0x0D) | ||
| 1476 | break; | ||
| 1477 | } | ||
| 1421 | if (facilities.reverse && | 1478 | if (facilities.reverse && |
| 1422 | (facilities.reverse & 0x81) != 0x81) | 1479 | (facilities.reverse & 0x81) != 0x81) |
| 1423 | break; | 1480 | break; |
diff --git a/net/x25/x25_facilities.c b/net/x25/x25_facilities.c index a21f6646eb3a..771bab00754b 100644 --- a/net/x25/x25_facilities.c +++ b/net/x25/x25_facilities.c | |||
| @@ -35,7 +35,7 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities, | |||
| 35 | struct x25_dte_facilities *dte_facs, unsigned long *vc_fac_mask) | 35 | struct x25_dte_facilities *dte_facs, unsigned long *vc_fac_mask) |
| 36 | { | 36 | { |
| 37 | unsigned char *p = skb->data; | 37 | unsigned char *p = skb->data; |
| 38 | unsigned int len = *p++; | 38 | unsigned int len; |
| 39 | 39 | ||
| 40 | *vc_fac_mask = 0; | 40 | *vc_fac_mask = 0; |
| 41 | 41 | ||
| @@ -50,6 +50,14 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities, | |||
| 50 | memset(dte_facs->called_ae, '\0', sizeof(dte_facs->called_ae)); | 50 | memset(dte_facs->called_ae, '\0', sizeof(dte_facs->called_ae)); |
| 51 | memset(dte_facs->calling_ae, '\0', sizeof(dte_facs->calling_ae)); | 51 | memset(dte_facs->calling_ae, '\0', sizeof(dte_facs->calling_ae)); |
| 52 | 52 | ||
| 53 | if (skb->len < 1) | ||
| 54 | return 0; | ||
| 55 | |||
| 56 | len = *p++; | ||
| 57 | |||
| 58 | if (len >= skb->len) | ||
| 59 | return -1; | ||
| 60 | |||
| 53 | while (len > 0) { | 61 | while (len > 0) { |
| 54 | switch (*p & X25_FAC_CLASS_MASK) { | 62 | switch (*p & X25_FAC_CLASS_MASK) { |
| 55 | case X25_FAC_CLASS_A: | 63 | case X25_FAC_CLASS_A: |
| @@ -247,6 +255,8 @@ int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk, | |||
| 247 | memcpy(new, ours, sizeof(*new)); | 255 | memcpy(new, ours, sizeof(*new)); |
| 248 | 256 | ||
| 249 | len = x25_parse_facilities(skb, &theirs, dte, &x25->vc_facil_mask); | 257 | len = x25_parse_facilities(skb, &theirs, dte, &x25->vc_facil_mask); |
| 258 | if (len < 0) | ||
| 259 | return len; | ||
| 250 | 260 | ||
| 251 | /* | 261 | /* |
| 252 | * They want reverse charging, we won't accept it. | 262 | * They want reverse charging, we won't accept it. |
| @@ -259,9 +269,18 @@ int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk, | |||
| 259 | new->reverse = theirs.reverse; | 269 | new->reverse = theirs.reverse; |
| 260 | 270 | ||
| 261 | if (theirs.throughput) { | 271 | if (theirs.throughput) { |
| 262 | if (theirs.throughput < ours->throughput) { | 272 | int theirs_in = theirs.throughput & 0x0f; |
| 263 | SOCK_DEBUG(sk, "X.25: throughput negotiated down\n"); | 273 | int theirs_out = theirs.throughput & 0xf0; |
| 264 | new->throughput = theirs.throughput; | 274 | int ours_in = ours->throughput & 0x0f; |
| 275 | int ours_out = ours->throughput & 0xf0; | ||
| 276 | if (!ours_in || theirs_in < ours_in) { | ||
| 277 | SOCK_DEBUG(sk, "X.25: inbound throughput negotiated\n"); | ||
| 278 | new->throughput = (new->throughput & 0xf0) | theirs_in; | ||
| 279 | } | ||
| 280 | if (!ours_out || theirs_out < ours_out) { | ||
| 281 | SOCK_DEBUG(sk, | ||
| 282 | "X.25: outbound throughput negotiated\n"); | ||
| 283 | new->throughput = (new->throughput & 0x0f) | theirs_out; | ||
| 265 | } | 284 | } |
| 266 | } | 285 | } |
| 267 | 286 | ||
diff --git a/net/x25/x25_in.c b/net/x25/x25_in.c index a31b3b9e5966..372ac226e648 100644 --- a/net/x25/x25_in.c +++ b/net/x25/x25_in.c | |||
| @@ -90,6 +90,7 @@ static int x25_queue_rx_frame(struct sock *sk, struct sk_buff *skb, int more) | |||
| 90 | static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametype) | 90 | static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametype) |
| 91 | { | 91 | { |
| 92 | struct x25_address source_addr, dest_addr; | 92 | struct x25_address source_addr, dest_addr; |
| 93 | int len; | ||
| 93 | 94 | ||
| 94 | switch (frametype) { | 95 | switch (frametype) { |
| 95 | case X25_CALL_ACCEPTED: { | 96 | case X25_CALL_ACCEPTED: { |
| @@ -107,11 +108,17 @@ static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametyp | |||
| 107 | * Parse the data in the frame. | 108 | * Parse the data in the frame. |
| 108 | */ | 109 | */ |
| 109 | skb_pull(skb, X25_STD_MIN_LEN); | 110 | skb_pull(skb, X25_STD_MIN_LEN); |
| 110 | skb_pull(skb, x25_addr_ntoa(skb->data, &source_addr, &dest_addr)); | 111 | |
| 111 | skb_pull(skb, | 112 | len = x25_parse_address_block(skb, &source_addr, |
| 112 | x25_parse_facilities(skb, &x25->facilities, | 113 | &dest_addr); |
| 114 | if (len > 0) | ||
| 115 | skb_pull(skb, len); | ||
| 116 | |||
| 117 | len = x25_parse_facilities(skb, &x25->facilities, | ||
| 113 | &x25->dte_facilities, | 118 | &x25->dte_facilities, |
| 114 | &x25->vc_facil_mask)); | 119 | &x25->vc_facil_mask); |
| 120 | if (len > 0) | ||
| 121 | skb_pull(skb, len); | ||
| 115 | /* | 122 | /* |
| 116 | * Copy any Call User Data. | 123 | * Copy any Call User Data. |
| 117 | */ | 124 | */ |
