diff options
Diffstat (limited to 'net/ipv4/cipso_ipv4.c')
-rw-r--r-- | net/ipv4/cipso_ipv4.c | 130 |
1 files changed, 118 insertions, 12 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 |