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 const struct in_addr *addr4 = addr; 430 const struct in_addr *mask4 = mask; 431 432 ret_val = netlbl_unlhsh_add_addr4(iface, addr4, mask4, secid); 433 if (audit_buf != NULL) 434 netlbl_af4list_audit_addr(audit_buf, 1, 435 dev_name, 436 addr4->s_addr, 437 mask4->s_addr); 438 break; 439 } 440 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 441 case sizeof(struct in6_addr): { 442 const struct in6_addr *addr6 = addr; 443 const struct in6_addr *mask6 = mask; 444 445 ret_val = netlbl_unlhsh_add_addr6(iface, addr6, mask6, secid); 446 if (audit_buf != NULL) 447 netlbl_af6list_audit_addr(audit_buf, 1, 448 dev_name, 449 addr6, mask6); 450 break; 451 } 452 #endif /* IPv6 */ 453 default: 454 ret_val = -EINVAL; 455 } 456 if (ret_val == 0) 457 atomic_inc(&netlabel_mgmt_protocount); 458 459 unlhsh_add_return: 460 rcu_read_unlock(); 461 if (audit_buf != NULL) { 462 if (security_secid_to_secctx(secid, 463 &secctx, 464 &secctx_len) == 0) { 465 audit_log_format(audit_buf, " sec_obj=%s", secctx); 466 security_release_secctx(secctx, secctx_len); 467 } 468 audit_log_format(audit_buf, " res=%u", ret_val == 0 ? 1 : 0); 469 audit_log_end(audit_buf); 470 } 471 return ret_val; 472 } 473 474 /** 475 * netlbl_unlhsh_remove_addr4 - Remove an IPv4 address entry 476 * @net: network namespace 477 * @iface: interface entry 478 * @addr: IP address 479 * @mask: IP address mask 480 * @audit_info: NetLabel audit information 481 * 482 * Description: 483 * Remove an IP address entry from the unlabeled connection hash table. 484 * Returns zero on success, negative values on failure. 485 * 486 */ 487 static int netlbl_unlhsh_remove_addr4(struct net *net, 488 struct netlbl_unlhsh_iface *iface, 489 const struct in_addr *addr, 490 const struct in_addr *mask, 491 struct netlbl_audit *audit_info) 492 { 493 struct netlbl_af4list *list_entry; 494 struct netlbl_unlhsh_addr4 *entry; 495 struct audit_buffer *audit_buf; 496 struct net_device *dev; 497 char *secctx; 498 u32 secctx_len; 499 500 spin_lock(&netlbl_unlhsh_lock); 501 list_entry = netlbl_af4list_remove(addr->s_addr, mask->s_addr, 502 &iface->addr4_list); 503 spin_unlock(&netlbl_unlhsh_lock); 504 if (list_entry != NULL) 505 entry = netlbl_unlhsh_addr4_entry(list_entry); 506 else 507 entry = NULL; 508 509 audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_STCDEL, 510 audit_info); 511 if (audit_buf != NULL) { 512 dev = dev_get_by_index(net, iface->ifindex); 513 netlbl_af4list_audit_addr(audit_buf, 1, 514 (dev != NULL ? dev->name : NULL), 515 addr->s_addr, mask->s_addr); 516 if (dev != NULL) 517 dev_put(dev); 518 if (entry != NULL && 519 security_secid_to_secctx(entry->secid, 520 &secctx, &secctx_len) == 0) { 521 audit_log_format(audit_buf, " sec_obj=%s", secctx); 522 security_release_secctx(secctx, secctx_len); 523 } 524 audit_log_format(audit_buf, " res=%u", entry != NULL ? 1 : 0); 525 audit_log_end(audit_buf); 526 } 527 528 if (entry == NULL) 529 return -ENOENT; 530 531 kfree_rcu(entry, rcu); 532 return 0; 533 } 534 535 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 536 /** 537 * netlbl_unlhsh_remove_addr6 - Remove an IPv6 address entry 538 * @net: network namespace 539 * @iface: interface entry 540 * @addr: IP address 541 * @mask: IP address mask 542 * @audit_info: NetLabel audit information 543 * 544 * Description: 545 * Remove an IP address entry from the unlabeled connection hash table. 546 * Returns zero on success, negative values on failure. 547 * 548 */ 549 static int netlbl_unlhsh_remove_addr6(struct net *net, 550 struct netlbl_unlhsh_iface *iface, 551 const struct in6_addr *addr, 552 const struct in6_addr *mask, 553 struct netlbl_audit *audit_info) 554 { 555 struct netlbl_af6list *list_entry; 556 struct netlbl_unlhsh_addr6 *entry; 557 struct audit_buffer *audit_buf; 558 struct net_device *dev; 559 char *secctx; 560 u32 secctx_len; 561 562 spin_lock(&netlbl_unlhsh_lock); 563 list_entry = netlbl_af6list_remove(addr, mask, &iface->addr6_list); 564 spin_unlock(&netlbl_unlhsh_lock); 565 if (list_entry != NULL) 566 entry = netlbl_unlhsh_addr6_entry(list_entry); 567 else 568 entry = NULL; 569 570 audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_STCDEL, 571 audit_info); 572 if (audit_buf != NULL) { 573 dev = dev_get_by_index(net, iface->ifindex); 574 netlbl_af6list_audit_addr(audit_buf, 1, 575 (dev != NULL ? dev->name : NULL), 576 addr, mask); 577 if (dev != NULL) 578 dev_put(dev); 579 if (entry != NULL && 580 security_secid_to_secctx(entry->secid, 581 &secctx, &secctx_len) == 0) { 582 audit_log_format(audit_buf, " sec_obj=%s", secctx); 583 security_release_secctx(secctx, secctx_len); 584 } 585 audit_log_format(audit_buf, " res=%u", entry != NULL ? 1 : 0); 586 audit_log_end(audit_buf); 587 } 588 589 if (entry == NULL) 590 return -ENOENT; 591 592 kfree_rcu(entry, rcu); 593 return 0; 594 } 595 #endif /* IPv6 */ 596 597 /** 598 * netlbl_unlhsh_condremove_iface - Remove an interface entry 599 * @iface: the interface entry 600 * 601 * Description: 602 * Remove an interface entry from the unlabeled connection hash table if it is 603 * empty. An interface entry is considered to be empty if there are no 604 * address entries assigned to it. 605 * 606 */ 607 static void netlbl_unlhsh_condremove_iface(struct netlbl_unlhsh_iface *iface) 608 { 609 struct netlbl_af4list *iter4; 610 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 611 struct netlbl_af6list *iter6; 612 #endif /* IPv6 */ 613 614 spin_lock(&netlbl_unlhsh_lock); 615 netlbl_af4list_foreach_rcu(iter4, &iface->addr4_list) 616 goto unlhsh_condremove_failure; 617 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 618 netlbl_af6list_foreach_rcu(iter6, &iface->addr6_list) 619 goto unlhsh_condremove_failure; 620 #endif /* IPv6 */ 621 iface->valid = 0; 622 if (iface->ifindex > 0) 623 list_del_rcu(&iface->list); 624 else 625 rcu_assign_pointer(netlbl_unlhsh_def, NULL); 626 spin_unlock(&netlbl_unlhsh_lock); 627 628 call_rcu(&iface->rcu, netlbl_unlhsh_free_iface); 629 return; 630 631 unlhsh_condremove_failure: 632 spin_unlock(&netlbl_unlhsh_lock); 633 } 634 635 /** 636 * netlbl_unlhsh_remove - Remove an entry from the unlabeled hash table 637 * @net: network namespace 638 * @dev_name: interface name 639 * @addr: IP address in network byte order 640 * @mask: address mask in network byte order 641 * @addr_len: length of address/mask (4 for IPv4, 16 for IPv6) 642 * @audit_info: NetLabel audit information 643 * 644 * Description: 645 * Removes and existing entry from the unlabeled connection hash table. 646 * Returns zero on success, negative values on failure. 647 * 648 */ 649 int netlbl_unlhsh_remove(struct net *net, 650 const char *dev_name, 651 const void *addr, 652 const void *mask, 653 u32 addr_len, 654 struct netlbl_audit *audit_info) 655 { 656 int ret_val; 657 struct net_device *dev; 658 struct netlbl_unlhsh_iface *iface; 659 660 if (addr_len != sizeof(struct in_addr) && 661 addr_len != sizeof(struct in6_addr)) 662 return -EINVAL; 663 664 rcu_read_lock(); 665 if (dev_name != NULL) { 666 dev = dev_get_by_name_rcu(net, dev_name); 667 if (dev == NULL) { 668 ret_val = -ENODEV; 669 goto unlhsh_remove_return; 670 } 671 iface = netlbl_unlhsh_search_iface(dev->ifindex); 672 } else 673 iface = rcu_dereference(netlbl_unlhsh_def); 674 if (iface == NULL) { 675 ret_val = -ENOENT; 676 goto unlhsh_remove_return; 677 } 678 switch (addr_len) { 679 case sizeof(struct in_addr): 680 ret_val = netlbl_unlhsh_remove_addr4(net, 681 iface, addr, mask, 682 audit_info); 683 break; 684 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 685 case sizeof(struct in6_addr): 686 ret_val = netlbl_unlhsh_remove_addr6(net, 687 iface, addr, mask, 688 audit_info); 689 break; 690 #endif /* IPv6 */ 691 default: 692 ret_val = -EINVAL; 693 } 694 if (ret_val == 0) { 695 netlbl_unlhsh_condremove_iface(iface); 696 atomic_dec(&netlabel_mgmt_protocount); 697 } 698 699 unlhsh_remove_return: 700 rcu_read_unlock(); 701 return ret_val; 702 } 703 704 /* 705 * General Helper Functions 706 */ 707 708 /** 709 * netlbl_unlhsh_netdev_handler - Network device notification handler 710 * @this: notifier block 711 * @event: the event 712 * @ptr: the network device (cast to void) 713 * 714 * Description: 715 * Handle network device events, although at present all we care about is a 716 * network device going away. In the case of a device going away we clear any 717 * related entries from the unlabeled connection hash table. 718 * 719 */ 720 static int netlbl_unlhsh_netdev_handler(struct notifier_block *this, 721 unsigned long event, 722 void *ptr) 723 { 724 struct net_device *dev = ptr; 725 struct netlbl_unlhsh_iface *iface = NULL; 726 727 if (!net_eq(dev_net(dev), &init_net)) 728 return NOTIFY_DONE; 729 730 /* XXX - should this be a check for NETDEV_DOWN or _UNREGISTER? */ 731 if (event == NETDEV_DOWN) { 732 spin_lock(&netlbl_unlhsh_lock); 733 iface = netlbl_unlhsh_search_iface(dev->ifindex); 734 if (iface != NULL && iface->valid) { 735 iface->valid = 0; 736 list_del_rcu(&iface->list); 737 } else 738 iface = NULL; 739 spin_unlock(&netlbl_unlhsh_lock); 740 } 741 742 if (iface != NULL) 743 call_rcu(&iface->rcu, netlbl_unlhsh_free_iface); 744 745 return NOTIFY_DONE; 746 } 747 748 /** 749 * netlbl_unlabel_acceptflg_set - Set the unlabeled accept flag 750 * @value: desired value 751 * @audit_info: NetLabel audit information 752 * 753 * Description: 754 * Set the value of the unlabeled accept flag to @value. 755 * 756 */ 757 static void netlbl_unlabel_acceptflg_set(u8 value, 758 struct netlbl_audit *audit_info) 759 { 760 struct audit_buffer *audit_buf; 761 u8 old_val; 762 763 old_val = netlabel_unlabel_acceptflg; 764 netlabel_unlabel_acceptflg = value; 765 audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_ALLOW, 766 audit_info); 767 if (audit_buf != NULL) { 768 audit_log_format(audit_buf, 769 " unlbl_accept=%u old=%u", value, old_val); 770 audit_log_end(audit_buf); 771 } 772 } 773 774 /** 775 * netlbl_unlabel_addrinfo_get - Get the IPv4/6 address information 776 * @info: the Generic NETLINK info block 777 * @addr: the IP address 778 * @mask: the IP address mask 779 * @len: the address length 780 * 781 * Description: 782 * Examine the Generic NETLINK message and extract the IP address information. 783 * Returns zero on success, negative values on failure. 784 * 785 */ 786 static int netlbl_unlabel_addrinfo_get(struct genl_info *info, 787 void **addr, 788 void **mask, 789 u32 *len) 790 { 791 u32 addr_len; 792 793 if (info->attrs[NLBL_UNLABEL_A_IPV4ADDR]) { 794 addr_len = nla_len(info->attrs[NLBL_UNLABEL_A_IPV4ADDR]); 795 if (addr_len != sizeof(struct in_addr) && 796 addr_len != nla_len(info->attrs[NLBL_UNLABEL_A_IPV4MASK])) 797 return -EINVAL; 798 *len = addr_len; 799 *addr = nla_data(info->attrs[NLBL_UNLABEL_A_IPV4ADDR]); 800 *mask = nla_data(info->attrs[NLBL_UNLABEL_A_IPV4MASK]); 801 return 0; 802 } else if (info->attrs[NLBL_UNLABEL_A_IPV6ADDR]) { 803 addr_len = nla_len(info->attrs[NLBL_UNLABEL_A_IPV6ADDR]); 804 if (addr_len != sizeof(struct in6_addr) && 805 addr_len != nla_len(info->attrs[NLBL_UNLABEL_A_IPV6MASK])) 806 return -EINVAL; 807 *len = addr_len; 808 *addr = nla_data(info->attrs[NLBL_UNLABEL_A_IPV6ADDR]); 809 *mask = nla_data(info->attrs[NLBL_UNLABEL_A_IPV6MASK]); 810 return 0; 811 } 812 813 return -EINVAL; 814 } 815 816 /* 817 * NetLabel Command Handlers 818 */ 819 820 /** 821 * netlbl_unlabel_accept - Handle an ACCEPT message 822 * @skb: the NETLINK buffer 823 * @info: the Generic NETLINK info block 824 * 825 * Description: 826 * Process a user generated ACCEPT message and set the accept flag accordingly. 827 * Returns zero on success, negative values on failure. 828 * 829 */ 830 static int netlbl_unlabel_accept(struct sk_buff *skb, struct genl_info *info) 831 { 832 u8 value; 833 struct netlbl_audit audit_info; 834 835 if (info->attrs[NLBL_UNLABEL_A_ACPTFLG]) { 836 value = nla_get_u8(info->attrs[NLBL_UNLABEL_A_ACPTFLG]); 837 if (value == 1 || value == 0) { 838 netlbl_netlink_auditinfo(skb, &audit_info); 839 netlbl_unlabel_acceptflg_set(value, &audit_info); 840 return 0; 841 } 842 } 843 844 return -EINVAL; 845 } 846 847 /** 848 * netlbl_unlabel_list - Handle a LIST message 849 * @skb: the NETLINK buffer 850 * @info: the Generic NETLINK info block 851 * 852 * Description: 853 * Process a user generated LIST message and respond with the current status. 854 * Returns zero on success, negative values on failure. 855 * 856 */ 857 static int netlbl_unlabel_list(struct sk_buff *skb, struct genl_info *info) 858 { 859 int ret_val = -EINVAL; 860 struct sk_buff *ans_skb; 861 void *data; 862 863 ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 864 if (ans_skb == NULL) 865 goto list_failure; 866 data = genlmsg_put_reply(ans_skb, info, &netlbl_unlabel_gnl_family, 867 0, NLBL_UNLABEL_C_LIST); 868 if (data == NULL) { 869 ret_val = -ENOMEM; 870 goto list_failure; 871 } 872 873 ret_val = nla_put_u8(ans_skb, 874 NLBL_UNLABEL_A_ACPTFLG, 875 netlabel_unlabel_acceptflg); 876 if (ret_val != 0) 877 goto list_failure; 878 879 genlmsg_end(ans_skb, data); 880 return genlmsg_reply(ans_skb, info); 881 882 list_failure: 883 kfree_skb(ans_skb); 884 return ret_val; 885 } 886 887 /** 888 * netlbl_unlabel_staticadd - Handle a STATICADD message 889 * @skb: the NETLINK buffer 890 * @info: the Generic NETLINK info block 891 * 892 * Description: 893 * Process a user generated STATICADD message and add a new unlabeled 894 * connection entry to the hash table. Returns zero on success, negative 895 * values on failure. 896 * 897 */ 898 static int netlbl_unlabel_staticadd(struct sk_buff *skb, 899 struct genl_info *info) 900 { 901 int ret_val; 902 char *dev_name; 903 void *addr; 904 void *mask; 905 u32 addr_len; 906 u32 secid; 907 struct netlbl_audit audit_info; 908 909 /* Don't allow users to add both IPv4 and IPv6 addresses for a 910 * single entry. However, allow users to create two entries, one each 911 * for IPv4 and IPv4, with the same LSM security context which should 912 * achieve the same result. */ 913 if (!info->attrs[NLBL_UNLABEL_A_SECCTX] || 914 !info->attrs[NLBL_UNLABEL_A_IFACE] || 915 !((!info->attrs[NLBL_UNLABEL_A_IPV4ADDR] || 916 !info->attrs[NLBL_UNLABEL_A_IPV4MASK]) ^ 917 (!info->attrs[NLBL_UNLABEL_A_IPV6ADDR] || 918 !info->attrs[NLBL_UNLABEL_A_IPV6MASK]))) 919 return -EINVAL; 920 921 netlbl_netlink_auditinfo(skb, &audit_info); 922 923 ret_val = netlbl_unlabel_addrinfo_get(info, &addr, &mask, &addr_len); 924 if (ret_val != 0) 925 return ret_val; 926 dev_name = nla_data(info->attrs[NLBL_UNLABEL_A_IFACE]); 927 ret_val = security_secctx_to_secid( 928 nla_data(info->attrs[NLBL_UNLABEL_A_SECCTX]), 929 nla_len(info->attrs[NLBL_UNLABEL_A_SECCTX]), 930 &secid); 931 if (ret_val != 0) 932 return ret_val; 933 934 return netlbl_unlhsh_add(&init_net, 935 dev_name, addr, mask, addr_len, secid, 936 &audit_info); 937 } 938 939 /** 940 * netlbl_unlabel_staticadddef - Handle a STATICADDDEF message 941 * @skb: the NETLINK buffer 942 * @info: the Generic NETLINK info block 943 * 944 * Description: 945 * Process a user generated STATICADDDEF message and add a new default 946 * unlabeled connection entry. Returns zero on success, negative values on 947 * failure. 948 * 949 */ 950 static int netlbl_unlabel_staticadddef(struct sk_buff *skb, 951 struct genl_info *info) 952 { 953 int ret_val; 954 void *addr; 955 void *mask; 956 u32 addr_len; 957 u32 secid; 958 struct netlbl_audit audit_info; 959 960 /* Don't allow users to add both IPv4 and IPv6 addresses for a 961 * single entry. However, allow users to create two entries, one each 962 * for IPv4 and IPv6, with the same LSM security context which should 963 * achieve the same result. */ 964 if (!info->attrs[NLBL_UNLABEL_A_SECCTX] || 965 !((!info->attrs[NLBL_UNLABEL_A_IPV4ADDR] || 966 !info->attrs[NLBL_UNLABEL_A_IPV4MASK]) ^ 967 (!info->attrs[NLBL_UNLABEL_A_IPV6ADDR] || 968 !info->attrs[NLBL_UNLABEL_A_IPV6MASK]))) 969 return -EINVAL; 970 971 netlbl_netlink_auditinfo(skb, &audit_info); 972 973 ret_val = netlbl_unlabel_addrinfo_get(info, &addr, &mask, &addr_len); 974 if (ret_val != 0) 975 return ret_val; 976 ret_val = security_secctx_to_secid( 977 nla_data(info->attrs[NLBL_UNLABEL_A_SECCTX]), 978 nla_len(info->attrs[NLBL_UNLABEL_A_SECCTX]), 979 &secid); 980 if (ret_val != 0) 981 return ret_val; 982 983 return netlbl_unlhsh_add(&init_net, 984 NULL, addr, mask, addr_len, secid, 985 &audit_info); 986 } 987 988 /** 989 * netlbl_unlabel_staticremove - Handle a STATICREMOVE message 990 * @skb: the NETLINK buffer 991 * @info: the Generic NETLINK info block 992 * 993 * Description: 994 * Process a user generated STATICREMOVE message and remove the specified 995 * unlabeled connection entry. Returns zero on success, negative values on 996 * failure. 997 * 998 */ 999 static int netlbl_unlabel_staticremove(struct sk_buff *skb, 1000 struct genl_info *info) 1001 { 1002 int ret_val; 1003 char *dev_name; 1004 void *addr; 1005 void *mask; 1006 u32 addr_len; 1007 struct netlbl_audit audit_info; 1008 1009 /* See the note in netlbl_unlabel_staticadd() about not allowing both 1010 * IPv4 and IPv6 in the same entry. */ 1011 if (!info->attrs[NLBL_UNLABEL_A_IFACE] || 1012 !((!info->attrs[NLBL_UNLABEL_A_IPV4ADDR] || 1013 !info->attrs[NLBL_UNLABEL_A_IPV4MASK]) ^ 1014 (!info->attrs[NLBL_UNLABEL_A_IPV6ADDR] || 1015 !info->attrs[NLBL_UNLABEL_A_IPV6MASK]))) 1016 return -EINVAL; 1017 1018 netlbl_netlink_auditinfo(skb, &audit_info); 1019 1020 ret_val = netlbl_unlabel_addrinfo_get(info, &addr, &mask, &addr_len); 1021 if (ret_val != 0) 1022 return ret_val; 1023 dev_name = nla_data(info->attrs[NLBL_UNLABEL_A_IFACE]); 1024 1025 return netlbl_unlhsh_remove(&init_net, 1026 dev_name, addr, mask, addr_len, 1027 &audit_info); 1028 } 1029 1030 /** 1031 * netlbl_unlabel_staticremovedef - Handle a STATICREMOVEDEF message 1032 * @skb: the NETLINK buffer 1033 * @info: the Generic NETLINK info block 1034 * 1035 * Description: 1036 * Process a user generated STATICREMOVEDEF message and remove the default 1037 * unlabeled connection entry. Returns zero on success, negative values on 1038 * failure. 1039 * 1040 */ 1041 static int netlbl_unlabel_staticremovedef(struct sk_buff *skb, 1042 struct genl_info *info) 1043 { 1044 int ret_val; 1045 void *addr; 1046 void *mask; 1047 u32 addr_len; 1048 struct netlbl_audit audit_info; 1049 1050 /* See the note in netlbl_unlabel_staticadd() about not allowing both 1051 * IPv4 and IPv6 in the same entry. */ 1052 if (!((!info->attrs[NLBL_UNLABEL_A_IPV4ADDR] || 1053 !info->attrs[NLBL_UNLABEL_A_IPV4MASK]) ^ 1054 (!info->attrs[NLBL_UNLABEL_A_IPV6ADDR] || 1055 !info->attrs[NLBL_UNLABEL_A_IPV6MASK]))) 1056 return -EINVAL; 1057 1058 netlbl_netlink_auditinfo(skb, &audit_info); 1059 1060 ret_val = netlbl_unlabel_addrinfo_get(info, &addr, &mask, &addr_len); 1061 if (ret_val != 0) 1062 return ret_val; 1063 1064 return netlbl_unlhsh_remove(&init_net, 1065 NULL, addr, mask, addr_len, 1066 &audit_info); 1067 } 1068 1069 1070 /** 1071 * netlbl_unlabel_staticlist_gen - Generate messages for STATICLIST[DEF] 1072 * @cmd: command/message 1073 * @iface: the interface entry 1074 * @addr4: the IPv4 address entry 1075 * @addr6: the IPv6 address entry 1076 * @arg: the netlbl_unlhsh_walk_arg structure 1077 * 1078 * Description: 1079 * This function is designed to be used to generate a response for a 1080 * STATICLIST or STATICLISTDEF message. When called either @addr4 or @addr6 1081 * can be specified, not both, the other unspecified entry should be set to 1082 * NULL by the caller. Returns the size of the message on success, negative 1083 * values on failure. 1084 * 1085 */ 1086 static int netlbl_unlabel_staticlist_gen(u32 cmd, 1087 const struct netlbl_unlhsh_iface *iface, 1088 const struct netlbl_unlhsh_addr4 *addr4, 1089 const struct netlbl_unlhsh_addr6 *addr6, 1090 void *arg) 1091 { 1092 int ret_val = -ENOMEM; 1093 struct netlbl_unlhsh_walk_arg *cb_arg = arg; 1094 struct net_device *dev; 1095 void *data; 1096 u32 secid; 1097 char *secctx; 1098 u32 secctx_len; 1099 1100 data = genlmsg_put(cb_arg->skb, NETLINK_CB(cb_arg->nl_cb->skb).pid, 1101 cb_arg->seq, &netlbl_unlabel_gnl_family, 1102 NLM_F_MULTI, cmd); 1103 if (data == NULL) 1104 goto list_cb_failure; 1105 1106 if (iface->ifindex > 0) { 1107 dev = dev_get_by_index(&init_net, iface->ifindex); 1108 if (!dev) { 1109 ret_val = -ENODEV; 1110 goto list_cb_failure; 1111 } 1112 ret_val = nla_put_string(cb_arg->skb, 1113 NLBL_UNLABEL_A_IFACE, dev->name); 1114 dev_put(dev); 1115 if (ret_val != 0) 1116 goto list_cb_failure; 1117 } 1118 1119 if (addr4) { 1120 struct in_addr addr_struct; 1121 1122 addr_struct.s_addr = addr4->list.addr; 1123 ret_val = nla_put(cb_arg->skb, 1124 NLBL_UNLABEL_A_IPV4ADDR, 1125 sizeof(struct in_addr), 1126 &addr_struct); 1127 if (ret_val != 0) 1128 goto list_cb_failure; 1129 1130 addr_struct.s_addr = addr4->list.mask; 1131 ret_val = nla_put(cb_arg->skb, 1132 NLBL_UNLABEL_A_IPV4MASK, 1133 sizeof(struct in_addr), 1134 &addr_struct); 1135 if (ret_val != 0) 1136 goto list_cb_failure; 1137 1138 secid = addr4->secid; 1139 } else { 1140 ret_val = nla_put(cb_arg->skb, 1141 NLBL_UNLABEL_A_IPV6ADDR, 1142 sizeof(struct in6_addr), 1143 &addr6->list.addr); 1144 if (ret_val != 0) 1145 goto list_cb_failure; 1146 1147 ret_val = nla_put(cb_arg->skb, 1148 NLBL_UNLABEL_A_IPV6MASK, 1149 sizeof(struct in6_addr), 1150 &addr6->list.mask); 1151 if (ret_val != 0) 1152 goto list_cb_failure; 1153 1154 secid = addr6->secid; 1155 } 1156 1157 ret_val = security_secid_to_secctx(secid, &secctx, &secctx_len); 1158 if (ret_val != 0) 1159 goto list_cb_failure; 1160 ret_val = nla_put(cb_arg->skb, 1161 NLBL_UNLABEL_A_SECCTX, 1162 secctx_len, 1163 secctx); 1164 security_release_secctx(secctx, secctx_len); 1165 if (ret_val != 0) 1166 goto list_cb_failure; 1167 1168 cb_arg->seq++; 1169 return genlmsg_end(cb_arg->skb, data); 1170 1171 list_cb_failure: 1172 genlmsg_cancel(cb_arg->skb, data); 1173 return ret_val; 1174 } 1175 1176 /** 1177 * netlbl_unlabel_staticlist - Handle a STATICLIST message 1178 * @skb: the NETLINK buffer 1179 * @cb: the NETLINK callback 1180 * 1181 * Description: 1182 * Process a user generated STATICLIST message and dump the unlabeled 1183 * connection hash table in a form suitable for use in a kernel generated 1184 * STATICLIST message. Returns the length of @skb. 1185 * 1186 */ 1187 static int netlbl_unlabel_staticlist(struct sk_buff *skb, 1188 struct netlink_callback *cb) 1189 { 1190 struct netlbl_unlhsh_walk_arg cb_arg; 1191 u32 skip_bkt = cb->args[0]; 1192 u32 skip_chain = cb->args[1]; 1193 u32 skip_addr4 = cb->args[2]; 1194 u32 skip_addr6 = cb->args[3]; 1195 u32 iter_bkt; 1196 u32 iter_chain = 0, iter_addr4 = 0, iter_addr6 = 0; 1197 struct netlbl_unlhsh_iface *iface; 1198 struct list_head *iter_list; 1199 struct netlbl_af4list *addr4; 1200 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 1201 struct netlbl_af6list *addr6; 1202 #endif 1203 1204 cb_arg.nl_cb = cb; 1205 cb_arg.skb = skb; 1206 cb_arg.seq = cb->nlh->nlmsg_seq; 1207 1208 rcu_read_lock(); 1209 for (iter_bkt = skip_bkt; 1210 iter_bkt < rcu_dereference(netlbl_unlhsh)->size; 1211 iter_bkt++, iter_chain = 0, iter_addr4 = 0, iter_addr6 = 0) { 1212 iter_list = &rcu_dereference(netlbl_unlhsh)->tbl[iter_bkt]; 1213 list_for_each_entry_rcu(iface, iter_list, list) { 1214 if (!iface->valid || 1215 iter_chain++ < skip_chain) 1216 continue; 1217 netlbl_af4list_foreach_rcu(addr4, 1218 &iface->addr4_list) { 1219 if (iter_addr4++ < skip_addr4) 1220 continue; 1221 if (netlbl_unlabel_staticlist_gen( 1222 NLBL_UNLABEL_C_STATICLIST, 1223 iface, 1224 netlbl_unlhsh_addr4_entry(addr4), 1225 NULL, 1226 &cb_arg) < 0) { 1227 iter_addr4--; 1228 iter_chain--; 1229 goto unlabel_staticlist_return; 1230 } 1231 } 1232 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 1233 netlbl_af6list_foreach_rcu(addr6, 1234 &iface->addr6_list) { 1235 if (iter_addr6++ < skip_addr6) 1236 continue; 1237 if (netlbl_unlabel_staticlist_gen( 1238 NLBL_UNLABEL_C_STATICLIST, 1239 iface, 1240 NULL, 1241 netlbl_unlhsh_addr6_entry(addr6), 1242 &cb_arg) < 0) { 1243 iter_addr6--; 1244 iter_chain--; 1245 goto unlabel_staticlist_return; 1246 } 1247 } 1248 #endif /* IPv6 */ 1249 } 1250 } 1251 1252 unlabel_staticlist_return: 1253 rcu_read_unlock(); 1254 cb->args[0] = skip_bkt; 1255 cb->args[1] = skip_chain; 1256 cb->args[2] = skip_addr4; 1257 cb->args[3] = skip_addr6; 1258 return skb->len; 1259 } 1260 1261 /** 1262 * netlbl_unlabel_staticlistdef - Handle a STATICLISTDEF message 1263 * @skb: the NETLINK buffer 1264 * @cb: the NETLINK callback 1265 * 1266 * Description: 1267 * Process a user generated STATICLISTDEF message and dump the default 1268 * unlabeled connection entry in a form suitable for use in a kernel generated 1269 * STATICLISTDEF message. Returns the length of @skb. 1270 * 1271 */ 1272 static int netlbl_unlabel_staticlistdef(struct sk_buff *skb, 1273 struct netlink_callback *cb) 1274 { 1275 struct netlbl_unlhsh_walk_arg cb_arg; 1276 struct netlbl_unlhsh_iface *iface; 1277 u32 skip_addr4 = cb->args[0]; 1278 u32 skip_addr6 = cb->args[1]; 1279 u32 iter_addr4 = 0; 1280 struct netlbl_af4list *addr4; 1281 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 1282 u32 iter_addr6 = 0; 1283 struct netlbl_af6list *addr6; 1284 #endif 1285 1286 cb_arg.nl_cb = cb; 1287 cb_arg.skb = skb; 1288 cb_arg.seq = cb->nlh->nlmsg_seq; 1289 1290 rcu_read_lock(); 1291 iface = rcu_dereference(netlbl_unlhsh_def); 1292 if (iface == NULL || !iface->valid) 1293 goto unlabel_staticlistdef_return; 1294 1295 netlbl_af4list_foreach_rcu(addr4, &iface->addr4_list) { 1296 if (iter_addr4++ < skip_addr4) 1297 continue; 1298 if (netlbl_unlabel_staticlist_gen(NLBL_UNLABEL_C_STATICLISTDEF, 1299 iface, 1300 netlbl_unlhsh_addr4_entry(addr4), 1301 NULL, 1302 &cb_arg) < 0) { 1303 iter_addr4--; 1304 goto unlabel_staticlistdef_return; 1305 } 1306 } 1307 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 1308 netlbl_af6list_foreach_rcu(addr6, &iface->addr6_list) { 1309 if (iter_addr6++ < skip_addr6) 1310 continue; 1311 if (netlbl_unlabel_staticlist_gen(NLBL_UNLABEL_C_STATICLISTDEF, 1312 iface, 1313 NULL, 1314 netlbl_unlhsh_addr6_entry(addr6), 1315 &cb_arg) < 0) { 1316 iter_addr6--; 1317 goto unlabel_staticlistdef_return; 1318 } 1319 } 1320 #endif /* IPv6 */ 1321 1322 unlabel_staticlistdef_return: 1323 rcu_read_unlock(); 1324 cb->args[0] = skip_addr4; 1325 cb->args[1] = skip_addr6; 1326 return skb->len; 1327 } 1328 1329 /* 1330 * NetLabel Generic NETLINK Command Definitions 1331 */ 1332 1333 static struct genl_ops netlbl_unlabel_genl_ops[] = { 1334 { 1335 .cmd = NLBL_UNLABEL_C_STATICADD, 1336 .flags = GENL_ADMIN_PERM, 1337 .policy = netlbl_unlabel_genl_policy, 1338 .doit = netlbl_unlabel_staticadd, 1339 .dumpit = NULL, 1340 }, 1341 { 1342 .cmd = NLBL_UNLABEL_C_STATICREMOVE, 1343 .flags = GENL_ADMIN_PERM, 1344 .policy = netlbl_unlabel_genl_policy, 1345 .doit = netlbl_unlabel_staticremove, 1346 .dumpit = NULL, 1347 }, 1348 { 1349 .cmd = NLBL_UNLABEL_C_STATICLIST, 1350 .flags = 0, 1351 .policy = netlbl_unlabel_genl_policy, 1352 .doit = NULL, 1353 .dumpit = netlbl_unlabel_staticlist, 1354 }, 1355 { 1356 .cmd = NLBL_UNLABEL_C_STATICADDDEF, 1357 .flags = GENL_ADMIN_PERM, 1358 .policy = netlbl_unlabel_genl_policy, 1359 .doit = netlbl_unlabel_staticadddef, 1360 .dumpit = NULL, 1361 }, 1362 { 1363 .cmd = NLBL_UNLABEL_C_STATICREMOVEDEF, 1364 .flags = GENL_ADMIN_PERM, 1365 .policy = netlbl_unlabel_genl_policy, 1366 .doit = netlbl_unlabel_staticremovedef, 1367 .dumpit = NULL, 1368 }, 1369 { 1370 .cmd = NLBL_UNLABEL_C_STATICLISTDEF, 1371 .flags = 0, 1372 .policy = netlbl_unlabel_genl_policy, 1373 .doit = NULL, 1374 .dumpit = netlbl_unlabel_staticlistdef, 1375 }, 1376 { 1377 .cmd = NLBL_UNLABEL_C_ACCEPT, 1378 .flags = GENL_ADMIN_PERM, 1379 .policy = netlbl_unlabel_genl_policy, 1380 .doit = netlbl_unlabel_accept, 1381 .dumpit = NULL, 1382 }, 1383 { 1384 .cmd = NLBL_UNLABEL_C_LIST, 1385 .flags = 0, 1386 .policy = netlbl_unlabel_genl_policy, 1387 .doit = netlbl_unlabel_list, 1388 .dumpit = NULL, 1389 }, 1390 }; 1391 1392 /* 1393 * NetLabel Generic NETLINK Protocol Functions 1394 */ 1395 1396 /** 1397 * netlbl_unlabel_genl_init - Register the Unlabeled NetLabel component 1398 * 1399 * Description: 1400 * Register the unlabeled packet NetLabel component with the Generic NETLINK 1401 * mechanism. Returns zero on success, negative values on failure. 1402 * 1403 */ 1404 int __init netlbl_unlabel_genl_init(void) 1405 { 1406 return genl_register_family_with_ops(&netlbl_unlabel_gnl_family, 1407 netlbl_unlabel_genl_ops, ARRAY_SIZE(netlbl_unlabel_genl_ops)); 1408 } 1409 1410 /* 1411 * NetLabel KAPI Hooks 1412 */ 1413 1414 static struct notifier_block netlbl_unlhsh_netdev_notifier = { 1415 .notifier_call = netlbl_unlhsh_netdev_handler, 1416 }; 1417 1418 /** 1419 * netlbl_unlabel_init - Initialize the unlabeled connection hash table 1420 * @size: the number of bits to use for the hash buckets 1421 * 1422 * Description: 1423 * Initializes the unlabeled connection hash table and registers a network 1424 * device notification handler. This function should only be called by the 1425 * NetLabel subsystem itself during initialization. Returns zero on success, 1426 * non-zero values on error. 1427 * 1428 */ 1429 int __init netlbl_unlabel_init(u32 size) 1430 { 1431 u32 iter; 1432 struct netlbl_unlhsh_tbl *hsh_tbl; 1433 1434 if (size == 0) 1435 return -EINVAL; 1436 1437 hsh_tbl = kmalloc(sizeof(*hsh_tbl), GFP_KERNEL); 1438 if (hsh_tbl == NULL) 1439 return -ENOMEM; 1440 hsh_tbl->size = 1 << size; 1441 hsh_tbl->tbl = kcalloc(hsh_tbl->size, 1442 sizeof(struct list_head), 1443 GFP_KERNEL); 1444 if (hsh_tbl->tbl == NULL) { 1445 kfree(hsh_tbl); 1446 return -ENOMEM; 1447 } 1448 for (iter = 0; iter < hsh_tbl->size; iter++) 1449 INIT_LIST_HEAD(&hsh_tbl->tbl[iter]); 1450 1451 rcu_read_lock(); 1452 spin_lock(&netlbl_unlhsh_lock); 1453 rcu_assign_pointer(netlbl_unlhsh, hsh_tbl); 1454 spin_unlock(&netlbl_unlhsh_lock); 1455 rcu_read_unlock(); 1456 1457 register_netdevice_notifier(&netlbl_unlhsh_netdev_notifier); 1458 1459 return 0; 1460 } 1461 1462 /** 1463 * netlbl_unlabel_getattr - Get the security attributes for an unlabled packet 1464 * @skb: the packet 1465 * @family: protocol family 1466 * @secattr: the security attributes 1467 * 1468 * Description: 1469 * Determine the security attributes, if any, for an unlabled packet and return 1470 * them in @secattr. Returns zero on success and negative values on failure. 1471 * 1472 */ 1473 int netlbl_unlabel_getattr(const struct sk_buff *skb, 1474 u16 family, 1475 struct netlbl_lsm_secattr *secattr) 1476 { 1477 struct netlbl_unlhsh_iface *iface; 1478 1479 rcu_read_lock(); 1480 iface = netlbl_unlhsh_search_iface(skb->skb_iif); 1481 if (iface == NULL) 1482 iface = rcu_dereference(netlbl_unlhsh_def); 1483 if (iface == NULL || !iface->valid) 1484 goto unlabel_getattr_nolabel; 1485 switch (family) { 1486 case PF_INET: { 1487 struct iphdr *hdr4; 1488 struct netlbl_af4list *addr4; 1489 1490 hdr4 = ip_hdr(skb); 1491 addr4 = netlbl_af4list_search(hdr4->saddr, 1492 &iface->addr4_list); 1493 if (addr4 == NULL) 1494 goto unlabel_getattr_nolabel; 1495 secattr->attr.secid = netlbl_unlhsh_addr4_entry(addr4)->secid; 1496 break; 1497 } 1498 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 1499 case PF_INET6: { 1500 struct ipv6hdr *hdr6; 1501 struct netlbl_af6list *addr6; 1502 1503 hdr6 = ipv6_hdr(skb); 1504 addr6 = netlbl_af6list_search(&hdr6->saddr, 1505 &iface->addr6_list); 1506 if (addr6 == NULL) 1507 goto unlabel_getattr_nolabel; 1508 secattr->attr.secid = netlbl_unlhsh_addr6_entry(addr6)->secid; 1509 break; 1510 } 1511 #endif /* IPv6 */ 1512 default: 1513 goto unlabel_getattr_nolabel; 1514 } 1515 rcu_read_unlock(); 1516 1517 secattr->flags |= NETLBL_SECATTR_SECID; 1518 secattr->type = NETLBL_NLTYPE_UNLABELED; 1519 return 0; 1520 1521 unlabel_getattr_nolabel: 1522 rcu_read_unlock(); 1523 if (netlabel_unlabel_acceptflg == 0) 1524 return -ENOMSG; 1525 secattr->type = NETLBL_NLTYPE_UNLABELED; 1526 return 0; 1527 } 1528 1529 /** 1530 * netlbl_unlabel_defconf - Set the default config to allow unlabeled packets 1531 * 1532 * Description: 1533 * Set the default NetLabel configuration to allow incoming unlabeled packets 1534 * and to send unlabeled network traffic by default. 1535 * 1536 */ 1537 int __init netlbl_unlabel_defconf(void) 1538 { 1539 int ret_val; 1540 struct netlbl_dom_map *entry; 1541 struct netlbl_audit audit_info; 1542 1543 /* Only the kernel is allowed to call this function and the only time 1544 * it is called is at bootup before the audit subsystem is reporting 1545 * messages so don't worry to much about these values. */ 1546 security_task_getsecid(current, &audit_info.secid); 1547 audit_info.loginuid = 0; 1548 audit_info.sessionid = 0; 1549 1550 entry = kzalloc(sizeof(*entry), GFP_KERNEL); 1551 if (entry == NULL) 1552 return -ENOMEM; 1553 entry->type = NETLBL_NLTYPE_UNLABELED; 1554 ret_val = netlbl_domhsh_add_default(entry, &audit_info); 1555 if (ret_val != 0) 1556 return ret_val; 1557 1558 netlbl_unlabel_acceptflg_set(1, &audit_info); 1559 1560 return 0; 1561 } 1562