aboutsummaryrefslogtreecommitdiffstats
path: root/net/netlabel/netlabel_unlabeled.c
diff options
context:
space:
mode:
authorAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
committerAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
commitada47b5fe13d89735805b566185f4885f5a3f750 (patch)
tree644b88f8a71896307d71438e9b3af49126ffb22b /net/netlabel/netlabel_unlabeled.c
parent43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff)
parent3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff)
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'net/netlabel/netlabel_unlabeled.c')
-rw-r--r--net/netlabel/netlabel_unlabeled.c76
1 files changed, 22 insertions, 54 deletions
diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c
index fb357f010189..a3d64aabe2f7 100644
--- a/net/netlabel/netlabel_unlabeled.c
+++ b/net/netlabel/netlabel_unlabeled.c
@@ -43,6 +43,7 @@
43#include <linux/notifier.h> 43#include <linux/notifier.h>
44#include <linux/netdevice.h> 44#include <linux/netdevice.h>
45#include <linux/security.h> 45#include <linux/security.h>
46#include <linux/slab.h>
46#include <net/sock.h> 47#include <net/sock.h>
47#include <net/netlink.h> 48#include <net/netlink.h>
48#include <net/genetlink.h> 49#include <net/genetlink.h>
@@ -114,6 +115,9 @@ struct netlbl_unlhsh_walk_arg {
114/* 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
115 * hash table should be okay */ 116 * hash table should be okay */
116static DEFINE_SPINLOCK(netlbl_unlhsh_lock); 117static 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))
117static struct netlbl_unlhsh_tbl *netlbl_unlhsh = NULL; 121static struct netlbl_unlhsh_tbl *netlbl_unlhsh = NULL;
118static struct netlbl_unlhsh_iface *netlbl_unlhsh_def = NULL; 122static struct netlbl_unlhsh_iface *netlbl_unlhsh_def = NULL;
119 123
@@ -235,15 +239,13 @@ static void netlbl_unlhsh_free_iface(struct rcu_head *entry)
235 * Description: 239 * Description:
236 * 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
237 * 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
238 * 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.
239 * 244 *
240 */ 245 */
241static u32 netlbl_unlhsh_hash(int ifindex) 246static u32 netlbl_unlhsh_hash(int ifindex)
242{ 247{
243 /* this is taken _almost_ directly from 248 return ifindex & (netlbl_unlhsh_rcu_deref(netlbl_unlhsh)->size - 1);
244 * security/selinux/netif.c:sel_netif_hasfn() as they do pretty much
245 * the same thing */
246 return ifindex & (rcu_dereference(netlbl_unlhsh)->size - 1);
247} 249}
248 250
249/** 251/**
@@ -253,7 +255,8 @@ static u32 netlbl_unlhsh_hash(int ifindex)
253 * Description: 255 * Description:
254 * 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
255 * interface entry which matches @ifindex, otherwise NULL is returned. The 257 * interface entry which matches @ifindex, otherwise NULL is returned. The
256 * 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.
257 * 260 *
258 */ 261 */
259static struct netlbl_unlhsh_iface *netlbl_unlhsh_search_iface(int ifindex) 262static struct netlbl_unlhsh_iface *netlbl_unlhsh_search_iface(int ifindex)
@@ -263,7 +266,7 @@ static struct netlbl_unlhsh_iface *netlbl_unlhsh_search_iface(int ifindex)
263 struct netlbl_unlhsh_iface *iter; 266 struct netlbl_unlhsh_iface *iter;
264 267
265 bkt = netlbl_unlhsh_hash(ifindex); 268 bkt = netlbl_unlhsh_hash(ifindex);
266 bkt_list = &rcu_dereference(netlbl_unlhsh)->tbl[bkt]; 269 bkt_list = &netlbl_unlhsh_rcu_deref(netlbl_unlhsh)->tbl[bkt];
267 list_for_each_entry_rcu(iter, bkt_list, list) 270 list_for_each_entry_rcu(iter, bkt_list, list)
268 if (iter->valid && iter->ifindex == ifindex) 271 if (iter->valid && iter->ifindex == ifindex)
269 return iter; 272 return iter;
@@ -272,33 +275,6 @@ static struct netlbl_unlhsh_iface *netlbl_unlhsh_search_iface(int ifindex)
272} 275}
273 276
274/** 277/**
275 * netlbl_unlhsh_search_iface_def - Search for a matching interface entry
276 * @ifindex: the network interface
277 *
278 * Description:
279 * Searches the unlabeled connection hash table and returns a pointer to the
280 * interface entry which matches @ifindex. If an exact match can not be found
281 * and there is a valid default entry, the default entry is returned, otherwise
282 * NULL is returned. The caller is responsible for calling the
283 * rcu_read_[un]lock() functions.
284 *
285 */
286static struct netlbl_unlhsh_iface *netlbl_unlhsh_search_iface_def(int ifindex)
287{
288 struct netlbl_unlhsh_iface *entry;
289
290 entry = netlbl_unlhsh_search_iface(ifindex);
291 if (entry != NULL)
292 return entry;
293
294 entry = rcu_dereference(netlbl_unlhsh_def);
295 if (entry != NULL && entry->valid)
296 return entry;
297
298 return NULL;
299}
300
301/**
302 * 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
303 * @iface: the associated interface entry 279 * @iface: the associated interface entry
304 * @addr: IPv4 address in network byte order 280 * @addr: IPv4 address in network byte order
@@ -308,8 +284,7 @@ static struct netlbl_unlhsh_iface *netlbl_unlhsh_search_iface_def(int ifindex)
308 * Description: 284 * Description:
309 * 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
310 * interface entry specified by @iface. On success zero is returned, otherwise 286 * interface entry specified by @iface. On success zero is returned, otherwise
311 * a negative value is returned. The caller is responsible for calling the 287 * a negative value is returned.
312 * rcu_read_[un]lock() functions.
313 * 288 *
314 */ 289 */
315static int netlbl_unlhsh_add_addr4(struct netlbl_unlhsh_iface *iface, 290static int netlbl_unlhsh_add_addr4(struct netlbl_unlhsh_iface *iface,
@@ -327,7 +302,6 @@ static int netlbl_unlhsh_add_addr4(struct netlbl_unlhsh_iface *iface,
327 entry->list.addr = addr->s_addr & mask->s_addr; 302 entry->list.addr = addr->s_addr & mask->s_addr;
328 entry->list.mask = mask->s_addr; 303 entry->list.mask = mask->s_addr;
329 entry->list.valid = 1; 304 entry->list.valid = 1;
330 INIT_RCU_HEAD(&entry->rcu);
331 entry->secid = secid; 305 entry->secid = secid;
332 306
333 spin_lock(&netlbl_unlhsh_lock); 307 spin_lock(&netlbl_unlhsh_lock);
@@ -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 */
357static int netlbl_unlhsh_add_addr6(struct netlbl_unlhsh_iface *iface, 330static int netlbl_unlhsh_add_addr6(struct netlbl_unlhsh_iface *iface,
@@ -373,7 +346,6 @@ static int netlbl_unlhsh_add_addr6(struct netlbl_unlhsh_iface *iface,
373 entry->list.addr.s6_addr32[3] &= mask->s6_addr32[3]; 346 entry->list.addr.s6_addr32[3] &= mask->s6_addr32[3];
374 ipv6_addr_copy(&entry->list.mask, mask); 347 ipv6_addr_copy(&entry->list.mask, mask);
375 entry->list.valid = 1; 348 entry->list.valid = 1;
376 INIT_RCU_HEAD(&entry->rcu);
377 entry->secid = secid; 349 entry->secid = secid;
378 350
379 spin_lock(&netlbl_unlhsh_lock); 351 spin_lock(&netlbl_unlhsh_lock);
@@ -393,8 +365,7 @@ static int netlbl_unlhsh_add_addr6(struct netlbl_unlhsh_iface *iface,
393 * Description: 365 * Description:
394 * 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.
395 * 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
396 * is returned. The caller is responsible for calling the rcu_read_[un]lock() 368 * is returned.
397 * functions.
398 * 369 *
399 */ 370 */
400static struct netlbl_unlhsh_iface *netlbl_unlhsh_add_iface(int ifindex) 371static struct netlbl_unlhsh_iface *netlbl_unlhsh_add_iface(int ifindex)
@@ -410,7 +381,6 @@ static struct netlbl_unlhsh_iface *netlbl_unlhsh_add_iface(int ifindex)
410 INIT_LIST_HEAD(&iface->addr4_list); 381 INIT_LIST_HEAD(&iface->addr4_list);
411 INIT_LIST_HEAD(&iface->addr6_list); 382 INIT_LIST_HEAD(&iface->addr6_list);
412 iface->valid = 1; 383 iface->valid = 1;
413 INIT_RCU_HEAD(&iface->rcu);
414 384
415 spin_lock(&netlbl_unlhsh_lock); 385 spin_lock(&netlbl_unlhsh_lock);
416 if (ifindex > 0) { 386 if (ifindex > 0) {
@@ -418,10 +388,10 @@ static struct netlbl_unlhsh_iface *netlbl_unlhsh_add_iface(int ifindex)
418 if (netlbl_unlhsh_search_iface(ifindex) != NULL) 388 if (netlbl_unlhsh_search_iface(ifindex) != NULL)
419 goto add_iface_failure; 389 goto add_iface_failure;
420 list_add_tail_rcu(&iface->list, 390 list_add_tail_rcu(&iface->list,
421 &rcu_dereference(netlbl_unlhsh)->tbl[bkt]); 391 &netlbl_unlhsh_rcu_deref(netlbl_unlhsh)->tbl[bkt]);
422 } else { 392 } else {
423 INIT_LIST_HEAD(&iface->list); 393 INIT_LIST_HEAD(&iface->list);
424 if (rcu_dereference(netlbl_unlhsh_def) != NULL) 394 if (netlbl_unlhsh_rcu_deref(netlbl_unlhsh_def) != NULL)
425 goto add_iface_failure; 395 goto add_iface_failure;
426 rcu_assign_pointer(netlbl_unlhsh_def, iface); 396 rcu_assign_pointer(netlbl_unlhsh_def, iface);
427 } 397 }
@@ -472,13 +442,12 @@ int netlbl_unlhsh_add(struct net *net,
472 442
473 rcu_read_lock(); 443 rcu_read_lock();
474 if (dev_name != NULL) { 444 if (dev_name != NULL) {
475 dev = dev_get_by_name(net, dev_name); 445 dev = dev_get_by_name_rcu(net, dev_name);
476 if (dev == NULL) { 446 if (dev == NULL) {
477 ret_val = -ENODEV; 447 ret_val = -ENODEV;
478 goto unlhsh_add_return; 448 goto unlhsh_add_return;
479 } 449 }
480 ifindex = dev->ifindex; 450 ifindex = dev->ifindex;
481 dev_put(dev);
482 iface = netlbl_unlhsh_search_iface(ifindex); 451 iface = netlbl_unlhsh_search_iface(ifindex);
483 } else { 452 } else {
484 ifindex = 0; 453 ifindex = 0;
@@ -552,8 +521,7 @@ unlhsh_add_return:
552 * 521 *
553 * Description: 522 * Description:
554 * Remove an IP address entry from the unlabeled connection hash table. 523 * Remove an IP address entry from the unlabeled connection hash table.
555 * Returns zero on success, negative values on failure. The caller is 524 * Returns zero on success, negative values on failure.
556 * responsible for calling the rcu_read_[un]lock() functions.
557 * 525 *
558 */ 526 */
559static int netlbl_unlhsh_remove_addr4(struct net *net, 527static int netlbl_unlhsh_remove_addr4(struct net *net,
@@ -615,8 +583,7 @@ static int netlbl_unlhsh_remove_addr4(struct net *net,
615 * 583 *
616 * Description: 584 * Description:
617 * Remove an IP address entry from the unlabeled connection hash table. 585 * Remove an IP address entry from the unlabeled connection hash table.
618 * Returns zero on success, negative values on failure. The caller is 586 * Returns zero on success, negative values on failure.
619 * responsible for calling the rcu_read_[un]lock() functions.
620 * 587 *
621 */ 588 */
622static int netlbl_unlhsh_remove_addr6(struct net *net, 589static int netlbl_unlhsh_remove_addr6(struct net *net,
@@ -737,13 +704,12 @@ int netlbl_unlhsh_remove(struct net *net,
737 704
738 rcu_read_lock(); 705 rcu_read_lock();
739 if (dev_name != NULL) { 706 if (dev_name != NULL) {
740 dev = dev_get_by_name(net, dev_name); 707 dev = dev_get_by_name_rcu(net, dev_name);
741 if (dev == NULL) { 708 if (dev == NULL) {
742 ret_val = -ENODEV; 709 ret_val = -ENODEV;
743 goto unlhsh_remove_return; 710 goto unlhsh_remove_return;
744 } 711 }
745 iface = netlbl_unlhsh_search_iface(dev->ifindex); 712 iface = netlbl_unlhsh_search_iface(dev->ifindex);
746 dev_put(dev);
747 } else 713 } else
748 iface = rcu_dereference(netlbl_unlhsh_def); 714 iface = rcu_dereference(netlbl_unlhsh_def);
749 if (iface == NULL) { 715 if (iface == NULL) {
@@ -1552,8 +1518,10 @@ int netlbl_unlabel_getattr(const struct sk_buff *skb,
1552 struct netlbl_unlhsh_iface *iface; 1518 struct netlbl_unlhsh_iface *iface;
1553 1519
1554 rcu_read_lock(); 1520 rcu_read_lock();
1555 iface = netlbl_unlhsh_search_iface_def(skb->iif); 1521 iface = netlbl_unlhsh_search_iface(skb->skb_iif);
1556 if (iface == NULL) 1522 if (iface == NULL)
1523 iface = rcu_dereference(netlbl_unlhsh_def);
1524 if (iface == NULL || !iface->valid)
1557 goto unlabel_getattr_nolabel; 1525 goto unlabel_getattr_nolabel;
1558 switch (family) { 1526 switch (family) {
1559 case PF_INET: { 1527 case PF_INET: {