diff options
Diffstat (limited to 'net')
| -rw-r--r-- | net/bluetooth/l2cap.c | 3 | ||||
| -rw-r--r-- | net/bluetooth/rfcomm/sock.c | 3 | ||||
| -rw-r--r-- | net/bluetooth/sco.c | 3 | ||||
| -rw-r--r-- | net/can/bcm.c | 3 | ||||
| -rw-r--r-- | net/ieee802154/af_ieee802154.c | 3 | ||||
| -rw-r--r-- | net/ipv4/af_inet.c | 5 | ||||
| -rw-r--r-- | net/ipv4/tcp.c | 1 | ||||
| -rw-r--r-- | net/mac80211/mesh_hwmp.c | 4 | ||||
| -rw-r--r-- | net/mac80211/tx.c | 6 | ||||
| -rw-r--r-- | net/mac80211/util.c | 18 | ||||
| -rw-r--r-- | net/netlabel/netlabel_domainhash.c | 28 | ||||
| -rw-r--r-- | net/netlabel/netlabel_unlabeled.c | 66 | ||||
| -rw-r--r-- | net/netlink/af_netlink.c | 3 | ||||
| -rw-r--r-- | net/wireless/reg.c | 12 |
14 files changed, 80 insertions, 78 deletions
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 7794a2e2adce..99d68c34e4f1 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c | |||
| @@ -1002,7 +1002,8 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al | |||
| 1002 | 1002 | ||
| 1003 | BT_DBG("sk %p", sk); | 1003 | BT_DBG("sk %p", sk); |
| 1004 | 1004 | ||
| 1005 | if (!addr || addr->sa_family != AF_BLUETOOTH) | 1005 | if (!addr || alen < sizeof(addr->sa_family) || |
| 1006 | addr->sa_family != AF_BLUETOOTH) | ||
| 1006 | return -EINVAL; | 1007 | return -EINVAL; |
| 1007 | 1008 | ||
| 1008 | memset(&la, 0, sizeof(la)); | 1009 | memset(&la, 0, sizeof(la)); |
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 7f439765403d..8ed3c37684fa 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c | |||
| @@ -397,7 +397,8 @@ static int rfcomm_sock_connect(struct socket *sock, struct sockaddr *addr, int a | |||
| 397 | 397 | ||
| 398 | BT_DBG("sk %p", sk); | 398 | BT_DBG("sk %p", sk); |
| 399 | 399 | ||
| 400 | if (addr->sa_family != AF_BLUETOOTH || alen < sizeof(struct sockaddr_rc)) | 400 | if (alen < sizeof(struct sockaddr_rc) || |
| 401 | addr->sa_family != AF_BLUETOOTH) | ||
| 401 | return -EINVAL; | 402 | return -EINVAL; |
| 402 | 403 | ||
| 403 | lock_sock(sk); | 404 | lock_sock(sk); |
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index e5b16b76b22e..ca6b2ad1c3fc 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c | |||
| @@ -499,7 +499,8 @@ static int sco_sock_connect(struct socket *sock, struct sockaddr *addr, int alen | |||
| 499 | 499 | ||
| 500 | BT_DBG("sk %p", sk); | 500 | BT_DBG("sk %p", sk); |
| 501 | 501 | ||
| 502 | if (addr->sa_family != AF_BLUETOOTH || alen < sizeof(struct sockaddr_sco)) | 502 | if (alen < sizeof(struct sockaddr_sco) || |
| 503 | addr->sa_family != AF_BLUETOOTH) | ||
| 503 | return -EINVAL; | 504 | return -EINVAL; |
| 504 | 505 | ||
| 505 | if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND) | 506 | if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND) |
diff --git a/net/can/bcm.c b/net/can/bcm.c index a2dee522b43e..907dc871fac8 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c | |||
| @@ -1479,6 +1479,9 @@ static int bcm_connect(struct socket *sock, struct sockaddr *uaddr, int len, | |||
| 1479 | struct sock *sk = sock->sk; | 1479 | struct sock *sk = sock->sk; |
| 1480 | struct bcm_sock *bo = bcm_sk(sk); | 1480 | struct bcm_sock *bo = bcm_sk(sk); |
| 1481 | 1481 | ||
| 1482 | if (len < sizeof(*addr)) | ||
| 1483 | return -EINVAL; | ||
| 1484 | |||
| 1482 | if (bo->bound) | 1485 | if (bo->bound) |
| 1483 | return -EISCONN; | 1486 | return -EISCONN; |
| 1484 | 1487 | ||
diff --git a/net/ieee802154/af_ieee802154.c b/net/ieee802154/af_ieee802154.c index 79886d546bab..c7da600750bb 100644 --- a/net/ieee802154/af_ieee802154.c +++ b/net/ieee802154/af_ieee802154.c | |||
| @@ -127,6 +127,9 @@ static int ieee802154_sock_connect(struct socket *sock, struct sockaddr *uaddr, | |||
| 127 | { | 127 | { |
| 128 | struct sock *sk = sock->sk; | 128 | struct sock *sk = sock->sk; |
| 129 | 129 | ||
| 130 | if (addr_len < sizeof(uaddr->sa_family)) | ||
| 131 | return -EINVAL; | ||
| 132 | |||
| 130 | if (uaddr->sa_family == AF_UNSPEC) | 133 | if (uaddr->sa_family == AF_UNSPEC) |
| 131 | return sk->sk_prot->disconnect(sk, flags); | 134 | return sk->sk_prot->disconnect(sk, flags); |
| 132 | 135 | ||
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 2ed85714540f..f71357422380 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c | |||
| @@ -531,6 +531,8 @@ int inet_dgram_connect(struct socket *sock, struct sockaddr * uaddr, | |||
| 531 | { | 531 | { |
| 532 | struct sock *sk = sock->sk; | 532 | struct sock *sk = sock->sk; |
| 533 | 533 | ||
| 534 | if (addr_len < sizeof(uaddr->sa_family)) | ||
| 535 | return -EINVAL; | ||
| 534 | if (uaddr->sa_family == AF_UNSPEC) | 536 | if (uaddr->sa_family == AF_UNSPEC) |
| 535 | return sk->sk_prot->disconnect(sk, flags); | 537 | return sk->sk_prot->disconnect(sk, flags); |
| 536 | 538 | ||
| @@ -574,6 +576,9 @@ int inet_stream_connect(struct socket *sock, struct sockaddr *uaddr, | |||
| 574 | int err; | 576 | int err; |
| 575 | long timeo; | 577 | long timeo; |
| 576 | 578 | ||
| 579 | if (addr_len < sizeof(uaddr->sa_family)) | ||
| 580 | return -EINVAL; | ||
| 581 | |||
| 577 | lock_sock(sk); | 582 | lock_sock(sk); |
| 578 | 583 | ||
| 579 | if (uaddr->sa_family == AF_UNSPEC) { | 584 | if (uaddr->sa_family == AF_UNSPEC) { |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 7a1f1d78893f..0f8caf64caa3 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
| @@ -1369,6 +1369,7 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc, | |||
| 1369 | sk_eat_skb(sk, skb, 0); | 1369 | sk_eat_skb(sk, skb, 0); |
| 1370 | if (!desc->count) | 1370 | if (!desc->count) |
| 1371 | break; | 1371 | break; |
| 1372 | tp->copied_seq = seq; | ||
| 1372 | } | 1373 | } |
| 1373 | tp->copied_seq = seq; | 1374 | tp->copied_seq = seq; |
| 1374 | 1375 | ||
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 122c11380ffe..fefc45c4b4e8 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c | |||
| @@ -392,7 +392,7 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata, | |||
| 392 | if (SN_GT(mpath->sn, orig_sn) || | 392 | if (SN_GT(mpath->sn, orig_sn) || |
| 393 | (mpath->sn == orig_sn && | 393 | (mpath->sn == orig_sn && |
| 394 | action == MPATH_PREQ && | 394 | action == MPATH_PREQ && |
| 395 | new_metric > mpath->metric)) { | 395 | new_metric >= mpath->metric)) { |
| 396 | process = false; | 396 | process = false; |
| 397 | fresh_info = false; | 397 | fresh_info = false; |
| 398 | } | 398 | } |
| @@ -612,7 +612,7 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata, | |||
| 612 | 612 | ||
| 613 | mesh_path_sel_frame_tx(MPATH_PREP, flags, orig_addr, | 613 | mesh_path_sel_frame_tx(MPATH_PREP, flags, orig_addr, |
| 614 | cpu_to_le32(orig_sn), 0, target_addr, | 614 | cpu_to_le32(orig_sn), 0, target_addr, |
| 615 | cpu_to_le32(target_sn), mpath->next_hop->sta.addr, hopcount, | 615 | cpu_to_le32(target_sn), next_hop, hopcount, |
| 616 | ttl, cpu_to_le32(lifetime), cpu_to_le32(metric), | 616 | ttl, cpu_to_le32(lifetime), cpu_to_le32(metric), |
| 617 | 0, sdata); | 617 | 0, sdata); |
| 618 | rcu_read_unlock(); | 618 | rcu_read_unlock(); |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index cbe53ed4fb0b..cfc473e1b050 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
| @@ -1991,6 +1991,7 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local, | |||
| 1991 | void ieee80211_tx_pending(unsigned long data) | 1991 | void ieee80211_tx_pending(unsigned long data) |
| 1992 | { | 1992 | { |
| 1993 | struct ieee80211_local *local = (struct ieee80211_local *)data; | 1993 | struct ieee80211_local *local = (struct ieee80211_local *)data; |
| 1994 | struct ieee80211_sub_if_data *sdata; | ||
| 1994 | unsigned long flags; | 1995 | unsigned long flags; |
| 1995 | int i; | 1996 | int i; |
| 1996 | bool txok; | 1997 | bool txok; |
| @@ -2029,6 +2030,11 @@ void ieee80211_tx_pending(unsigned long data) | |||
| 2029 | if (!txok) | 2030 | if (!txok) |
| 2030 | break; | 2031 | break; |
| 2031 | } | 2032 | } |
| 2033 | |||
| 2034 | if (skb_queue_empty(&local->pending[i])) | ||
| 2035 | list_for_each_entry_rcu(sdata, &local->interfaces, list) | ||
| 2036 | netif_tx_wake_queue( | ||
| 2037 | netdev_get_tx_queue(sdata->dev, i)); | ||
| 2032 | } | 2038 | } |
| 2033 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | 2039 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); |
| 2034 | 2040 | ||
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index c453226f06b2..53af57047435 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
| @@ -279,13 +279,13 @@ static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue, | |||
| 279 | /* someone still has this queue stopped */ | 279 | /* someone still has this queue stopped */ |
| 280 | return; | 280 | return; |
| 281 | 281 | ||
| 282 | if (!skb_queue_empty(&local->pending[queue])) | 282 | if (skb_queue_empty(&local->pending[queue])) { |
| 283 | rcu_read_lock(); | ||
| 284 | list_for_each_entry_rcu(sdata, &local->interfaces, list) | ||
| 285 | netif_tx_wake_queue(netdev_get_tx_queue(sdata->dev, queue)); | ||
| 286 | rcu_read_unlock(); | ||
| 287 | } else | ||
| 283 | tasklet_schedule(&local->tx_pending_tasklet); | 288 | tasklet_schedule(&local->tx_pending_tasklet); |
| 284 | |||
| 285 | rcu_read_lock(); | ||
| 286 | list_for_each_entry_rcu(sdata, &local->interfaces, list) | ||
| 287 | netif_tx_wake_queue(netdev_get_tx_queue(sdata->dev, queue)); | ||
| 288 | rcu_read_unlock(); | ||
| 289 | } | 289 | } |
| 290 | 290 | ||
| 291 | void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue, | 291 | void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue, |
| @@ -1097,9 +1097,9 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
| 1097 | */ | 1097 | */ |
| 1098 | res = drv_start(local); | 1098 | res = drv_start(local); |
| 1099 | if (res) { | 1099 | if (res) { |
| 1100 | WARN(local->suspended, "Harware became unavailable " | 1100 | WARN(local->suspended, "Hardware became unavailable " |
| 1101 | "upon resume. This is could be a software issue" | 1101 | "upon resume. This could be a software issue " |
| 1102 | "prior to suspend or a hardware issue\n"); | 1102 | "prior to suspend or a hardware issue.\n"); |
| 1103 | return res; | 1103 | return res; |
| 1104 | } | 1104 | } |
| 1105 | 1105 | ||
diff --git a/net/netlabel/netlabel_domainhash.c b/net/netlabel/netlabel_domainhash.c index 016ab9c75ebd..d37b7f80fa37 100644 --- a/net/netlabel/netlabel_domainhash.c +++ b/net/netlabel/netlabel_domainhash.c | |||
| @@ -51,9 +51,12 @@ struct netlbl_domhsh_tbl { | |||
| 51 | }; | 51 | }; |
| 52 | 52 | ||
| 53 | /* Domain hash table */ | 53 | /* Domain hash table */ |
| 54 | /* XXX - updates should be so rare that having one spinlock for the entire | 54 | /* updates should be so rare that having one spinlock for the entire hash table |
| 55 | * hash table should be okay */ | 55 | * should be okay */ |
| 56 | static DEFINE_SPINLOCK(netlbl_domhsh_lock); | 56 | static DEFINE_SPINLOCK(netlbl_domhsh_lock); |
| 57 | #define netlbl_domhsh_rcu_deref(p) \ | ||
| 58 | rcu_dereference_check(p, rcu_read_lock_held() || \ | ||
| 59 | lockdep_is_held(&netlbl_domhsh_lock)) | ||
| 57 | static struct netlbl_domhsh_tbl *netlbl_domhsh = NULL; | 60 | static struct netlbl_domhsh_tbl *netlbl_domhsh = NULL; |
| 58 | static struct netlbl_dom_map *netlbl_domhsh_def = NULL; | 61 | static struct netlbl_dom_map *netlbl_domhsh_def = NULL; |
| 59 | 62 | ||
| @@ -107,7 +110,8 @@ static void netlbl_domhsh_free_entry(struct rcu_head *entry) | |||
| 107 | * Description: | 110 | * Description: |
| 108 | * This is the hashing function for the domain hash table, it returns the | 111 | * This is the hashing function for the domain hash table, it returns the |
| 109 | * correct bucket number for the domain. The caller is responsibile for | 112 | * correct bucket number for the domain. The caller is responsibile for |
| 110 | * calling the rcu_read_[un]lock() functions. | 113 | * ensuring that the hash table is protected with either a RCU read lock or the |
| 114 | * hash table lock. | ||
| 111 | * | 115 | * |
| 112 | */ | 116 | */ |
| 113 | static u32 netlbl_domhsh_hash(const char *key) | 117 | static u32 netlbl_domhsh_hash(const char *key) |
| @@ -121,7 +125,7 @@ static u32 netlbl_domhsh_hash(const char *key) | |||
| 121 | 125 | ||
| 122 | for (iter = 0, val = 0, len = strlen(key); iter < len; iter++) | 126 | for (iter = 0, val = 0, len = strlen(key); iter < len; iter++) |
| 123 | val = (val << 4 | (val >> (8 * sizeof(u32) - 4))) ^ key[iter]; | 127 | val = (val << 4 | (val >> (8 * sizeof(u32) - 4))) ^ key[iter]; |
| 124 | return val & (rcu_dereference(netlbl_domhsh)->size - 1); | 128 | return val & (netlbl_domhsh_rcu_deref(netlbl_domhsh)->size - 1); |
| 125 | } | 129 | } |
| 126 | 130 | ||
| 127 | /** | 131 | /** |
| @@ -131,7 +135,8 @@ static u32 netlbl_domhsh_hash(const char *key) | |||
| 131 | * Description: | 135 | * Description: |
| 132 | * Searches the domain hash table and returns a pointer to the hash table | 136 | * Searches the domain hash table and returns a pointer to the hash table |
| 133 | * entry if found, otherwise NULL is returned. The caller is responsibile for | 137 | * entry if found, otherwise NULL is returned. The caller is responsibile for |
| 134 | * the rcu hash table locks (i.e. the caller much call rcu_read_[un]lock()). | 138 | * ensuring that the hash table is protected with either a RCU read lock or the |
| 139 | * hash table lock. | ||
| 135 | * | 140 | * |
| 136 | */ | 141 | */ |
| 137 | static struct netlbl_dom_map *netlbl_domhsh_search(const char *domain) | 142 | static struct netlbl_dom_map *netlbl_domhsh_search(const char *domain) |
| @@ -142,7 +147,7 @@ static struct netlbl_dom_map *netlbl_domhsh_search(const char *domain) | |||
| 142 | 147 | ||
| 143 | if (domain != NULL) { | 148 | if (domain != NULL) { |
| 144 | bkt = netlbl_domhsh_hash(domain); | 149 | bkt = netlbl_domhsh_hash(domain); |
| 145 | bkt_list = &rcu_dereference(netlbl_domhsh)->tbl[bkt]; | 150 | bkt_list = &netlbl_domhsh_rcu_deref(netlbl_domhsh)->tbl[bkt]; |
| 146 | list_for_each_entry_rcu(iter, bkt_list, list) | 151 | list_for_each_entry_rcu(iter, bkt_list, list) |
| 147 | if (iter->valid && strcmp(iter->domain, domain) == 0) | 152 | if (iter->valid && strcmp(iter->domain, domain) == 0) |
| 148 | return iter; | 153 | return iter; |
| @@ -160,8 +165,8 @@ static struct netlbl_dom_map *netlbl_domhsh_search(const char *domain) | |||
| 160 | * Searches the domain hash table and returns a pointer to the hash table | 165 | * Searches the domain hash table and returns a pointer to the hash table |
| 161 | * entry if an exact match is found, if an exact match is not present in the | 166 | * entry if an exact match is found, if an exact match is not present in the |
| 162 | * hash table then the default entry is returned if valid otherwise NULL is | 167 | * hash table then the default entry is returned if valid otherwise NULL is |
| 163 | * returned. The caller is responsibile for the rcu hash table locks | 168 | * returned. The caller is responsibile ensuring that the hash table is |
| 164 | * (i.e. the caller much call rcu_read_[un]lock()). | 169 | * protected with either a RCU read lock or the hash table lock. |
| 165 | * | 170 | * |
| 166 | */ | 171 | */ |
| 167 | static struct netlbl_dom_map *netlbl_domhsh_search_def(const char *domain) | 172 | static struct netlbl_dom_map *netlbl_domhsh_search_def(const char *domain) |
| @@ -170,7 +175,7 @@ static struct netlbl_dom_map *netlbl_domhsh_search_def(const char *domain) | |||
| 170 | 175 | ||
| 171 | entry = netlbl_domhsh_search(domain); | 176 | entry = netlbl_domhsh_search(domain); |
| 172 | if (entry == NULL) { | 177 | if (entry == NULL) { |
| 173 | entry = rcu_dereference(netlbl_domhsh_def); | 178 | entry = netlbl_domhsh_rcu_deref(netlbl_domhsh_def); |
| 174 | if (entry != NULL && !entry->valid) | 179 | if (entry != NULL && !entry->valid) |
| 175 | entry = NULL; | 180 | entry = NULL; |
| 176 | } | 181 | } |
| @@ -307,8 +312,11 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry, | |||
| 307 | struct netlbl_af6list *tmp6; | 312 | struct netlbl_af6list *tmp6; |
| 308 | #endif /* IPv6 */ | 313 | #endif /* IPv6 */ |
| 309 | 314 | ||
| 315 | /* XXX - we can remove this RCU read lock as the spinlock protects the | ||
| 316 | * entire function, but before we do we need to fixup the | ||
| 317 | * netlbl_af[4,6]list RCU functions to do "the right thing" with | ||
| 318 | * respect to rcu_dereference() when only a spinlock is held. */ | ||
| 310 | rcu_read_lock(); | 319 | rcu_read_lock(); |
| 311 | |||
| 312 | spin_lock(&netlbl_domhsh_lock); | 320 | spin_lock(&netlbl_domhsh_lock); |
| 313 | if (entry->domain != NULL) | 321 | if (entry->domain != NULL) |
| 314 | entry_old = netlbl_domhsh_search(entry->domain); | 322 | entry_old = netlbl_domhsh_search(entry->domain); |
diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c index d7ea2cf390b7..a3d64aabe2f7 100644 --- a/net/netlabel/netlabel_unlabeled.c +++ b/net/netlabel/netlabel_unlabeled.c | |||
| @@ -115,6 +115,9 @@ struct netlbl_unlhsh_walk_arg { | |||
| 115 | /* updates should be so rare that having one spinlock for the entire | 115 | /* updates should be so rare that having one spinlock for the entire |
| 116 | * hash table should be okay */ | 116 | * hash table should be okay */ |
| 117 | static DEFINE_SPINLOCK(netlbl_unlhsh_lock); | 117 | static DEFINE_SPINLOCK(netlbl_unlhsh_lock); |
| 118 | #define netlbl_unlhsh_rcu_deref(p) \ | ||
| 119 | rcu_dereference_check(p, rcu_read_lock_held() || \ | ||
| 120 | lockdep_is_held(&netlbl_unlhsh_lock)) | ||
| 118 | static struct netlbl_unlhsh_tbl *netlbl_unlhsh = NULL; | 121 | static struct netlbl_unlhsh_tbl *netlbl_unlhsh = NULL; |
| 119 | static struct netlbl_unlhsh_iface *netlbl_unlhsh_def = NULL; | 122 | static struct netlbl_unlhsh_iface *netlbl_unlhsh_def = NULL; |
| 120 | 123 | ||
| @@ -236,15 +239,13 @@ static void netlbl_unlhsh_free_iface(struct rcu_head *entry) | |||
| 236 | * Description: | 239 | * Description: |
| 237 | * This is the hashing function for the unlabeled hash table, it returns the | 240 | * This is the hashing function for the unlabeled hash table, it returns the |
| 238 | * bucket number for the given device/interface. The caller is responsible for | 241 | * bucket number for the given device/interface. The caller is responsible for |
| 239 | * calling the rcu_read_[un]lock() functions. | 242 | * ensuring that the hash table is protected with either a RCU read lock or |
| 243 | * the hash table lock. | ||
| 240 | * | 244 | * |
| 241 | */ | 245 | */ |
| 242 | static u32 netlbl_unlhsh_hash(int ifindex) | 246 | static u32 netlbl_unlhsh_hash(int ifindex) |
| 243 | { | 247 | { |
| 244 | /* this is taken _almost_ directly from | 248 | return ifindex & (netlbl_unlhsh_rcu_deref(netlbl_unlhsh)->size - 1); |
| 245 | * security/selinux/netif.c:sel_netif_hasfn() as they do pretty much | ||
| 246 | * the same thing */ | ||
| 247 | return ifindex & (rcu_dereference(netlbl_unlhsh)->size - 1); | ||
| 248 | } | 249 | } |
| 249 | 250 | ||
| 250 | /** | 251 | /** |
| @@ -254,7 +255,8 @@ static u32 netlbl_unlhsh_hash(int ifindex) | |||
| 254 | * Description: | 255 | * Description: |
| 255 | * Searches the unlabeled connection hash table and returns a pointer to the | 256 | * Searches the unlabeled connection hash table and returns a pointer to the |
| 256 | * interface entry which matches @ifindex, otherwise NULL is returned. The | 257 | * interface entry which matches @ifindex, otherwise NULL is returned. The |
| 257 | * caller is responsible for calling the rcu_read_[un]lock() functions. | 258 | * caller is responsible for ensuring that the hash table is protected with |
| 259 | * either a RCU read lock or the hash table lock. | ||
| 258 | * | 260 | * |
| 259 | */ | 261 | */ |
| 260 | static struct netlbl_unlhsh_iface *netlbl_unlhsh_search_iface(int ifindex) | 262 | static struct netlbl_unlhsh_iface *netlbl_unlhsh_search_iface(int ifindex) |
| @@ -264,7 +266,7 @@ static struct netlbl_unlhsh_iface *netlbl_unlhsh_search_iface(int ifindex) | |||
| 264 | struct netlbl_unlhsh_iface *iter; | 266 | struct netlbl_unlhsh_iface *iter; |
| 265 | 267 | ||
| 266 | bkt = netlbl_unlhsh_hash(ifindex); | 268 | bkt = netlbl_unlhsh_hash(ifindex); |
| 267 | bkt_list = &rcu_dereference(netlbl_unlhsh)->tbl[bkt]; | 269 | bkt_list = &netlbl_unlhsh_rcu_deref(netlbl_unlhsh)->tbl[bkt]; |
| 268 | list_for_each_entry_rcu(iter, bkt_list, list) | 270 | list_for_each_entry_rcu(iter, bkt_list, list) |
| 269 | if (iter->valid && iter->ifindex == ifindex) | 271 | if (iter->valid && iter->ifindex == ifindex) |
| 270 | return iter; | 272 | return iter; |
| @@ -273,33 +275,6 @@ static struct netlbl_unlhsh_iface *netlbl_unlhsh_search_iface(int ifindex) | |||
| 273 | } | 275 | } |
| 274 | 276 | ||
| 275 | /** | 277 | /** |
| 276 | * netlbl_unlhsh_search_iface_def - Search for a matching interface entry | ||
| 277 | * @ifindex: the network interface | ||
| 278 | * | ||
| 279 | * Description: | ||
| 280 | * Searches the unlabeled connection hash table and returns a pointer to the | ||
| 281 | * interface entry which matches @ifindex. If an exact match can not be found | ||
| 282 | * and there is a valid default entry, the default entry is returned, otherwise | ||
| 283 | * NULL is returned. The caller is responsible for calling the | ||
| 284 | * rcu_read_[un]lock() functions. | ||
| 285 | * | ||
| 286 | */ | ||
| 287 | static struct netlbl_unlhsh_iface *netlbl_unlhsh_search_iface_def(int ifindex) | ||
| 288 | { | ||
| 289 | struct netlbl_unlhsh_iface *entry; | ||
| 290 | |||
| 291 | entry = netlbl_unlhsh_search_iface(ifindex); | ||
| 292 | if (entry != NULL) | ||
| 293 | return entry; | ||
| 294 | |||
| 295 | entry = rcu_dereference(netlbl_unlhsh_def); | ||
| 296 | if (entry != NULL && entry->valid) | ||
| 297 | return entry; | ||
| 298 | |||
| 299 | return NULL; | ||
| 300 | } | ||
| 301 | |||
| 302 | /** | ||
| 303 | * netlbl_unlhsh_add_addr4 - Add a new IPv4 address entry to the hash table | 278 | * netlbl_unlhsh_add_addr4 - Add a new IPv4 address entry to the hash table |
| 304 | * @iface: the associated interface entry | 279 | * @iface: the associated interface entry |
| 305 | * @addr: IPv4 address in network byte order | 280 | * @addr: IPv4 address in network byte order |
| @@ -309,8 +284,7 @@ static struct netlbl_unlhsh_iface *netlbl_unlhsh_search_iface_def(int ifindex) | |||
| 309 | * Description: | 284 | * Description: |
| 310 | * Add a new address entry into the unlabeled connection hash table using the | 285 | * Add a new address entry into the unlabeled connection hash table using the |
| 311 | * interface entry specified by @iface. On success zero is returned, otherwise | 286 | * interface entry specified by @iface. On success zero is returned, otherwise |
| 312 | * a negative value is returned. The caller is responsible for calling the | 287 | * a negative value is returned. |
| 313 | * rcu_read_[un]lock() functions. | ||
| 314 | * | 288 | * |
| 315 | */ | 289 | */ |
| 316 | static int netlbl_unlhsh_add_addr4(struct netlbl_unlhsh_iface *iface, | 290 | static int netlbl_unlhsh_add_addr4(struct netlbl_unlhsh_iface *iface, |
| @@ -350,8 +324,7 @@ static int netlbl_unlhsh_add_addr4(struct netlbl_unlhsh_iface *iface, | |||
| 350 | * Description: | 324 | * Description: |
| 351 | * Add a new address entry into the unlabeled connection hash table using the | 325 | * Add a new address entry into the unlabeled connection hash table using the |
| 352 | * interface entry specified by @iface. On success zero is returned, otherwise | 326 | * interface entry specified by @iface. On success zero is returned, otherwise |
| 353 | * a negative value is returned. The caller is responsible for calling the | 327 | * a negative value is returned. |
| 354 | * rcu_read_[un]lock() functions. | ||
| 355 | * | 328 | * |
| 356 | */ | 329 | */ |
| 357 | static int netlbl_unlhsh_add_addr6(struct netlbl_unlhsh_iface *iface, | 330 | static int netlbl_unlhsh_add_addr6(struct netlbl_unlhsh_iface *iface, |
| @@ -392,8 +365,7 @@ static int netlbl_unlhsh_add_addr6(struct netlbl_unlhsh_iface *iface, | |||
| 392 | * Description: | 365 | * Description: |
| 393 | * Add a new, empty, interface entry into the unlabeled connection hash table. | 366 | * Add a new, empty, interface entry into the unlabeled connection hash table. |
| 394 | * On success a pointer to the new interface entry is returned, on failure NULL | 367 | * On success a pointer to the new interface entry is returned, on failure NULL |
| 395 | * is returned. The caller is responsible for calling the rcu_read_[un]lock() | 368 | * is returned. |
| 396 | * functions. | ||
| 397 | * | 369 | * |
| 398 | */ | 370 | */ |
| 399 | static struct netlbl_unlhsh_iface *netlbl_unlhsh_add_iface(int ifindex) | 371 | static struct netlbl_unlhsh_iface *netlbl_unlhsh_add_iface(int ifindex) |
| @@ -416,10 +388,10 @@ static struct netlbl_unlhsh_iface *netlbl_unlhsh_add_iface(int ifindex) | |||
| 416 | if (netlbl_unlhsh_search_iface(ifindex) != NULL) | 388 | if (netlbl_unlhsh_search_iface(ifindex) != NULL) |
| 417 | goto add_iface_failure; | 389 | goto add_iface_failure; |
| 418 | list_add_tail_rcu(&iface->list, | 390 | list_add_tail_rcu(&iface->list, |
| 419 | &rcu_dereference(netlbl_unlhsh)->tbl[bkt]); | 391 | &netlbl_unlhsh_rcu_deref(netlbl_unlhsh)->tbl[bkt]); |
| 420 | } else { | 392 | } else { |
| 421 | INIT_LIST_HEAD(&iface->list); | 393 | INIT_LIST_HEAD(&iface->list); |
| 422 | if (rcu_dereference(netlbl_unlhsh_def) != NULL) | 394 | if (netlbl_unlhsh_rcu_deref(netlbl_unlhsh_def) != NULL) |
| 423 | goto add_iface_failure; | 395 | goto add_iface_failure; |
| 424 | rcu_assign_pointer(netlbl_unlhsh_def, iface); | 396 | rcu_assign_pointer(netlbl_unlhsh_def, iface); |
| 425 | } | 397 | } |
| @@ -549,8 +521,7 @@ unlhsh_add_return: | |||
| 549 | * | 521 | * |
| 550 | * Description: | 522 | * Description: |
| 551 | * Remove an IP address entry from the unlabeled connection hash table. | 523 | * Remove an IP address entry from the unlabeled connection hash table. |
| 552 | * Returns zero on success, negative values on failure. The caller is | 524 | * Returns zero on success, negative values on failure. |
| 553 | * responsible for calling the rcu_read_[un]lock() functions. | ||
| 554 | * | 525 | * |
| 555 | */ | 526 | */ |
| 556 | static int netlbl_unlhsh_remove_addr4(struct net *net, | 527 | static int netlbl_unlhsh_remove_addr4(struct net *net, |
| @@ -612,8 +583,7 @@ static int netlbl_unlhsh_remove_addr4(struct net *net, | |||
| 612 | * | 583 | * |
| 613 | * Description: | 584 | * Description: |
| 614 | * Remove an IP address entry from the unlabeled connection hash table. | 585 | * Remove an IP address entry from the unlabeled connection hash table. |
| 615 | * Returns zero on success, negative values on failure. The caller is | 586 | * Returns zero on success, negative values on failure. |
| 616 | * responsible for calling the rcu_read_[un]lock() functions. | ||
| 617 | * | 587 | * |
| 618 | */ | 588 | */ |
| 619 | static int netlbl_unlhsh_remove_addr6(struct net *net, | 589 | static int netlbl_unlhsh_remove_addr6(struct net *net, |
| @@ -1548,8 +1518,10 @@ int netlbl_unlabel_getattr(const struct sk_buff *skb, | |||
| 1548 | struct netlbl_unlhsh_iface *iface; | 1518 | struct netlbl_unlhsh_iface *iface; |
| 1549 | 1519 | ||
| 1550 | rcu_read_lock(); | 1520 | rcu_read_lock(); |
| 1551 | iface = netlbl_unlhsh_search_iface_def(skb->skb_iif); | 1521 | iface = netlbl_unlhsh_search_iface(skb->skb_iif); |
| 1552 | if (iface == NULL) | 1522 | if (iface == NULL) |
| 1523 | iface = rcu_dereference(netlbl_unlhsh_def); | ||
| 1524 | if (iface == NULL || !iface->valid) | ||
| 1553 | goto unlabel_getattr_nolabel; | 1525 | goto unlabel_getattr_nolabel; |
| 1554 | switch (family) { | 1526 | switch (family) { |
| 1555 | case PF_INET: { | 1527 | case PF_INET: { |
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index acbbae1e89b5..795424396aff 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
| @@ -683,6 +683,9 @@ static int netlink_connect(struct socket *sock, struct sockaddr *addr, | |||
| 683 | struct netlink_sock *nlk = nlk_sk(sk); | 683 | struct netlink_sock *nlk = nlk_sk(sk); |
| 684 | struct sockaddr_nl *nladdr = (struct sockaddr_nl *)addr; | 684 | struct sockaddr_nl *nladdr = (struct sockaddr_nl *)addr; |
| 685 | 685 | ||
| 686 | if (alen < sizeof(addr->sa_family)) | ||
| 687 | return -EINVAL; | ||
| 688 | |||
| 686 | if (addr->sa_family == AF_UNSPEC) { | 689 | if (addr->sa_family == AF_UNSPEC) { |
| 687 | sk->sk_state = NETLINK_UNCONNECTED; | 690 | sk->sk_state = NETLINK_UNCONNECTED; |
| 688 | nlk->dst_pid = 0; | 691 | nlk->dst_pid = 0; |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index b7604b823f46..422da20d1e5b 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
| @@ -325,7 +325,7 @@ struct reg_regdb_search_request { | |||
| 325 | }; | 325 | }; |
| 326 | 326 | ||
| 327 | static LIST_HEAD(reg_regdb_search_list); | 327 | static LIST_HEAD(reg_regdb_search_list); |
| 328 | static DEFINE_SPINLOCK(reg_regdb_search_lock); | 328 | static DEFINE_MUTEX(reg_regdb_search_mutex); |
| 329 | 329 | ||
| 330 | static void reg_regdb_search(struct work_struct *work) | 330 | static void reg_regdb_search(struct work_struct *work) |
| 331 | { | 331 | { |
| @@ -333,7 +333,7 @@ static void reg_regdb_search(struct work_struct *work) | |||
| 333 | const struct ieee80211_regdomain *curdom, *regdom; | 333 | const struct ieee80211_regdomain *curdom, *regdom; |
| 334 | int i, r; | 334 | int i, r; |
| 335 | 335 | ||
| 336 | spin_lock(®_regdb_search_lock); | 336 | mutex_lock(®_regdb_search_mutex); |
| 337 | while (!list_empty(®_regdb_search_list)) { | 337 | while (!list_empty(®_regdb_search_list)) { |
| 338 | request = list_first_entry(®_regdb_search_list, | 338 | request = list_first_entry(®_regdb_search_list, |
| 339 | struct reg_regdb_search_request, | 339 | struct reg_regdb_search_request, |
| @@ -347,18 +347,16 @@ static void reg_regdb_search(struct work_struct *work) | |||
| 347 | r = reg_copy_regd(®dom, curdom); | 347 | r = reg_copy_regd(®dom, curdom); |
| 348 | if (r) | 348 | if (r) |
| 349 | break; | 349 | break; |
| 350 | spin_unlock(®_regdb_search_lock); | ||
| 351 | mutex_lock(&cfg80211_mutex); | 350 | mutex_lock(&cfg80211_mutex); |
| 352 | set_regdom(regdom); | 351 | set_regdom(regdom); |
| 353 | mutex_unlock(&cfg80211_mutex); | 352 | mutex_unlock(&cfg80211_mutex); |
| 354 | spin_lock(®_regdb_search_lock); | ||
| 355 | break; | 353 | break; |
| 356 | } | 354 | } |
| 357 | } | 355 | } |
| 358 | 356 | ||
| 359 | kfree(request); | 357 | kfree(request); |
| 360 | } | 358 | } |
| 361 | spin_unlock(®_regdb_search_lock); | 359 | mutex_unlock(®_regdb_search_mutex); |
| 362 | } | 360 | } |
| 363 | 361 | ||
| 364 | static DECLARE_WORK(reg_regdb_work, reg_regdb_search); | 362 | static DECLARE_WORK(reg_regdb_work, reg_regdb_search); |
| @@ -376,9 +374,9 @@ static void reg_regdb_query(const char *alpha2) | |||
| 376 | 374 | ||
| 377 | memcpy(request->alpha2, alpha2, 2); | 375 | memcpy(request->alpha2, alpha2, 2); |
| 378 | 376 | ||
| 379 | spin_lock(®_regdb_search_lock); | 377 | mutex_lock(®_regdb_search_mutex); |
| 380 | list_add_tail(&request->list, ®_regdb_search_list); | 378 | list_add_tail(&request->list, ®_regdb_search_list); |
| 381 | spin_unlock(®_regdb_search_lock); | 379 | mutex_unlock(®_regdb_search_mutex); |
| 382 | 380 | ||
| 383 | schedule_work(®_regdb_work); | 381 | schedule_work(®_regdb_work); |
| 384 | } | 382 | } |
