diff options
| -rw-r--r-- | include/net/cipso_ipv4.h | 17 | ||||
| -rw-r--r-- | include/net/netlabel.h | 12 | ||||
| -rw-r--r-- | net/ipv4/cipso_ipv4.c | 130 | ||||
| -rw-r--r-- | net/netlabel/netlabel_kapi.c | 152 | ||||
| -rw-r--r-- | security/selinux/hooks.c | 54 | ||||
| -rw-r--r-- | security/selinux/include/netlabel.h | 27 | ||||
| -rw-r--r-- | security/selinux/netlabel.c | 186 | ||||
| -rw-r--r-- | security/smack/smack_lsm.c | 2 |
8 files changed, 360 insertions, 220 deletions
diff --git a/include/net/cipso_ipv4.h b/include/net/cipso_ipv4.h index bedc7f62e35d..abd443604c9f 100644 --- a/include/net/cipso_ipv4.h +++ b/include/net/cipso_ipv4.h | |||
| @@ -40,6 +40,7 @@ | |||
| 40 | #include <linux/net.h> | 40 | #include <linux/net.h> |
| 41 | #include <linux/skbuff.h> | 41 | #include <linux/skbuff.h> |
| 42 | #include <net/netlabel.h> | 42 | #include <net/netlabel.h> |
| 43 | #include <net/request_sock.h> | ||
| 43 | #include <asm/atomic.h> | 44 | #include <asm/atomic.h> |
| 44 | 45 | ||
| 45 | /* known doi values */ | 46 | /* known doi values */ |
| @@ -215,6 +216,10 @@ int cipso_v4_sock_setattr(struct sock *sk, | |||
| 215 | const struct netlbl_lsm_secattr *secattr); | 216 | const struct netlbl_lsm_secattr *secattr); |
| 216 | void cipso_v4_sock_delattr(struct sock *sk); | 217 | void cipso_v4_sock_delattr(struct sock *sk); |
| 217 | int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr); | 218 | int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr); |
| 219 | int cipso_v4_req_setattr(struct request_sock *req, | ||
| 220 | const struct cipso_v4_doi *doi_def, | ||
| 221 | const struct netlbl_lsm_secattr *secattr); | ||
| 222 | void cipso_v4_req_delattr(struct request_sock *req); | ||
| 218 | int cipso_v4_skbuff_setattr(struct sk_buff *skb, | 223 | int cipso_v4_skbuff_setattr(struct sk_buff *skb, |
| 219 | const struct cipso_v4_doi *doi_def, | 224 | const struct cipso_v4_doi *doi_def, |
| 220 | const struct netlbl_lsm_secattr *secattr); | 225 | const struct netlbl_lsm_secattr *secattr); |
| @@ -247,6 +252,18 @@ static inline int cipso_v4_sock_getattr(struct sock *sk, | |||
| 247 | return -ENOSYS; | 252 | return -ENOSYS; |
| 248 | } | 253 | } |
| 249 | 254 | ||
| 255 | static inline int cipso_v4_req_setattr(struct request_sock *req, | ||
| 256 | const struct cipso_v4_doi *doi_def, | ||
| 257 | const struct netlbl_lsm_secattr *secattr) | ||
| 258 | { | ||
| 259 | return -ENOSYS; | ||
| 260 | } | ||
| 261 | |||
| 262 | static inline void cipso_v4_req_delattr(struct request_sock *req) | ||
| 263 | { | ||
| 264 | return; | ||
| 265 | } | ||
| 266 | |||
| 250 | static inline int cipso_v4_skbuff_setattr(struct sk_buff *skb, | 267 | static inline int cipso_v4_skbuff_setattr(struct sk_buff *skb, |
| 251 | const struct cipso_v4_doi *doi_def, | 268 | const struct cipso_v4_doi *doi_def, |
| 252 | const struct netlbl_lsm_secattr *secattr) | 269 | const struct netlbl_lsm_secattr *secattr) |
diff --git a/include/net/netlabel.h b/include/net/netlabel.h index 749011eedc0b..bdb10e5183d5 100644 --- a/include/net/netlabel.h +++ b/include/net/netlabel.h | |||
| @@ -36,6 +36,7 @@ | |||
| 36 | #include <linux/in.h> | 36 | #include <linux/in.h> |
| 37 | #include <linux/in6.h> | 37 | #include <linux/in6.h> |
| 38 | #include <net/netlink.h> | 38 | #include <net/netlink.h> |
| 39 | #include <net/request_sock.h> | ||
| 39 | #include <asm/atomic.h> | 40 | #include <asm/atomic.h> |
| 40 | 41 | ||
| 41 | struct cipso_v4_doi; | 42 | struct cipso_v4_doi; |
| @@ -406,6 +407,7 @@ int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap *catmap, | |||
| 406 | */ | 407 | */ |
| 407 | int netlbl_enabled(void); | 408 | int netlbl_enabled(void); |
| 408 | int netlbl_sock_setattr(struct sock *sk, | 409 | int netlbl_sock_setattr(struct sock *sk, |
| 410 | u16 family, | ||
| 409 | const struct netlbl_lsm_secattr *secattr); | 411 | const struct netlbl_lsm_secattr *secattr); |
| 410 | void netlbl_sock_delattr(struct sock *sk); | 412 | void netlbl_sock_delattr(struct sock *sk); |
| 411 | int netlbl_sock_getattr(struct sock *sk, | 413 | int netlbl_sock_getattr(struct sock *sk, |
| @@ -413,6 +415,8 @@ int netlbl_sock_getattr(struct sock *sk, | |||
| 413 | int netlbl_conn_setattr(struct sock *sk, | 415 | int netlbl_conn_setattr(struct sock *sk, |
| 414 | struct sockaddr *addr, | 416 | struct sockaddr *addr, |
| 415 | const struct netlbl_lsm_secattr *secattr); | 417 | const struct netlbl_lsm_secattr *secattr); |
| 418 | int netlbl_req_setattr(struct request_sock *req, | ||
| 419 | const struct netlbl_lsm_secattr *secattr); | ||
| 416 | int netlbl_skbuff_setattr(struct sk_buff *skb, | 420 | int netlbl_skbuff_setattr(struct sk_buff *skb, |
| 417 | u16 family, | 421 | u16 family, |
| 418 | const struct netlbl_lsm_secattr *secattr); | 422 | const struct netlbl_lsm_secattr *secattr); |
| @@ -519,7 +523,8 @@ static inline int netlbl_enabled(void) | |||
| 519 | return 0; | 523 | return 0; |
| 520 | } | 524 | } |
| 521 | static inline int netlbl_sock_setattr(struct sock *sk, | 525 | static inline int netlbl_sock_setattr(struct sock *sk, |
| 522 | const struct netlbl_lsm_secattr *secattr) | 526 | u16 family, |
| 527 | const struct netlbl_lsm_secattr *secattr) | ||
| 523 | { | 528 | { |
| 524 | return -ENOSYS; | 529 | return -ENOSYS; |
| 525 | } | 530 | } |
| @@ -537,6 +542,11 @@ static inline int netlbl_conn_setattr(struct sock *sk, | |||
| 537 | { | 542 | { |
| 538 | return -ENOSYS; | 543 | return -ENOSYS; |
| 539 | } | 544 | } |
| 545 | static inline int netlbl_req_setattr(struct request_sock *req, | ||
| 546 | const struct netlbl_lsm_secattr *secattr) | ||
| 547 | { | ||
| 548 | return -ENOSYS; | ||
| 549 | } | ||
| 540 | static inline int netlbl_skbuff_setattr(struct sk_buff *skb, | 550 | static inline int netlbl_skbuff_setattr(struct sk_buff *skb, |
| 541 | u16 family, | 551 | u16 family, |
| 542 | const struct netlbl_lsm_secattr *secattr) | 552 | const struct netlbl_lsm_secattr *secattr) |
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index 7bc992976d29..039cc1ffe977 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c | |||
| @@ -1942,23 +1942,85 @@ socket_setattr_failure: | |||
| 1942 | } | 1942 | } |
| 1943 | 1943 | ||
| 1944 | /** | 1944 | /** |
| 1945 | * cipso_v4_sock_delattr - Delete the CIPSO option from a socket | 1945 | * cipso_v4_req_setattr - Add a CIPSO option to a connection request socket |
| 1946 | * @sk: the socket | 1946 | * @req: the connection request socket |
| 1947 | * @doi_def: the CIPSO DOI to use | ||
| 1948 | * @secattr: the specific security attributes of the socket | ||
| 1947 | * | 1949 | * |
| 1948 | * Description: | 1950 | * Description: |
| 1949 | * Removes the CIPSO option from a socket, if present. | 1951 | * Set the CIPSO option on the given socket using the DOI definition and |
| 1952 | * security attributes passed to the function. Returns zero on success and | ||
| 1953 | * negative values on failure. | ||
| 1950 | * | 1954 | * |
| 1951 | */ | 1955 | */ |
| 1952 | void cipso_v4_sock_delattr(struct sock *sk) | 1956 | int cipso_v4_req_setattr(struct request_sock *req, |
| 1957 | const struct cipso_v4_doi *doi_def, | ||
| 1958 | const struct netlbl_lsm_secattr *secattr) | ||
| 1953 | { | 1959 | { |
| 1954 | u8 hdr_delta; | 1960 | int ret_val = -EPERM; |
| 1955 | struct ip_options *opt; | 1961 | unsigned char *buf = NULL; |
| 1956 | struct inet_sock *sk_inet; | 1962 | u32 buf_len; |
| 1963 | u32 opt_len; | ||
| 1964 | struct ip_options *opt = NULL; | ||
| 1965 | struct inet_request_sock *req_inet; | ||
| 1957 | 1966 | ||
| 1958 | sk_inet = inet_sk(sk); | 1967 | /* We allocate the maximum CIPSO option size here so we are probably |
| 1959 | opt = sk_inet->opt; | 1968 | * being a little wasteful, but it makes our life _much_ easier later |
| 1960 | if (opt == NULL || opt->cipso == 0) | 1969 | * on and after all we are only talking about 40 bytes. */ |
| 1961 | return; | 1970 | buf_len = CIPSO_V4_OPT_LEN_MAX; |
| 1971 | buf = kmalloc(buf_len, GFP_ATOMIC); | ||
| 1972 | if (buf == NULL) { | ||
| 1973 | ret_val = -ENOMEM; | ||
| 1974 | goto req_setattr_failure; | ||
| 1975 | } | ||
| 1976 | |||
| 1977 | ret_val = cipso_v4_genopt(buf, buf_len, doi_def, secattr); | ||
| 1978 | if (ret_val < 0) | ||
| 1979 | goto req_setattr_failure; | ||
| 1980 | buf_len = ret_val; | ||
| 1981 | |||
| 1982 | /* We can't use ip_options_get() directly because it makes a call to | ||
| 1983 | * ip_options_get_alloc() which allocates memory with GFP_KERNEL and | ||
| 1984 | * we won't always have CAP_NET_RAW even though we _always_ want to | ||
| 1985 | * set the IPOPT_CIPSO option. */ | ||
| 1986 | opt_len = (buf_len + 3) & ~3; | ||
| 1987 | opt = kzalloc(sizeof(*opt) + opt_len, GFP_ATOMIC); | ||
| 1988 | if (opt == NULL) { | ||
| 1989 | ret_val = -ENOMEM; | ||
| 1990 | goto req_setattr_failure; | ||
| 1991 | } | ||
| 1992 | memcpy(opt->__data, buf, buf_len); | ||
| 1993 | opt->optlen = opt_len; | ||
| 1994 | opt->cipso = sizeof(struct iphdr); | ||
| 1995 | kfree(buf); | ||
| 1996 | buf = NULL; | ||
| 1997 | |||
| 1998 | req_inet = inet_rsk(req); | ||
| 1999 | opt = xchg(&req_inet->opt, opt); | ||
| 2000 | kfree(opt); | ||
| 2001 | |||
| 2002 | return 0; | ||
| 2003 | |||
| 2004 | req_setattr_failure: | ||
| 2005 | kfree(buf); | ||
| 2006 | kfree(opt); | ||
| 2007 | return ret_val; | ||
| 2008 | } | ||
| 2009 | |||
| 2010 | /** | ||
| 2011 | * cipso_v4_delopt - Delete the CIPSO option from a set of IP options | ||
| 2012 | * @opt_ptr: IP option pointer | ||
| 2013 | * | ||
| 2014 | * Description: | ||
| 2015 | * Deletes the CIPSO IP option from a set of IP options and makes the necessary | ||
| 2016 | * adjustments to the IP option structure. Returns zero on success, negative | ||
| 2017 | * values on failure. | ||
| 2018 | * | ||
| 2019 | */ | ||
| 2020 | int cipso_v4_delopt(struct ip_options **opt_ptr) | ||
| 2021 | { | ||
| 2022 | int hdr_delta = 0; | ||
| 2023 | struct ip_options *opt = *opt_ptr; | ||
| 1962 | 2024 | ||
| 1963 | if (opt->srr || opt->rr || opt->ts || opt->router_alert) { | 2025 | if (opt->srr || opt->rr || opt->ts || opt->router_alert) { |
| 1964 | u8 cipso_len; | 2026 | u8 cipso_len; |
| @@ -2003,11 +2065,34 @@ void cipso_v4_sock_delattr(struct sock *sk) | |||
| 2003 | } else { | 2065 | } else { |
| 2004 | /* only the cipso option was present on the socket so we can | 2066 | /* only the cipso option was present on the socket so we can |
| 2005 | * remove the entire option struct */ | 2067 | * remove the entire option struct */ |
| 2006 | sk_inet->opt = NULL; | 2068 | *opt_ptr = NULL; |
| 2007 | hdr_delta = opt->optlen; | 2069 | hdr_delta = opt->optlen; |
| 2008 | kfree(opt); | 2070 | kfree(opt); |
| 2009 | } | 2071 | } |
| 2010 | 2072 | ||
| 2073 | return hdr_delta; | ||
| 2074 | } | ||
| 2075 | |||
| 2076 | /** | ||
| 2077 | * cipso_v4_sock_delattr - Delete the CIPSO option from a socket | ||
| 2078 | * @sk: the socket | ||
| 2079 | * | ||
| 2080 | * Description: | ||
| 2081 | * Removes the CIPSO option from a socket, if present. | ||
| 2082 | * | ||
| 2083 | */ | ||
| 2084 | void cipso_v4_sock_delattr(struct sock *sk) | ||
| 2085 | { | ||
| 2086 | int hdr_delta; | ||
| 2087 | struct ip_options *opt; | ||
| 2088 | struct inet_sock *sk_inet; | ||
| 2089 | |||
| 2090 | sk_inet = inet_sk(sk); | ||
| 2091 | opt = sk_inet->opt; | ||
| 2092 | if (opt == NULL || opt->cipso == 0) | ||
| 2093 | return; | ||
| 2094 | |||
| 2095 | hdr_delta = cipso_v4_delopt(&sk_inet->opt); | ||
| 2011 | if (sk_inet->is_icsk && hdr_delta > 0) { | 2096 | if (sk_inet->is_icsk && hdr_delta > 0) { |
| 2012 | struct inet_connection_sock *sk_conn = inet_csk(sk); | 2097 | struct inet_connection_sock *sk_conn = inet_csk(sk); |
| 2013 | sk_conn->icsk_ext_hdr_len -= hdr_delta; | 2098 | sk_conn->icsk_ext_hdr_len -= hdr_delta; |
| @@ -2016,6 +2101,27 @@ void cipso_v4_sock_delattr(struct sock *sk) | |||
| 2016 | } | 2101 | } |
| 2017 | 2102 | ||
| 2018 | /** | 2103 | /** |
| 2104 | * cipso_v4_req_delattr - Delete the CIPSO option from a request socket | ||
| 2105 | * @reg: the request socket | ||
| 2106 | * | ||
| 2107 | * Description: | ||
| 2108 | * Removes the CIPSO option from a request socket, if present. | ||
| 2109 | * | ||
| 2110 | */ | ||
| 2111 | void cipso_v4_req_delattr(struct request_sock *req) | ||
| 2112 | { | ||
| 2113 | struct ip_options *opt; | ||
| 2114 | struct inet_request_sock *req_inet; | ||
| 2115 | |||
| 2116 | req_inet = inet_rsk(req); | ||
| 2117 | opt = req_inet->opt; | ||
| 2118 | if (opt == NULL || opt->cipso == 0) | ||
| 2119 | return; | ||
| 2120 | |||
| 2121 | cipso_v4_delopt(&req_inet->opt); | ||
| 2122 | } | ||
| 2123 | |||
| 2124 | /** | ||
| 2019 | * cipso_v4_getattr - Helper function for the cipso_v4_*_getattr functions | 2125 | * cipso_v4_getattr - Helper function for the cipso_v4_*_getattr functions |
| 2020 | * @cipso: the CIPSO v4 option | 2126 | * @cipso: the CIPSO v4 option |
| 2021 | * @secattr: the security attributes | 2127 | * @secattr: the security attributes |
diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c index fd9229db075c..cae2f5f4cac0 100644 --- a/net/netlabel/netlabel_kapi.c +++ b/net/netlabel/netlabel_kapi.c | |||
| @@ -619,8 +619,9 @@ int netlbl_enabled(void) | |||
| 619 | } | 619 | } |
| 620 | 620 | ||
| 621 | /** | 621 | /** |
| 622 | * netlbl_socket_setattr - Label a socket using the correct protocol | 622 | * netlbl_sock_setattr - Label a socket using the correct protocol |
| 623 | * @sk: the socket to label | 623 | * @sk: the socket to label |
| 624 | * @family: protocol family | ||
| 624 | * @secattr: the security attributes | 625 | * @secattr: the security attributes |
| 625 | * | 626 | * |
| 626 | * Description: | 627 | * Description: |
| @@ -633,29 +634,45 @@ int netlbl_enabled(void) | |||
| 633 | * | 634 | * |
| 634 | */ | 635 | */ |
| 635 | int netlbl_sock_setattr(struct sock *sk, | 636 | int netlbl_sock_setattr(struct sock *sk, |
| 637 | u16 family, | ||
| 636 | const struct netlbl_lsm_secattr *secattr) | 638 | const struct netlbl_lsm_secattr *secattr) |
| 637 | { | 639 | { |
| 638 | int ret_val = -ENOENT; | 640 | int ret_val; |
| 639 | struct netlbl_dom_map *dom_entry; | 641 | struct netlbl_dom_map *dom_entry; |
| 640 | 642 | ||
| 641 | rcu_read_lock(); | 643 | rcu_read_lock(); |
| 642 | dom_entry = netlbl_domhsh_getentry(secattr->domain); | 644 | dom_entry = netlbl_domhsh_getentry(secattr->domain); |
| 643 | if (dom_entry == NULL) | 645 | if (dom_entry == NULL) { |
| 646 | ret_val = -ENOENT; | ||
| 644 | goto socket_setattr_return; | 647 | goto socket_setattr_return; |
| 645 | switch (dom_entry->type) { | 648 | } |
| 646 | case NETLBL_NLTYPE_ADDRSELECT: | 649 | switch (family) { |
| 647 | ret_val = -EDESTADDRREQ; | 650 | case AF_INET: |
| 648 | break; | 651 | switch (dom_entry->type) { |
| 649 | case NETLBL_NLTYPE_CIPSOV4: | 652 | case NETLBL_NLTYPE_ADDRSELECT: |
| 650 | ret_val = cipso_v4_sock_setattr(sk, | 653 | ret_val = -EDESTADDRREQ; |
| 651 | dom_entry->type_def.cipsov4, | 654 | break; |
| 652 | secattr); | 655 | case NETLBL_NLTYPE_CIPSOV4: |
| 656 | ret_val = cipso_v4_sock_setattr(sk, | ||
| 657 | dom_entry->type_def.cipsov4, | ||
| 658 | secattr); | ||
| 659 | break; | ||
| 660 | case NETLBL_NLTYPE_UNLABELED: | ||
| 661 | ret_val = 0; | ||
| 662 | break; | ||
| 663 | default: | ||
| 664 | ret_val = -ENOENT; | ||
| 665 | } | ||
| 653 | break; | 666 | break; |
| 654 | case NETLBL_NLTYPE_UNLABELED: | 667 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
| 668 | case AF_INET6: | ||
| 669 | /* since we don't support any IPv6 labeling protocols right | ||
| 670 | * now we can optimize everything away until we do */ | ||
| 655 | ret_val = 0; | 671 | ret_val = 0; |
| 656 | break; | 672 | break; |
| 673 | #endif /* IPv6 */ | ||
| 657 | default: | 674 | default: |
| 658 | ret_val = -ENOENT; | 675 | ret_val = -EPROTONOSUPPORT; |
| 659 | } | 676 | } |
| 660 | 677 | ||
| 661 | socket_setattr_return: | 678 | socket_setattr_return: |
| @@ -689,9 +706,25 @@ void netlbl_sock_delattr(struct sock *sk) | |||
| 689 | * on failure. | 706 | * on failure. |
| 690 | * | 707 | * |
| 691 | */ | 708 | */ |
| 692 | int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr) | 709 | int netlbl_sock_getattr(struct sock *sk, |
| 710 | struct netlbl_lsm_secattr *secattr) | ||
| 693 | { | 711 | { |
| 694 | return cipso_v4_sock_getattr(sk, secattr); | 712 | int ret_val; |
| 713 | |||
| 714 | switch (sk->sk_family) { | ||
| 715 | case AF_INET: | ||
| 716 | ret_val = cipso_v4_sock_getattr(sk, secattr); | ||
| 717 | break; | ||
| 718 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
| 719 | case AF_INET6: | ||
| 720 | ret_val = -ENOMSG; | ||
| 721 | break; | ||
| 722 | #endif /* IPv6 */ | ||
| 723 | default: | ||
| 724 | ret_val = -EPROTONOSUPPORT; | ||
| 725 | } | ||
| 726 | |||
| 727 | return ret_val; | ||
| 695 | } | 728 | } |
| 696 | 729 | ||
| 697 | /** | 730 | /** |
| @@ -748,7 +781,7 @@ int netlbl_conn_setattr(struct sock *sk, | |||
| 748 | break; | 781 | break; |
| 749 | #endif /* IPv6 */ | 782 | #endif /* IPv6 */ |
| 750 | default: | 783 | default: |
| 751 | ret_val = 0; | 784 | ret_val = -EPROTONOSUPPORT; |
| 752 | } | 785 | } |
| 753 | 786 | ||
| 754 | conn_setattr_return: | 787 | conn_setattr_return: |
| @@ -757,6 +790,77 @@ conn_setattr_return: | |||
| 757 | } | 790 | } |
| 758 | 791 | ||
| 759 | /** | 792 | /** |
| 793 | * netlbl_req_setattr - Label a request socket using the correct protocol | ||
| 794 | * @req: the request socket to label | ||
| 795 | * @secattr: the security attributes | ||
| 796 | * | ||
| 797 | * Description: | ||
| 798 | * Attach the correct label to the given socket using the security attributes | ||
| 799 | * specified in @secattr. Returns zero on success, negative values on failure. | ||
| 800 | * | ||
| 801 | */ | ||
| 802 | int netlbl_req_setattr(struct request_sock *req, | ||
| 803 | const struct netlbl_lsm_secattr *secattr) | ||
| 804 | { | ||
| 805 | int ret_val; | ||
| 806 | struct netlbl_dom_map *dom_entry; | ||
| 807 | struct netlbl_domaddr4_map *af4_entry; | ||
| 808 | u32 proto_type; | ||
| 809 | struct cipso_v4_doi *proto_cv4; | ||
| 810 | |||
| 811 | rcu_read_lock(); | ||
| 812 | dom_entry = netlbl_domhsh_getentry(secattr->domain); | ||
| 813 | if (dom_entry == NULL) { | ||
| 814 | ret_val = -ENOENT; | ||
| 815 | goto req_setattr_return; | ||
| 816 | } | ||
| 817 | switch (req->rsk_ops->family) { | ||
| 818 | case AF_INET: | ||
| 819 | if (dom_entry->type == NETLBL_NLTYPE_ADDRSELECT) { | ||
| 820 | struct inet_request_sock *req_inet = inet_rsk(req); | ||
| 821 | af4_entry = netlbl_domhsh_getentry_af4(secattr->domain, | ||
| 822 | req_inet->rmt_addr); | ||
| 823 | if (af4_entry == NULL) { | ||
| 824 | ret_val = -ENOENT; | ||
| 825 | goto req_setattr_return; | ||
| 826 | } | ||
| 827 | proto_type = af4_entry->type; | ||
| 828 | proto_cv4 = af4_entry->type_def.cipsov4; | ||
| 829 | } else { | ||
| 830 | proto_type = dom_entry->type; | ||
| 831 | proto_cv4 = dom_entry->type_def.cipsov4; | ||
| 832 | } | ||
| 833 | switch (proto_type) { | ||
| 834 | case NETLBL_NLTYPE_CIPSOV4: | ||
| 835 | ret_val = cipso_v4_req_setattr(req, proto_cv4, secattr); | ||
| 836 | break; | ||
| 837 | case NETLBL_NLTYPE_UNLABELED: | ||
| 838 | /* just delete the protocols we support for right now | ||
| 839 | * but we could remove other protocols if needed */ | ||
| 840 | cipso_v4_req_delattr(req); | ||
| 841 | ret_val = 0; | ||
| 842 | break; | ||
| 843 | default: | ||
| 844 | ret_val = -ENOENT; | ||
| 845 | } | ||
| 846 | break; | ||
| 847 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
| 848 | case AF_INET6: | ||
| 849 | /* since we don't support any IPv6 labeling protocols right | ||
| 850 | * now we can optimize everything away until we do */ | ||
| 851 | ret_val = 0; | ||
| 852 | break; | ||
| 853 | #endif /* IPv6 */ | ||
| 854 | default: | ||
| 855 | ret_val = -EPROTONOSUPPORT; | ||
| 856 | } | ||
| 857 | |||
| 858 | req_setattr_return: | ||
| 859 | rcu_read_unlock(); | ||
| 860 | return ret_val; | ||
| 861 | } | ||
| 862 | |||
| 863 | /** | ||
| 760 | * netlbl_skbuff_setattr - Label a packet using the correct protocol | 864 | * netlbl_skbuff_setattr - Label a packet using the correct protocol |
| 761 | * @skb: the packet | 865 | * @skb: the packet |
| 762 | * @family: protocol family | 866 | * @family: protocol family |
| @@ -808,7 +912,7 @@ int netlbl_skbuff_setattr(struct sk_buff *skb, | |||
| 808 | break; | 912 | break; |
| 809 | #endif /* IPv6 */ | 913 | #endif /* IPv6 */ |
| 810 | default: | 914 | default: |
| 811 | ret_val = 0; | 915 | ret_val = -EPROTONOSUPPORT; |
| 812 | } | 916 | } |
| 813 | 917 | ||
| 814 | skbuff_setattr_return: | 918 | skbuff_setattr_return: |
| @@ -833,9 +937,17 @@ int netlbl_skbuff_getattr(const struct sk_buff *skb, | |||
| 833 | u16 family, | 937 | u16 family, |
| 834 | struct netlbl_lsm_secattr *secattr) | 938 | struct netlbl_lsm_secattr *secattr) |
| 835 | { | 939 | { |
| 836 | if (CIPSO_V4_OPTEXIST(skb) && | 940 | switch (family) { |
| 837 | cipso_v4_skbuff_getattr(skb, secattr) == 0) | 941 | case AF_INET: |
| 838 | return 0; | 942 | if (CIPSO_V4_OPTEXIST(skb) && |
| 943 | cipso_v4_skbuff_getattr(skb, secattr) == 0) | ||
| 944 | return 0; | ||
| 945 | break; | ||
| 946 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
| 947 | case AF_INET6: | ||
| 948 | break; | ||
| 949 | #endif /* IPv6 */ | ||
| 950 | } | ||
| 839 | 951 | ||
| 840 | return netlbl_unlabel_getattr(skb, family, secattr); | 952 | return netlbl_unlabel_getattr(skb, family, secattr); |
| 841 | } | 953 | } |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 7c52ba243c64..ee2e781d11d7 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
| @@ -311,7 +311,7 @@ static int sk_alloc_security(struct sock *sk, int family, gfp_t priority) | |||
| 311 | ssec->sid = SECINITSID_UNLABELED; | 311 | ssec->sid = SECINITSID_UNLABELED; |
| 312 | sk->sk_security = ssec; | 312 | sk->sk_security = ssec; |
| 313 | 313 | ||
| 314 | selinux_netlbl_sk_security_reset(ssec, family); | 314 | selinux_netlbl_sk_security_reset(ssec); |
| 315 | 315 | ||
| 316 | return 0; | 316 | return 0; |
| 317 | } | 317 | } |
| @@ -2945,7 +2945,6 @@ static void selinux_inode_getsecid(const struct inode *inode, u32 *secid) | |||
| 2945 | static int selinux_revalidate_file_permission(struct file *file, int mask) | 2945 | static int selinux_revalidate_file_permission(struct file *file, int mask) |
| 2946 | { | 2946 | { |
| 2947 | const struct cred *cred = current_cred(); | 2947 | const struct cred *cred = current_cred(); |
| 2948 | int rc; | ||
| 2949 | struct inode *inode = file->f_path.dentry->d_inode; | 2948 | struct inode *inode = file->f_path.dentry->d_inode; |
| 2950 | 2949 | ||
| 2951 | if (!mask) { | 2950 | if (!mask) { |
| @@ -2957,29 +2956,15 @@ static int selinux_revalidate_file_permission(struct file *file, int mask) | |||
| 2957 | if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE)) | 2956 | if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE)) |
| 2958 | mask |= MAY_APPEND; | 2957 | mask |= MAY_APPEND; |
| 2959 | 2958 | ||
| 2960 | rc = file_has_perm(cred, file, | 2959 | return file_has_perm(cred, file, |
| 2961 | file_mask_to_av(inode->i_mode, mask)); | 2960 | file_mask_to_av(inode->i_mode, mask)); |
| 2962 | if (rc) | ||
| 2963 | return rc; | ||
| 2964 | |||
| 2965 | return selinux_netlbl_inode_permission(inode, mask); | ||
| 2966 | } | 2961 | } |
| 2967 | 2962 | ||
| 2968 | static int selinux_file_permission(struct file *file, int mask) | 2963 | static int selinux_file_permission(struct file *file, int mask) |
| 2969 | { | 2964 | { |
| 2970 | struct inode *inode = file->f_path.dentry->d_inode; | 2965 | if (!mask) |
| 2971 | struct file_security_struct *fsec = file->f_security; | ||
| 2972 | struct inode_security_struct *isec = inode->i_security; | ||
| 2973 | u32 sid = current_sid(); | ||
| 2974 | |||
| 2975 | if (!mask) { | ||
| 2976 | /* No permission to check. Existence test. */ | 2966 | /* No permission to check. Existence test. */ |
| 2977 | return 0; | 2967 | return 0; |
| 2978 | } | ||
| 2979 | |||
| 2980 | if (sid == fsec->sid && fsec->isid == isec->sid | ||
| 2981 | && fsec->pseqno == avc_policy_seqno()) | ||
| 2982 | return selinux_netlbl_inode_permission(inode, mask); | ||
| 2983 | 2968 | ||
| 2984 | return selinux_revalidate_file_permission(file, mask); | 2969 | return selinux_revalidate_file_permission(file, mask); |
| 2985 | } | 2970 | } |
| @@ -3723,7 +3708,7 @@ static int selinux_socket_post_create(struct socket *sock, int family, | |||
| 3723 | sksec = sock->sk->sk_security; | 3708 | sksec = sock->sk->sk_security; |
| 3724 | sksec->sid = isec->sid; | 3709 | sksec->sid = isec->sid; |
| 3725 | sksec->sclass = isec->sclass; | 3710 | sksec->sclass = isec->sclass; |
| 3726 | err = selinux_netlbl_socket_post_create(sock); | 3711 | err = selinux_netlbl_socket_post_create(sock->sk, family); |
| 3727 | } | 3712 | } |
| 3728 | 3713 | ||
| 3729 | return err; | 3714 | return err; |
| @@ -3914,13 +3899,7 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock) | |||
| 3914 | static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg, | 3899 | static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg, |
| 3915 | int size) | 3900 | int size) |
| 3916 | { | 3901 | { |
| 3917 | int rc; | 3902 | return socket_has_perm(current, sock, SOCKET__WRITE); |
| 3918 | |||
| 3919 | rc = socket_has_perm(current, sock, SOCKET__WRITE); | ||
| 3920 | if (rc) | ||
| 3921 | return rc; | ||
| 3922 | |||
| 3923 | return selinux_netlbl_inode_permission(SOCK_INODE(sock), MAY_WRITE); | ||
| 3924 | } | 3903 | } |
| 3925 | 3904 | ||
| 3926 | static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg, | 3905 | static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg, |
| @@ -4304,7 +4283,7 @@ static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk) | |||
| 4304 | newssec->peer_sid = ssec->peer_sid; | 4283 | newssec->peer_sid = ssec->peer_sid; |
| 4305 | newssec->sclass = ssec->sclass; | 4284 | newssec->sclass = ssec->sclass; |
| 4306 | 4285 | ||
| 4307 | selinux_netlbl_sk_security_reset(newssec, newsk->sk_family); | 4286 | selinux_netlbl_sk_security_reset(newssec); |
| 4308 | } | 4287 | } |
| 4309 | 4288 | ||
| 4310 | static void selinux_sk_getsecid(struct sock *sk, u32 *secid) | 4289 | static void selinux_sk_getsecid(struct sock *sk, u32 *secid) |
| @@ -4348,16 +4327,15 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb, | |||
| 4348 | if (peersid == SECSID_NULL) { | 4327 | if (peersid == SECSID_NULL) { |
| 4349 | req->secid = sksec->sid; | 4328 | req->secid = sksec->sid; |
| 4350 | req->peer_secid = SECSID_NULL; | 4329 | req->peer_secid = SECSID_NULL; |
| 4351 | return 0; | 4330 | } else { |
| 4331 | err = security_sid_mls_copy(sksec->sid, peersid, &newsid); | ||
| 4332 | if (err) | ||
| 4333 | return err; | ||
| 4334 | req->secid = newsid; | ||
| 4335 | req->peer_secid = peersid; | ||
| 4352 | } | 4336 | } |
| 4353 | 4337 | ||
| 4354 | err = security_sid_mls_copy(sksec->sid, peersid, &newsid); | 4338 | return selinux_netlbl_inet_conn_request(req, family); |
| 4355 | if (err) | ||
| 4356 | return err; | ||
| 4357 | |||
| 4358 | req->secid = newsid; | ||
| 4359 | req->peer_secid = peersid; | ||
| 4360 | return 0; | ||
| 4361 | } | 4339 | } |
| 4362 | 4340 | ||
| 4363 | static void selinux_inet_csk_clone(struct sock *newsk, | 4341 | static void selinux_inet_csk_clone(struct sock *newsk, |
| @@ -4374,7 +4352,7 @@ static void selinux_inet_csk_clone(struct sock *newsk, | |||
| 4374 | 4352 | ||
| 4375 | /* We don't need to take any sort of lock here as we are the only | 4353 | /* We don't need to take any sort of lock here as we are the only |
| 4376 | * thread with access to newsksec */ | 4354 | * thread with access to newsksec */ |
| 4377 | selinux_netlbl_sk_security_reset(newsksec, req->rsk_ops->family); | 4355 | selinux_netlbl_inet_csk_clone(newsk, req->rsk_ops->family); |
| 4378 | } | 4356 | } |
| 4379 | 4357 | ||
| 4380 | static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb) | 4358 | static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb) |
| @@ -4387,8 +4365,6 @@ static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb) | |||
| 4387 | family = PF_INET; | 4365 | family = PF_INET; |
| 4388 | 4366 | ||
| 4389 | selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid); | 4367 | selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid); |
| 4390 | |||
| 4391 | selinux_netlbl_inet_conn_established(sk, family); | ||
| 4392 | } | 4368 | } |
| 4393 | 4369 | ||
| 4394 | static void selinux_req_classify_flow(const struct request_sock *req, | 4370 | static void selinux_req_classify_flow(const struct request_sock *req, |
diff --git a/security/selinux/include/netlabel.h b/security/selinux/include/netlabel.h index b913c8d06038..b4b5b9b2f0be 100644 --- a/security/selinux/include/netlabel.h +++ b/security/selinux/include/netlabel.h | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include <linux/net.h> | 32 | #include <linux/net.h> |
| 33 | #include <linux/skbuff.h> | 33 | #include <linux/skbuff.h> |
| 34 | #include <net/sock.h> | 34 | #include <net/sock.h> |
| 35 | #include <net/request_sock.h> | ||
| 35 | 36 | ||
| 36 | #include "avc.h" | 37 | #include "avc.h" |
| 37 | #include "objsec.h" | 38 | #include "objsec.h" |
| @@ -42,8 +43,7 @@ void selinux_netlbl_cache_invalidate(void); | |||
| 42 | void selinux_netlbl_err(struct sk_buff *skb, int error, int gateway); | 43 | void selinux_netlbl_err(struct sk_buff *skb, int error, int gateway); |
| 43 | 44 | ||
| 44 | void selinux_netlbl_sk_security_free(struct sk_security_struct *ssec); | 45 | void selinux_netlbl_sk_security_free(struct sk_security_struct *ssec); |
| 45 | void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec, | 46 | void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec); |
| 46 | int family); | ||
| 47 | 47 | ||
| 48 | int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, | 48 | int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, |
| 49 | u16 family, | 49 | u16 family, |
| @@ -53,9 +53,9 @@ int selinux_netlbl_skbuff_setsid(struct sk_buff *skb, | |||
| 53 | u16 family, | 53 | u16 family, |
| 54 | u32 sid); | 54 | u32 sid); |
| 55 | 55 | ||
| 56 | void selinux_netlbl_inet_conn_established(struct sock *sk, u16 family); | 56 | int selinux_netlbl_inet_conn_request(struct request_sock *req, u16 family); |
| 57 | int selinux_netlbl_socket_post_create(struct socket *sock); | 57 | void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family); |
| 58 | int selinux_netlbl_inode_permission(struct inode *inode, int mask); | 58 | int selinux_netlbl_socket_post_create(struct sock *sk, u16 family); |
| 59 | int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, | 59 | int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, |
| 60 | struct sk_buff *skb, | 60 | struct sk_buff *skb, |
| 61 | u16 family, | 61 | u16 family, |
| @@ -85,8 +85,7 @@ static inline void selinux_netlbl_sk_security_free( | |||
| 85 | } | 85 | } |
| 86 | 86 | ||
| 87 | static inline void selinux_netlbl_sk_security_reset( | 87 | static inline void selinux_netlbl_sk_security_reset( |
| 88 | struct sk_security_struct *ssec, | 88 | struct sk_security_struct *ssec) |
| 89 | int family) | ||
| 90 | { | 89 | { |
| 91 | return; | 90 | return; |
| 92 | } | 91 | } |
| @@ -113,17 +112,17 @@ static inline int selinux_netlbl_conn_setsid(struct sock *sk, | |||
| 113 | return 0; | 112 | return 0; |
| 114 | } | 113 | } |
| 115 | 114 | ||
| 116 | static inline void selinux_netlbl_inet_conn_established(struct sock *sk, | 115 | static inline int selinux_netlbl_inet_conn_request(struct request_sock *req, |
| 117 | u16 family) | 116 | u16 family) |
| 118 | { | 117 | { |
| 119 | return; | 118 | return 0; |
| 120 | } | 119 | } |
| 121 | static inline int selinux_netlbl_socket_post_create(struct socket *sock) | 120 | static inline void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family) |
| 122 | { | 121 | { |
| 123 | return 0; | 122 | return; |
| 124 | } | 123 | } |
| 125 | static inline int selinux_netlbl_inode_permission(struct inode *inode, | 124 | static inline int selinux_netlbl_socket_post_create(struct sock *sk, |
| 126 | int mask) | 125 | u16 family) |
| 127 | { | 126 | { |
| 128 | return 0; | 127 | return 0; |
| 129 | } | 128 | } |
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c index 350794ab9b42..2e984413c7b2 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c | |||
| @@ -100,41 +100,6 @@ static struct netlbl_lsm_secattr *selinux_netlbl_sock_genattr(struct sock *sk) | |||
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | /** | 102 | /** |
| 103 | * selinux_netlbl_sock_setsid - Label a socket using the NetLabel mechanism | ||
| 104 | * @sk: the socket to label | ||
| 105 | * | ||
| 106 | * Description: | ||
| 107 | * Attempt to label a socket using the NetLabel mechanism. Returns zero values | ||
| 108 | * on success, negative values on failure. | ||
| 109 | * | ||
| 110 | */ | ||
| 111 | static int selinux_netlbl_sock_setsid(struct sock *sk) | ||
| 112 | { | ||
| 113 | int rc; | ||
| 114 | struct sk_security_struct *sksec = sk->sk_security; | ||
| 115 | struct netlbl_lsm_secattr *secattr; | ||
| 116 | |||
| 117 | if (sksec->nlbl_state != NLBL_REQUIRE) | ||
| 118 | return 0; | ||
| 119 | |||
| 120 | secattr = selinux_netlbl_sock_genattr(sk); | ||
| 121 | if (secattr == NULL) | ||
| 122 | return -ENOMEM; | ||
| 123 | rc = netlbl_sock_setattr(sk, secattr); | ||
| 124 | switch (rc) { | ||
| 125 | case 0: | ||
| 126 | sksec->nlbl_state = NLBL_LABELED; | ||
| 127 | break; | ||
| 128 | case -EDESTADDRREQ: | ||
| 129 | sksec->nlbl_state = NLBL_REQSKB; | ||
| 130 | rc = 0; | ||
| 131 | break; | ||
| 132 | } | ||
| 133 | |||
| 134 | return rc; | ||
| 135 | } | ||
| 136 | |||
| 137 | /** | ||
| 138 | * selinux_netlbl_cache_invalidate - Invalidate the NetLabel cache | 103 | * selinux_netlbl_cache_invalidate - Invalidate the NetLabel cache |
| 139 | * | 104 | * |
| 140 | * Description: | 105 | * Description: |
| @@ -188,13 +153,9 @@ void selinux_netlbl_sk_security_free(struct sk_security_struct *ssec) | |||
| 188 | * The caller is responsibile for all the NetLabel sk_security_struct locking. | 153 | * The caller is responsibile for all the NetLabel sk_security_struct locking. |
| 189 | * | 154 | * |
| 190 | */ | 155 | */ |
| 191 | void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec, | 156 | void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec) |
| 192 | int family) | ||
| 193 | { | 157 | { |
| 194 | if (family == PF_INET) | 158 | ssec->nlbl_state = NLBL_UNSET; |
| 195 | ssec->nlbl_state = NLBL_REQUIRE; | ||
| 196 | else | ||
| 197 | ssec->nlbl_state = NLBL_UNSET; | ||
| 198 | } | 159 | } |
| 199 | 160 | ||
| 200 | /** | 161 | /** |
| @@ -281,127 +242,86 @@ skbuff_setsid_return: | |||
| 281 | } | 242 | } |
| 282 | 243 | ||
| 283 | /** | 244 | /** |
| 284 | * selinux_netlbl_inet_conn_established - Netlabel the newly accepted connection | 245 | * selinux_netlbl_inet_conn_request - Label an incoming stream connection |
| 285 | * @sk: the new connection | 246 | * @req: incoming connection request socket |
| 286 | * | 247 | * |
| 287 | * Description: | 248 | * Description: |
| 288 | * A new connection has been established on @sk so make sure it is labeled | 249 | * A new incoming connection request is represented by @req, we need to label |
| 289 | * correctly with the NetLabel susbsystem. | 250 | * the new request_sock here and the stack will ensure the on-the-wire label |
| 251 | * will get preserved when a full sock is created once the connection handshake | ||
| 252 | * is complete. Returns zero on success, negative values on failure. | ||
| 290 | * | 253 | * |
| 291 | */ | 254 | */ |
| 292 | void selinux_netlbl_inet_conn_established(struct sock *sk, u16 family) | 255 | int selinux_netlbl_inet_conn_request(struct request_sock *req, u16 family) |
| 293 | { | 256 | { |
| 294 | int rc; | 257 | int rc; |
| 295 | struct sk_security_struct *sksec = sk->sk_security; | 258 | struct netlbl_lsm_secattr secattr; |
| 296 | struct netlbl_lsm_secattr *secattr; | ||
| 297 | struct inet_sock *sk_inet = inet_sk(sk); | ||
| 298 | struct sockaddr_in addr; | ||
| 299 | |||
| 300 | if (sksec->nlbl_state != NLBL_REQUIRE) | ||
| 301 | return; | ||
| 302 | 259 | ||
| 303 | secattr = selinux_netlbl_sock_genattr(sk); | 260 | if (family != PF_INET) |
| 304 | if (secattr == NULL) | 261 | return 0; |
| 305 | return; | ||
| 306 | 262 | ||
| 307 | rc = netlbl_sock_setattr(sk, secattr); | 263 | netlbl_secattr_init(&secattr); |
| 308 | switch (rc) { | 264 | rc = security_netlbl_sid_to_secattr(req->secid, &secattr); |
| 309 | case 0: | 265 | if (rc != 0) |
| 310 | sksec->nlbl_state = NLBL_LABELED; | 266 | goto inet_conn_request_return; |
| 311 | break; | 267 | rc = netlbl_req_setattr(req, &secattr); |
| 312 | case -EDESTADDRREQ: | 268 | inet_conn_request_return: |
| 313 | /* no PF_INET6 support yet because we don't support any IPv6 | 269 | netlbl_secattr_destroy(&secattr); |
| 314 | * labeling protocols */ | 270 | return rc; |
| 315 | if (family != PF_INET) { | ||
| 316 | sksec->nlbl_state = NLBL_UNSET; | ||
| 317 | return; | ||
| 318 | } | ||
| 319 | |||
| 320 | addr.sin_family = family; | ||
| 321 | addr.sin_addr.s_addr = sk_inet->daddr; | ||
| 322 | if (netlbl_conn_setattr(sk, (struct sockaddr *)&addr, | ||
| 323 | secattr) != 0) { | ||
| 324 | /* we failed to label the connected socket (could be | ||
| 325 | * for a variety of reasons, the actual "why" isn't | ||
| 326 | * important here) so we have to go to our backup plan, | ||
| 327 | * labeling the packets individually in the netfilter | ||
| 328 | * local output hook. this is okay but we need to | ||
| 329 | * adjust the MSS of the connection to take into | ||
| 330 | * account any labeling overhead, since we don't know | ||
| 331 | * the exact overhead at this point we'll use the worst | ||
| 332 | * case value which is 40 bytes for IPv4 */ | ||
| 333 | struct inet_connection_sock *sk_conn = inet_csk(sk); | ||
| 334 | sk_conn->icsk_ext_hdr_len += 40 - | ||
| 335 | (sk_inet->opt ? sk_inet->opt->optlen : 0); | ||
| 336 | sk_conn->icsk_sync_mss(sk, sk_conn->icsk_pmtu_cookie); | ||
| 337 | |||
| 338 | sksec->nlbl_state = NLBL_REQSKB; | ||
| 339 | } else | ||
| 340 | sksec->nlbl_state = NLBL_CONNLABELED; | ||
| 341 | break; | ||
| 342 | default: | ||
| 343 | /* note that we are failing to label the socket which could be | ||
| 344 | * a bad thing since it means traffic could leave the system | ||
| 345 | * without the desired labeling, however, all is not lost as | ||
| 346 | * we have a check in selinux_netlbl_inode_permission() to | ||
| 347 | * pick up the pieces that we might drop here because we can't | ||
| 348 | * return an error code */ | ||
| 349 | break; | ||
| 350 | } | ||
| 351 | } | 271 | } |
| 352 | 272 | ||
| 353 | /** | 273 | /** |
| 354 | * selinux_netlbl_socket_post_create - Label a socket using NetLabel | 274 | * selinux_netlbl_inet_csk_clone - Initialize the newly created sock |
| 355 | * @sock: the socket to label | 275 | * @sk: the new sock |
| 356 | * | 276 | * |
| 357 | * Description: | 277 | * Description: |
| 358 | * Attempt to label a socket using the NetLabel mechanism using the given | 278 | * A new connection has been established using @sk, we've already labeled the |
| 359 | * SID. Returns zero values on success, negative values on failure. | 279 | * socket via the request_sock struct in selinux_netlbl_inet_conn_request() but |
| 280 | * we need to set the NetLabel state here since we now have a sock structure. | ||
| 360 | * | 281 | * |
| 361 | */ | 282 | */ |
| 362 | int selinux_netlbl_socket_post_create(struct socket *sock) | 283 | void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family) |
| 363 | { | 284 | { |
| 364 | return selinux_netlbl_sock_setsid(sock->sk); | 285 | struct sk_security_struct *sksec = sk->sk_security; |
| 286 | |||
| 287 | if (family == PF_INET) | ||
| 288 | sksec->nlbl_state = NLBL_LABELED; | ||
| 289 | else | ||
| 290 | sksec->nlbl_state = NLBL_UNSET; | ||
| 365 | } | 291 | } |
| 366 | 292 | ||
| 367 | /** | 293 | /** |
| 368 | * selinux_netlbl_inode_permission - Verify the socket is NetLabel labeled | 294 | * selinux_netlbl_socket_post_create - Label a socket using NetLabel |
| 369 | * @inode: the file descriptor's inode | 295 | * @sock: the socket to label |
| 370 | * @mask: the permission mask | 296 | * @family: protocol family |
| 371 | * | 297 | * |
| 372 | * Description: | 298 | * Description: |
| 373 | * Looks at a file's inode and if it is marked as a socket protected by | 299 | * Attempt to label a socket using the NetLabel mechanism using the given |
| 374 | * NetLabel then verify that the socket has been labeled, if not try to label | 300 | * SID. Returns zero values on success, negative values on failure. |
| 375 | * the socket now with the inode's SID. Returns zero on success, negative | ||
| 376 | * values on failure. | ||
| 377 | * | 301 | * |
| 378 | */ | 302 | */ |
| 379 | int selinux_netlbl_inode_permission(struct inode *inode, int mask) | 303 | int selinux_netlbl_socket_post_create(struct sock *sk, u16 family) |
| 380 | { | 304 | { |
| 381 | int rc; | 305 | int rc; |
| 382 | struct sock *sk; | 306 | struct sk_security_struct *sksec = sk->sk_security; |
| 383 | struct socket *sock; | 307 | struct netlbl_lsm_secattr *secattr; |
| 384 | struct sk_security_struct *sksec; | ||
| 385 | 308 | ||
| 386 | if (!S_ISSOCK(inode->i_mode) || | 309 | if (family != PF_INET) |
| 387 | ((mask & (MAY_WRITE | MAY_APPEND)) == 0)) | ||
| 388 | return 0; | ||
| 389 | sock = SOCKET_I(inode); | ||
| 390 | sk = sock->sk; | ||
| 391 | if (sk == NULL) | ||
| 392 | return 0; | ||
| 393 | sksec = sk->sk_security; | ||
| 394 | if (sksec == NULL || sksec->nlbl_state != NLBL_REQUIRE) | ||
| 395 | return 0; | 310 | return 0; |
| 396 | 311 | ||
| 397 | local_bh_disable(); | 312 | secattr = selinux_netlbl_sock_genattr(sk); |
| 398 | bh_lock_sock_nested(sk); | 313 | if (secattr == NULL) |
| 399 | if (likely(sksec->nlbl_state == NLBL_REQUIRE)) | 314 | return -ENOMEM; |
| 400 | rc = selinux_netlbl_sock_setsid(sk); | 315 | rc = netlbl_sock_setattr(sk, family, secattr); |
| 401 | else | 316 | switch (rc) { |
| 317 | case 0: | ||
| 318 | sksec->nlbl_state = NLBL_LABELED; | ||
| 319 | break; | ||
| 320 | case -EDESTADDRREQ: | ||
| 321 | sksec->nlbl_state = NLBL_REQSKB; | ||
| 402 | rc = 0; | 322 | rc = 0; |
| 403 | bh_unlock_sock(sk); | 323 | break; |
| 404 | local_bh_enable(); | 324 | } |
| 405 | 325 | ||
| 406 | return rc; | 326 | return rc; |
| 407 | } | 327 | } |
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index fd20d15f5b9a..23ad420a49aa 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
| @@ -1387,7 +1387,7 @@ static int smack_netlabel(struct sock *sk, int labeled) | |||
| 1387 | else { | 1387 | else { |
| 1388 | netlbl_secattr_init(&secattr); | 1388 | netlbl_secattr_init(&secattr); |
| 1389 | smack_to_secattr(ssp->smk_out, &secattr); | 1389 | smack_to_secattr(ssp->smk_out, &secattr); |
| 1390 | rc = netlbl_sock_setattr(sk, &secattr); | 1390 | rc = netlbl_sock_setattr(sk, sk->sk_family, &secattr); |
| 1391 | netlbl_secattr_destroy(&secattr); | 1391 | netlbl_secattr_destroy(&secattr); |
| 1392 | } | 1392 | } |
| 1393 | 1393 | ||
