Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.34-rc2 1629 lines 45 kB view raw
1/* 2 * NetLabel Unlabeled Support 3 * 4 * This file defines functions for dealing with unlabeled packets for the 5 * NetLabel system. The NetLabel system manages static and dynamic label 6 * mappings for network protocols such as CIPSO and RIPSO. 7 * 8 * Author: Paul Moore <paul.moore@hp.com> 9 * 10 */ 11 12/* 13 * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 - 2008 14 * 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 17 * the Free Software Foundation; either version 2 of the License, or 18 * (at your option) any later version. 19 * 20 * This program is distributed in the hope that it will be useful, 21 * but WITHOUT ANY WARRANTY; without even the implied warranty of 22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 23 * the GNU General Public License for more details. 24 * 25 * You should have received a copy of the GNU General Public License 26 * along with this program; if not, write to the Free Software 27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 28 * 29 */ 30 31#include <linux/types.h> 32#include <linux/rcupdate.h> 33#include <linux/list.h> 34#include <linux/spinlock.h> 35#include <linux/socket.h> 36#include <linux/string.h> 37#include <linux/skbuff.h> 38#include <linux/audit.h> 39#include <linux/in.h> 40#include <linux/in6.h> 41#include <linux/ip.h> 42#include <linux/ipv6.h> 43#include <linux/notifier.h> 44#include <linux/netdevice.h> 45#include <linux/security.h> 46#include <net/sock.h> 47#include <net/netlink.h> 48#include <net/genetlink.h> 49#include <net/ip.h> 50#include <net/ipv6.h> 51#include <net/net_namespace.h> 52#include <net/netlabel.h> 53#include <asm/bug.h> 54#include <asm/atomic.h> 55 56#include "netlabel_user.h" 57#include "netlabel_addrlist.h" 58#include "netlabel_domainhash.h" 59#include "netlabel_unlabeled.h" 60#include "netlabel_mgmt.h" 61 62/* NOTE: at present we always use init's network namespace since we don't 63 * presently support different namespaces even though the majority of 64 * the functions in this file are "namespace safe" */ 65 66/* The unlabeled connection hash table which we use to map network interfaces 67 * and addresses of unlabeled packets to a user specified secid value for the 68 * LSM. The hash table is used to lookup the network interface entry 69 * (struct netlbl_unlhsh_iface) and then the interface entry is used to 70 * lookup an IP address match from an ordered list. If a network interface 71 * match can not be found in the hash table then the default entry 72 * (netlbl_unlhsh_def) is used. The IP address entry list 73 * (struct netlbl_unlhsh_addr) is ordered such that the entries with a 74 * larger netmask come first. 75 */ 76struct netlbl_unlhsh_tbl { 77 struct list_head *tbl; 78 u32 size; 79}; 80#define netlbl_unlhsh_addr4_entry(iter) \ 81 container_of(iter, struct netlbl_unlhsh_addr4, list) 82struct netlbl_unlhsh_addr4 { 83 u32 secid; 84 85 struct netlbl_af4list list; 86 struct rcu_head rcu; 87}; 88#define netlbl_unlhsh_addr6_entry(iter) \ 89 container_of(iter, struct netlbl_unlhsh_addr6, list) 90struct netlbl_unlhsh_addr6 { 91 u32 secid; 92 93 struct netlbl_af6list list; 94 struct rcu_head rcu; 95}; 96struct netlbl_unlhsh_iface { 97 int ifindex; 98 struct list_head addr4_list; 99 struct list_head addr6_list; 100 101 u32 valid; 102 struct list_head list; 103 struct rcu_head rcu; 104}; 105 106/* Argument struct for netlbl_unlhsh_walk() */ 107struct netlbl_unlhsh_walk_arg { 108 struct netlink_callback *nl_cb; 109 struct sk_buff *skb; 110 u32 seq; 111}; 112 113/* Unlabeled connection hash table */ 114/* updates should be so rare that having one spinlock for the entire 115 * hash table should be okay */ 116static DEFINE_SPINLOCK(netlbl_unlhsh_lock); 117static struct netlbl_unlhsh_tbl *netlbl_unlhsh = NULL; 118static struct netlbl_unlhsh_iface *netlbl_unlhsh_def = NULL; 119 120/* Accept unlabeled packets flag */ 121static u8 netlabel_unlabel_acceptflg = 0; 122 123/* NetLabel Generic NETLINK unlabeled family */ 124static struct genl_family netlbl_unlabel_gnl_family = { 125 .id = GENL_ID_GENERATE, 126 .hdrsize = 0, 127 .name = NETLBL_NLTYPE_UNLABELED_NAME, 128 .version = NETLBL_PROTO_VERSION, 129 .maxattr = NLBL_UNLABEL_A_MAX, 130}; 131 132/* NetLabel Netlink attribute policy */ 133static const struct nla_policy netlbl_unlabel_genl_policy[NLBL_UNLABEL_A_MAX + 1] = { 134 [NLBL_UNLABEL_A_ACPTFLG] = { .type = NLA_U8 }, 135 [NLBL_UNLABEL_A_IPV6ADDR] = { .type = NLA_BINARY, 136 .len = sizeof(struct in6_addr) }, 137 [NLBL_UNLABEL_A_IPV6MASK] = { .type = NLA_BINARY, 138 .len = sizeof(struct in6_addr) }, 139 [NLBL_UNLABEL_A_IPV4ADDR] = { .type = NLA_BINARY, 140 .len = sizeof(struct in_addr) }, 141 [NLBL_UNLABEL_A_IPV4MASK] = { .type = NLA_BINARY, 142 .len = sizeof(struct in_addr) }, 143 [NLBL_UNLABEL_A_IFACE] = { .type = NLA_NUL_STRING, 144 .len = IFNAMSIZ - 1 }, 145 [NLBL_UNLABEL_A_SECCTX] = { .type = NLA_BINARY } 146}; 147 148/* 149 * Unlabeled Connection Hash Table Functions 150 */ 151 152/** 153 * netlbl_unlhsh_free_addr4 - Frees an IPv4 address entry from the hash table 154 * @entry: the entry's RCU field 155 * 156 * Description: 157 * This function is designed to be used as a callback to the call_rcu() 158 * function so that memory allocated to a hash table address entry can be 159 * released safely. 160 * 161 */ 162static void netlbl_unlhsh_free_addr4(struct rcu_head *entry) 163{ 164 struct netlbl_unlhsh_addr4 *ptr; 165 166 ptr = container_of(entry, struct netlbl_unlhsh_addr4, rcu); 167 kfree(ptr); 168} 169 170#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 171/** 172 * netlbl_unlhsh_free_addr6 - Frees an IPv6 address entry from the hash table 173 * @entry: the entry's RCU field 174 * 175 * Description: 176 * This function is designed to be used as a callback to the call_rcu() 177 * function so that memory allocated to a hash table address entry can be 178 * released safely. 179 * 180 */ 181static void netlbl_unlhsh_free_addr6(struct rcu_head *entry) 182{ 183 struct netlbl_unlhsh_addr6 *ptr; 184 185 ptr = container_of(entry, struct netlbl_unlhsh_addr6, rcu); 186 kfree(ptr); 187} 188#endif /* IPv6 */ 189 190/** 191 * netlbl_unlhsh_free_iface - Frees an interface entry from the hash table 192 * @entry: the entry's RCU field 193 * 194 * Description: 195 * This function is designed to be used as a callback to the call_rcu() 196 * function so that memory allocated to a hash table interface entry can be 197 * released safely. It is important to note that this function does not free 198 * the IPv4 and IPv6 address lists contained as part of an interface entry. It 199 * is up to the rest of the code to make sure an interface entry is only freed 200 * once it's address lists are empty. 201 * 202 */ 203static void netlbl_unlhsh_free_iface(struct rcu_head *entry) 204{ 205 struct netlbl_unlhsh_iface *iface; 206 struct netlbl_af4list *iter4; 207 struct netlbl_af4list *tmp4; 208#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 209 struct netlbl_af6list *iter6; 210 struct netlbl_af6list *tmp6; 211#endif /* IPv6 */ 212 213 iface = container_of(entry, struct netlbl_unlhsh_iface, rcu); 214 215 /* no need for locks here since we are the only one with access to this 216 * structure */ 217 218 netlbl_af4list_foreach_safe(iter4, tmp4, &iface->addr4_list) { 219 netlbl_af4list_remove_entry(iter4); 220 kfree(netlbl_unlhsh_addr4_entry(iter4)); 221 } 222#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 223 netlbl_af6list_foreach_safe(iter6, tmp6, &iface->addr6_list) { 224 netlbl_af6list_remove_entry(iter6); 225 kfree(netlbl_unlhsh_addr6_entry(iter6)); 226 } 227#endif /* IPv6 */ 228 kfree(iface); 229} 230 231/** 232 * netlbl_unlhsh_hash - Hashing function for the hash table 233 * @ifindex: the network interface/device to hash 234 * 235 * Description: 236 * 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 238 * calling the rcu_read_[un]lock() functions. 239 * 240 */ 241static u32 netlbl_unlhsh_hash(int ifindex) 242{ 243 /* this is taken _almost_ directly from 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 249/** 250 * netlbl_unlhsh_search_iface - Search for a matching interface entry 251 * @ifindex: the network interface 252 * 253 * Description: 254 * Searches the unlabeled connection hash table and returns a pointer to the 255 * interface entry which matches @ifindex, otherwise NULL is returned. The 256 * caller is responsible for calling the rcu_read_[un]lock() functions. 257 * 258 */ 259static struct netlbl_unlhsh_iface *netlbl_unlhsh_search_iface(int ifindex) 260{ 261 u32 bkt; 262 struct list_head *bkt_list; 263 struct netlbl_unlhsh_iface *iter; 264 265 bkt = netlbl_unlhsh_hash(ifindex); 266 bkt_list = &rcu_dereference(netlbl_unlhsh)->tbl[bkt]; 267 list_for_each_entry_rcu(iter, bkt_list, list) 268 if (iter->valid && iter->ifindex == ifindex) 269 return iter; 270 271 return NULL; 272} 273 274/** 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 303 * @iface: the associated interface entry 304 * @addr: IPv4 address in network byte order 305 * @mask: IPv4 address mask in network byte order 306 * @secid: LSM secid value for entry 307 * 308 * Description: 309 * 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 311 * a negative value is returned. The caller is responsible for calling the 312 * rcu_read_[un]lock() functions. 313 * 314 */ 315static int netlbl_unlhsh_add_addr4(struct netlbl_unlhsh_iface *iface, 316 const struct in_addr *addr, 317 const struct in_addr *mask, 318 u32 secid) 319{ 320 int ret_val; 321 struct netlbl_unlhsh_addr4 *entry; 322 323 entry = kzalloc(sizeof(*entry), GFP_ATOMIC); 324 if (entry == NULL) 325 return -ENOMEM; 326 327 entry->list.addr = addr->s_addr & mask->s_addr; 328 entry->list.mask = mask->s_addr; 329 entry->list.valid = 1; 330 entry->secid = secid; 331 332 spin_lock(&netlbl_unlhsh_lock); 333 ret_val = netlbl_af4list_add(&entry->list, &iface->addr4_list); 334 spin_unlock(&netlbl_unlhsh_lock); 335 336 if (ret_val != 0) 337 kfree(entry); 338 return ret_val; 339} 340 341#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 342/** 343 * netlbl_unlhsh_add_addr6 - Add a new IPv6 address entry to the hash table 344 * @iface: the associated interface entry 345 * @addr: IPv6 address in network byte order 346 * @mask: IPv6 address mask in network byte order 347 * @secid: LSM secid value for entry 348 * 349 * Description: 350 * 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 352 * a negative value is returned. The caller is responsible for calling the 353 * rcu_read_[un]lock() functions. 354 * 355 */ 356static int netlbl_unlhsh_add_addr6(struct netlbl_unlhsh_iface *iface, 357 const struct in6_addr *addr, 358 const struct in6_addr *mask, 359 u32 secid) 360{ 361 int ret_val; 362 struct netlbl_unlhsh_addr6 *entry; 363 364 entry = kzalloc(sizeof(*entry), GFP_ATOMIC); 365 if (entry == NULL) 366 return -ENOMEM; 367 368 ipv6_addr_copy(&entry->list.addr, addr); 369 entry->list.addr.s6_addr32[0] &= mask->s6_addr32[0]; 370 entry->list.addr.s6_addr32[1] &= mask->s6_addr32[1]; 371 entry->list.addr.s6_addr32[2] &= mask->s6_addr32[2]; 372 entry->list.addr.s6_addr32[3] &= mask->s6_addr32[3]; 373 ipv6_addr_copy(&entry->list.mask, mask); 374 entry->list.valid = 1; 375 entry->secid = secid; 376 377 spin_lock(&netlbl_unlhsh_lock); 378 ret_val = netlbl_af6list_add(&entry->list, &iface->addr6_list); 379 spin_unlock(&netlbl_unlhsh_lock); 380 381 if (ret_val != 0) 382 kfree(entry); 383 return 0; 384} 385#endif /* IPv6 */ 386 387/** 388 * netlbl_unlhsh_add_iface - Adds a new interface entry to the hash table 389 * @ifindex: network interface 390 * 391 * Description: 392 * 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 394 * is returned. The caller is responsible for calling the rcu_read_[un]lock() 395 * functions. 396 * 397 */ 398static struct netlbl_unlhsh_iface *netlbl_unlhsh_add_iface(int ifindex) 399{ 400 u32 bkt; 401 struct netlbl_unlhsh_iface *iface; 402 403 iface = kzalloc(sizeof(*iface), GFP_ATOMIC); 404 if (iface == NULL) 405 return NULL; 406 407 iface->ifindex = ifindex; 408 INIT_LIST_HEAD(&iface->addr4_list); 409 INIT_LIST_HEAD(&iface->addr6_list); 410 iface->valid = 1; 411 412 spin_lock(&netlbl_unlhsh_lock); 413 if (ifindex > 0) { 414 bkt = netlbl_unlhsh_hash(ifindex); 415 if (netlbl_unlhsh_search_iface(ifindex) != NULL) 416 goto add_iface_failure; 417 list_add_tail_rcu(&iface->list, 418 &rcu_dereference(netlbl_unlhsh)->tbl[bkt]); 419 } else { 420 INIT_LIST_HEAD(&iface->list); 421 if (rcu_dereference(netlbl_unlhsh_def) != NULL) 422 goto add_iface_failure; 423 rcu_assign_pointer(netlbl_unlhsh_def, iface); 424 } 425 spin_unlock(&netlbl_unlhsh_lock); 426 427 return iface; 428 429add_iface_failure: 430 spin_unlock(&netlbl_unlhsh_lock); 431 kfree(iface); 432 return NULL; 433} 434 435/** 436 * netlbl_unlhsh_add - Adds a new entry to the unlabeled connection hash table 437 * @net: network namespace 438 * @dev_name: interface name 439 * @addr: IP address in network byte order 440 * @mask: address mask in network byte order 441 * @addr_len: length of address/mask (4 for IPv4, 16 for IPv6) 442 * @secid: LSM secid value for the entry 443 * @audit_info: NetLabel audit information 444 * 445 * Description: 446 * Adds a new entry to the unlabeled connection hash table. Returns zero on 447 * success, negative values on failure. 448 * 449 */ 450int netlbl_unlhsh_add(struct net *net, 451 const char *dev_name, 452 const void *addr, 453 const void *mask, 454 u32 addr_len, 455 u32 secid, 456 struct netlbl_audit *audit_info) 457{ 458 int ret_val; 459 int ifindex; 460 struct net_device *dev; 461 struct netlbl_unlhsh_iface *iface; 462 struct audit_buffer *audit_buf = NULL; 463 char *secctx = NULL; 464 u32 secctx_len; 465 466 if (addr_len != sizeof(struct in_addr) && 467 addr_len != sizeof(struct in6_addr)) 468 return -EINVAL; 469 470 rcu_read_lock(); 471 if (dev_name != NULL) { 472 dev = dev_get_by_name_rcu(net, dev_name); 473 if (dev == NULL) { 474 ret_val = -ENODEV; 475 goto unlhsh_add_return; 476 } 477 ifindex = dev->ifindex; 478 iface = netlbl_unlhsh_search_iface(ifindex); 479 } else { 480 ifindex = 0; 481 iface = rcu_dereference(netlbl_unlhsh_def); 482 } 483 if (iface == NULL) { 484 iface = netlbl_unlhsh_add_iface(ifindex); 485 if (iface == NULL) { 486 ret_val = -ENOMEM; 487 goto unlhsh_add_return; 488 } 489 } 490 audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_STCADD, 491 audit_info); 492 switch (addr_len) { 493 case sizeof(struct in_addr): { 494 struct in_addr *addr4, *mask4; 495 496 addr4 = (struct in_addr *)addr; 497 mask4 = (struct in_addr *)mask; 498 ret_val = netlbl_unlhsh_add_addr4(iface, addr4, mask4, secid); 499 if (audit_buf != NULL) 500 netlbl_af4list_audit_addr(audit_buf, 1, 501 dev_name, 502 addr4->s_addr, 503 mask4->s_addr); 504 break; 505 } 506#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 507 case sizeof(struct in6_addr): { 508 struct in6_addr *addr6, *mask6; 509 510 addr6 = (struct in6_addr *)addr; 511 mask6 = (struct in6_addr *)mask; 512 ret_val = netlbl_unlhsh_add_addr6(iface, addr6, mask6, secid); 513 if (audit_buf != NULL) 514 netlbl_af6list_audit_addr(audit_buf, 1, 515 dev_name, 516 addr6, mask6); 517 break; 518 } 519#endif /* IPv6 */ 520 default: 521 ret_val = -EINVAL; 522 } 523 if (ret_val == 0) 524 atomic_inc(&netlabel_mgmt_protocount); 525 526unlhsh_add_return: 527 rcu_read_unlock(); 528 if (audit_buf != NULL) { 529 if (security_secid_to_secctx(secid, 530 &secctx, 531 &secctx_len) == 0) { 532 audit_log_format(audit_buf, " sec_obj=%s", secctx); 533 security_release_secctx(secctx, secctx_len); 534 } 535 audit_log_format(audit_buf, " res=%u", ret_val == 0 ? 1 : 0); 536 audit_log_end(audit_buf); 537 } 538 return ret_val; 539} 540 541/** 542 * netlbl_unlhsh_remove_addr4 - Remove an IPv4 address entry 543 * @net: network namespace 544 * @iface: interface entry 545 * @addr: IP address 546 * @mask: IP address mask 547 * @audit_info: NetLabel audit information 548 * 549 * Description: 550 * Remove an IP address entry from the unlabeled connection hash table. 551 * Returns zero on success, negative values on failure. The caller is 552 * responsible for calling the rcu_read_[un]lock() functions. 553 * 554 */ 555static int netlbl_unlhsh_remove_addr4(struct net *net, 556 struct netlbl_unlhsh_iface *iface, 557 const struct in_addr *addr, 558 const struct in_addr *mask, 559 struct netlbl_audit *audit_info) 560{ 561 struct netlbl_af4list *list_entry; 562 struct netlbl_unlhsh_addr4 *entry; 563 struct audit_buffer *audit_buf; 564 struct net_device *dev; 565 char *secctx; 566 u32 secctx_len; 567 568 spin_lock(&netlbl_unlhsh_lock); 569 list_entry = netlbl_af4list_remove(addr->s_addr, mask->s_addr, 570 &iface->addr4_list); 571 spin_unlock(&netlbl_unlhsh_lock); 572 if (list_entry != NULL) 573 entry = netlbl_unlhsh_addr4_entry(list_entry); 574 else 575 entry = NULL; 576 577 audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_STCDEL, 578 audit_info); 579 if (audit_buf != NULL) { 580 dev = dev_get_by_index(net, iface->ifindex); 581 netlbl_af4list_audit_addr(audit_buf, 1, 582 (dev != NULL ? dev->name : NULL), 583 addr->s_addr, mask->s_addr); 584 if (dev != NULL) 585 dev_put(dev); 586 if (entry != NULL && 587 security_secid_to_secctx(entry->secid, 588 &secctx, &secctx_len) == 0) { 589 audit_log_format(audit_buf, " sec_obj=%s", secctx); 590 security_release_secctx(secctx, secctx_len); 591 } 592 audit_log_format(audit_buf, " res=%u", entry != NULL ? 1 : 0); 593 audit_log_end(audit_buf); 594 } 595 596 if (entry == NULL) 597 return -ENOENT; 598 599 call_rcu(&entry->rcu, netlbl_unlhsh_free_addr4); 600 return 0; 601} 602 603#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 604/** 605 * netlbl_unlhsh_remove_addr6 - Remove an IPv6 address entry 606 * @net: network namespace 607 * @iface: interface entry 608 * @addr: IP address 609 * @mask: IP address mask 610 * @audit_info: NetLabel audit information 611 * 612 * Description: 613 * Remove an IP address entry from the unlabeled connection hash table. 614 * Returns zero on success, negative values on failure. The caller is 615 * responsible for calling the rcu_read_[un]lock() functions. 616 * 617 */ 618static int netlbl_unlhsh_remove_addr6(struct net *net, 619 struct netlbl_unlhsh_iface *iface, 620 const struct in6_addr *addr, 621 const struct in6_addr *mask, 622 struct netlbl_audit *audit_info) 623{ 624 struct netlbl_af6list *list_entry; 625 struct netlbl_unlhsh_addr6 *entry; 626 struct audit_buffer *audit_buf; 627 struct net_device *dev; 628 char *secctx; 629 u32 secctx_len; 630 631 spin_lock(&netlbl_unlhsh_lock); 632 list_entry = netlbl_af6list_remove(addr, mask, &iface->addr6_list); 633 spin_unlock(&netlbl_unlhsh_lock); 634 if (list_entry != NULL) 635 entry = netlbl_unlhsh_addr6_entry(list_entry); 636 else 637 entry = NULL; 638 639 audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_STCDEL, 640 audit_info); 641 if (audit_buf != NULL) { 642 dev = dev_get_by_index(net, iface->ifindex); 643 netlbl_af6list_audit_addr(audit_buf, 1, 644 (dev != NULL ? dev->name : NULL), 645 addr, mask); 646 if (dev != NULL) 647 dev_put(dev); 648 if (entry != NULL && 649 security_secid_to_secctx(entry->secid, 650 &secctx, &secctx_len) == 0) { 651 audit_log_format(audit_buf, " sec_obj=%s", secctx); 652 security_release_secctx(secctx, secctx_len); 653 } 654 audit_log_format(audit_buf, " res=%u", entry != NULL ? 1 : 0); 655 audit_log_end(audit_buf); 656 } 657 658 if (entry == NULL) 659 return -ENOENT; 660 661 call_rcu(&entry->rcu, netlbl_unlhsh_free_addr6); 662 return 0; 663} 664#endif /* IPv6 */ 665 666/** 667 * netlbl_unlhsh_condremove_iface - Remove an interface entry 668 * @iface: the interface entry 669 * 670 * Description: 671 * Remove an interface entry from the unlabeled connection hash table if it is 672 * empty. An interface entry is considered to be empty if there are no 673 * address entries assigned to it. 674 * 675 */ 676static void netlbl_unlhsh_condremove_iface(struct netlbl_unlhsh_iface *iface) 677{ 678 struct netlbl_af4list *iter4; 679#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 680 struct netlbl_af6list *iter6; 681#endif /* IPv6 */ 682 683 spin_lock(&netlbl_unlhsh_lock); 684 netlbl_af4list_foreach_rcu(iter4, &iface->addr4_list) 685 goto unlhsh_condremove_failure; 686#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 687 netlbl_af6list_foreach_rcu(iter6, &iface->addr6_list) 688 goto unlhsh_condremove_failure; 689#endif /* IPv6 */ 690 iface->valid = 0; 691 if (iface->ifindex > 0) 692 list_del_rcu(&iface->list); 693 else 694 rcu_assign_pointer(netlbl_unlhsh_def, NULL); 695 spin_unlock(&netlbl_unlhsh_lock); 696 697 call_rcu(&iface->rcu, netlbl_unlhsh_free_iface); 698 return; 699 700unlhsh_condremove_failure: 701 spin_unlock(&netlbl_unlhsh_lock); 702 return; 703} 704 705/** 706 * netlbl_unlhsh_remove - Remove an entry from the unlabeled hash table 707 * @net: network namespace 708 * @dev_name: interface name 709 * @addr: IP address in network byte order 710 * @mask: address mask in network byte order 711 * @addr_len: length of address/mask (4 for IPv4, 16 for IPv6) 712 * @audit_info: NetLabel audit information 713 * 714 * Description: 715 * Removes and existing entry from the unlabeled connection hash table. 716 * Returns zero on success, negative values on failure. 717 * 718 */ 719int netlbl_unlhsh_remove(struct net *net, 720 const char *dev_name, 721 const void *addr, 722 const void *mask, 723 u32 addr_len, 724 struct netlbl_audit *audit_info) 725{ 726 int ret_val; 727 struct net_device *dev; 728 struct netlbl_unlhsh_iface *iface; 729 730 if (addr_len != sizeof(struct in_addr) && 731 addr_len != sizeof(struct in6_addr)) 732 return -EINVAL; 733 734 rcu_read_lock(); 735 if (dev_name != NULL) { 736 dev = dev_get_by_name_rcu(net, dev_name); 737 if (dev == NULL) { 738 ret_val = -ENODEV; 739 goto unlhsh_remove_return; 740 } 741 iface = netlbl_unlhsh_search_iface(dev->ifindex); 742 } else 743 iface = rcu_dereference(netlbl_unlhsh_def); 744 if (iface == NULL) { 745 ret_val = -ENOENT; 746 goto unlhsh_remove_return; 747 } 748 switch (addr_len) { 749 case sizeof(struct in_addr): 750 ret_val = netlbl_unlhsh_remove_addr4(net, 751 iface, addr, mask, 752 audit_info); 753 break; 754#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 755 case sizeof(struct in6_addr): 756 ret_val = netlbl_unlhsh_remove_addr6(net, 757 iface, addr, mask, 758 audit_info); 759 break; 760#endif /* IPv6 */ 761 default: 762 ret_val = -EINVAL; 763 } 764 if (ret_val == 0) { 765 netlbl_unlhsh_condremove_iface(iface); 766 atomic_dec(&netlabel_mgmt_protocount); 767 } 768 769unlhsh_remove_return: 770 rcu_read_unlock(); 771 return ret_val; 772} 773 774/* 775 * General Helper Functions 776 */ 777 778/** 779 * netlbl_unlhsh_netdev_handler - Network device notification handler 780 * @this: notifier block 781 * @event: the event 782 * @ptr: the network device (cast to void) 783 * 784 * Description: 785 * Handle network device events, although at present all we care about is a 786 * network device going away. In the case of a device going away we clear any 787 * related entries from the unlabeled connection hash table. 788 * 789 */ 790static int netlbl_unlhsh_netdev_handler(struct notifier_block *this, 791 unsigned long event, 792 void *ptr) 793{ 794 struct net_device *dev = ptr; 795 struct netlbl_unlhsh_iface *iface = NULL; 796 797 if (!net_eq(dev_net(dev), &init_net)) 798 return NOTIFY_DONE; 799 800 /* XXX - should this be a check for NETDEV_DOWN or _UNREGISTER? */ 801 if (event == NETDEV_DOWN) { 802 spin_lock(&netlbl_unlhsh_lock); 803 iface = netlbl_unlhsh_search_iface(dev->ifindex); 804 if (iface != NULL && iface->valid) { 805 iface->valid = 0; 806 list_del_rcu(&iface->list); 807 } else 808 iface = NULL; 809 spin_unlock(&netlbl_unlhsh_lock); 810 } 811 812 if (iface != NULL) 813 call_rcu(&iface->rcu, netlbl_unlhsh_free_iface); 814 815 return NOTIFY_DONE; 816} 817 818/** 819 * netlbl_unlabel_acceptflg_set - Set the unlabeled accept flag 820 * @value: desired value 821 * @audit_info: NetLabel audit information 822 * 823 * Description: 824 * Set the value of the unlabeled accept flag to @value. 825 * 826 */ 827static void netlbl_unlabel_acceptflg_set(u8 value, 828 struct netlbl_audit *audit_info) 829{ 830 struct audit_buffer *audit_buf; 831 u8 old_val; 832 833 old_val = netlabel_unlabel_acceptflg; 834 netlabel_unlabel_acceptflg = value; 835 audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_ALLOW, 836 audit_info); 837 if (audit_buf != NULL) { 838 audit_log_format(audit_buf, 839 " unlbl_accept=%u old=%u", value, old_val); 840 audit_log_end(audit_buf); 841 } 842} 843 844/** 845 * netlbl_unlabel_addrinfo_get - Get the IPv4/6 address information 846 * @info: the Generic NETLINK info block 847 * @addr: the IP address 848 * @mask: the IP address mask 849 * @len: the address length 850 * 851 * Description: 852 * Examine the Generic NETLINK message and extract the IP address information. 853 * Returns zero on success, negative values on failure. 854 * 855 */ 856static int netlbl_unlabel_addrinfo_get(struct genl_info *info, 857 void **addr, 858 void **mask, 859 u32 *len) 860{ 861 u32 addr_len; 862 863 if (info->attrs[NLBL_UNLABEL_A_IPV4ADDR]) { 864 addr_len = nla_len(info->attrs[NLBL_UNLABEL_A_IPV4ADDR]); 865 if (addr_len != sizeof(struct in_addr) && 866 addr_len != nla_len(info->attrs[NLBL_UNLABEL_A_IPV4MASK])) 867 return -EINVAL; 868 *len = addr_len; 869 *addr = nla_data(info->attrs[NLBL_UNLABEL_A_IPV4ADDR]); 870 *mask = nla_data(info->attrs[NLBL_UNLABEL_A_IPV4MASK]); 871 return 0; 872 } else if (info->attrs[NLBL_UNLABEL_A_IPV6ADDR]) { 873 addr_len = nla_len(info->attrs[NLBL_UNLABEL_A_IPV6ADDR]); 874 if (addr_len != sizeof(struct in6_addr) && 875 addr_len != nla_len(info->attrs[NLBL_UNLABEL_A_IPV6MASK])) 876 return -EINVAL; 877 *len = addr_len; 878 *addr = nla_data(info->attrs[NLBL_UNLABEL_A_IPV6ADDR]); 879 *mask = nla_data(info->attrs[NLBL_UNLABEL_A_IPV6MASK]); 880 return 0; 881 } 882 883 return -EINVAL; 884} 885 886/* 887 * NetLabel Command Handlers 888 */ 889 890/** 891 * netlbl_unlabel_accept - Handle an ACCEPT message 892 * @skb: the NETLINK buffer 893 * @info: the Generic NETLINK info block 894 * 895 * Description: 896 * Process a user generated ACCEPT message and set the accept flag accordingly. 897 * Returns zero on success, negative values on failure. 898 * 899 */ 900static int netlbl_unlabel_accept(struct sk_buff *skb, struct genl_info *info) 901{ 902 u8 value; 903 struct netlbl_audit audit_info; 904 905 if (info->attrs[NLBL_UNLABEL_A_ACPTFLG]) { 906 value = nla_get_u8(info->attrs[NLBL_UNLABEL_A_ACPTFLG]); 907 if (value == 1 || value == 0) { 908 netlbl_netlink_auditinfo(skb, &audit_info); 909 netlbl_unlabel_acceptflg_set(value, &audit_info); 910 return 0; 911 } 912 } 913 914 return -EINVAL; 915} 916 917/** 918 * netlbl_unlabel_list - Handle a LIST message 919 * @skb: the NETLINK buffer 920 * @info: the Generic NETLINK info block 921 * 922 * Description: 923 * Process a user generated LIST message and respond with the current status. 924 * Returns zero on success, negative values on failure. 925 * 926 */ 927static int netlbl_unlabel_list(struct sk_buff *skb, struct genl_info *info) 928{ 929 int ret_val = -EINVAL; 930 struct sk_buff *ans_skb; 931 void *data; 932 933 ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 934 if (ans_skb == NULL) 935 goto list_failure; 936 data = genlmsg_put_reply(ans_skb, info, &netlbl_unlabel_gnl_family, 937 0, NLBL_UNLABEL_C_LIST); 938 if (data == NULL) { 939 ret_val = -ENOMEM; 940 goto list_failure; 941 } 942 943 ret_val = nla_put_u8(ans_skb, 944 NLBL_UNLABEL_A_ACPTFLG, 945 netlabel_unlabel_acceptflg); 946 if (ret_val != 0) 947 goto list_failure; 948 949 genlmsg_end(ans_skb, data); 950 return genlmsg_reply(ans_skb, info); 951 952list_failure: 953 kfree_skb(ans_skb); 954 return ret_val; 955} 956 957/** 958 * netlbl_unlabel_staticadd - Handle a STATICADD message 959 * @skb: the NETLINK buffer 960 * @info: the Generic NETLINK info block 961 * 962 * Description: 963 * Process a user generated STATICADD message and add a new unlabeled 964 * connection entry to the hash table. Returns zero on success, negative 965 * values on failure. 966 * 967 */ 968static int netlbl_unlabel_staticadd(struct sk_buff *skb, 969 struct genl_info *info) 970{ 971 int ret_val; 972 char *dev_name; 973 void *addr; 974 void *mask; 975 u32 addr_len; 976 u32 secid; 977 struct netlbl_audit audit_info; 978 979 /* Don't allow users to add both IPv4 and IPv6 addresses for a 980 * single entry. However, allow users to create two entries, one each 981 * for IPv4 and IPv4, with the same LSM security context which should 982 * achieve the same result. */ 983 if (!info->attrs[NLBL_UNLABEL_A_SECCTX] || 984 !info->attrs[NLBL_UNLABEL_A_IFACE] || 985 !((!info->attrs[NLBL_UNLABEL_A_IPV4ADDR] || 986 !info->attrs[NLBL_UNLABEL_A_IPV4MASK]) ^ 987 (!info->attrs[NLBL_UNLABEL_A_IPV6ADDR] || 988 !info->attrs[NLBL_UNLABEL_A_IPV6MASK]))) 989 return -EINVAL; 990 991 netlbl_netlink_auditinfo(skb, &audit_info); 992 993 ret_val = netlbl_unlabel_addrinfo_get(info, &addr, &mask, &addr_len); 994 if (ret_val != 0) 995 return ret_val; 996 dev_name = nla_data(info->attrs[NLBL_UNLABEL_A_IFACE]); 997 ret_val = security_secctx_to_secid( 998 nla_data(info->attrs[NLBL_UNLABEL_A_SECCTX]), 999 nla_len(info->attrs[NLBL_UNLABEL_A_SECCTX]), 1000 &secid); 1001 if (ret_val != 0) 1002 return ret_val; 1003 1004 return netlbl_unlhsh_add(&init_net, 1005 dev_name, addr, mask, addr_len, secid, 1006 &audit_info); 1007} 1008 1009/** 1010 * netlbl_unlabel_staticadddef - Handle a STATICADDDEF message 1011 * @skb: the NETLINK buffer 1012 * @info: the Generic NETLINK info block 1013 * 1014 * Description: 1015 * Process a user generated STATICADDDEF message and add a new default 1016 * unlabeled connection entry. Returns zero on success, negative values on 1017 * failure. 1018 * 1019 */ 1020static int netlbl_unlabel_staticadddef(struct sk_buff *skb, 1021 struct genl_info *info) 1022{ 1023 int ret_val; 1024 void *addr; 1025 void *mask; 1026 u32 addr_len; 1027 u32 secid; 1028 struct netlbl_audit audit_info; 1029 1030 /* Don't allow users to add both IPv4 and IPv6 addresses for a 1031 * single entry. However, allow users to create two entries, one each 1032 * for IPv4 and IPv6, with the same LSM security context which should 1033 * achieve the same result. */ 1034 if (!info->attrs[NLBL_UNLABEL_A_SECCTX] || 1035 !((!info->attrs[NLBL_UNLABEL_A_IPV4ADDR] || 1036 !info->attrs[NLBL_UNLABEL_A_IPV4MASK]) ^ 1037 (!info->attrs[NLBL_UNLABEL_A_IPV6ADDR] || 1038 !info->attrs[NLBL_UNLABEL_A_IPV6MASK]))) 1039 return -EINVAL; 1040 1041 netlbl_netlink_auditinfo(skb, &audit_info); 1042 1043 ret_val = netlbl_unlabel_addrinfo_get(info, &addr, &mask, &addr_len); 1044 if (ret_val != 0) 1045 return ret_val; 1046 ret_val = security_secctx_to_secid( 1047 nla_data(info->attrs[NLBL_UNLABEL_A_SECCTX]), 1048 nla_len(info->attrs[NLBL_UNLABEL_A_SECCTX]), 1049 &secid); 1050 if (ret_val != 0) 1051 return ret_val; 1052 1053 return netlbl_unlhsh_add(&init_net, 1054 NULL, addr, mask, addr_len, secid, 1055 &audit_info); 1056} 1057 1058/** 1059 * netlbl_unlabel_staticremove - Handle a STATICREMOVE message 1060 * @skb: the NETLINK buffer 1061 * @info: the Generic NETLINK info block 1062 * 1063 * Description: 1064 * Process a user generated STATICREMOVE message and remove the specified 1065 * unlabeled connection entry. Returns zero on success, negative values on 1066 * failure. 1067 * 1068 */ 1069static int netlbl_unlabel_staticremove(struct sk_buff *skb, 1070 struct genl_info *info) 1071{ 1072 int ret_val; 1073 char *dev_name; 1074 void *addr; 1075 void *mask; 1076 u32 addr_len; 1077 struct netlbl_audit audit_info; 1078 1079 /* See the note in netlbl_unlabel_staticadd() about not allowing both 1080 * IPv4 and IPv6 in the same entry. */ 1081 if (!info->attrs[NLBL_UNLABEL_A_IFACE] || 1082 !((!info->attrs[NLBL_UNLABEL_A_IPV4ADDR] || 1083 !info->attrs[NLBL_UNLABEL_A_IPV4MASK]) ^ 1084 (!info->attrs[NLBL_UNLABEL_A_IPV6ADDR] || 1085 !info->attrs[NLBL_UNLABEL_A_IPV6MASK]))) 1086 return -EINVAL; 1087 1088 netlbl_netlink_auditinfo(skb, &audit_info); 1089 1090 ret_val = netlbl_unlabel_addrinfo_get(info, &addr, &mask, &addr_len); 1091 if (ret_val != 0) 1092 return ret_val; 1093 dev_name = nla_data(info->attrs[NLBL_UNLABEL_A_IFACE]); 1094 1095 return netlbl_unlhsh_remove(&init_net, 1096 dev_name, addr, mask, addr_len, 1097 &audit_info); 1098} 1099 1100/** 1101 * netlbl_unlabel_staticremovedef - Handle a STATICREMOVEDEF message 1102 * @skb: the NETLINK buffer 1103 * @info: the Generic NETLINK info block 1104 * 1105 * Description: 1106 * Process a user generated STATICREMOVEDEF message and remove the default 1107 * unlabeled connection entry. Returns zero on success, negative values on 1108 * failure. 1109 * 1110 */ 1111static int netlbl_unlabel_staticremovedef(struct sk_buff *skb, 1112 struct genl_info *info) 1113{ 1114 int ret_val; 1115 void *addr; 1116 void *mask; 1117 u32 addr_len; 1118 struct netlbl_audit audit_info; 1119 1120 /* See the note in netlbl_unlabel_staticadd() about not allowing both 1121 * IPv4 and IPv6 in the same entry. */ 1122 if (!((!info->attrs[NLBL_UNLABEL_A_IPV4ADDR] || 1123 !info->attrs[NLBL_UNLABEL_A_IPV4MASK]) ^ 1124 (!info->attrs[NLBL_UNLABEL_A_IPV6ADDR] || 1125 !info->attrs[NLBL_UNLABEL_A_IPV6MASK]))) 1126 return -EINVAL; 1127 1128 netlbl_netlink_auditinfo(skb, &audit_info); 1129 1130 ret_val = netlbl_unlabel_addrinfo_get(info, &addr, &mask, &addr_len); 1131 if (ret_val != 0) 1132 return ret_val; 1133 1134 return netlbl_unlhsh_remove(&init_net, 1135 NULL, addr, mask, addr_len, 1136 &audit_info); 1137} 1138 1139 1140/** 1141 * netlbl_unlabel_staticlist_gen - Generate messages for STATICLIST[DEF] 1142 * @cmd: command/message 1143 * @iface: the interface entry 1144 * @addr4: the IPv4 address entry 1145 * @addr6: the IPv6 address entry 1146 * @arg: the netlbl_unlhsh_walk_arg structure 1147 * 1148 * Description: 1149 * This function is designed to be used to generate a response for a 1150 * STATICLIST or STATICLISTDEF message. When called either @addr4 or @addr6 1151 * can be specified, not both, the other unspecified entry should be set to 1152 * NULL by the caller. Returns the size of the message on success, negative 1153 * values on failure. 1154 * 1155 */ 1156static int netlbl_unlabel_staticlist_gen(u32 cmd, 1157 const struct netlbl_unlhsh_iface *iface, 1158 const struct netlbl_unlhsh_addr4 *addr4, 1159 const struct netlbl_unlhsh_addr6 *addr6, 1160 void *arg) 1161{ 1162 int ret_val = -ENOMEM; 1163 struct netlbl_unlhsh_walk_arg *cb_arg = arg; 1164 struct net_device *dev; 1165 void *data; 1166 u32 secid; 1167 char *secctx; 1168 u32 secctx_len; 1169 1170 data = genlmsg_put(cb_arg->skb, NETLINK_CB(cb_arg->nl_cb->skb).pid, 1171 cb_arg->seq, &netlbl_unlabel_gnl_family, 1172 NLM_F_MULTI, cmd); 1173 if (data == NULL) 1174 goto list_cb_failure; 1175 1176 if (iface->ifindex > 0) { 1177 dev = dev_get_by_index(&init_net, iface->ifindex); 1178 if (!dev) { 1179 ret_val = -ENODEV; 1180 goto list_cb_failure; 1181 } 1182 ret_val = nla_put_string(cb_arg->skb, 1183 NLBL_UNLABEL_A_IFACE, dev->name); 1184 dev_put(dev); 1185 if (ret_val != 0) 1186 goto list_cb_failure; 1187 } 1188 1189 if (addr4) { 1190 struct in_addr addr_struct; 1191 1192 addr_struct.s_addr = addr4->list.addr; 1193 ret_val = nla_put(cb_arg->skb, 1194 NLBL_UNLABEL_A_IPV4ADDR, 1195 sizeof(struct in_addr), 1196 &addr_struct); 1197 if (ret_val != 0) 1198 goto list_cb_failure; 1199 1200 addr_struct.s_addr = addr4->list.mask; 1201 ret_val = nla_put(cb_arg->skb, 1202 NLBL_UNLABEL_A_IPV4MASK, 1203 sizeof(struct in_addr), 1204 &addr_struct); 1205 if (ret_val != 0) 1206 goto list_cb_failure; 1207 1208 secid = addr4->secid; 1209 } else { 1210 ret_val = nla_put(cb_arg->skb, 1211 NLBL_UNLABEL_A_IPV6ADDR, 1212 sizeof(struct in6_addr), 1213 &addr6->list.addr); 1214 if (ret_val != 0) 1215 goto list_cb_failure; 1216 1217 ret_val = nla_put(cb_arg->skb, 1218 NLBL_UNLABEL_A_IPV6MASK, 1219 sizeof(struct in6_addr), 1220 &addr6->list.mask); 1221 if (ret_val != 0) 1222 goto list_cb_failure; 1223 1224 secid = addr6->secid; 1225 } 1226 1227 ret_val = security_secid_to_secctx(secid, &secctx, &secctx_len); 1228 if (ret_val != 0) 1229 goto list_cb_failure; 1230 ret_val = nla_put(cb_arg->skb, 1231 NLBL_UNLABEL_A_SECCTX, 1232 secctx_len, 1233 secctx); 1234 security_release_secctx(secctx, secctx_len); 1235 if (ret_val != 0) 1236 goto list_cb_failure; 1237 1238 cb_arg->seq++; 1239 return genlmsg_end(cb_arg->skb, data); 1240 1241list_cb_failure: 1242 genlmsg_cancel(cb_arg->skb, data); 1243 return ret_val; 1244} 1245 1246/** 1247 * netlbl_unlabel_staticlist - Handle a STATICLIST message 1248 * @skb: the NETLINK buffer 1249 * @cb: the NETLINK callback 1250 * 1251 * Description: 1252 * Process a user generated STATICLIST message and dump the unlabeled 1253 * connection hash table in a form suitable for use in a kernel generated 1254 * STATICLIST message. Returns the length of @skb. 1255 * 1256 */ 1257static int netlbl_unlabel_staticlist(struct sk_buff *skb, 1258 struct netlink_callback *cb) 1259{ 1260 struct netlbl_unlhsh_walk_arg cb_arg; 1261 u32 skip_bkt = cb->args[0]; 1262 u32 skip_chain = cb->args[1]; 1263 u32 skip_addr4 = cb->args[2]; 1264 u32 skip_addr6 = cb->args[3]; 1265 u32 iter_bkt; 1266 u32 iter_chain = 0, iter_addr4 = 0, iter_addr6 = 0; 1267 struct netlbl_unlhsh_iface *iface; 1268 struct list_head *iter_list; 1269 struct netlbl_af4list *addr4; 1270#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 1271 struct netlbl_af6list *addr6; 1272#endif 1273 1274 cb_arg.nl_cb = cb; 1275 cb_arg.skb = skb; 1276 cb_arg.seq = cb->nlh->nlmsg_seq; 1277 1278 rcu_read_lock(); 1279 for (iter_bkt = skip_bkt; 1280 iter_bkt < rcu_dereference(netlbl_unlhsh)->size; 1281 iter_bkt++, iter_chain = 0, iter_addr4 = 0, iter_addr6 = 0) { 1282 iter_list = &rcu_dereference(netlbl_unlhsh)->tbl[iter_bkt]; 1283 list_for_each_entry_rcu(iface, iter_list, list) { 1284 if (!iface->valid || 1285 iter_chain++ < skip_chain) 1286 continue; 1287 netlbl_af4list_foreach_rcu(addr4, 1288 &iface->addr4_list) { 1289 if (iter_addr4++ < skip_addr4) 1290 continue; 1291 if (netlbl_unlabel_staticlist_gen( 1292 NLBL_UNLABEL_C_STATICLIST, 1293 iface, 1294 netlbl_unlhsh_addr4_entry(addr4), 1295 NULL, 1296 &cb_arg) < 0) { 1297 iter_addr4--; 1298 iter_chain--; 1299 goto unlabel_staticlist_return; 1300 } 1301 } 1302#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 1303 netlbl_af6list_foreach_rcu(addr6, 1304 &iface->addr6_list) { 1305 if (iter_addr6++ < skip_addr6) 1306 continue; 1307 if (netlbl_unlabel_staticlist_gen( 1308 NLBL_UNLABEL_C_STATICLIST, 1309 iface, 1310 NULL, 1311 netlbl_unlhsh_addr6_entry(addr6), 1312 &cb_arg) < 0) { 1313 iter_addr6--; 1314 iter_chain--; 1315 goto unlabel_staticlist_return; 1316 } 1317 } 1318#endif /* IPv6 */ 1319 } 1320 } 1321 1322unlabel_staticlist_return: 1323 rcu_read_unlock(); 1324 cb->args[0] = skip_bkt; 1325 cb->args[1] = skip_chain; 1326 cb->args[2] = skip_addr4; 1327 cb->args[3] = skip_addr6; 1328 return skb->len; 1329} 1330 1331/** 1332 * netlbl_unlabel_staticlistdef - Handle a STATICLISTDEF message 1333 * @skb: the NETLINK buffer 1334 * @cb: the NETLINK callback 1335 * 1336 * Description: 1337 * Process a user generated STATICLISTDEF message and dump the default 1338 * unlabeled connection entry in a form suitable for use in a kernel generated 1339 * STATICLISTDEF message. Returns the length of @skb. 1340 * 1341 */ 1342static int netlbl_unlabel_staticlistdef(struct sk_buff *skb, 1343 struct netlink_callback *cb) 1344{ 1345 struct netlbl_unlhsh_walk_arg cb_arg; 1346 struct netlbl_unlhsh_iface *iface; 1347 u32 skip_addr4 = cb->args[0]; 1348 u32 skip_addr6 = cb->args[1]; 1349 u32 iter_addr4 = 0; 1350 struct netlbl_af4list *addr4; 1351#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 1352 u32 iter_addr6 = 0; 1353 struct netlbl_af6list *addr6; 1354#endif 1355 1356 cb_arg.nl_cb = cb; 1357 cb_arg.skb = skb; 1358 cb_arg.seq = cb->nlh->nlmsg_seq; 1359 1360 rcu_read_lock(); 1361 iface = rcu_dereference(netlbl_unlhsh_def); 1362 if (iface == NULL || !iface->valid) 1363 goto unlabel_staticlistdef_return; 1364 1365 netlbl_af4list_foreach_rcu(addr4, &iface->addr4_list) { 1366 if (iter_addr4++ < skip_addr4) 1367 continue; 1368 if (netlbl_unlabel_staticlist_gen(NLBL_UNLABEL_C_STATICLISTDEF, 1369 iface, 1370 netlbl_unlhsh_addr4_entry(addr4), 1371 NULL, 1372 &cb_arg) < 0) { 1373 iter_addr4--; 1374 goto unlabel_staticlistdef_return; 1375 } 1376 } 1377#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 1378 netlbl_af6list_foreach_rcu(addr6, &iface->addr6_list) { 1379 if (iter_addr6++ < skip_addr6) 1380 continue; 1381 if (netlbl_unlabel_staticlist_gen(NLBL_UNLABEL_C_STATICLISTDEF, 1382 iface, 1383 NULL, 1384 netlbl_unlhsh_addr6_entry(addr6), 1385 &cb_arg) < 0) { 1386 iter_addr6--; 1387 goto unlabel_staticlistdef_return; 1388 } 1389 } 1390#endif /* IPv6 */ 1391 1392unlabel_staticlistdef_return: 1393 rcu_read_unlock(); 1394 cb->args[0] = skip_addr4; 1395 cb->args[1] = skip_addr6; 1396 return skb->len; 1397} 1398 1399/* 1400 * NetLabel Generic NETLINK Command Definitions 1401 */ 1402 1403static struct genl_ops netlbl_unlabel_genl_ops[] = { 1404 { 1405 .cmd = NLBL_UNLABEL_C_STATICADD, 1406 .flags = GENL_ADMIN_PERM, 1407 .policy = netlbl_unlabel_genl_policy, 1408 .doit = netlbl_unlabel_staticadd, 1409 .dumpit = NULL, 1410 }, 1411 { 1412 .cmd = NLBL_UNLABEL_C_STATICREMOVE, 1413 .flags = GENL_ADMIN_PERM, 1414 .policy = netlbl_unlabel_genl_policy, 1415 .doit = netlbl_unlabel_staticremove, 1416 .dumpit = NULL, 1417 }, 1418 { 1419 .cmd = NLBL_UNLABEL_C_STATICLIST, 1420 .flags = 0, 1421 .policy = netlbl_unlabel_genl_policy, 1422 .doit = NULL, 1423 .dumpit = netlbl_unlabel_staticlist, 1424 }, 1425 { 1426 .cmd = NLBL_UNLABEL_C_STATICADDDEF, 1427 .flags = GENL_ADMIN_PERM, 1428 .policy = netlbl_unlabel_genl_policy, 1429 .doit = netlbl_unlabel_staticadddef, 1430 .dumpit = NULL, 1431 }, 1432 { 1433 .cmd = NLBL_UNLABEL_C_STATICREMOVEDEF, 1434 .flags = GENL_ADMIN_PERM, 1435 .policy = netlbl_unlabel_genl_policy, 1436 .doit = netlbl_unlabel_staticremovedef, 1437 .dumpit = NULL, 1438 }, 1439 { 1440 .cmd = NLBL_UNLABEL_C_STATICLISTDEF, 1441 .flags = 0, 1442 .policy = netlbl_unlabel_genl_policy, 1443 .doit = NULL, 1444 .dumpit = netlbl_unlabel_staticlistdef, 1445 }, 1446 { 1447 .cmd = NLBL_UNLABEL_C_ACCEPT, 1448 .flags = GENL_ADMIN_PERM, 1449 .policy = netlbl_unlabel_genl_policy, 1450 .doit = netlbl_unlabel_accept, 1451 .dumpit = NULL, 1452 }, 1453 { 1454 .cmd = NLBL_UNLABEL_C_LIST, 1455 .flags = 0, 1456 .policy = netlbl_unlabel_genl_policy, 1457 .doit = netlbl_unlabel_list, 1458 .dumpit = NULL, 1459 }, 1460}; 1461 1462/* 1463 * NetLabel Generic NETLINK Protocol Functions 1464 */ 1465 1466/** 1467 * netlbl_unlabel_genl_init - Register the Unlabeled NetLabel component 1468 * 1469 * Description: 1470 * Register the unlabeled packet NetLabel component with the Generic NETLINK 1471 * mechanism. Returns zero on success, negative values on failure. 1472 * 1473 */ 1474int __init netlbl_unlabel_genl_init(void) 1475{ 1476 return genl_register_family_with_ops(&netlbl_unlabel_gnl_family, 1477 netlbl_unlabel_genl_ops, ARRAY_SIZE(netlbl_unlabel_genl_ops)); 1478} 1479 1480/* 1481 * NetLabel KAPI Hooks 1482 */ 1483 1484static struct notifier_block netlbl_unlhsh_netdev_notifier = { 1485 .notifier_call = netlbl_unlhsh_netdev_handler, 1486}; 1487 1488/** 1489 * netlbl_unlabel_init - Initialize the unlabeled connection hash table 1490 * @size: the number of bits to use for the hash buckets 1491 * 1492 * Description: 1493 * Initializes the unlabeled connection hash table and registers a network 1494 * device notification handler. This function should only be called by the 1495 * NetLabel subsystem itself during initialization. Returns zero on success, 1496 * non-zero values on error. 1497 * 1498 */ 1499int __init netlbl_unlabel_init(u32 size) 1500{ 1501 u32 iter; 1502 struct netlbl_unlhsh_tbl *hsh_tbl; 1503 1504 if (size == 0) 1505 return -EINVAL; 1506 1507 hsh_tbl = kmalloc(sizeof(*hsh_tbl), GFP_KERNEL); 1508 if (hsh_tbl == NULL) 1509 return -ENOMEM; 1510 hsh_tbl->size = 1 << size; 1511 hsh_tbl->tbl = kcalloc(hsh_tbl->size, 1512 sizeof(struct list_head), 1513 GFP_KERNEL); 1514 if (hsh_tbl->tbl == NULL) { 1515 kfree(hsh_tbl); 1516 return -ENOMEM; 1517 } 1518 for (iter = 0; iter < hsh_tbl->size; iter++) 1519 INIT_LIST_HEAD(&hsh_tbl->tbl[iter]); 1520 1521 rcu_read_lock(); 1522 spin_lock(&netlbl_unlhsh_lock); 1523 rcu_assign_pointer(netlbl_unlhsh, hsh_tbl); 1524 spin_unlock(&netlbl_unlhsh_lock); 1525 rcu_read_unlock(); 1526 1527 register_netdevice_notifier(&netlbl_unlhsh_netdev_notifier); 1528 1529 return 0; 1530} 1531 1532/** 1533 * netlbl_unlabel_getattr - Get the security attributes for an unlabled packet 1534 * @skb: the packet 1535 * @family: protocol family 1536 * @secattr: the security attributes 1537 * 1538 * Description: 1539 * Determine the security attributes, if any, for an unlabled packet and return 1540 * them in @secattr. Returns zero on success and negative values on failure. 1541 * 1542 */ 1543int netlbl_unlabel_getattr(const struct sk_buff *skb, 1544 u16 family, 1545 struct netlbl_lsm_secattr *secattr) 1546{ 1547 struct netlbl_unlhsh_iface *iface; 1548 1549 rcu_read_lock(); 1550 iface = netlbl_unlhsh_search_iface_def(skb->skb_iif); 1551 if (iface == NULL) 1552 goto unlabel_getattr_nolabel; 1553 switch (family) { 1554 case PF_INET: { 1555 struct iphdr *hdr4; 1556 struct netlbl_af4list *addr4; 1557 1558 hdr4 = ip_hdr(skb); 1559 addr4 = netlbl_af4list_search(hdr4->saddr, 1560 &iface->addr4_list); 1561 if (addr4 == NULL) 1562 goto unlabel_getattr_nolabel; 1563 secattr->attr.secid = netlbl_unlhsh_addr4_entry(addr4)->secid; 1564 break; 1565 } 1566#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 1567 case PF_INET6: { 1568 struct ipv6hdr *hdr6; 1569 struct netlbl_af6list *addr6; 1570 1571 hdr6 = ipv6_hdr(skb); 1572 addr6 = netlbl_af6list_search(&hdr6->saddr, 1573 &iface->addr6_list); 1574 if (addr6 == NULL) 1575 goto unlabel_getattr_nolabel; 1576 secattr->attr.secid = netlbl_unlhsh_addr6_entry(addr6)->secid; 1577 break; 1578 } 1579#endif /* IPv6 */ 1580 default: 1581 goto unlabel_getattr_nolabel; 1582 } 1583 rcu_read_unlock(); 1584 1585 secattr->flags |= NETLBL_SECATTR_SECID; 1586 secattr->type = NETLBL_NLTYPE_UNLABELED; 1587 return 0; 1588 1589unlabel_getattr_nolabel: 1590 rcu_read_unlock(); 1591 if (netlabel_unlabel_acceptflg == 0) 1592 return -ENOMSG; 1593 secattr->type = NETLBL_NLTYPE_UNLABELED; 1594 return 0; 1595} 1596 1597/** 1598 * netlbl_unlabel_defconf - Set the default config to allow unlabeled packets 1599 * 1600 * Description: 1601 * Set the default NetLabel configuration to allow incoming unlabeled packets 1602 * and to send unlabeled network traffic by default. 1603 * 1604 */ 1605int __init netlbl_unlabel_defconf(void) 1606{ 1607 int ret_val; 1608 struct netlbl_dom_map *entry; 1609 struct netlbl_audit audit_info; 1610 1611 /* Only the kernel is allowed to call this function and the only time 1612 * it is called is at bootup before the audit subsystem is reporting 1613 * messages so don't worry to much about these values. */ 1614 security_task_getsecid(current, &audit_info.secid); 1615 audit_info.loginuid = 0; 1616 audit_info.sessionid = 0; 1617 1618 entry = kzalloc(sizeof(*entry), GFP_KERNEL); 1619 if (entry == NULL) 1620 return -ENOMEM; 1621 entry->type = NETLBL_NLTYPE_UNLABELED; 1622 ret_val = netlbl_domhsh_add_default(entry, &audit_info); 1623 if (ret_val != 0) 1624 return ret_val; 1625 1626 netlbl_unlabel_acceptflg_set(1, &audit_info); 1627 1628 return 0; 1629}