diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-04-06 11:34:06 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-04-06 11:34:06 -0400 |
commit | cb4361c1dc29cd870f664c004b1817106fbce0fa (patch) | |
tree | c31533210d738c9074b21b8f31fe0399b39545f0 /net/netlabel/netlabel_unlabeled.c | |
parent | 309361e09ca9e9670dc8664e5d14125bf82078af (diff) | |
parent | fb9e2d887243499b8d28efcf80821c4f6a092395 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (37 commits)
smc91c92_cs: fix the problem of "Unable to find hardware address"
r8169: clean up my printk uglyness
net: Hook up cxgb4 to Kconfig and Makefile
cxgb4: Add main driver file and driver Makefile
cxgb4: Add remaining driver headers and L2T management
cxgb4: Add packet queues and packet DMA code
cxgb4: Add HW and FW support code
cxgb4: Add register, message, and FW definitions
netlabel: Fix several rcu_dereference() calls used without RCU read locks
bonding: fix potential deadlock in bond_uninit()
net: check the length of the socket address passed to connect(2)
stmmac: add documentation for the driver.
stmmac: fix kconfig for crc32 build error
be2net: fix bug in vlan rx path for big endian architecture
be2net: fix flashing on big endian architectures
be2net: fix a bug in flashing the redboot section
bonding: bond_xmit_roundrobin() fix
drivers/net: Add missing unlock
net: gianfar - align BD ring size console messages
net: gianfar - initialize per-queue statistics
...
Diffstat (limited to 'net/netlabel/netlabel_unlabeled.c')
-rw-r--r-- | net/netlabel/netlabel_unlabeled.c | 66 |
1 files changed, 19 insertions, 47 deletions
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: { |