aboutsummaryrefslogtreecommitdiffstats
path: root/net/netlabel/netlabel_unlabeled.c
diff options
context:
space:
mode:
authorArjan van de Ven <arjan@linux.intel.com>2008-10-17 12:20:26 -0400
committerArjan van de Ven <arjan@linux.intel.com>2008-10-17 12:20:26 -0400
commit651dab4264e4ba0e563f5ff56f748127246e9065 (patch)
tree016630974bdcb00fe529b673f96d389e0fd6dc94 /net/netlabel/netlabel_unlabeled.c
parent40b8606253552109815786e5d4b0de98782d31f5 (diff)
parent2e532d68a2b3e2aa6b19731501222069735c741c (diff)
Merge commit 'linus/master' into merge-linus
Conflicts: arch/x86/kvm/i8254.c
Diffstat (limited to 'net/netlabel/netlabel_unlabeled.c')
-rw-r--r--net/netlabel/netlabel_unlabeled.c456
1 files changed, 153 insertions, 303 deletions
diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c
index 921c118ead89..e8a5c32b0f10 100644
--- a/net/netlabel/netlabel_unlabeled.c
+++ b/net/netlabel/netlabel_unlabeled.c
@@ -10,7 +10,7 @@
10 */ 10 */
11 11
12/* 12/*
13 * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 - 2007 13 * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 - 2008
14 * 14 *
15 * This program is free software; you can redistribute it and/or modify 15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by 16 * it under the terms of the GNU General Public License as published by
@@ -54,6 +54,7 @@
54#include <asm/atomic.h> 54#include <asm/atomic.h>
55 55
56#include "netlabel_user.h" 56#include "netlabel_user.h"
57#include "netlabel_addrlist.h"
57#include "netlabel_domainhash.h" 58#include "netlabel_domainhash.h"
58#include "netlabel_unlabeled.h" 59#include "netlabel_unlabeled.h"
59#include "netlabel_mgmt.h" 60#include "netlabel_mgmt.h"
@@ -76,22 +77,20 @@ struct netlbl_unlhsh_tbl {
76 struct list_head *tbl; 77 struct list_head *tbl;
77 u32 size; 78 u32 size;
78}; 79};
80#define netlbl_unlhsh_addr4_entry(iter) \
81 container_of(iter, struct netlbl_unlhsh_addr4, list)
79struct netlbl_unlhsh_addr4 { 82struct netlbl_unlhsh_addr4 {
80 __be32 addr;
81 __be32 mask;
82 u32 secid; 83 u32 secid;
83 84
84 u32 valid; 85 struct netlbl_af4list list;
85 struct list_head list;
86 struct rcu_head rcu; 86 struct rcu_head rcu;
87}; 87};
88#define netlbl_unlhsh_addr6_entry(iter) \
89 container_of(iter, struct netlbl_unlhsh_addr6, list)
88struct netlbl_unlhsh_addr6 { 90struct netlbl_unlhsh_addr6 {
89 struct in6_addr addr;
90 struct in6_addr mask;
91 u32 secid; 91 u32 secid;
92 92
93 u32 valid; 93 struct netlbl_af6list list;
94 struct list_head list;
95 struct rcu_head rcu; 94 struct rcu_head rcu;
96}; 95};
97struct netlbl_unlhsh_iface { 96struct netlbl_unlhsh_iface {
@@ -147,76 +146,6 @@ static const struct nla_policy netlbl_unlabel_genl_policy[NLBL_UNLABEL_A_MAX + 1
147}; 146};
148 147
149/* 148/*
150 * Audit Helper Functions
151 */
152
153/**
154 * netlbl_unlabel_audit_addr4 - Audit an IPv4 address
155 * @audit_buf: audit buffer
156 * @dev: network interface
157 * @addr: IP address
158 * @mask: IP address mask
159 *
160 * Description:
161 * Write the IPv4 address and address mask, if necessary, to @audit_buf.
162 *
163 */
164static void netlbl_unlabel_audit_addr4(struct audit_buffer *audit_buf,
165 const char *dev,
166 __be32 addr, __be32 mask)
167{
168 u32 mask_val = ntohl(mask);
169
170 if (dev != NULL)
171 audit_log_format(audit_buf, " netif=%s", dev);
172 audit_log_format(audit_buf, " src=" NIPQUAD_FMT, NIPQUAD(addr));
173 if (mask_val != 0xffffffff) {
174 u32 mask_len = 0;
175 while (mask_val > 0) {
176 mask_val <<= 1;
177 mask_len++;
178 }
179 audit_log_format(audit_buf, " src_prefixlen=%d", mask_len);
180 }
181}
182
183#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
184/**
185 * netlbl_unlabel_audit_addr6 - Audit an IPv6 address
186 * @audit_buf: audit buffer
187 * @dev: network interface
188 * @addr: IP address
189 * @mask: IP address mask
190 *
191 * Description:
192 * Write the IPv6 address and address mask, if necessary, to @audit_buf.
193 *
194 */
195static void netlbl_unlabel_audit_addr6(struct audit_buffer *audit_buf,
196 const char *dev,
197 const struct in6_addr *addr,
198 const struct in6_addr *mask)
199{
200 if (dev != NULL)
201 audit_log_format(audit_buf, " netif=%s", dev);
202 audit_log_format(audit_buf, " src=" NIP6_FMT, NIP6(*addr));
203 if (ntohl(mask->s6_addr32[3]) != 0xffffffff) {
204 u32 mask_len = 0;
205 u32 mask_val;
206 int iter = -1;
207 while (ntohl(mask->s6_addr32[++iter]) == 0xffffffff)
208 mask_len += 32;
209 mask_val = ntohl(mask->s6_addr32[iter]);
210 while (mask_val > 0) {
211 mask_val <<= 1;
212 mask_len++;
213 }
214 audit_log_format(audit_buf, " src_prefixlen=%d", mask_len);
215 }
216}
217#endif /* IPv6 */
218
219/*
220 * Unlabeled Connection Hash Table Functions 149 * Unlabeled Connection Hash Table Functions
221 */ 150 */
222 151
@@ -274,26 +203,28 @@ static void netlbl_unlhsh_free_addr6(struct rcu_head *entry)
274static void netlbl_unlhsh_free_iface(struct rcu_head *entry) 203static void netlbl_unlhsh_free_iface(struct rcu_head *entry)
275{ 204{
276 struct netlbl_unlhsh_iface *iface; 205 struct netlbl_unlhsh_iface *iface;
277 struct netlbl_unlhsh_addr4 *iter4; 206 struct netlbl_af4list *iter4;
278 struct netlbl_unlhsh_addr4 *tmp4; 207 struct netlbl_af4list *tmp4;
279 struct netlbl_unlhsh_addr6 *iter6; 208#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
280 struct netlbl_unlhsh_addr6 *tmp6; 209 struct netlbl_af6list *iter6;
210 struct netlbl_af6list *tmp6;
211#endif /* IPv6 */
281 212
282 iface = container_of(entry, struct netlbl_unlhsh_iface, rcu); 213 iface = container_of(entry, struct netlbl_unlhsh_iface, rcu);
283 214
284 /* no need for locks here since we are the only one with access to this 215 /* no need for locks here since we are the only one with access to this
285 * structure */ 216 * structure */
286 217
287 list_for_each_entry_safe(iter4, tmp4, &iface->addr4_list, list) 218 netlbl_af4list_foreach_safe(iter4, tmp4, &iface->addr4_list) {
288 if (iter4->valid) { 219 netlbl_af4list_remove_entry(iter4);
289 list_del_rcu(&iter4->list); 220 kfree(netlbl_unlhsh_addr4_entry(iter4));
290 kfree(iter4); 221 }
291 } 222#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
292 list_for_each_entry_safe(iter6, tmp6, &iface->addr6_list, list) 223 netlbl_af6list_foreach_safe(iter6, tmp6, &iface->addr6_list) {
293 if (iter6->valid) { 224 netlbl_af6list_remove_entry(iter6);
294 list_del_rcu(&iter6->list); 225 kfree(netlbl_unlhsh_addr6_entry(iter6));
295 kfree(iter6); 226 }
296 } 227#endif /* IPv6 */
297 kfree(iface); 228 kfree(iface);
298} 229}
299 230
@@ -316,59 +247,6 @@ static u32 netlbl_unlhsh_hash(int ifindex)
316} 247}
317 248
318/** 249/**
319 * netlbl_unlhsh_search_addr4 - Search for a matching IPv4 address entry
320 * @addr: IPv4 address
321 * @iface: the network interface entry
322 *
323 * Description:
324 * Searches the IPv4 address list of the network interface specified by @iface.
325 * If a matching address entry is found it is returned, otherwise NULL is
326 * returned. The caller is responsible for calling the rcu_read_[un]lock()
327 * functions.
328 *
329 */
330static struct netlbl_unlhsh_addr4 *netlbl_unlhsh_search_addr4(
331 __be32 addr,
332 const struct netlbl_unlhsh_iface *iface)
333{
334 struct netlbl_unlhsh_addr4 *iter;
335
336 list_for_each_entry_rcu(iter, &iface->addr4_list, list)
337 if (iter->valid && (addr & iter->mask) == iter->addr)
338 return iter;
339
340 return NULL;
341}
342
343#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
344/**
345 * netlbl_unlhsh_search_addr6 - Search for a matching IPv6 address entry
346 * @addr: IPv6 address
347 * @iface: the network interface entry
348 *
349 * Description:
350 * Searches the IPv6 address list of the network interface specified by @iface.
351 * If a matching address entry is found it is returned, otherwise NULL is
352 * returned. The caller is responsible for calling the rcu_read_[un]lock()
353 * functions.
354 *
355 */
356static struct netlbl_unlhsh_addr6 *netlbl_unlhsh_search_addr6(
357 const struct in6_addr *addr,
358 const struct netlbl_unlhsh_iface *iface)
359{
360 struct netlbl_unlhsh_addr6 *iter;
361
362 list_for_each_entry_rcu(iter, &iface->addr6_list, list)
363 if (iter->valid &&
364 ipv6_masked_addr_cmp(&iter->addr, &iter->mask, addr) == 0)
365 return iter;
366
367 return NULL;
368}
369#endif /* IPv6 */
370
371/**
372 * netlbl_unlhsh_search_iface - Search for a matching interface entry 250 * netlbl_unlhsh_search_iface - Search for a matching interface entry
373 * @ifindex: the network interface 251 * @ifindex: the network interface
374 * 252 *
@@ -381,12 +259,12 @@ static struct netlbl_unlhsh_addr6 *netlbl_unlhsh_search_addr6(
381static struct netlbl_unlhsh_iface *netlbl_unlhsh_search_iface(int ifindex) 259static struct netlbl_unlhsh_iface *netlbl_unlhsh_search_iface(int ifindex)
382{ 260{
383 u32 bkt; 261 u32 bkt;
262 struct list_head *bkt_list;
384 struct netlbl_unlhsh_iface *iter; 263 struct netlbl_unlhsh_iface *iter;
385 264
386 bkt = netlbl_unlhsh_hash(ifindex); 265 bkt = netlbl_unlhsh_hash(ifindex);
387 list_for_each_entry_rcu(iter, 266 bkt_list = &rcu_dereference(netlbl_unlhsh)->tbl[bkt];
388 &rcu_dereference(netlbl_unlhsh)->tbl[bkt], 267 list_for_each_entry_rcu(iter, bkt_list, list)
389 list)
390 if (iter->valid && iter->ifindex == ifindex) 268 if (iter->valid && iter->ifindex == ifindex)
391 return iter; 269 return iter;
392 270
@@ -439,43 +317,26 @@ static int netlbl_unlhsh_add_addr4(struct netlbl_unlhsh_iface *iface,
439 const struct in_addr *mask, 317 const struct in_addr *mask,
440 u32 secid) 318 u32 secid)
441{ 319{
320 int ret_val;
442 struct netlbl_unlhsh_addr4 *entry; 321 struct netlbl_unlhsh_addr4 *entry;
443 struct netlbl_unlhsh_addr4 *iter;
444 322
445 entry = kzalloc(sizeof(*entry), GFP_ATOMIC); 323 entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
446 if (entry == NULL) 324 if (entry == NULL)
447 return -ENOMEM; 325 return -ENOMEM;
448 326
449 entry->addr = addr->s_addr & mask->s_addr; 327 entry->list.addr = addr->s_addr & mask->s_addr;
450 entry->mask = mask->s_addr; 328 entry->list.mask = mask->s_addr;
451 entry->secid = secid; 329 entry->list.valid = 1;
452 entry->valid = 1;
453 INIT_RCU_HEAD(&entry->rcu); 330 INIT_RCU_HEAD(&entry->rcu);
331 entry->secid = secid;
454 332
455 spin_lock(&netlbl_unlhsh_lock); 333 spin_lock(&netlbl_unlhsh_lock);
456 iter = netlbl_unlhsh_search_addr4(entry->addr, iface); 334 ret_val = netlbl_af4list_add(&entry->list, &iface->addr4_list);
457 if (iter != NULL &&
458 iter->addr == addr->s_addr && iter->mask == mask->s_addr) {
459 spin_unlock(&netlbl_unlhsh_lock);
460 kfree(entry);
461 return -EEXIST;
462 }
463 /* in order to speed up address searches through the list (the common
464 * case) we need to keep the list in order based on the size of the
465 * address mask such that the entry with the widest mask (smallest
466 * numerical value) appears first in the list */
467 list_for_each_entry_rcu(iter, &iface->addr4_list, list)
468 if (iter->valid &&
469 ntohl(entry->mask) > ntohl(iter->mask)) {
470 __list_add_rcu(&entry->list,
471 iter->list.prev,
472 &iter->list);
473 spin_unlock(&netlbl_unlhsh_lock);
474 return 0;
475 }
476 list_add_tail_rcu(&entry->list, &iface->addr4_list);
477 spin_unlock(&netlbl_unlhsh_lock); 335 spin_unlock(&netlbl_unlhsh_lock);
478 return 0; 336
337 if (ret_val != 0)
338 kfree(entry);
339 return ret_val;
479} 340}
480 341
481#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 342#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
@@ -498,47 +359,29 @@ static int netlbl_unlhsh_add_addr6(struct netlbl_unlhsh_iface *iface,
498 const struct in6_addr *mask, 359 const struct in6_addr *mask,
499 u32 secid) 360 u32 secid)
500{ 361{
362 int ret_val;
501 struct netlbl_unlhsh_addr6 *entry; 363 struct netlbl_unlhsh_addr6 *entry;
502 struct netlbl_unlhsh_addr6 *iter;
503 364
504 entry = kzalloc(sizeof(*entry), GFP_ATOMIC); 365 entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
505 if (entry == NULL) 366 if (entry == NULL)
506 return -ENOMEM; 367 return -ENOMEM;
507 368
508 ipv6_addr_copy(&entry->addr, addr); 369 ipv6_addr_copy(&entry->list.addr, addr);
509 entry->addr.s6_addr32[0] &= mask->s6_addr32[0]; 370 entry->list.addr.s6_addr32[0] &= mask->s6_addr32[0];
510 entry->addr.s6_addr32[1] &= mask->s6_addr32[1]; 371 entry->list.addr.s6_addr32[1] &= mask->s6_addr32[1];
511 entry->addr.s6_addr32[2] &= mask->s6_addr32[2]; 372 entry->list.addr.s6_addr32[2] &= mask->s6_addr32[2];
512 entry->addr.s6_addr32[3] &= mask->s6_addr32[3]; 373 entry->list.addr.s6_addr32[3] &= mask->s6_addr32[3];
513 ipv6_addr_copy(&entry->mask, mask); 374 ipv6_addr_copy(&entry->list.mask, mask);
514 entry->secid = secid; 375 entry->list.valid = 1;
515 entry->valid = 1;
516 INIT_RCU_HEAD(&entry->rcu); 376 INIT_RCU_HEAD(&entry->rcu);
377 entry->secid = secid;
517 378
518 spin_lock(&netlbl_unlhsh_lock); 379 spin_lock(&netlbl_unlhsh_lock);
519 iter = netlbl_unlhsh_search_addr6(&entry->addr, iface); 380 ret_val = netlbl_af6list_add(&entry->list, &iface->addr6_list);
520 if (iter != NULL &&
521 (ipv6_addr_equal(&iter->addr, addr) &&
522 ipv6_addr_equal(&iter->mask, mask))) {
523 spin_unlock(&netlbl_unlhsh_lock);
524 kfree(entry);
525 return -EEXIST;
526 }
527 /* in order to speed up address searches through the list (the common
528 * case) we need to keep the list in order based on the size of the
529 * address mask such that the entry with the widest mask (smallest
530 * numerical value) appears first in the list */
531 list_for_each_entry_rcu(iter, &iface->addr6_list, list)
532 if (iter->valid &&
533 ipv6_addr_cmp(&entry->mask, &iter->mask) > 0) {
534 __list_add_rcu(&entry->list,
535 iter->list.prev,
536 &iter->list);
537 spin_unlock(&netlbl_unlhsh_lock);
538 return 0;
539 }
540 list_add_tail_rcu(&entry->list, &iface->addr6_list);
541 spin_unlock(&netlbl_unlhsh_lock); 381 spin_unlock(&netlbl_unlhsh_lock);
382
383 if (ret_val != 0)
384 kfree(entry);
542 return 0; 385 return 0;
543} 386}
544#endif /* IPv6 */ 387#endif /* IPv6 */
@@ -658,10 +501,10 @@ static int netlbl_unlhsh_add(struct net *net,
658 mask4 = (struct in_addr *)mask; 501 mask4 = (struct in_addr *)mask;
659 ret_val = netlbl_unlhsh_add_addr4(iface, addr4, mask4, secid); 502 ret_val = netlbl_unlhsh_add_addr4(iface, addr4, mask4, secid);
660 if (audit_buf != NULL) 503 if (audit_buf != NULL)
661 netlbl_unlabel_audit_addr4(audit_buf, 504 netlbl_af4list_audit_addr(audit_buf, 1,
662 dev_name, 505 dev_name,
663 addr4->s_addr, 506 addr4->s_addr,
664 mask4->s_addr); 507 mask4->s_addr);
665 break; 508 break;
666 } 509 }
667#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 510#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
@@ -672,9 +515,9 @@ static int netlbl_unlhsh_add(struct net *net,
672 mask6 = (struct in6_addr *)mask; 515 mask6 = (struct in6_addr *)mask;
673 ret_val = netlbl_unlhsh_add_addr6(iface, addr6, mask6, secid); 516 ret_val = netlbl_unlhsh_add_addr6(iface, addr6, mask6, secid);
674 if (audit_buf != NULL) 517 if (audit_buf != NULL)
675 netlbl_unlabel_audit_addr6(audit_buf, 518 netlbl_af6list_audit_addr(audit_buf, 1,
676 dev_name, 519 dev_name,
677 addr6, mask6); 520 addr6, mask6);
678 break; 521 break;
679 } 522 }
680#endif /* IPv6 */ 523#endif /* IPv6 */
@@ -719,35 +562,34 @@ static int netlbl_unlhsh_remove_addr4(struct net *net,
719 const struct in_addr *mask, 562 const struct in_addr *mask,
720 struct netlbl_audit *audit_info) 563 struct netlbl_audit *audit_info)
721{ 564{
722 int ret_val = -ENOENT; 565 int ret_val = 0;
566 struct netlbl_af4list *list_entry;
723 struct netlbl_unlhsh_addr4 *entry; 567 struct netlbl_unlhsh_addr4 *entry;
724 struct audit_buffer *audit_buf = NULL; 568 struct audit_buffer *audit_buf;
725 struct net_device *dev; 569 struct net_device *dev;
726 char *secctx = NULL; 570 char *secctx;
727 u32 secctx_len; 571 u32 secctx_len;
728 572
729 spin_lock(&netlbl_unlhsh_lock); 573 spin_lock(&netlbl_unlhsh_lock);
730 entry = netlbl_unlhsh_search_addr4(addr->s_addr, iface); 574 list_entry = netlbl_af4list_remove(addr->s_addr, mask->s_addr,
731 if (entry != NULL && 575 &iface->addr4_list);
732 entry->addr == addr->s_addr && entry->mask == mask->s_addr) {
733 entry->valid = 0;
734 list_del_rcu(&entry->list);
735 ret_val = 0;
736 }
737 spin_unlock(&netlbl_unlhsh_lock); 576 spin_unlock(&netlbl_unlhsh_lock);
577 if (list_entry == NULL)
578 ret_val = -ENOENT;
579 entry = netlbl_unlhsh_addr4_entry(list_entry);
738 580
739 audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_STCDEL, 581 audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_STCDEL,
740 audit_info); 582 audit_info);
741 if (audit_buf != NULL) { 583 if (audit_buf != NULL) {
742 dev = dev_get_by_index(net, iface->ifindex); 584 dev = dev_get_by_index(net, iface->ifindex);
743 netlbl_unlabel_audit_addr4(audit_buf, 585 netlbl_af4list_audit_addr(audit_buf, 1,
744 (dev != NULL ? dev->name : NULL), 586 (dev != NULL ? dev->name : NULL),
745 entry->addr, entry->mask); 587 addr->s_addr, mask->s_addr);
746 if (dev != NULL) 588 if (dev != NULL)
747 dev_put(dev); 589 dev_put(dev);
748 if (security_secid_to_secctx(entry->secid, 590 if (entry && security_secid_to_secctx(entry->secid,
749 &secctx, 591 &secctx,
750 &secctx_len) == 0) { 592 &secctx_len) == 0) {
751 audit_log_format(audit_buf, " sec_obj=%s", secctx); 593 audit_log_format(audit_buf, " sec_obj=%s", secctx);
752 security_release_secctx(secctx, secctx_len); 594 security_release_secctx(secctx, secctx_len);
753 } 595 }
@@ -781,36 +623,33 @@ static int netlbl_unlhsh_remove_addr6(struct net *net,
781 const struct in6_addr *mask, 623 const struct in6_addr *mask,
782 struct netlbl_audit *audit_info) 624 struct netlbl_audit *audit_info)
783{ 625{
784 int ret_val = -ENOENT; 626 int ret_val = 0;
627 struct netlbl_af6list *list_entry;
785 struct netlbl_unlhsh_addr6 *entry; 628 struct netlbl_unlhsh_addr6 *entry;
786 struct audit_buffer *audit_buf = NULL; 629 struct audit_buffer *audit_buf;
787 struct net_device *dev; 630 struct net_device *dev;
788 char *secctx = NULL; 631 char *secctx;
789 u32 secctx_len; 632 u32 secctx_len;
790 633
791 spin_lock(&netlbl_unlhsh_lock); 634 spin_lock(&netlbl_unlhsh_lock);
792 entry = netlbl_unlhsh_search_addr6(addr, iface); 635 list_entry = netlbl_af6list_remove(addr, mask, &iface->addr6_list);
793 if (entry != NULL &&
794 (ipv6_addr_equal(&entry->addr, addr) &&
795 ipv6_addr_equal(&entry->mask, mask))) {
796 entry->valid = 0;
797 list_del_rcu(&entry->list);
798 ret_val = 0;
799 }
800 spin_unlock(&netlbl_unlhsh_lock); 636 spin_unlock(&netlbl_unlhsh_lock);
637 if (list_entry == NULL)
638 ret_val = -ENOENT;
639 entry = netlbl_unlhsh_addr6_entry(list_entry);
801 640
802 audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_STCDEL, 641 audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_STCDEL,
803 audit_info); 642 audit_info);
804 if (audit_buf != NULL) { 643 if (audit_buf != NULL) {
805 dev = dev_get_by_index(net, iface->ifindex); 644 dev = dev_get_by_index(net, iface->ifindex);
806 netlbl_unlabel_audit_addr6(audit_buf, 645 netlbl_af6list_audit_addr(audit_buf, 1,
807 (dev != NULL ? dev->name : NULL), 646 (dev != NULL ? dev->name : NULL),
808 addr, mask); 647 addr, mask);
809 if (dev != NULL) 648 if (dev != NULL)
810 dev_put(dev); 649 dev_put(dev);
811 if (security_secid_to_secctx(entry->secid, 650 if (entry && security_secid_to_secctx(entry->secid,
812 &secctx, 651 &secctx,
813 &secctx_len) == 0) { 652 &secctx_len) == 0) {
814 audit_log_format(audit_buf, " sec_obj=%s", secctx); 653 audit_log_format(audit_buf, " sec_obj=%s", secctx);
815 security_release_secctx(secctx, secctx_len); 654 security_release_secctx(secctx, secctx_len);
816 } 655 }
@@ -836,16 +675,18 @@ static int netlbl_unlhsh_remove_addr6(struct net *net,
836 */ 675 */
837static void netlbl_unlhsh_condremove_iface(struct netlbl_unlhsh_iface *iface) 676static void netlbl_unlhsh_condremove_iface(struct netlbl_unlhsh_iface *iface)
838{ 677{
839 struct netlbl_unlhsh_addr4 *iter4; 678 struct netlbl_af4list *iter4;
840 struct netlbl_unlhsh_addr6 *iter6; 679#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
680 struct netlbl_af6list *iter6;
681#endif /* IPv6 */
841 682
842 spin_lock(&netlbl_unlhsh_lock); 683 spin_lock(&netlbl_unlhsh_lock);
843 list_for_each_entry_rcu(iter4, &iface->addr4_list, list) 684 netlbl_af4list_foreach_rcu(iter4, &iface->addr4_list)
844 if (iter4->valid) 685 goto unlhsh_condremove_failure;
845 goto unlhsh_condremove_failure; 686#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
846 list_for_each_entry_rcu(iter6, &iface->addr6_list, list) 687 netlbl_af6list_foreach_rcu(iter6, &iface->addr6_list)
847 if (iter6->valid) 688 goto unlhsh_condremove_failure;
848 goto unlhsh_condremove_failure; 689#endif /* IPv6 */
849 iface->valid = 0; 690 iface->valid = 0;
850 if (iface->ifindex > 0) 691 if (iface->ifindex > 0)
851 list_del_rcu(&iface->list); 692 list_del_rcu(&iface->list);
@@ -1349,7 +1190,7 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd,
1349 if (addr4) { 1190 if (addr4) {
1350 struct in_addr addr_struct; 1191 struct in_addr addr_struct;
1351 1192
1352 addr_struct.s_addr = addr4->addr; 1193 addr_struct.s_addr = addr4->list.addr;
1353 ret_val = nla_put(cb_arg->skb, 1194 ret_val = nla_put(cb_arg->skb,
1354 NLBL_UNLABEL_A_IPV4ADDR, 1195 NLBL_UNLABEL_A_IPV4ADDR,
1355 sizeof(struct in_addr), 1196 sizeof(struct in_addr),
@@ -1357,7 +1198,7 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd,
1357 if (ret_val != 0) 1198 if (ret_val != 0)
1358 goto list_cb_failure; 1199 goto list_cb_failure;
1359 1200
1360 addr_struct.s_addr = addr4->mask; 1201 addr_struct.s_addr = addr4->list.mask;
1361 ret_val = nla_put(cb_arg->skb, 1202 ret_val = nla_put(cb_arg->skb,
1362 NLBL_UNLABEL_A_IPV4MASK, 1203 NLBL_UNLABEL_A_IPV4MASK,
1363 sizeof(struct in_addr), 1204 sizeof(struct in_addr),
@@ -1370,14 +1211,14 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd,
1370 ret_val = nla_put(cb_arg->skb, 1211 ret_val = nla_put(cb_arg->skb,
1371 NLBL_UNLABEL_A_IPV6ADDR, 1212 NLBL_UNLABEL_A_IPV6ADDR,
1372 sizeof(struct in6_addr), 1213 sizeof(struct in6_addr),
1373 &addr6->addr); 1214 &addr6->list.addr);
1374 if (ret_val != 0) 1215 if (ret_val != 0)
1375 goto list_cb_failure; 1216 goto list_cb_failure;
1376 1217
1377 ret_val = nla_put(cb_arg->skb, 1218 ret_val = nla_put(cb_arg->skb,
1378 NLBL_UNLABEL_A_IPV6MASK, 1219 NLBL_UNLABEL_A_IPV6MASK,
1379 sizeof(struct in6_addr), 1220 sizeof(struct in6_addr),
1380 &addr6->mask); 1221 &addr6->list.mask);
1381 if (ret_val != 0) 1222 if (ret_val != 0)
1382 goto list_cb_failure; 1223 goto list_cb_failure;
1383 1224
@@ -1425,8 +1266,11 @@ static int netlbl_unlabel_staticlist(struct sk_buff *skb,
1425 u32 iter_bkt; 1266 u32 iter_bkt;
1426 u32 iter_chain = 0, iter_addr4 = 0, iter_addr6 = 0; 1267 u32 iter_chain = 0, iter_addr4 = 0, iter_addr6 = 0;
1427 struct netlbl_unlhsh_iface *iface; 1268 struct netlbl_unlhsh_iface *iface;
1428 struct netlbl_unlhsh_addr4 *addr4; 1269 struct list_head *iter_list;
1429 struct netlbl_unlhsh_addr6 *addr6; 1270 struct netlbl_af4list *addr4;
1271#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
1272 struct netlbl_af6list *addr6;
1273#endif
1430 1274
1431 cb_arg.nl_cb = cb; 1275 cb_arg.nl_cb = cb;
1432 cb_arg.skb = skb; 1276 cb_arg.skb = skb;
@@ -1436,44 +1280,43 @@ static int netlbl_unlabel_staticlist(struct sk_buff *skb,
1436 for (iter_bkt = skip_bkt; 1280 for (iter_bkt = skip_bkt;
1437 iter_bkt < rcu_dereference(netlbl_unlhsh)->size; 1281 iter_bkt < rcu_dereference(netlbl_unlhsh)->size;
1438 iter_bkt++, iter_chain = 0, iter_addr4 = 0, iter_addr6 = 0) { 1282 iter_bkt++, iter_chain = 0, iter_addr4 = 0, iter_addr6 = 0) {
1439 list_for_each_entry_rcu(iface, 1283 iter_list = &rcu_dereference(netlbl_unlhsh)->tbl[iter_bkt];
1440 &rcu_dereference(netlbl_unlhsh)->tbl[iter_bkt], 1284 list_for_each_entry_rcu(iface, iter_list, list) {
1441 list) {
1442 if (!iface->valid || 1285 if (!iface->valid ||
1443 iter_chain++ < skip_chain) 1286 iter_chain++ < skip_chain)
1444 continue; 1287 continue;
1445 list_for_each_entry_rcu(addr4, 1288 netlbl_af4list_foreach_rcu(addr4,
1446 &iface->addr4_list, 1289 &iface->addr4_list) {
1447 list) { 1290 if (iter_addr4++ < skip_addr4)
1448 if (!addr4->valid || iter_addr4++ < skip_addr4)
1449 continue; 1291 continue;
1450 if (netlbl_unlabel_staticlist_gen( 1292 if (netlbl_unlabel_staticlist_gen(
1451 NLBL_UNLABEL_C_STATICLIST, 1293 NLBL_UNLABEL_C_STATICLIST,
1452 iface, 1294 iface,
1453 addr4, 1295 netlbl_unlhsh_addr4_entry(addr4),
1454 NULL, 1296 NULL,
1455 &cb_arg) < 0) { 1297 &cb_arg) < 0) {
1456 iter_addr4--; 1298 iter_addr4--;
1457 iter_chain--; 1299 iter_chain--;
1458 goto unlabel_staticlist_return; 1300 goto unlabel_staticlist_return;
1459 } 1301 }
1460 } 1302 }
1461 list_for_each_entry_rcu(addr6, 1303#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
1462 &iface->addr6_list, 1304 netlbl_af6list_foreach_rcu(addr6,
1463 list) { 1305 &iface->addr6_list) {
1464 if (!addr6->valid || iter_addr6++ < skip_addr6) 1306 if (iter_addr6++ < skip_addr6)
1465 continue; 1307 continue;
1466 if (netlbl_unlabel_staticlist_gen( 1308 if (netlbl_unlabel_staticlist_gen(
1467 NLBL_UNLABEL_C_STATICLIST, 1309 NLBL_UNLABEL_C_STATICLIST,
1468 iface, 1310 iface,
1469 NULL, 1311 NULL,
1470 addr6, 1312 netlbl_unlhsh_addr6_entry(addr6),
1471 &cb_arg) < 0) { 1313 &cb_arg) < 0) {
1472 iter_addr6--; 1314 iter_addr6--;
1473 iter_chain--; 1315 iter_chain--;
1474 goto unlabel_staticlist_return; 1316 goto unlabel_staticlist_return;
1475 } 1317 }
1476 } 1318 }
1319#endif /* IPv6 */
1477 } 1320 }
1478 } 1321 }
1479 1322
@@ -1504,9 +1347,12 @@ static int netlbl_unlabel_staticlistdef(struct sk_buff *skb,
1504 struct netlbl_unlhsh_iface *iface; 1347 struct netlbl_unlhsh_iface *iface;
1505 u32 skip_addr4 = cb->args[0]; 1348 u32 skip_addr4 = cb->args[0];
1506 u32 skip_addr6 = cb->args[1]; 1349 u32 skip_addr6 = cb->args[1];
1507 u32 iter_addr4 = 0, iter_addr6 = 0; 1350 u32 iter_addr4 = 0;
1508 struct netlbl_unlhsh_addr4 *addr4; 1351 struct netlbl_af4list *addr4;
1509 struct netlbl_unlhsh_addr6 *addr6; 1352#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
1353 u32 iter_addr6 = 0;
1354 struct netlbl_af6list *addr6;
1355#endif
1510 1356
1511 cb_arg.nl_cb = cb; 1357 cb_arg.nl_cb = cb;
1512 cb_arg.skb = skb; 1358 cb_arg.skb = skb;
@@ -1517,30 +1363,32 @@ static int netlbl_unlabel_staticlistdef(struct sk_buff *skb,
1517 if (iface == NULL || !iface->valid) 1363 if (iface == NULL || !iface->valid)
1518 goto unlabel_staticlistdef_return; 1364 goto unlabel_staticlistdef_return;
1519 1365
1520 list_for_each_entry_rcu(addr4, &iface->addr4_list, list) { 1366 netlbl_af4list_foreach_rcu(addr4, &iface->addr4_list) {
1521 if (!addr4->valid || iter_addr4++ < skip_addr4) 1367 if (iter_addr4++ < skip_addr4)
1522 continue; 1368 continue;
1523 if (netlbl_unlabel_staticlist_gen(NLBL_UNLABEL_C_STATICLISTDEF, 1369 if (netlbl_unlabel_staticlist_gen(NLBL_UNLABEL_C_STATICLISTDEF,
1524 iface, 1370 iface,
1525 addr4, 1371 netlbl_unlhsh_addr4_entry(addr4),
1526 NULL, 1372 NULL,
1527 &cb_arg) < 0) { 1373 &cb_arg) < 0) {
1528 iter_addr4--; 1374 iter_addr4--;
1529 goto unlabel_staticlistdef_return; 1375 goto unlabel_staticlistdef_return;
1530 } 1376 }
1531 } 1377 }
1532 list_for_each_entry_rcu(addr6, &iface->addr6_list, list) { 1378#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
1533 if (!addr6->valid || iter_addr6++ < skip_addr6) 1379 netlbl_af6list_foreach_rcu(addr6, &iface->addr6_list) {
1380 if (iter_addr6++ < skip_addr6)
1534 continue; 1381 continue;
1535 if (netlbl_unlabel_staticlist_gen(NLBL_UNLABEL_C_STATICLISTDEF, 1382 if (netlbl_unlabel_staticlist_gen(NLBL_UNLABEL_C_STATICLISTDEF,
1536 iface, 1383 iface,
1537 NULL, 1384 NULL,
1538 addr6, 1385 netlbl_unlhsh_addr6_entry(addr6),
1539 &cb_arg) < 0) { 1386 &cb_arg) < 0) {
1540 iter_addr6--; 1387 iter_addr6--;
1541 goto unlabel_staticlistdef_return; 1388 goto unlabel_staticlistdef_return;
1542 } 1389 }
1543 } 1390 }
1391#endif /* IPv6 */
1544 1392
1545unlabel_staticlistdef_return: 1393unlabel_staticlistdef_return:
1546 rcu_read_unlock(); 1394 rcu_read_unlock();
@@ -1718,25 +1566,27 @@ int netlbl_unlabel_getattr(const struct sk_buff *skb,
1718 switch (family) { 1566 switch (family) {
1719 case PF_INET: { 1567 case PF_INET: {
1720 struct iphdr *hdr4; 1568 struct iphdr *hdr4;
1721 struct netlbl_unlhsh_addr4 *addr4; 1569 struct netlbl_af4list *addr4;
1722 1570
1723 hdr4 = ip_hdr(skb); 1571 hdr4 = ip_hdr(skb);
1724 addr4 = netlbl_unlhsh_search_addr4(hdr4->saddr, iface); 1572 addr4 = netlbl_af4list_search(hdr4->saddr,
1573 &iface->addr4_list);
1725 if (addr4 == NULL) 1574 if (addr4 == NULL)
1726 goto unlabel_getattr_nolabel; 1575 goto unlabel_getattr_nolabel;
1727 secattr->attr.secid = addr4->secid; 1576 secattr->attr.secid = netlbl_unlhsh_addr4_entry(addr4)->secid;
1728 break; 1577 break;
1729 } 1578 }
1730#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 1579#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
1731 case PF_INET6: { 1580 case PF_INET6: {
1732 struct ipv6hdr *hdr6; 1581 struct ipv6hdr *hdr6;
1733 struct netlbl_unlhsh_addr6 *addr6; 1582 struct netlbl_af6list *addr6;
1734 1583
1735 hdr6 = ipv6_hdr(skb); 1584 hdr6 = ipv6_hdr(skb);
1736 addr6 = netlbl_unlhsh_search_addr6(&hdr6->saddr, iface); 1585 addr6 = netlbl_af6list_search(&hdr6->saddr,
1586 &iface->addr6_list);
1737 if (addr6 == NULL) 1587 if (addr6 == NULL)
1738 goto unlabel_getattr_nolabel; 1588 goto unlabel_getattr_nolabel;
1739 secattr->attr.secid = addr6->secid; 1589 secattr->attr.secid = netlbl_unlhsh_addr6_entry(addr6)->secid;
1740 break; 1590 break;
1741 } 1591 }
1742#endif /* IPv6 */ 1592#endif /* IPv6 */