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 IS_ENABLED(CONFIG_IPV6) 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 IS_ENABLED(CONFIG_IPV6) 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 IS_ENABLED(CONFIG_IPV6) 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 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 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_assign_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 IS_ENABLED(CONFIG_IPV6) 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 IS_ENABLED(CONFIG_IPV6) 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 IS_ENABLED(CONFIG_IPV6) 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 IS_ENABLED(CONFIG_IPV6) 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 IS_ENABLED(CONFIG_IPV6) 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 netdevice notifier info (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, void *ptr) 721 { 722 struct net_device *dev = netdev_notifier_info_to_dev(ptr); 723 struct netlbl_unlhsh_iface *iface = NULL; 724 725 if (!net_eq(dev_net(dev), &init_net)) 726 return NOTIFY_DONE; 727 728 /* XXX - should this be a check for NETDEV_DOWN or _UNREGISTER? */ 729 if (event == NETDEV_DOWN) { 730 spin_lock(&netlbl_unlhsh_lock); 731 iface = netlbl_unlhsh_search_iface(dev->ifindex); 732 if (iface != NULL && iface->valid) { 733 iface->valid = 0; 734 list_del_rcu(&iface->list); 735 } else 736 iface = NULL; 737 spin_unlock(&netlbl_unlhsh_lock); 738 } 739 740 if (iface != NULL) 741 call_rcu(&iface->rcu, netlbl_unlhsh_free_iface); 742 743 return NOTIFY_DONE; 744 } 745 746 /** 747 * netlbl_unlabel_acceptflg_set - Set the unlabeled accept flag 748 * @value: desired value 749 * @audit_info: NetLabel audit information 750 * 751 * Description: 752 * Set the value of the unlabeled accept flag to @value. 753 * 754 */ 755 static void netlbl_unlabel_acceptflg_set(u8 value, 756 struct netlbl_audit *audit_info) 757 { 758 struct audit_buffer *audit_buf; 759 u8 old_val; 760 761 old_val = netlabel_unlabel_acceptflg; 762 netlabel_unlabel_acceptflg = value; 763 audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_ALLOW, 764 audit_info); 765 if (audit_buf != NULL) { 766 audit_log_format(audit_buf, 767 " unlbl_accept=%u old=%u", value, old_val); 768 audit_log_end(audit_buf); 769 } 770 } 771 772 /** 773 * netlbl_unlabel_addrinfo_get - Get the IPv4/6 address information 774 * @info: the Generic NETLINK info block 775 * @addr: the IP address 776 * @mask: the IP address mask 777 * @len: the address length 778 * 779 * Description: 780 * Examine the Generic NETLINK message and extract the IP address information. 781 * Returns zero on success, negative values on failure. 782 * 783 */ 784 static int netlbl_unlabel_addrinfo_get(struct genl_info *info, 785 void **addr, 786 void **mask, 787 u32 *len) 788 { 789 u32 addr_len; 790 791 if (info->attrs[NLBL_UNLABEL_A_IPV4ADDR]) { 792 addr_len = nla_len(info->attrs[NLBL_UNLABEL_A_IPV4ADDR]); 793 if (addr_len != sizeof(struct in_addr) && 794 addr_len != nla_len(info->attrs[NLBL_UNLABEL_A_IPV4MASK])) 795 return -EINVAL; 796 *len = addr_len; 797 *addr = nla_data(info->attrs[NLBL_UNLABEL_A_IPV4ADDR]); 798 *mask = nla_data(info->attrs[NLBL_UNLABEL_A_IPV4MASK]); 799 return 0; 800 } else if (info->attrs[NLBL_UNLABEL_A_IPV6ADDR]) { 801 addr_len = nla_len(info->attrs[NLBL_UNLABEL_A_IPV6ADDR]); 802 if (addr_len != sizeof(struct in6_addr) && 803 addr_len != nla_len(info->attrs[NLBL_UNLABEL_A_IPV6MASK])) 804 return -EINVAL; 805 *len = addr_len; 806 *addr = nla_data(info->attrs[NLBL_UNLABEL_A_IPV6ADDR]); 807 *mask = nla_data(info->attrs[NLBL_UNLABEL_A_IPV6MASK]); 808 return 0; 809 } 810 811 return -EINVAL; 812 } 813 814 /* 815 * NetLabel Command Handlers 816 */ 817 818 /** 819 * netlbl_unlabel_accept - Handle an ACCEPT message 820 * @skb: the NETLINK buffer 821 * @info: the Generic NETLINK info block 822 * 823 * Description: 824 * Process a user generated ACCEPT message and set the accept flag accordingly. 825 * Returns zero on success, negative values on failure. 826 * 827 */ 828 static int netlbl_unlabel_accept(struct sk_buff *skb, struct genl_info *info) 829 { 830 u8 value; 831 struct netlbl_audit audit_info; 832 833 if (info->attrs[NLBL_UNLABEL_A_ACPTFLG]) { 834 value = nla_get_u8(info->attrs[NLBL_UNLABEL_A_ACPTFLG]); 835 if (value == 1 || value == 0) { 836 netlbl_netlink_auditinfo(skb, &audit_info); 837 netlbl_unlabel_acceptflg_set(value, &audit_info); 838 return 0; 839 } 840 } 841 842 return -EINVAL; 843 } 844 845 /** 846 * netlbl_unlabel_list - Handle a LIST message 847 * @skb: the NETLINK buffer 848 * @info: the Generic NETLINK info block 849 * 850 * Description: 851 * Process a user generated LIST message and respond with the current status. 852 * Returns zero on success, negative values on failure. 853 * 854 */ 855 static int netlbl_unlabel_list(struct sk_buff *skb, struct genl_info *info) 856 { 857 int ret_val = -EINVAL; 858 struct sk_buff *ans_skb; 859 void *data; 860 861 ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 862 if (ans_skb == NULL) 863 goto list_failure; 864 data = genlmsg_put_reply(ans_skb, info, &netlbl_unlabel_gnl_family, 865 0, NLBL_UNLABEL_C_LIST); 866 if (data == NULL) { 867 ret_val = -ENOMEM; 868 goto list_failure; 869 } 870 871 ret_val = nla_put_u8(ans_skb, 872 NLBL_UNLABEL_A_ACPTFLG, 873 netlabel_unlabel_acceptflg); 874 if (ret_val != 0) 875 goto list_failure; 876 877 genlmsg_end(ans_skb, data); 878 return genlmsg_reply(ans_skb, info); 879 880 list_failure: 881 kfree_skb(ans_skb); 882 return ret_val; 883 } 884 885 /** 886 * netlbl_unlabel_staticadd - Handle a STATICADD message 887 * @skb: the NETLINK buffer 888 * @info: the Generic NETLINK info block 889 * 890 * Description: 891 * Process a user generated STATICADD message and add a new unlabeled 892 * connection entry to the hash table. Returns zero on success, negative 893 * values on failure. 894 * 895 */ 896 static int netlbl_unlabel_staticadd(struct sk_buff *skb, 897 struct genl_info *info) 898 { 899 int ret_val; 900 char *dev_name; 901 void *addr; 902 void *mask; 903 u32 addr_len; 904 u32 secid; 905 struct netlbl_audit audit_info; 906 907 /* Don't allow users to add both IPv4 and IPv6 addresses for a 908 * single entry. However, allow users to create two entries, one each 909 * for IPv4 and IPv4, with the same LSM security context which should 910 * achieve the same result. */ 911 if (!info->attrs[NLBL_UNLABEL_A_SECCTX] || 912 !info->attrs[NLBL_UNLABEL_A_IFACE] || 913 !((!info->attrs[NLBL_UNLABEL_A_IPV4ADDR] || 914 !info->attrs[NLBL_UNLABEL_A_IPV4MASK]) ^ 915 (!info->attrs[NLBL_UNLABEL_A_IPV6ADDR] || 916 !info->attrs[NLBL_UNLABEL_A_IPV6MASK]))) 917 return -EINVAL; 918 919 netlbl_netlink_auditinfo(skb, &audit_info); 920 921 ret_val = netlbl_unlabel_addrinfo_get(info, &addr, &mask, &addr_len); 922 if (ret_val != 0) 923 return ret_val; 924 dev_name = nla_data(info->attrs[NLBL_UNLABEL_A_IFACE]); 925 ret_val = security_secctx_to_secid( 926 nla_data(info->attrs[NLBL_UNLABEL_A_SECCTX]), 927 nla_len(info->attrs[NLBL_UNLABEL_A_SECCTX]), 928 &secid); 929 if (ret_val != 0) 930 return ret_val; 931 932 return netlbl_unlhsh_add(&init_net, 933 dev_name, addr, mask, addr_len, secid, 934 &audit_info); 935 } 936 937 /** 938 * netlbl_unlabel_staticadddef - Handle a STATICADDDEF message 939 * @skb: the NETLINK buffer 940 * @info: the Generic NETLINK info block 941 * 942 * Description: 943 * Process a user generated STATICADDDEF message and add a new default 944 * unlabeled connection entry. Returns zero on success, negative values on 945 * failure. 946 * 947 */ 948 static int netlbl_unlabel_staticadddef(struct sk_buff *skb, 949 struct genl_info *info) 950 { 951 int ret_val; 952 void *addr; 953 void *mask; 954 u32 addr_len; 955 u32 secid; 956 struct netlbl_audit audit_info; 957 958 /* Don't allow users to add both IPv4 and IPv6 addresses for a 959 * single entry. However, allow users to create two entries, one each 960 * for IPv4 and IPv6, with the same LSM security context which should 961 * achieve the same result. */ 962 if (!info->attrs[NLBL_UNLABEL_A_SECCTX] || 963 !((!info->attrs[NLBL_UNLABEL_A_IPV4ADDR] || 964 !info->attrs[NLBL_UNLABEL_A_IPV4MASK]) ^ 965 (!info->attrs[NLBL_UNLABEL_A_IPV6ADDR] || 966 !info->attrs[NLBL_UNLABEL_A_IPV6MASK]))) 967 return -EINVAL; 968 969 netlbl_netlink_auditinfo(skb, &audit_info); 970 971 ret_val = netlbl_unlabel_addrinfo_get(info, &addr, &mask, &addr_len); 972 if (ret_val != 0) 973 return ret_val; 974 ret_val = security_secctx_to_secid( 975 nla_data(info->attrs[NLBL_UNLABEL_A_SECCTX]), 976 nla_len(info->attrs[NLBL_UNLABEL_A_SECCTX]), 977 &secid); 978 if (ret_val != 0) 979 return ret_val; 980 981 return netlbl_unlhsh_add(&init_net, 982 NULL, addr, mask, addr_len, secid, 983 &audit_info); 984 } 985 986 /** 987 * netlbl_unlabel_staticremove - Handle a STATICREMOVE message 988 * @skb: the NETLINK buffer 989 * @info: the Generic NETLINK info block 990 * 991 * Description: 992 * Process a user generated STATICREMOVE message and remove the specified 993 * unlabeled connection entry. Returns zero on success, negative values on 994 * failure. 995 * 996 */ 997 static int netlbl_unlabel_staticremove(struct sk_buff *skb, 998 struct genl_info *info) 999 { 1000 int ret_val; 1001 char *dev_name; 1002 void *addr; 1003 void *mask; 1004 u32 addr_len; 1005 struct netlbl_audit audit_info; 1006 1007 /* See the note in netlbl_unlabel_staticadd() about not allowing both 1008 * IPv4 and IPv6 in the same entry. */ 1009 if (!info->attrs[NLBL_UNLABEL_A_IFACE] || 1010 !((!info->attrs[NLBL_UNLABEL_A_IPV4ADDR] || 1011 !info->attrs[NLBL_UNLABEL_A_IPV4MASK]) ^ 1012 (!info->attrs[NLBL_UNLABEL_A_IPV6ADDR] || 1013 !info->attrs[NLBL_UNLABEL_A_IPV6MASK]))) 1014 return -EINVAL; 1015 1016 netlbl_netlink_auditinfo(skb, &audit_info); 1017 1018 ret_val = netlbl_unlabel_addrinfo_get(info, &addr, &mask, &addr_len); 1019 if (ret_val != 0) 1020 return ret_val; 1021 dev_name = nla_data(info->attrs[NLBL_UNLABEL_A_IFACE]); 1022 1023 return netlbl_unlhsh_remove(&init_net, 1024 dev_name, addr, mask, addr_len, 1025 &audit_info); 1026 } 1027 1028 /** 1029 * netlbl_unlabel_staticremovedef - Handle a STATICREMOVEDEF message 1030 * @skb: the NETLINK buffer 1031 * @info: the Generic NETLINK info block 1032 * 1033 * Description: 1034 * Process a user generated STATICREMOVEDEF message and remove the default 1035 * unlabeled connection entry. Returns zero on success, negative values on 1036 * failure. 1037 * 1038 */ 1039 static int netlbl_unlabel_staticremovedef(struct sk_buff *skb, 1040 struct genl_info *info) 1041 { 1042 int ret_val; 1043 void *addr; 1044 void *mask; 1045 u32 addr_len; 1046 struct netlbl_audit audit_info; 1047 1048 /* See the note in netlbl_unlabel_staticadd() about not allowing both 1049 * IPv4 and IPv6 in the same entry. */ 1050 if (!((!info->attrs[NLBL_UNLABEL_A_IPV4ADDR] || 1051 !info->attrs[NLBL_UNLABEL_A_IPV4MASK]) ^ 1052 (!info->attrs[NLBL_UNLABEL_A_IPV6ADDR] || 1053 !info->attrs[NLBL_UNLABEL_A_IPV6MASK]))) 1054 return -EINVAL; 1055 1056 netlbl_netlink_auditinfo(skb, &audit_info); 1057 1058 ret_val = netlbl_unlabel_addrinfo_get(info, &addr, &mask, &addr_len); 1059 if (ret_val != 0) 1060 return ret_val; 1061 1062 return netlbl_unlhsh_remove(&init_net, 1063 NULL, addr, mask, addr_len, 1064 &audit_info); 1065 } 1066 1067 1068 /** 1069 * netlbl_unlabel_staticlist_gen - Generate messages for STATICLIST[DEF] 1070 * @cmd: command/message 1071 * @iface: the interface entry 1072 * @addr4: the IPv4 address entry 1073 * @addr6: the IPv6 address entry 1074 * @arg: the netlbl_unlhsh_walk_arg structure 1075 * 1076 * Description: 1077 * This function is designed to be used to generate a response for a 1078 * STATICLIST or STATICLISTDEF message. When called either @addr4 or @addr6 1079 * can be specified, not both, the other unspecified entry should be set to 1080 * NULL by the caller. Returns the size of the message on success, negative 1081 * values on failure. 1082 * 1083 */ 1084 static int netlbl_unlabel_staticlist_gen(u32 cmd, 1085 const struct netlbl_unlhsh_iface *iface, 1086 const struct netlbl_unlhsh_addr4 *addr4, 1087 const struct netlbl_unlhsh_addr6 *addr6, 1088 void *arg) 1089 { 1090 int ret_val = -ENOMEM; 1091 struct netlbl_unlhsh_walk_arg *cb_arg = arg; 1092 struct net_device *dev; 1093 void *data; 1094 u32 secid; 1095 char *secctx; 1096 u32 secctx_len; 1097 1098 data = genlmsg_put(cb_arg->skb, NETLINK_CB(cb_arg->nl_cb->skb).portid, 1099 cb_arg->seq, &netlbl_unlabel_gnl_family, 1100 NLM_F_MULTI, cmd); 1101 if (data == NULL) 1102 goto list_cb_failure; 1103 1104 if (iface->ifindex > 0) { 1105 dev = dev_get_by_index(&init_net, iface->ifindex); 1106 if (!dev) { 1107 ret_val = -ENODEV; 1108 goto list_cb_failure; 1109 } 1110 ret_val = nla_put_string(cb_arg->skb, 1111 NLBL_UNLABEL_A_IFACE, dev->name); 1112 dev_put(dev); 1113 if (ret_val != 0) 1114 goto list_cb_failure; 1115 } 1116 1117 if (addr4) { 1118 struct in_addr addr_struct; 1119 1120 addr_struct.s_addr = addr4->list.addr; 1121 ret_val = nla_put(cb_arg->skb, 1122 NLBL_UNLABEL_A_IPV4ADDR, 1123 sizeof(struct in_addr), 1124 &addr_struct); 1125 if (ret_val != 0) 1126 goto list_cb_failure; 1127 1128 addr_struct.s_addr = addr4->list.mask; 1129 ret_val = nla_put(cb_arg->skb, 1130 NLBL_UNLABEL_A_IPV4MASK, 1131 sizeof(struct in_addr), 1132 &addr_struct); 1133 if (ret_val != 0) 1134 goto list_cb_failure; 1135 1136 secid = addr4->secid; 1137 } else { 1138 ret_val = nla_put(cb_arg->skb, 1139 NLBL_UNLABEL_A_IPV6ADDR, 1140 sizeof(struct in6_addr), 1141 &addr6->list.addr); 1142 if (ret_val != 0) 1143 goto list_cb_failure; 1144 1145 ret_val = nla_put(cb_arg->skb, 1146 NLBL_UNLABEL_A_IPV6MASK, 1147 sizeof(struct in6_addr), 1148 &addr6->list.mask); 1149 if (ret_val != 0) 1150 goto list_cb_failure; 1151 1152 secid = addr6->secid; 1153 } 1154 1155 ret_val = security_secid_to_secctx(secid, &secctx, &secctx_len); 1156 if (ret_val != 0) 1157 goto list_cb_failure; 1158 ret_val = nla_put(cb_arg->skb, 1159 NLBL_UNLABEL_A_SECCTX, 1160 secctx_len, 1161 secctx); 1162 security_release_secctx(secctx, secctx_len); 1163 if (ret_val != 0) 1164 goto list_cb_failure; 1165 1166 cb_arg->seq++; 1167 return genlmsg_end(cb_arg->skb, data); 1168 1169 list_cb_failure: 1170 genlmsg_cancel(cb_arg->skb, data); 1171 return ret_val; 1172 } 1173 1174 /** 1175 * netlbl_unlabel_staticlist - Handle a STATICLIST message 1176 * @skb: the NETLINK buffer 1177 * @cb: the NETLINK callback 1178 * 1179 * Description: 1180 * Process a user generated STATICLIST message and dump the unlabeled 1181 * connection hash table in a form suitable for use in a kernel generated 1182 * STATICLIST message. Returns the length of @skb. 1183 * 1184 */ 1185 static int netlbl_unlabel_staticlist(struct sk_buff *skb, 1186 struct netlink_callback *cb) 1187 { 1188 struct netlbl_unlhsh_walk_arg cb_arg; 1189 u32 skip_bkt = cb->args[0]; 1190 u32 skip_chain = cb->args[1]; 1191 u32 iter_bkt; 1192 u32 iter_chain = 0, iter_addr4 = 0, iter_addr6 = 0; 1193 struct netlbl_unlhsh_iface *iface; 1194 struct list_head *iter_list; 1195 struct netlbl_af4list *addr4; 1196 #if IS_ENABLED(CONFIG_IPV6) 1197 struct netlbl_af6list *addr6; 1198 #endif 1199 1200 cb_arg.nl_cb = cb; 1201 cb_arg.skb = skb; 1202 cb_arg.seq = cb->nlh->nlmsg_seq; 1203 1204 rcu_read_lock(); 1205 for (iter_bkt = skip_bkt; 1206 iter_bkt < rcu_dereference(netlbl_unlhsh)->size; 1207 iter_bkt++, iter_chain = 0, iter_addr4 = 0, iter_addr6 = 0) { 1208 iter_list = &rcu_dereference(netlbl_unlhsh)->tbl[iter_bkt]; 1209 list_for_each_entry_rcu(iface, iter_list, list) { 1210 if (!iface->valid || 1211 iter_chain++ < skip_chain) 1212 continue; 1213 netlbl_af4list_foreach_rcu(addr4, 1214 &iface->addr4_list) { 1215 if (iter_addr4++ < cb->args[2]) 1216 continue; 1217 if (netlbl_unlabel_staticlist_gen( 1218 NLBL_UNLABEL_C_STATICLIST, 1219 iface, 1220 netlbl_unlhsh_addr4_entry(addr4), 1221 NULL, 1222 &cb_arg) < 0) { 1223 iter_addr4--; 1224 iter_chain--; 1225 goto unlabel_staticlist_return; 1226 } 1227 } 1228 #if IS_ENABLED(CONFIG_IPV6) 1229 netlbl_af6list_foreach_rcu(addr6, 1230 &iface->addr6_list) { 1231 if (iter_addr6++ < cb->args[3]) 1232 continue; 1233 if (netlbl_unlabel_staticlist_gen( 1234 NLBL_UNLABEL_C_STATICLIST, 1235 iface, 1236 NULL, 1237 netlbl_unlhsh_addr6_entry(addr6), 1238 &cb_arg) < 0) { 1239 iter_addr6--; 1240 iter_chain--; 1241 goto unlabel_staticlist_return; 1242 } 1243 } 1244 #endif /* IPv6 */ 1245 } 1246 } 1247 1248 unlabel_staticlist_return: 1249 rcu_read_unlock(); 1250 cb->args[0] = iter_bkt; 1251 cb->args[1] = iter_chain; 1252 cb->args[2] = iter_addr4; 1253 cb->args[3] = iter_addr6; 1254 return skb->len; 1255 } 1256 1257 /** 1258 * netlbl_unlabel_staticlistdef - Handle a STATICLISTDEF message 1259 * @skb: the NETLINK buffer 1260 * @cb: the NETLINK callback 1261 * 1262 * Description: 1263 * Process a user generated STATICLISTDEF message and dump the default 1264 * unlabeled connection entry in a form suitable for use in a kernel generated 1265 * STATICLISTDEF message. Returns the length of @skb. 1266 * 1267 */ 1268 static int netlbl_unlabel_staticlistdef(struct sk_buff *skb, 1269 struct netlink_callback *cb) 1270 { 1271 struct netlbl_unlhsh_walk_arg cb_arg; 1272 struct netlbl_unlhsh_iface *iface; 1273 u32 iter_addr4 = 0, iter_addr6 = 0; 1274 struct netlbl_af4list *addr4; 1275 #if IS_ENABLED(CONFIG_IPV6) 1276 struct netlbl_af6list *addr6; 1277 #endif 1278 1279 cb_arg.nl_cb = cb; 1280 cb_arg.skb = skb; 1281 cb_arg.seq = cb->nlh->nlmsg_seq; 1282 1283 rcu_read_lock(); 1284 iface = rcu_dereference(netlbl_unlhsh_def); 1285 if (iface == NULL || !iface->valid) 1286 goto unlabel_staticlistdef_return; 1287 1288 netlbl_af4list_foreach_rcu(addr4, &iface->addr4_list) { 1289 if (iter_addr4++ < cb->args[0]) 1290 continue; 1291 if (netlbl_unlabel_staticlist_gen(NLBL_UNLABEL_C_STATICLISTDEF, 1292 iface, 1293 netlbl_unlhsh_addr4_entry(addr4), 1294 NULL, 1295 &cb_arg) < 0) { 1296 iter_addr4--; 1297 goto unlabel_staticlistdef_return; 1298 } 1299 } 1300 #if IS_ENABLED(CONFIG_IPV6) 1301 netlbl_af6list_foreach_rcu(addr6, &iface->addr6_list) { 1302 if (iter_addr6++ < cb->args[1]) 1303 continue; 1304 if (netlbl_unlabel_staticlist_gen(NLBL_UNLABEL_C_STATICLISTDEF, 1305 iface, 1306 NULL, 1307 netlbl_unlhsh_addr6_entry(addr6), 1308 &cb_arg) < 0) { 1309 iter_addr6--; 1310 goto unlabel_staticlistdef_return; 1311 } 1312 } 1313 #endif /* IPv6 */ 1314 1315 unlabel_staticlistdef_return: 1316 rcu_read_unlock(); 1317 cb->args[0] = iter_addr4; 1318 cb->args[1] = iter_addr6; 1319 return skb->len; 1320 } 1321 1322 /* 1323 * NetLabel Generic NETLINK Command Definitions 1324 */ 1325 1326 static const struct genl_ops netlbl_unlabel_genl_ops[] = { 1327 { 1328 .cmd = NLBL_UNLABEL_C_STATICADD, 1329 .flags = GENL_ADMIN_PERM, 1330 .policy = netlbl_unlabel_genl_policy, 1331 .doit = netlbl_unlabel_staticadd, 1332 .dumpit = NULL, 1333 }, 1334 { 1335 .cmd = NLBL_UNLABEL_C_STATICREMOVE, 1336 .flags = GENL_ADMIN_PERM, 1337 .policy = netlbl_unlabel_genl_policy, 1338 .doit = netlbl_unlabel_staticremove, 1339 .dumpit = NULL, 1340 }, 1341 { 1342 .cmd = NLBL_UNLABEL_C_STATICLIST, 1343 .flags = 0, 1344 .policy = netlbl_unlabel_genl_policy, 1345 .doit = NULL, 1346 .dumpit = netlbl_unlabel_staticlist, 1347 }, 1348 { 1349 .cmd = NLBL_UNLABEL_C_STATICADDDEF, 1350 .flags = GENL_ADMIN_PERM, 1351 .policy = netlbl_unlabel_genl_policy, 1352 .doit = netlbl_unlabel_staticadddef, 1353 .dumpit = NULL, 1354 }, 1355 { 1356 .cmd = NLBL_UNLABEL_C_STATICREMOVEDEF, 1357 .flags = GENL_ADMIN_PERM, 1358 .policy = netlbl_unlabel_genl_policy, 1359 .doit = netlbl_unlabel_staticremovedef, 1360 .dumpit = NULL, 1361 }, 1362 { 1363 .cmd = NLBL_UNLABEL_C_STATICLISTDEF, 1364 .flags = 0, 1365 .policy = netlbl_unlabel_genl_policy, 1366 .doit = NULL, 1367 .dumpit = netlbl_unlabel_staticlistdef, 1368 }, 1369 { 1370 .cmd = NLBL_UNLABEL_C_ACCEPT, 1371 .flags = GENL_ADMIN_PERM, 1372 .policy = netlbl_unlabel_genl_policy, 1373 .doit = netlbl_unlabel_accept, 1374 .dumpit = NULL, 1375 }, 1376 { 1377 .cmd = NLBL_UNLABEL_C_LIST, 1378 .flags = 0, 1379 .policy = netlbl_unlabel_genl_policy, 1380 .doit = netlbl_unlabel_list, 1381 .dumpit = NULL, 1382 }, 1383 }; 1384 1385 /* 1386 * NetLabel Generic NETLINK Protocol Functions 1387 */ 1388 1389 /** 1390 * netlbl_unlabel_genl_init - Register the Unlabeled NetLabel component 1391 * 1392 * Description: 1393 * Register the unlabeled packet NetLabel component with the Generic NETLINK 1394 * mechanism. Returns zero on success, negative values on failure. 1395 * 1396 */ 1397 int __init netlbl_unlabel_genl_init(void) 1398 { 1399 return genl_register_family_with_ops(&netlbl_unlabel_gnl_family, 1400 netlbl_unlabel_genl_ops); 1401 } 1402 1403 /* 1404 * NetLabel KAPI Hooks 1405 */ 1406 1407 static struct notifier_block netlbl_unlhsh_netdev_notifier = { 1408 .notifier_call = netlbl_unlhsh_netdev_handler, 1409 }; 1410 1411 /** 1412 * netlbl_unlabel_init - Initialize the unlabeled connection hash table 1413 * @size: the number of bits to use for the hash buckets 1414 * 1415 * Description: 1416 * Initializes the unlabeled connection hash table and registers a network 1417 * device notification handler. This function should only be called by the 1418 * NetLabel subsystem itself during initialization. Returns zero on success, 1419 * non-zero values on error. 1420 * 1421 */ 1422 int __init netlbl_unlabel_init(u32 size) 1423 { 1424 u32 iter; 1425 struct netlbl_unlhsh_tbl *hsh_tbl; 1426 1427 if (size == 0) 1428 return -EINVAL; 1429 1430 hsh_tbl = kmalloc(sizeof(*hsh_tbl), GFP_KERNEL); 1431 if (hsh_tbl == NULL) 1432 return -ENOMEM; 1433 hsh_tbl->size = 1 << size; 1434 hsh_tbl->tbl = kcalloc(hsh_tbl->size, 1435 sizeof(struct list_head), 1436 GFP_KERNEL); 1437 if (hsh_tbl->tbl == NULL) { 1438 kfree(hsh_tbl); 1439 return -ENOMEM; 1440 } 1441 for (iter = 0; iter < hsh_tbl->size; iter++) 1442 INIT_LIST_HEAD(&hsh_tbl->tbl[iter]); 1443 1444 spin_lock(&netlbl_unlhsh_lock); 1445 rcu_assign_pointer(netlbl_unlhsh, hsh_tbl); 1446 spin_unlock(&netlbl_unlhsh_lock); 1447 1448 register_netdevice_notifier(&netlbl_unlhsh_netdev_notifier); 1449 1450 return 0; 1451 } 1452 1453 /** 1454 * netlbl_unlabel_getattr - Get the security attributes for an unlabled packet 1455 * @skb: the packet 1456 * @family: protocol family 1457 * @secattr: the security attributes 1458 * 1459 * Description: 1460 * Determine the security attributes, if any, for an unlabled packet and return 1461 * them in @secattr. Returns zero on success and negative values on failure. 1462 * 1463 */ 1464 int netlbl_unlabel_getattr(const struct sk_buff *skb, 1465 u16 family, 1466 struct netlbl_lsm_secattr *secattr) 1467 { 1468 struct netlbl_unlhsh_iface *iface; 1469 1470 rcu_read_lock(); 1471 iface = netlbl_unlhsh_search_iface(skb->skb_iif); 1472 if (iface == NULL) 1473 iface = rcu_dereference(netlbl_unlhsh_def); 1474 if (iface == NULL || !iface->valid) 1475 goto unlabel_getattr_nolabel; 1476 switch (family) { 1477 case PF_INET: { 1478 struct iphdr *hdr4; 1479 struct netlbl_af4list *addr4; 1480 1481 hdr4 = ip_hdr(skb); 1482 addr4 = netlbl_af4list_search(hdr4->saddr, 1483 &iface->addr4_list); 1484 if (addr4 == NULL) 1485 goto unlabel_getattr_nolabel; 1486 secattr->attr.secid = netlbl_unlhsh_addr4_entry(addr4)->secid; 1487 break; 1488 } 1489 #if IS_ENABLED(CONFIG_IPV6) 1490 case PF_INET6: { 1491 struct ipv6hdr *hdr6; 1492 struct netlbl_af6list *addr6; 1493 1494 hdr6 = ipv6_hdr(skb); 1495 addr6 = netlbl_af6list_search(&hdr6->saddr, 1496 &iface->addr6_list); 1497 if (addr6 == NULL) 1498 goto unlabel_getattr_nolabel; 1499 secattr->attr.secid = netlbl_unlhsh_addr6_entry(addr6)->secid; 1500 break; 1501 } 1502 #endif /* IPv6 */ 1503 default: 1504 goto unlabel_getattr_nolabel; 1505 } 1506 rcu_read_unlock(); 1507 1508 secattr->flags |= NETLBL_SECATTR_SECID; 1509 secattr->type = NETLBL_NLTYPE_UNLABELED; 1510 return 0; 1511 1512 unlabel_getattr_nolabel: 1513 rcu_read_unlock(); 1514 if (netlabel_unlabel_acceptflg == 0) 1515 return -ENOMSG; 1516 secattr->type = NETLBL_NLTYPE_UNLABELED; 1517 return 0; 1518 } 1519 1520 /** 1521 * netlbl_unlabel_defconf - Set the default config to allow unlabeled packets 1522 * 1523 * Description: 1524 * Set the default NetLabel configuration to allow incoming unlabeled packets 1525 * and to send unlabeled network traffic by default. 1526 * 1527 */ 1528 int __init netlbl_unlabel_defconf(void) 1529 { 1530 int ret_val; 1531 struct netlbl_dom_map *entry; 1532 struct netlbl_audit audit_info; 1533 1534 /* Only the kernel is allowed to call this function and the only time 1535 * it is called is at bootup before the audit subsystem is reporting 1536 * messages so don't worry to much about these values. */ 1537 security_task_getsecid(current, &audit_info.secid); 1538 audit_info.loginuid = GLOBAL_ROOT_UID; 1539 audit_info.sessionid = 0; 1540 1541 entry = kzalloc(sizeof(*entry), GFP_KERNEL); 1542 if (entry == NULL) 1543 return -ENOMEM; 1544 entry->def.type = NETLBL_NLTYPE_UNLABELED; 1545 ret_val = netlbl_domhsh_add_default(entry, &audit_info); 1546 if (ret_val != 0) 1547 return ret_val; 1548 1549 netlbl_unlabel_acceptflg_set(1, &audit_info); 1550 1551 return 0; 1552 } 1553