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