diff options
| author | Paul Moore <paul.moore@hp.com> | 2008-10-10 10:16:33 -0400 |
|---|---|---|
| committer | Paul Moore <paul.moore@hp.com> | 2008-10-10 10:16:33 -0400 |
| commit | 014ab19a69c325f52d7bae54ceeda73d6307ae0c (patch) | |
| tree | 8a69c490accb7d5454bdfeb8c078d846729aeb60 /net | |
| parent | 948bf85c1bc9a84754786a9d5dd99b7ecc46451e (diff) | |
selinux: Set socket NetLabel based on connection endpoint
Previous work enabled the use of address based NetLabel selectors, which while
highly useful, brought the potential for additional per-packet overhead when
used. This patch attempts to solve that by applying NetLabel socket labels
when sockets are connect()'d. This should alleviate the per-packet NetLabel
labeling for all connected sockets (yes, it even works for connected DGRAM
sockets).
Signed-off-by: Paul Moore <paul.moore@hp.com>
Reviewed-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'net')
| -rw-r--r-- | net/ipv4/cipso_ipv4.c | 74 | ||||
| -rw-r--r-- | net/netlabel/netlabel_kapi.c | 78 |
2 files changed, 151 insertions, 1 deletions
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index e13d6dbb66ab..23768b9d6b64 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c | |||
| @@ -1810,6 +1810,80 @@ socket_setattr_failure: | |||
| 1810 | } | 1810 | } |
| 1811 | 1811 | ||
| 1812 | /** | 1812 | /** |
| 1813 | * cipso_v4_sock_delattr - Delete the CIPSO option from a socket | ||
| 1814 | * @sk: the socket | ||
| 1815 | * | ||
| 1816 | * Description: | ||
| 1817 | * Removes the CIPSO option from a socket, if present. | ||
| 1818 | * | ||
| 1819 | */ | ||
| 1820 | void cipso_v4_sock_delattr(struct sock *sk) | ||
| 1821 | { | ||
| 1822 | u8 hdr_delta; | ||
| 1823 | struct ip_options *opt; | ||
| 1824 | struct inet_sock *sk_inet; | ||
| 1825 | |||
| 1826 | sk_inet = inet_sk(sk); | ||
| 1827 | opt = sk_inet->opt; | ||
| 1828 | if (opt == NULL || opt->cipso == 0) | ||
| 1829 | return; | ||
| 1830 | |||
| 1831 | if (opt->srr || opt->rr || opt->ts || opt->router_alert) { | ||
| 1832 | u8 cipso_len; | ||
| 1833 | u8 cipso_off; | ||
| 1834 | unsigned char *cipso_ptr; | ||
| 1835 | int iter; | ||
| 1836 | int optlen_new; | ||
| 1837 | |||
| 1838 | cipso_off = opt->cipso - sizeof(struct iphdr); | ||
| 1839 | cipso_ptr = &opt->__data[cipso_off]; | ||
| 1840 | cipso_len = cipso_ptr[1]; | ||
| 1841 | |||
| 1842 | if (opt->srr > opt->cipso) | ||
| 1843 | opt->srr -= cipso_len; | ||
| 1844 | if (opt->rr > opt->cipso) | ||
| 1845 | opt->rr -= cipso_len; | ||
| 1846 | if (opt->ts > opt->cipso) | ||
| 1847 | opt->ts -= cipso_len; | ||
| 1848 | if (opt->router_alert > opt->cipso) | ||
| 1849 | opt->router_alert -= cipso_len; | ||
| 1850 | opt->cipso = 0; | ||
| 1851 | |||
| 1852 | memmove(cipso_ptr, cipso_ptr + cipso_len, | ||
| 1853 | opt->optlen - cipso_off - cipso_len); | ||
| 1854 | |||
| 1855 | /* determining the new total option length is tricky because of | ||
| 1856 | * the padding necessary, the only thing i can think to do at | ||
| 1857 | * this point is walk the options one-by-one, skipping the | ||
| 1858 | * padding at the end to determine the actual option size and | ||
| 1859 | * from there we can determine the new total option length */ | ||
| 1860 | iter = 0; | ||
| 1861 | optlen_new = 0; | ||
| 1862 | while (iter < opt->optlen) | ||
| 1863 | if (opt->__data[iter] != IPOPT_NOP) { | ||
| 1864 | iter += opt->__data[iter + 1]; | ||
| 1865 | optlen_new = iter; | ||
| 1866 | } else | ||
| 1867 | iter++; | ||
| 1868 | hdr_delta = opt->optlen; | ||
| 1869 | opt->optlen = (optlen_new + 3) & ~3; | ||
| 1870 | hdr_delta -= opt->optlen; | ||
| 1871 | } else { | ||
| 1872 | /* only the cipso option was present on the socket so we can | ||
| 1873 | * remove the entire option struct */ | ||
| 1874 | sk_inet->opt = NULL; | ||
| 1875 | hdr_delta = opt->optlen; | ||
| 1876 | kfree(opt); | ||
| 1877 | } | ||
| 1878 | |||
| 1879 | if (sk_inet->is_icsk && hdr_delta > 0) { | ||
| 1880 | struct inet_connection_sock *sk_conn = inet_csk(sk); | ||
| 1881 | sk_conn->icsk_ext_hdr_len -= hdr_delta; | ||
| 1882 | sk_conn->icsk_sync_mss(sk, sk_conn->icsk_pmtu_cookie); | ||
| 1883 | } | ||
| 1884 | } | ||
| 1885 | |||
| 1886 | /** | ||
| 1813 | * cipso_v4_getattr - Helper function for the cipso_v4_*_getattr functions | 1887 | * cipso_v4_getattr - Helper function for the cipso_v4_*_getattr functions |
| 1814 | * @cipso: the CIPSO v4 option | 1888 | * @cipso: the CIPSO v4 option |
| 1815 | * @secattr: the security attributes | 1889 | * @secattr: the security attributes |
diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c index cc8047d1f505..78fc557689b2 100644 --- a/net/netlabel/netlabel_kapi.c +++ b/net/netlabel/netlabel_kapi.c | |||
| @@ -10,7 +10,7 @@ | |||
| 10 | */ | 10 | */ |
| 11 | 11 | ||
| 12 | /* | 12 | /* |
| 13 | * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 | 13 | * (c) Copyright Hewlett-Packard Development Company, L.P., 2006, 2008 |
| 14 | * | 14 | * |
| 15 | * This program is free software; you can redistribute it and/or modify | 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 | 16 | * it under the terms of the GNU General Public License as published by |
| @@ -456,6 +456,20 @@ socket_setattr_return: | |||
| 456 | } | 456 | } |
| 457 | 457 | ||
| 458 | /** | 458 | /** |
| 459 | * netlbl_sock_delattr - Delete all the NetLabel labels on a socket | ||
| 460 | * @sk: the socket | ||
| 461 | * | ||
| 462 | * Description: | ||
| 463 | * Remove all the NetLabel labeling from @sk. The caller is responsible for | ||
| 464 | * ensuring that @sk is locked. | ||
| 465 | * | ||
| 466 | */ | ||
| 467 | void netlbl_sock_delattr(struct sock *sk) | ||
| 468 | { | ||
| 469 | cipso_v4_sock_delattr(sk); | ||
| 470 | } | ||
| 471 | |||
| 472 | /** | ||
| 459 | * netlbl_sock_getattr - Determine the security attributes of a sock | 473 | * netlbl_sock_getattr - Determine the security attributes of a sock |
| 460 | * @sk: the sock | 474 | * @sk: the sock |
| 461 | * @secattr: the security attributes | 475 | * @secattr: the security attributes |
| @@ -473,6 +487,68 @@ int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr) | |||
| 473 | } | 487 | } |
| 474 | 488 | ||
| 475 | /** | 489 | /** |
| 490 | * netlbl_conn_setattr - Label a connected socket using the correct protocol | ||
| 491 | * @sk: the socket to label | ||
| 492 | * @addr: the destination address | ||
| 493 | * @secattr: the security attributes | ||
| 494 | * | ||
| 495 | * Description: | ||
| 496 | * Attach the correct label to the given connected socket using the security | ||
| 497 | * attributes specified in @secattr. The caller is responsible for ensuring | ||
| 498 | * that @sk is locked. Returns zero on success, negative values on failure. | ||
| 499 | * | ||
| 500 | */ | ||
| 501 | int netlbl_conn_setattr(struct sock *sk, | ||
| 502 | struct sockaddr *addr, | ||
| 503 | const struct netlbl_lsm_secattr *secattr) | ||
| 504 | { | ||
| 505 | int ret_val; | ||
| 506 | struct sockaddr_in *addr4; | ||
| 507 | struct netlbl_domaddr4_map *af4_entry; | ||
| 508 | |||
| 509 | rcu_read_lock(); | ||
| 510 | switch (addr->sa_family) { | ||
| 511 | case AF_INET: | ||
| 512 | addr4 = (struct sockaddr_in *)addr; | ||
| 513 | af4_entry = netlbl_domhsh_getentry_af4(secattr->domain, | ||
| 514 | addr4->sin_addr.s_addr); | ||
| 515 | if (af4_entry == NULL) { | ||
| 516 | ret_val = -ENOENT; | ||
| 517 | goto conn_setattr_return; | ||
| 518 | } | ||
| 519 | switch (af4_entry->type) { | ||
| 520 | case NETLBL_NLTYPE_CIPSOV4: | ||
| 521 | ret_val = cipso_v4_sock_setattr(sk, | ||
| 522 | af4_entry->type_def.cipsov4, | ||
| 523 | secattr); | ||
| 524 | break; | ||
| 525 | case NETLBL_NLTYPE_UNLABELED: | ||
| 526 | /* just delete the protocols we support for right now | ||
| 527 | * but we could remove other protocols if needed */ | ||
| 528 | cipso_v4_sock_delattr(sk); | ||
| 529 | ret_val = 0; | ||
| 530 | break; | ||
| 531 | default: | ||
| 532 | ret_val = -ENOENT; | ||
| 533 | } | ||
| 534 | break; | ||
| 535 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
| 536 | case AF_INET6: | ||
| 537 | /* since we don't support any IPv6 labeling protocols right | ||
| 538 | * now we can optimize everything away until we do */ | ||
| 539 | ret_val = 0; | ||
| 540 | break; | ||
| 541 | #endif /* IPv6 */ | ||
| 542 | default: | ||
| 543 | ret_val = 0; | ||
| 544 | } | ||
| 545 | |||
| 546 | conn_setattr_return: | ||
| 547 | rcu_read_unlock(); | ||
| 548 | return ret_val; | ||
| 549 | } | ||
| 550 | |||
| 551 | /** | ||
| 476 | * netlbl_skbuff_setattr - Label a packet using the correct protocol | 552 | * netlbl_skbuff_setattr - Label a packet using the correct protocol |
| 477 | * @skb: the packet | 553 | * @skb: the packet |
| 478 | * @family: protocol family | 554 | * @family: protocol family |
