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