diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/cipso_ipv4.c | 130 | ||||
-rw-r--r-- | net/netlabel/netlabel_kapi.c | 152 |
2 files changed, 250 insertions, 32 deletions
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 | } |