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