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