aboutsummaryrefslogtreecommitdiffstats
path: root/net/netlabel/netlabel_unlabeled.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/netlabel/netlabel_unlabeled.c')
-rw-r--r--net/netlabel/netlabel_unlabeled.c66
1 files changed, 19 insertions, 47 deletions
diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c
index 852d9d7976b9..3b4fde7622a3 100644
--- a/net/netlabel/netlabel_unlabeled.c
+++ b/net/netlabel/netlabel_unlabeled.c
@@ -114,6 +114,9 @@ struct netlbl_unlhsh_walk_arg {
114/* updates should be so rare that having one spinlock for the entire 114/* updates should be so rare that having one spinlock for the entire
115 * hash table should be okay */ 115 * hash table should be okay */
116static DEFINE_SPINLOCK(netlbl_unlhsh_lock); 116static DEFINE_SPINLOCK(netlbl_unlhsh_lock);
117#define netlbl_unlhsh_rcu_deref(p) \
118 rcu_dereference_check(p, rcu_read_lock_held() || \
119 lockdep_is_held(&netlbl_unlhsh_lock))
117static struct netlbl_unlhsh_tbl *netlbl_unlhsh = NULL; 120static struct netlbl_unlhsh_tbl *netlbl_unlhsh = NULL;
118static struct netlbl_unlhsh_iface *netlbl_unlhsh_def = NULL; 121static struct netlbl_unlhsh_iface *netlbl_unlhsh_def = NULL;
119 122
@@ -235,15 +238,13 @@ static void netlbl_unlhsh_free_iface(struct rcu_head *entry)
235 * Description: 238 * Description:
236 * This is the hashing function for the unlabeled hash table, it returns the 239 * 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 240 * bucket number for the given device/interface. The caller is responsible for
238 * calling the rcu_read_[un]lock() functions. 241 * ensuring that the hash table is protected with either a RCU read lock or
242 * the hash table lock.
239 * 243 *
240 */ 244 */
241static u32 netlbl_unlhsh_hash(int ifindex) 245static u32 netlbl_unlhsh_hash(int ifindex)
242{ 246{
243 /* this is taken _almost_ directly from 247 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} 248}
248 249
249/** 250/**
@@ -253,7 +254,8 @@ static u32 netlbl_unlhsh_hash(int ifindex)
253 * Description: 254 * Description:
254 * Searches the unlabeled connection hash table and returns a pointer to the 255 * Searches the unlabeled connection hash table and returns a pointer to the
255 * interface entry which matches @ifindex, otherwise NULL is returned. The 256 * interface entry which matches @ifindex, otherwise NULL is returned. The
256 * caller is responsible for calling the rcu_read_[un]lock() functions. 257 * caller is responsible for ensuring that the hash table is protected with
258 * either a RCU read lock or the hash table lock.
257 * 259 *
258 */ 260 */
259static struct netlbl_unlhsh_iface *netlbl_unlhsh_search_iface(int ifindex) 261static struct netlbl_unlhsh_iface *netlbl_unlhsh_search_iface(int ifindex)
@@ -263,7 +265,7 @@ static struct netlbl_unlhsh_iface *netlbl_unlhsh_search_iface(int ifindex)
263 struct netlbl_unlhsh_iface *iter; 265 struct netlbl_unlhsh_iface *iter;
264 266
265 bkt = netlbl_unlhsh_hash(ifindex); 267 bkt = netlbl_unlhsh_hash(ifindex);
266 bkt_list = &rcu_dereference(netlbl_unlhsh)->tbl[bkt]; 268 bkt_list = &netlbl_unlhsh_rcu_deref(netlbl_unlhsh)->tbl[bkt];
267 list_for_each_entry_rcu(iter, bkt_list, list) 269 list_for_each_entry_rcu(iter, bkt_list, list)
268 if (iter->valid && iter->ifindex == ifindex) 270 if (iter->valid && iter->ifindex == ifindex)
269 return iter; 271 return iter;
@@ -272,33 +274,6 @@ static struct netlbl_unlhsh_iface *netlbl_unlhsh_search_iface(int ifindex)
272} 274}
273 275
274/** 276/**
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 277 * netlbl_unlhsh_add_addr4 - Add a new IPv4 address entry to the hash table
303 * @iface: the associated interface entry 278 * @iface: the associated interface entry
304 * @addr: IPv4 address in network byte order 279 * @addr: IPv4 address in network byte order
@@ -308,8 +283,7 @@ static struct netlbl_unlhsh_iface *netlbl_unlhsh_search_iface_def(int ifindex)
308 * Description: 283 * Description:
309 * Add a new address entry into the unlabeled connection hash table using the 284 * 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 285 * interface entry specified by @iface. On success zero is returned, otherwise
311 * a negative value is returned. The caller is responsible for calling the 286 * a negative value is returned.
312 * rcu_read_[un]lock() functions.
313 * 287 *
314 */ 288 */
315static int netlbl_unlhsh_add_addr4(struct netlbl_unlhsh_iface *iface, 289static int netlbl_unlhsh_add_addr4(struct netlbl_unlhsh_iface *iface,
@@ -349,8 +323,7 @@ static int netlbl_unlhsh_add_addr4(struct netlbl_unlhsh_iface *iface,
349 * Description: 323 * Description:
350 * Add a new address entry into the unlabeled connection hash table using the 324 * Add a new address entry into the unlabeled connection hash table using the
351 * interface entry specified by @iface. On success zero is returned, otherwise 325 * interface entry specified by @iface. On success zero is returned, otherwise
352 * a negative value is returned. The caller is responsible for calling the 326 * a negative value is returned.
353 * rcu_read_[un]lock() functions.
354 * 327 *
355 */ 328 */
356static int netlbl_unlhsh_add_addr6(struct netlbl_unlhsh_iface *iface, 329static int netlbl_unlhsh_add_addr6(struct netlbl_unlhsh_iface *iface,
@@ -391,8 +364,7 @@ static int netlbl_unlhsh_add_addr6(struct netlbl_unlhsh_iface *iface,
391 * Description: 364 * Description:
392 * Add a new, empty, interface entry into the unlabeled connection hash table. 365 * Add a new, empty, interface entry into the unlabeled connection hash table.
393 * On success a pointer to the new interface entry is returned, on failure NULL 366 * On success a pointer to the new interface entry is returned, on failure NULL
394 * is returned. The caller is responsible for calling the rcu_read_[un]lock() 367 * is returned.
395 * functions.
396 * 368 *
397 */ 369 */
398static struct netlbl_unlhsh_iface *netlbl_unlhsh_add_iface(int ifindex) 370static struct netlbl_unlhsh_iface *netlbl_unlhsh_add_iface(int ifindex)
@@ -415,10 +387,10 @@ static struct netlbl_unlhsh_iface *netlbl_unlhsh_add_iface(int ifindex)
415 if (netlbl_unlhsh_search_iface(ifindex) != NULL) 387 if (netlbl_unlhsh_search_iface(ifindex) != NULL)
416 goto add_iface_failure; 388 goto add_iface_failure;
417 list_add_tail_rcu(&iface->list, 389 list_add_tail_rcu(&iface->list,
418 &rcu_dereference(netlbl_unlhsh)->tbl[bkt]); 390 &netlbl_unlhsh_rcu_deref(netlbl_unlhsh)->tbl[bkt]);
419 } else { 391 } else {
420 INIT_LIST_HEAD(&iface->list); 392 INIT_LIST_HEAD(&iface->list);
421 if (rcu_dereference(netlbl_unlhsh_def) != NULL) 393 if (netlbl_unlhsh_rcu_deref(netlbl_unlhsh_def) != NULL)
422 goto add_iface_failure; 394 goto add_iface_failure;
423 rcu_assign_pointer(netlbl_unlhsh_def, iface); 395 rcu_assign_pointer(netlbl_unlhsh_def, iface);
424 } 396 }
@@ -548,8 +520,7 @@ unlhsh_add_return:
548 * 520 *
549 * Description: 521 * Description:
550 * Remove an IP address entry from the unlabeled connection hash table. 522 * Remove an IP address entry from the unlabeled connection hash table.
551 * Returns zero on success, negative values on failure. The caller is 523 * Returns zero on success, negative values on failure.
552 * responsible for calling the rcu_read_[un]lock() functions.
553 * 524 *
554 */ 525 */
555static int netlbl_unlhsh_remove_addr4(struct net *net, 526static int netlbl_unlhsh_remove_addr4(struct net *net,
@@ -611,8 +582,7 @@ static int netlbl_unlhsh_remove_addr4(struct net *net,
611 * 582 *
612 * Description: 583 * Description:
613 * Remove an IP address entry from the unlabeled connection hash table. 584 * Remove an IP address entry from the unlabeled connection hash table.
614 * Returns zero on success, negative values on failure. The caller is 585 * Returns zero on success, negative values on failure.
615 * responsible for calling the rcu_read_[un]lock() functions.
616 * 586 *
617 */ 587 */
618static int netlbl_unlhsh_remove_addr6(struct net *net, 588static int netlbl_unlhsh_remove_addr6(struct net *net,
@@ -1547,8 +1517,10 @@ int netlbl_unlabel_getattr(const struct sk_buff *skb,
1547 struct netlbl_unlhsh_iface *iface; 1517 struct netlbl_unlhsh_iface *iface;
1548 1518
1549 rcu_read_lock(); 1519 rcu_read_lock();
1550 iface = netlbl_unlhsh_search_iface_def(skb->skb_iif); 1520 iface = netlbl_unlhsh_search_iface(skb->skb_iif);
1551 if (iface == NULL) 1521 if (iface == NULL)
1522 iface = rcu_dereference(netlbl_unlhsh_def);
1523 if (iface == NULL || !iface->valid)
1552 goto unlabel_getattr_nolabel; 1524 goto unlabel_getattr_nolabel;
1553 switch (family) { 1525 switch (family) {
1554 case PF_INET: { 1526 case PF_INET: {