diff options
Diffstat (limited to 'net/key/af_key.c')
| -rw-r--r-- | net/key/af_key.c | 197 |
1 files changed, 189 insertions, 8 deletions
diff --git a/net/key/af_key.c b/net/key/af_key.c index 39031684b65c..d32f7791f1e4 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c | |||
| @@ -336,6 +336,7 @@ static u8 sadb_ext_min_len[] = { | |||
| 336 | [SADB_X_EXT_NAT_T_SPORT] = (u8) sizeof(struct sadb_x_nat_t_port), | 336 | [SADB_X_EXT_NAT_T_SPORT] = (u8) sizeof(struct sadb_x_nat_t_port), |
| 337 | [SADB_X_EXT_NAT_T_DPORT] = (u8) sizeof(struct sadb_x_nat_t_port), | 337 | [SADB_X_EXT_NAT_T_DPORT] = (u8) sizeof(struct sadb_x_nat_t_port), |
| 338 | [SADB_X_EXT_NAT_T_OA] = (u8) sizeof(struct sadb_address), | 338 | [SADB_X_EXT_NAT_T_OA] = (u8) sizeof(struct sadb_address), |
| 339 | [SADB_X_EXT_SEC_CTX] = (u8) sizeof(struct sadb_x_sec_ctx), | ||
| 339 | }; | 340 | }; |
| 340 | 341 | ||
| 341 | /* Verify sadb_address_{len,prefixlen} against sa_family. */ | 342 | /* Verify sadb_address_{len,prefixlen} against sa_family. */ |
| @@ -383,6 +384,55 @@ static int verify_address_len(void *p) | |||
| 383 | return 0; | 384 | return 0; |
| 384 | } | 385 | } |
| 385 | 386 | ||
| 387 | static inline int pfkey_sec_ctx_len(struct sadb_x_sec_ctx *sec_ctx) | ||
| 388 | { | ||
| 389 | int len = 0; | ||
| 390 | |||
| 391 | len += sizeof(struct sadb_x_sec_ctx); | ||
| 392 | len += sec_ctx->sadb_x_ctx_len; | ||
| 393 | len += sizeof(uint64_t) - 1; | ||
| 394 | len /= sizeof(uint64_t); | ||
| 395 | |||
| 396 | return len; | ||
| 397 | } | ||
| 398 | |||
| 399 | static inline int verify_sec_ctx_len(void *p) | ||
| 400 | { | ||
| 401 | struct sadb_x_sec_ctx *sec_ctx = (struct sadb_x_sec_ctx *)p; | ||
| 402 | int len; | ||
| 403 | |||
| 404 | if (sec_ctx->sadb_x_ctx_len > PAGE_SIZE) | ||
| 405 | return -EINVAL; | ||
| 406 | |||
| 407 | len = pfkey_sec_ctx_len(sec_ctx); | ||
| 408 | |||
| 409 | if (sec_ctx->sadb_x_sec_len != len) | ||
| 410 | return -EINVAL; | ||
| 411 | |||
| 412 | return 0; | ||
| 413 | } | ||
| 414 | |||
| 415 | static inline struct xfrm_user_sec_ctx *pfkey_sadb2xfrm_user_sec_ctx(struct sadb_x_sec_ctx *sec_ctx) | ||
| 416 | { | ||
| 417 | struct xfrm_user_sec_ctx *uctx = NULL; | ||
| 418 | int ctx_size = sec_ctx->sadb_x_ctx_len; | ||
| 419 | |||
| 420 | uctx = kmalloc((sizeof(*uctx)+ctx_size), GFP_KERNEL); | ||
| 421 | |||
| 422 | if (!uctx) | ||
| 423 | return NULL; | ||
| 424 | |||
| 425 | uctx->len = pfkey_sec_ctx_len(sec_ctx); | ||
| 426 | uctx->exttype = sec_ctx->sadb_x_sec_exttype; | ||
| 427 | uctx->ctx_doi = sec_ctx->sadb_x_ctx_doi; | ||
| 428 | uctx->ctx_alg = sec_ctx->sadb_x_ctx_alg; | ||
| 429 | uctx->ctx_len = sec_ctx->sadb_x_ctx_len; | ||
| 430 | memcpy(uctx + 1, sec_ctx + 1, | ||
| 431 | uctx->ctx_len); | ||
| 432 | |||
| 433 | return uctx; | ||
| 434 | } | ||
| 435 | |||
| 386 | static int present_and_same_family(struct sadb_address *src, | 436 | static int present_and_same_family(struct sadb_address *src, |
| 387 | struct sadb_address *dst) | 437 | struct sadb_address *dst) |
| 388 | { | 438 | { |
| @@ -438,6 +488,10 @@ static int parse_exthdrs(struct sk_buff *skb, struct sadb_msg *hdr, void **ext_h | |||
| 438 | if (verify_address_len(p)) | 488 | if (verify_address_len(p)) |
| 439 | return -EINVAL; | 489 | return -EINVAL; |
| 440 | } | 490 | } |
| 491 | if (ext_type == SADB_X_EXT_SEC_CTX) { | ||
| 492 | if (verify_sec_ctx_len(p)) | ||
| 493 | return -EINVAL; | ||
| 494 | } | ||
| 441 | ext_hdrs[ext_type-1] = p; | 495 | ext_hdrs[ext_type-1] = p; |
| 442 | } | 496 | } |
| 443 | p += ext_len; | 497 | p += ext_len; |
| @@ -586,6 +640,9 @@ static struct sk_buff * pfkey_xfrm_state2msg(struct xfrm_state *x, int add_keys, | |||
| 586 | struct sadb_key *key; | 640 | struct sadb_key *key; |
| 587 | struct sadb_x_sa2 *sa2; | 641 | struct sadb_x_sa2 *sa2; |
| 588 | struct sockaddr_in *sin; | 642 | struct sockaddr_in *sin; |
| 643 | struct sadb_x_sec_ctx *sec_ctx; | ||
| 644 | struct xfrm_sec_ctx *xfrm_ctx; | ||
| 645 | int ctx_size = 0; | ||
| 589 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 646 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
| 590 | struct sockaddr_in6 *sin6; | 647 | struct sockaddr_in6 *sin6; |
| 591 | #endif | 648 | #endif |
| @@ -609,6 +666,12 @@ static struct sk_buff * pfkey_xfrm_state2msg(struct xfrm_state *x, int add_keys, | |||
| 609 | sizeof(struct sadb_address)*2 + | 666 | sizeof(struct sadb_address)*2 + |
| 610 | sockaddr_size*2 + | 667 | sockaddr_size*2 + |
| 611 | sizeof(struct sadb_x_sa2); | 668 | sizeof(struct sadb_x_sa2); |
| 669 | |||
| 670 | if ((xfrm_ctx = x->security)) { | ||
| 671 | ctx_size = PFKEY_ALIGN8(xfrm_ctx->ctx_len); | ||
| 672 | size += sizeof(struct sadb_x_sec_ctx) + ctx_size; | ||
| 673 | } | ||
| 674 | |||
| 612 | /* identity & sensitivity */ | 675 | /* identity & sensitivity */ |
| 613 | 676 | ||
| 614 | if ((x->props.family == AF_INET && | 677 | if ((x->props.family == AF_INET && |
| @@ -899,6 +962,20 @@ static struct sk_buff * pfkey_xfrm_state2msg(struct xfrm_state *x, int add_keys, | |||
| 899 | n_port->sadb_x_nat_t_port_reserved = 0; | 962 | n_port->sadb_x_nat_t_port_reserved = 0; |
| 900 | } | 963 | } |
| 901 | 964 | ||
| 965 | /* security context */ | ||
| 966 | if (xfrm_ctx) { | ||
| 967 | sec_ctx = (struct sadb_x_sec_ctx *) skb_put(skb, | ||
| 968 | sizeof(struct sadb_x_sec_ctx) + ctx_size); | ||
| 969 | sec_ctx->sadb_x_sec_len = | ||
| 970 | (sizeof(struct sadb_x_sec_ctx) + ctx_size) / sizeof(uint64_t); | ||
| 971 | sec_ctx->sadb_x_sec_exttype = SADB_X_EXT_SEC_CTX; | ||
| 972 | sec_ctx->sadb_x_ctx_doi = xfrm_ctx->ctx_doi; | ||
| 973 | sec_ctx->sadb_x_ctx_alg = xfrm_ctx->ctx_alg; | ||
| 974 | sec_ctx->sadb_x_ctx_len = xfrm_ctx->ctx_len; | ||
| 975 | memcpy(sec_ctx + 1, xfrm_ctx->ctx_str, | ||
| 976 | xfrm_ctx->ctx_len); | ||
| 977 | } | ||
| 978 | |||
| 902 | return skb; | 979 | return skb; |
| 903 | } | 980 | } |
| 904 | 981 | ||
| @@ -909,6 +986,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr, | |||
| 909 | struct sadb_lifetime *lifetime; | 986 | struct sadb_lifetime *lifetime; |
| 910 | struct sadb_sa *sa; | 987 | struct sadb_sa *sa; |
| 911 | struct sadb_key *key; | 988 | struct sadb_key *key; |
| 989 | struct sadb_x_sec_ctx *sec_ctx; | ||
| 912 | uint16_t proto; | 990 | uint16_t proto; |
| 913 | int err; | 991 | int err; |
| 914 | 992 | ||
| @@ -993,6 +1071,21 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr, | |||
| 993 | x->lft.soft_add_expires_seconds = lifetime->sadb_lifetime_addtime; | 1071 | x->lft.soft_add_expires_seconds = lifetime->sadb_lifetime_addtime; |
| 994 | x->lft.soft_use_expires_seconds = lifetime->sadb_lifetime_usetime; | 1072 | x->lft.soft_use_expires_seconds = lifetime->sadb_lifetime_usetime; |
| 995 | } | 1073 | } |
| 1074 | |||
| 1075 | sec_ctx = (struct sadb_x_sec_ctx *) ext_hdrs[SADB_X_EXT_SEC_CTX-1]; | ||
| 1076 | if (sec_ctx != NULL) { | ||
| 1077 | struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx); | ||
| 1078 | |||
| 1079 | if (!uctx) | ||
| 1080 | goto out; | ||
| 1081 | |||
| 1082 | err = security_xfrm_state_alloc(x, uctx); | ||
| 1083 | kfree(uctx); | ||
| 1084 | |||
| 1085 | if (err) | ||
| 1086 | goto out; | ||
| 1087 | } | ||
| 1088 | |||
| 996 | key = (struct sadb_key*) ext_hdrs[SADB_EXT_KEY_AUTH-1]; | 1089 | key = (struct sadb_key*) ext_hdrs[SADB_EXT_KEY_AUTH-1]; |
| 997 | if (sa->sadb_sa_auth) { | 1090 | if (sa->sadb_sa_auth) { |
| 998 | int keysize = 0; | 1091 | int keysize = 0; |
| @@ -1720,6 +1813,18 @@ parse_ipsecrequests(struct xfrm_policy *xp, struct sadb_x_policy *pol) | |||
| 1720 | return 0; | 1813 | return 0; |
| 1721 | } | 1814 | } |
| 1722 | 1815 | ||
| 1816 | static inline int pfkey_xfrm_policy2sec_ctx_size(struct xfrm_policy *xp) | ||
| 1817 | { | ||
| 1818 | struct xfrm_sec_ctx *xfrm_ctx = xp->security; | ||
| 1819 | |||
| 1820 | if (xfrm_ctx) { | ||
| 1821 | int len = sizeof(struct sadb_x_sec_ctx); | ||
| 1822 | len += xfrm_ctx->ctx_len; | ||
| 1823 | return PFKEY_ALIGN8(len); | ||
| 1824 | } | ||
| 1825 | return 0; | ||
| 1826 | } | ||
| 1827 | |||
| 1723 | static int pfkey_xfrm_policy2msg_size(struct xfrm_policy *xp) | 1828 | static int pfkey_xfrm_policy2msg_size(struct xfrm_policy *xp) |
| 1724 | { | 1829 | { |
| 1725 | int sockaddr_size = pfkey_sockaddr_size(xp->family); | 1830 | int sockaddr_size = pfkey_sockaddr_size(xp->family); |
| @@ -1733,7 +1838,8 @@ static int pfkey_xfrm_policy2msg_size(struct xfrm_policy *xp) | |||
| 1733 | (sockaddr_size * 2) + | 1838 | (sockaddr_size * 2) + |
| 1734 | sizeof(struct sadb_x_policy) + | 1839 | sizeof(struct sadb_x_policy) + |
| 1735 | (xp->xfrm_nr * (sizeof(struct sadb_x_ipsecrequest) + | 1840 | (xp->xfrm_nr * (sizeof(struct sadb_x_ipsecrequest) + |
| 1736 | (socklen * 2))); | 1841 | (socklen * 2))) + |
| 1842 | pfkey_xfrm_policy2sec_ctx_size(xp); | ||
| 1737 | } | 1843 | } |
| 1738 | 1844 | ||
| 1739 | static struct sk_buff * pfkey_xfrm_policy2msg_prep(struct xfrm_policy *xp) | 1845 | static struct sk_buff * pfkey_xfrm_policy2msg_prep(struct xfrm_policy *xp) |
| @@ -1757,6 +1863,8 @@ static void pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, i | |||
| 1757 | struct sadb_lifetime *lifetime; | 1863 | struct sadb_lifetime *lifetime; |
| 1758 | struct sadb_x_policy *pol; | 1864 | struct sadb_x_policy *pol; |
| 1759 | struct sockaddr_in *sin; | 1865 | struct sockaddr_in *sin; |
| 1866 | struct sadb_x_sec_ctx *sec_ctx; | ||
| 1867 | struct xfrm_sec_ctx *xfrm_ctx; | ||
| 1760 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 1868 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
| 1761 | struct sockaddr_in6 *sin6; | 1869 | struct sockaddr_in6 *sin6; |
| 1762 | #endif | 1870 | #endif |
| @@ -1941,6 +2049,21 @@ static void pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, i | |||
| 1941 | } | 2049 | } |
| 1942 | } | 2050 | } |
| 1943 | } | 2051 | } |
| 2052 | |||
| 2053 | /* security context */ | ||
| 2054 | if ((xfrm_ctx = xp->security)) { | ||
| 2055 | int ctx_size = pfkey_xfrm_policy2sec_ctx_size(xp); | ||
| 2056 | |||
| 2057 | sec_ctx = (struct sadb_x_sec_ctx *) skb_put(skb, ctx_size); | ||
| 2058 | sec_ctx->sadb_x_sec_len = ctx_size / sizeof(uint64_t); | ||
| 2059 | sec_ctx->sadb_x_sec_exttype = SADB_X_EXT_SEC_CTX; | ||
| 2060 | sec_ctx->sadb_x_ctx_doi = xfrm_ctx->ctx_doi; | ||
| 2061 | sec_ctx->sadb_x_ctx_alg = xfrm_ctx->ctx_alg; | ||
| 2062 | sec_ctx->sadb_x_ctx_len = xfrm_ctx->ctx_len; | ||
| 2063 | memcpy(sec_ctx + 1, xfrm_ctx->ctx_str, | ||
| 2064 | xfrm_ctx->ctx_len); | ||
| 2065 | } | ||
| 2066 | |||
| 1944 | hdr->sadb_msg_len = size / sizeof(uint64_t); | 2067 | hdr->sadb_msg_len = size / sizeof(uint64_t); |
| 1945 | hdr->sadb_msg_reserved = atomic_read(&xp->refcnt); | 2068 | hdr->sadb_msg_reserved = atomic_read(&xp->refcnt); |
| 1946 | } | 2069 | } |
| @@ -1976,12 +2099,13 @@ out: | |||
| 1976 | 2099 | ||
| 1977 | static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs) | 2100 | static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs) |
| 1978 | { | 2101 | { |
| 1979 | int err; | 2102 | int err = 0; |
| 1980 | struct sadb_lifetime *lifetime; | 2103 | struct sadb_lifetime *lifetime; |
| 1981 | struct sadb_address *sa; | 2104 | struct sadb_address *sa; |
| 1982 | struct sadb_x_policy *pol; | 2105 | struct sadb_x_policy *pol; |
| 1983 | struct xfrm_policy *xp; | 2106 | struct xfrm_policy *xp; |
| 1984 | struct km_event c; | 2107 | struct km_event c; |
| 2108 | struct sadb_x_sec_ctx *sec_ctx; | ||
| 1985 | 2109 | ||
| 1986 | if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1], | 2110 | if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1], |
| 1987 | ext_hdrs[SADB_EXT_ADDRESS_DST-1]) || | 2111 | ext_hdrs[SADB_EXT_ADDRESS_DST-1]) || |
| @@ -2028,6 +2152,22 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h | |||
| 2028 | if (xp->selector.dport) | 2152 | if (xp->selector.dport) |
| 2029 | xp->selector.dport_mask = ~0; | 2153 | xp->selector.dport_mask = ~0; |
| 2030 | 2154 | ||
| 2155 | sec_ctx = (struct sadb_x_sec_ctx *) ext_hdrs[SADB_X_EXT_SEC_CTX-1]; | ||
| 2156 | if (sec_ctx != NULL) { | ||
| 2157 | struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx); | ||
| 2158 | |||
| 2159 | if (!uctx) { | ||
| 2160 | err = -ENOBUFS; | ||
| 2161 | goto out; | ||
| 2162 | } | ||
| 2163 | |||
| 2164 | err = security_xfrm_policy_alloc(xp, uctx); | ||
| 2165 | kfree(uctx); | ||
| 2166 | |||
| 2167 | if (err) | ||
| 2168 | goto out; | ||
| 2169 | } | ||
| 2170 | |||
| 2031 | xp->lft.soft_byte_limit = XFRM_INF; | 2171 | xp->lft.soft_byte_limit = XFRM_INF; |
| 2032 | xp->lft.hard_byte_limit = XFRM_INF; | 2172 | xp->lft.hard_byte_limit = XFRM_INF; |
| 2033 | xp->lft.soft_packet_limit = XFRM_INF; | 2173 | xp->lft.soft_packet_limit = XFRM_INF; |
| @@ -2051,10 +2191,9 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h | |||
| 2051 | 2191 | ||
| 2052 | err = xfrm_policy_insert(pol->sadb_x_policy_dir-1, xp, | 2192 | err = xfrm_policy_insert(pol->sadb_x_policy_dir-1, xp, |
| 2053 | hdr->sadb_msg_type != SADB_X_SPDUPDATE); | 2193 | hdr->sadb_msg_type != SADB_X_SPDUPDATE); |
| 2054 | if (err) { | 2194 | |
| 2055 | kfree(xp); | 2195 | if (err) |
| 2056 | return err; | 2196 | goto out; |
| 2057 | } | ||
| 2058 | 2197 | ||
| 2059 | if (hdr->sadb_msg_type == SADB_X_SPDUPDATE) | 2198 | if (hdr->sadb_msg_type == SADB_X_SPDUPDATE) |
| 2060 | c.event = XFRM_MSG_UPDPOLICY; | 2199 | c.event = XFRM_MSG_UPDPOLICY; |
| @@ -2069,6 +2208,7 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h | |||
| 2069 | return 0; | 2208 | return 0; |
| 2070 | 2209 | ||
| 2071 | out: | 2210 | out: |
| 2211 | security_xfrm_policy_free(xp); | ||
| 2072 | kfree(xp); | 2212 | kfree(xp); |
| 2073 | return err; | 2213 | return err; |
| 2074 | } | 2214 | } |
| @@ -2078,9 +2218,10 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg | |||
| 2078 | int err; | 2218 | int err; |
| 2079 | struct sadb_address *sa; | 2219 | struct sadb_address *sa; |
| 2080 | struct sadb_x_policy *pol; | 2220 | struct sadb_x_policy *pol; |
| 2081 | struct xfrm_policy *xp; | 2221 | struct xfrm_policy *xp, tmp; |
| 2082 | struct xfrm_selector sel; | 2222 | struct xfrm_selector sel; |
| 2083 | struct km_event c; | 2223 | struct km_event c; |
| 2224 | struct sadb_x_sec_ctx *sec_ctx; | ||
| 2084 | 2225 | ||
| 2085 | if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1], | 2226 | if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1], |
| 2086 | ext_hdrs[SADB_EXT_ADDRESS_DST-1]) || | 2227 | ext_hdrs[SADB_EXT_ADDRESS_DST-1]) || |
| @@ -2109,7 +2250,24 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg | |||
| 2109 | if (sel.dport) | 2250 | if (sel.dport) |
| 2110 | sel.dport_mask = ~0; | 2251 | sel.dport_mask = ~0; |
| 2111 | 2252 | ||
| 2112 | xp = xfrm_policy_bysel(pol->sadb_x_policy_dir-1, &sel, 1); | 2253 | sec_ctx = (struct sadb_x_sec_ctx *) ext_hdrs[SADB_X_EXT_SEC_CTX-1]; |
| 2254 | memset(&tmp, 0, sizeof(struct xfrm_policy)); | ||
| 2255 | |||
| 2256 | if (sec_ctx != NULL) { | ||
| 2257 | struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx); | ||
| 2258 | |||
| 2259 | if (!uctx) | ||
| 2260 | return -ENOMEM; | ||
| 2261 | |||
| 2262 | err = security_xfrm_policy_alloc(&tmp, uctx); | ||
| 2263 | kfree(uctx); | ||
| 2264 | |||
| 2265 | if (err) | ||
| 2266 | return err; | ||
| 2267 | } | ||
| 2268 | |||
| 2269 | xp = xfrm_policy_bysel_ctx(pol->sadb_x_policy_dir-1, &sel, tmp.security, 1); | ||
| 2270 | security_xfrm_policy_free(&tmp); | ||
| 2113 | if (xp == NULL) | 2271 | if (xp == NULL) |
| 2114 | return -ENOENT; | 2272 | return -ENOENT; |
| 2115 | 2273 | ||
| @@ -2660,6 +2818,7 @@ static struct xfrm_policy *pfkey_compile_policy(u16 family, int opt, | |||
| 2660 | { | 2818 | { |
| 2661 | struct xfrm_policy *xp; | 2819 | struct xfrm_policy *xp; |
| 2662 | struct sadb_x_policy *pol = (struct sadb_x_policy*)data; | 2820 | struct sadb_x_policy *pol = (struct sadb_x_policy*)data; |
| 2821 | struct sadb_x_sec_ctx *sec_ctx; | ||
| 2663 | 2822 | ||
| 2664 | switch (family) { | 2823 | switch (family) { |
| 2665 | case AF_INET: | 2824 | case AF_INET: |
| @@ -2709,10 +2868,32 @@ static struct xfrm_policy *pfkey_compile_policy(u16 family, int opt, | |||
| 2709 | (*dir = parse_ipsecrequests(xp, pol)) < 0) | 2868 | (*dir = parse_ipsecrequests(xp, pol)) < 0) |
| 2710 | goto out; | 2869 | goto out; |
| 2711 | 2870 | ||
| 2871 | /* security context too */ | ||
| 2872 | if (len >= (pol->sadb_x_policy_len*8 + | ||
| 2873 | sizeof(struct sadb_x_sec_ctx))) { | ||
| 2874 | char *p = (char *)pol; | ||
| 2875 | struct xfrm_user_sec_ctx *uctx; | ||
| 2876 | |||
| 2877 | p += pol->sadb_x_policy_len*8; | ||
| 2878 | sec_ctx = (struct sadb_x_sec_ctx *)p; | ||
| 2879 | if (len < pol->sadb_x_policy_len*8 + | ||
| 2880 | sec_ctx->sadb_x_sec_len) | ||
| 2881 | goto out; | ||
| 2882 | if ((*dir = verify_sec_ctx_len(p))) | ||
| 2883 | goto out; | ||
| 2884 | uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx); | ||
| 2885 | *dir = security_xfrm_policy_alloc(xp, uctx); | ||
| 2886 | kfree(uctx); | ||
| 2887 | |||
| 2888 | if (*dir) | ||
| 2889 | goto out; | ||
| 2890 | } | ||
| 2891 | |||
| 2712 | *dir = pol->sadb_x_policy_dir-1; | 2892 | *dir = pol->sadb_x_policy_dir-1; |
| 2713 | return xp; | 2893 | return xp; |
| 2714 | 2894 | ||
| 2715 | out: | 2895 | out: |
| 2896 | security_xfrm_policy_free(xp); | ||
| 2716 | kfree(xp); | 2897 | kfree(xp); |
| 2717 | return NULL; | 2898 | return NULL; |
| 2718 | } | 2899 | } |
