.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * net/key/af_key.c An implementation of PF_KEYv2 sockets. |
---|
3 | | - * |
---|
4 | | - * This program is free software; you can redistribute it and/or |
---|
5 | | - * modify it under the terms of the GNU General Public License |
---|
6 | | - * as published by the Free Software Foundation; either version |
---|
7 | | - * 2 of the License, or (at your option) any later version. |
---|
8 | 4 | * |
---|
9 | 5 | * Authors: Maxim Giryaev <gem@asplinux.ru> |
---|
10 | 6 | * David S. Miller <davem@redhat.com> |
---|
.. | .. |
---|
932 | 928 | pfkey_sockaddr_fill(&x->props.saddr, 0, |
---|
933 | 929 | (struct sockaddr *) (addr + 1), |
---|
934 | 930 | x->props.family); |
---|
935 | | - if (!addr->sadb_address_prefixlen) |
---|
936 | | - BUG(); |
---|
| 931 | + BUG_ON(!addr->sadb_address_prefixlen); |
---|
937 | 932 | |
---|
938 | 933 | /* dst address */ |
---|
939 | 934 | addr = skb_put(skb, sizeof(struct sadb_address) + sockaddr_size); |
---|
.. | .. |
---|
948 | 943 | pfkey_sockaddr_fill(&x->id.daddr, 0, |
---|
949 | 944 | (struct sockaddr *) (addr + 1), |
---|
950 | 945 | x->props.family); |
---|
951 | | - if (!addr->sadb_address_prefixlen) |
---|
952 | | - BUG(); |
---|
| 946 | + BUG_ON(!addr->sadb_address_prefixlen); |
---|
953 | 947 | |
---|
954 | 948 | if (!xfrm_addr_equal(&x->sel.saddr, &x->props.saddr, |
---|
955 | 949 | x->props.family)) { |
---|
.. | .. |
---|
1707 | 1701 | pfk->registered |= (1<<hdr->sadb_msg_satype); |
---|
1708 | 1702 | } |
---|
1709 | 1703 | |
---|
| 1704 | + mutex_lock(&pfkey_mutex); |
---|
1710 | 1705 | xfrm_probe_algs(); |
---|
1711 | 1706 | |
---|
1712 | | - supp_skb = compose_sadb_supported(hdr, GFP_KERNEL); |
---|
| 1707 | + supp_skb = compose_sadb_supported(hdr, GFP_KERNEL | __GFP_ZERO); |
---|
| 1708 | + mutex_unlock(&pfkey_mutex); |
---|
| 1709 | + |
---|
1713 | 1710 | if (!supp_skb) { |
---|
1714 | 1711 | if (hdr->sadb_msg_satype != SADB_SATYPE_UNSPEC) |
---|
1715 | 1712 | pfk->registered &= ~(1<<hdr->sadb_msg_satype); |
---|
.. | .. |
---|
1855 | 1852 | if (ext_hdrs[SADB_X_EXT_FILTER - 1]) { |
---|
1856 | 1853 | struct sadb_x_filter *xfilter = ext_hdrs[SADB_X_EXT_FILTER - 1]; |
---|
1857 | 1854 | |
---|
1858 | | - if ((xfilter->sadb_x_filter_splen >= |
---|
| 1855 | + if ((xfilter->sadb_x_filter_splen > |
---|
1859 | 1856 | (sizeof(xfrm_address_t) << 3)) || |
---|
1860 | | - (xfilter->sadb_x_filter_dplen >= |
---|
| 1857 | + (xfilter->sadb_x_filter_dplen > |
---|
1861 | 1858 | (sizeof(xfrm_address_t) << 3))) { |
---|
1862 | 1859 | mutex_unlock(&pfk->dump_lock); |
---|
1863 | 1860 | return -EINVAL; |
---|
.. | .. |
---|
1947 | 1944 | } |
---|
1948 | 1945 | |
---|
1949 | 1946 | static int |
---|
1950 | | -parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq) |
---|
| 1947 | +parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_policy *pol, |
---|
| 1948 | + struct sadb_x_ipsecrequest *rq) |
---|
1951 | 1949 | { |
---|
1952 | 1950 | struct net *net = xp_net(xp); |
---|
1953 | 1951 | struct xfrm_tmpl *t = xp->xfrm_vec + xp->xfrm_nr; |
---|
.. | .. |
---|
1965 | 1963 | if ((mode = pfkey_mode_to_xfrm(rq->sadb_x_ipsecrequest_mode)) < 0) |
---|
1966 | 1964 | return -EINVAL; |
---|
1967 | 1965 | t->mode = mode; |
---|
1968 | | - if (rq->sadb_x_ipsecrequest_level == IPSEC_LEVEL_USE) |
---|
| 1966 | + if (rq->sadb_x_ipsecrequest_level == IPSEC_LEVEL_USE) { |
---|
| 1967 | + if ((mode == XFRM_MODE_TUNNEL || mode == XFRM_MODE_BEET) && |
---|
| 1968 | + pol->sadb_x_policy_dir == IPSEC_DIR_OUTBOUND) |
---|
| 1969 | + return -EINVAL; |
---|
1969 | 1970 | t->optional = 1; |
---|
1970 | | - else if (rq->sadb_x_ipsecrequest_level == IPSEC_LEVEL_UNIQUE) { |
---|
| 1971 | + } else if (rq->sadb_x_ipsecrequest_level == IPSEC_LEVEL_UNIQUE) { |
---|
1971 | 1972 | t->reqid = rq->sadb_x_ipsecrequest_reqid; |
---|
1972 | 1973 | if (t->reqid > IPSEC_MANUAL_REQID_MAX) |
---|
1973 | 1974 | t->reqid = 0; |
---|
.. | .. |
---|
2009 | 2010 | rq->sadb_x_ipsecrequest_len < sizeof(*rq)) |
---|
2010 | 2011 | return -EINVAL; |
---|
2011 | 2012 | |
---|
2012 | | - if ((err = parse_ipsecrequest(xp, rq)) < 0) |
---|
| 2013 | + if ((err = parse_ipsecrequest(xp, pol, rq)) < 0) |
---|
2013 | 2014 | return err; |
---|
2014 | 2015 | len -= rq->sadb_x_ipsecrequest_len; |
---|
2015 | 2016 | rq = (void*)((u8*)rq + rq->sadb_x_ipsecrequest_len); |
---|
.. | .. |
---|
2019 | 2020 | |
---|
2020 | 2021 | static inline int pfkey_xfrm_policy2sec_ctx_size(const struct xfrm_policy *xp) |
---|
2021 | 2022 | { |
---|
2022 | | - struct xfrm_sec_ctx *xfrm_ctx = xp->security; |
---|
| 2023 | + struct xfrm_sec_ctx *xfrm_ctx = xp->security; |
---|
2023 | 2024 | |
---|
2024 | 2025 | if (xfrm_ctx) { |
---|
2025 | 2026 | int len = sizeof(struct sadb_x_sec_ctx); |
---|
.. | .. |
---|
2413 | 2414 | return err; |
---|
2414 | 2415 | } |
---|
2415 | 2416 | |
---|
2416 | | - xp = xfrm_policy_bysel_ctx(net, DUMMY_MARK, 0, XFRM_POLICY_TYPE_MAIN, |
---|
| 2417 | + xp = xfrm_policy_bysel_ctx(net, &dummy_mark, 0, XFRM_POLICY_TYPE_MAIN, |
---|
2417 | 2418 | pol->sadb_x_policy_dir - 1, &sel, pol_ctx, |
---|
2418 | 2419 | 1, &err); |
---|
2419 | 2420 | security_xfrm_policy_free(pol_ctx); |
---|
.. | .. |
---|
2633 | 2634 | } |
---|
2634 | 2635 | |
---|
2635 | 2636 | return xfrm_migrate(&sel, dir, XFRM_POLICY_TYPE_MAIN, m, i, |
---|
2636 | | - kma ? &k : NULL, net, NULL); |
---|
| 2637 | + kma ? &k : NULL, net, NULL, 0); |
---|
2637 | 2638 | |
---|
2638 | 2639 | out: |
---|
2639 | 2640 | return err; |
---|
.. | .. |
---|
2664 | 2665 | return -EINVAL; |
---|
2665 | 2666 | |
---|
2666 | 2667 | delete = (hdr->sadb_msg_type == SADB_X_SPDDELETE2); |
---|
2667 | | - xp = xfrm_policy_byid(net, DUMMY_MARK, 0, XFRM_POLICY_TYPE_MAIN, |
---|
| 2668 | + xp = xfrm_policy_byid(net, &dummy_mark, 0, XFRM_POLICY_TYPE_MAIN, |
---|
2668 | 2669 | dir, pol->sadb_x_policy_id, delete, &err); |
---|
2669 | 2670 | if (xp == NULL) |
---|
2670 | 2671 | return -ENOENT; |
---|
.. | .. |
---|
2836 | 2837 | void *ext_hdrs[SADB_EXT_MAX]; |
---|
2837 | 2838 | int err; |
---|
2838 | 2839 | |
---|
| 2840 | + /* Non-zero return value of pfkey_broadcast() does not always signal |
---|
| 2841 | + * an error and even on an actual error we may still want to process |
---|
| 2842 | + * the message so rather ignore the return value. |
---|
| 2843 | + */ |
---|
2839 | 2844 | pfkey_broadcast(skb_clone(skb, GFP_KERNEL), GFP_KERNEL, |
---|
2840 | 2845 | BROADCAST_PROMISC_ONLY, NULL, sock_net(sk)); |
---|
2841 | 2846 | |
---|
.. | .. |
---|
2944 | 2949 | return sz + sizeof(struct sadb_prop); |
---|
2945 | 2950 | } |
---|
2946 | 2951 | |
---|
2947 | | -static void dump_ah_combs(struct sk_buff *skb, const struct xfrm_tmpl *t) |
---|
| 2952 | +static int dump_ah_combs(struct sk_buff *skb, const struct xfrm_tmpl *t) |
---|
2948 | 2953 | { |
---|
2949 | 2954 | struct sadb_prop *p; |
---|
| 2955 | + int sz = 0; |
---|
2950 | 2956 | int i; |
---|
2951 | 2957 | |
---|
2952 | 2958 | p = skb_put(skb, sizeof(struct sadb_prop)); |
---|
.. | .. |
---|
2974 | 2980 | c->sadb_comb_soft_addtime = 20*60*60; |
---|
2975 | 2981 | c->sadb_comb_hard_usetime = 8*60*60; |
---|
2976 | 2982 | c->sadb_comb_soft_usetime = 7*60*60; |
---|
| 2983 | + sz += sizeof(*c); |
---|
2977 | 2984 | } |
---|
2978 | 2985 | } |
---|
| 2986 | + |
---|
| 2987 | + return sz + sizeof(*p); |
---|
2979 | 2988 | } |
---|
2980 | 2989 | |
---|
2981 | | -static void dump_esp_combs(struct sk_buff *skb, const struct xfrm_tmpl *t) |
---|
| 2990 | +static int dump_esp_combs(struct sk_buff *skb, const struct xfrm_tmpl *t) |
---|
2982 | 2991 | { |
---|
2983 | 2992 | struct sadb_prop *p; |
---|
| 2993 | + int sz = 0; |
---|
2984 | 2994 | int i, k; |
---|
2985 | 2995 | |
---|
2986 | 2996 | p = skb_put(skb, sizeof(struct sadb_prop)); |
---|
.. | .. |
---|
3022 | 3032 | c->sadb_comb_soft_addtime = 20*60*60; |
---|
3023 | 3033 | c->sadb_comb_hard_usetime = 8*60*60; |
---|
3024 | 3034 | c->sadb_comb_soft_usetime = 7*60*60; |
---|
| 3035 | + sz += sizeof(*c); |
---|
3025 | 3036 | } |
---|
3026 | 3037 | } |
---|
| 3038 | + |
---|
| 3039 | + return sz + sizeof(*p); |
---|
3027 | 3040 | } |
---|
3028 | 3041 | |
---|
3029 | 3042 | static int key_notify_policy_expire(struct xfrm_policy *xp, const struct km_event *c) |
---|
.. | .. |
---|
3153 | 3166 | struct sadb_x_sec_ctx *sec_ctx; |
---|
3154 | 3167 | struct xfrm_sec_ctx *xfrm_ctx; |
---|
3155 | 3168 | int ctx_size = 0; |
---|
| 3169 | + int alg_size = 0; |
---|
3156 | 3170 | |
---|
3157 | 3171 | sockaddr_size = pfkey_sockaddr_size(x->props.family); |
---|
3158 | 3172 | if (!sockaddr_size) |
---|
.. | .. |
---|
3164 | 3178 | sizeof(struct sadb_x_policy); |
---|
3165 | 3179 | |
---|
3166 | 3180 | if (x->id.proto == IPPROTO_AH) |
---|
3167 | | - size += count_ah_combs(t); |
---|
| 3181 | + alg_size = count_ah_combs(t); |
---|
3168 | 3182 | else if (x->id.proto == IPPROTO_ESP) |
---|
3169 | | - size += count_esp_combs(t); |
---|
| 3183 | + alg_size = count_esp_combs(t); |
---|
3170 | 3184 | |
---|
3171 | 3185 | if ((xfrm_ctx = x->security)) { |
---|
3172 | 3186 | ctx_size = PFKEY_ALIGN8(xfrm_ctx->ctx_len); |
---|
3173 | 3187 | size += sizeof(struct sadb_x_sec_ctx) + ctx_size; |
---|
3174 | 3188 | } |
---|
3175 | 3189 | |
---|
3176 | | - skb = alloc_skb(size + 16, GFP_ATOMIC); |
---|
| 3190 | + skb = alloc_skb(size + alg_size + 16, GFP_ATOMIC); |
---|
3177 | 3191 | if (skb == NULL) |
---|
3178 | 3192 | return -ENOMEM; |
---|
3179 | 3193 | |
---|
.. | .. |
---|
3227 | 3241 | pol->sadb_x_policy_priority = xp->priority; |
---|
3228 | 3242 | |
---|
3229 | 3243 | /* Set sadb_comb's. */ |
---|
| 3244 | + alg_size = 0; |
---|
3230 | 3245 | if (x->id.proto == IPPROTO_AH) |
---|
3231 | | - dump_ah_combs(skb, t); |
---|
| 3246 | + alg_size = dump_ah_combs(skb, t); |
---|
3232 | 3247 | else if (x->id.proto == IPPROTO_ESP) |
---|
3233 | | - dump_esp_combs(skb, t); |
---|
| 3248 | + alg_size = dump_esp_combs(skb, t); |
---|
| 3249 | + |
---|
| 3250 | + hdr->sadb_msg_len += alg_size / 8; |
---|
3234 | 3251 | |
---|
3235 | 3252 | /* security context */ |
---|
3236 | 3253 | if (xfrm_ctx) { |
---|
.. | .. |
---|
3747 | 3764 | .ioctl = sock_no_ioctl, |
---|
3748 | 3765 | .listen = sock_no_listen, |
---|
3749 | 3766 | .shutdown = sock_no_shutdown, |
---|
3750 | | - .setsockopt = sock_no_setsockopt, |
---|
3751 | | - .getsockopt = sock_no_getsockopt, |
---|
3752 | 3767 | .mmap = sock_no_mmap, |
---|
3753 | 3768 | .sendpage = sock_no_sendpage, |
---|
3754 | 3769 | |
---|