diff options
-rw-r--r-- | include/net/xfrm.h | 12 | ||||
-rw-r--r-- | net/ipv4/ah4.c | 5 | ||||
-rw-r--r-- | net/ipv6/ah6.c | 5 | ||||
-rw-r--r-- | net/ipv6/esp6.c | 5 | ||||
-rw-r--r-- | net/key/af_key.c | 8 | ||||
-rw-r--r-- | net/xfrm/xfrm_device.c | 2 | ||||
-rw-r--r-- | net/xfrm/xfrm_policy.c | 13 | ||||
-rw-r--r-- | net/xfrm/xfrm_state.c | 35 | ||||
-rw-r--r-- | net/xfrm/xfrm_user.c | 37 |
9 files changed, 74 insertions, 48 deletions
diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 7e7e2b0d2915..01f5bc144ee5 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h | |||
@@ -631,7 +631,8 @@ struct xfrm_mgr { | |||
631 | u8 dir, u8 type, | 631 | u8 dir, u8 type, |
632 | const struct xfrm_migrate *m, | 632 | const struct xfrm_migrate *m, |
633 | int num_bundles, | 633 | int num_bundles, |
634 | const struct xfrm_kmaddress *k); | 634 | const struct xfrm_kmaddress *k, |
635 | const struct xfrm_encap_tmpl *encap); | ||
635 | bool (*is_alive)(const struct km_event *c); | 636 | bool (*is_alive)(const struct km_event *c); |
636 | }; | 637 | }; |
637 | 638 | ||
@@ -1675,13 +1676,16 @@ int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol); | |||
1675 | #ifdef CONFIG_XFRM_MIGRATE | 1676 | #ifdef CONFIG_XFRM_MIGRATE |
1676 | int km_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, | 1677 | int km_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, |
1677 | const struct xfrm_migrate *m, int num_bundles, | 1678 | const struct xfrm_migrate *m, int num_bundles, |
1678 | const struct xfrm_kmaddress *k); | 1679 | const struct xfrm_kmaddress *k, |
1680 | const struct xfrm_encap_tmpl *encap); | ||
1679 | struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *net); | 1681 | struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *net); |
1680 | struct xfrm_state *xfrm_state_migrate(struct xfrm_state *x, | 1682 | struct xfrm_state *xfrm_state_migrate(struct xfrm_state *x, |
1681 | struct xfrm_migrate *m); | 1683 | struct xfrm_migrate *m, |
1684 | struct xfrm_encap_tmpl *encap); | ||
1682 | int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, | 1685 | int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, |
1683 | struct xfrm_migrate *m, int num_bundles, | 1686 | struct xfrm_migrate *m, int num_bundles, |
1684 | struct xfrm_kmaddress *k, struct net *net); | 1687 | struct xfrm_kmaddress *k, struct net *net, |
1688 | struct xfrm_encap_tmpl *encap); | ||
1685 | #endif | 1689 | #endif |
1686 | 1690 | ||
1687 | int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport); | 1691 | int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport); |
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c index e8f862358518..37db44f60718 100644 --- a/net/ipv4/ah4.c +++ b/net/ipv4/ah4.c | |||
@@ -1,5 +1,6 @@ | |||
1 | #define pr_fmt(fmt) "IPsec: " fmt | 1 | #define pr_fmt(fmt) "IPsec: " fmt |
2 | 2 | ||
3 | #include <crypto/algapi.h> | ||
3 | #include <crypto/hash.h> | 4 | #include <crypto/hash.h> |
4 | #include <linux/err.h> | 5 | #include <linux/err.h> |
5 | #include <linux/module.h> | 6 | #include <linux/module.h> |
@@ -279,7 +280,7 @@ static void ah_input_done(struct crypto_async_request *base, int err) | |||
279 | auth_data = ah_tmp_auth(work_iph, ihl); | 280 | auth_data = ah_tmp_auth(work_iph, ihl); |
280 | icv = ah_tmp_icv(ahp->ahash, auth_data, ahp->icv_trunc_len); | 281 | icv = ah_tmp_icv(ahp->ahash, auth_data, ahp->icv_trunc_len); |
281 | 282 | ||
282 | err = memcmp(icv, auth_data, ahp->icv_trunc_len) ? -EBADMSG: 0; | 283 | err = crypto_memneq(icv, auth_data, ahp->icv_trunc_len) ? -EBADMSG : 0; |
283 | if (err) | 284 | if (err) |
284 | goto out; | 285 | goto out; |
285 | 286 | ||
@@ -417,7 +418,7 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb) | |||
417 | goto out_free; | 418 | goto out_free; |
418 | } | 419 | } |
419 | 420 | ||
420 | err = memcmp(icv, auth_data, ahp->icv_trunc_len) ? -EBADMSG: 0; | 421 | err = crypto_memneq(icv, auth_data, ahp->icv_trunc_len) ? -EBADMSG : 0; |
421 | if (err) | 422 | if (err) |
422 | goto out_free; | 423 | goto out_free; |
423 | 424 | ||
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index 755f38271dd5..7802b72196f3 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c | |||
@@ -25,6 +25,7 @@ | |||
25 | 25 | ||
26 | #define pr_fmt(fmt) "IPv6: " fmt | 26 | #define pr_fmt(fmt) "IPv6: " fmt |
27 | 27 | ||
28 | #include <crypto/algapi.h> | ||
28 | #include <crypto/hash.h> | 29 | #include <crypto/hash.h> |
29 | #include <linux/module.h> | 30 | #include <linux/module.h> |
30 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
@@ -483,7 +484,7 @@ static void ah6_input_done(struct crypto_async_request *base, int err) | |||
483 | auth_data = ah_tmp_auth(work_iph, hdr_len); | 484 | auth_data = ah_tmp_auth(work_iph, hdr_len); |
484 | icv = ah_tmp_icv(ahp->ahash, auth_data, ahp->icv_trunc_len); | 485 | icv = ah_tmp_icv(ahp->ahash, auth_data, ahp->icv_trunc_len); |
485 | 486 | ||
486 | err = memcmp(icv, auth_data, ahp->icv_trunc_len) ? -EBADMSG : 0; | 487 | err = crypto_memneq(icv, auth_data, ahp->icv_trunc_len) ? -EBADMSG : 0; |
487 | if (err) | 488 | if (err) |
488 | goto out; | 489 | goto out; |
489 | 490 | ||
@@ -631,7 +632,7 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb) | |||
631 | goto out_free; | 632 | goto out_free; |
632 | } | 633 | } |
633 | 634 | ||
634 | err = memcmp(icv, auth_data, ahp->icv_trunc_len) ? -EBADMSG : 0; | 635 | err = crypto_memneq(icv, auth_data, ahp->icv_trunc_len) ? -EBADMSG : 0; |
635 | if (err) | 636 | if (err) |
636 | goto out_free; | 637 | goto out_free; |
637 | 638 | ||
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index d8b40ff4b2e6..71faffdd55d9 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c | |||
@@ -118,7 +118,6 @@ static inline struct scatterlist *esp_req_sg(struct crypto_aead *aead, | |||
118 | 118 | ||
119 | static void esp_ssg_unref(struct xfrm_state *x, void *tmp) | 119 | static void esp_ssg_unref(struct xfrm_state *x, void *tmp) |
120 | { | 120 | { |
121 | __be32 *seqhi; | ||
122 | struct crypto_aead *aead = x->data; | 121 | struct crypto_aead *aead = x->data; |
123 | int seqhilen = 0; | 122 | int seqhilen = 0; |
124 | u8 *iv; | 123 | u8 *iv; |
@@ -128,7 +127,6 @@ static void esp_ssg_unref(struct xfrm_state *x, void *tmp) | |||
128 | if (x->props.flags & XFRM_STATE_ESN) | 127 | if (x->props.flags & XFRM_STATE_ESN) |
129 | seqhilen += sizeof(__be32); | 128 | seqhilen += sizeof(__be32); |
130 | 129 | ||
131 | seqhi = esp_tmp_seqhi(tmp); | ||
132 | iv = esp_tmp_iv(aead, tmp, seqhilen); | 130 | iv = esp_tmp_iv(aead, tmp, seqhilen); |
133 | req = esp_tmp_req(aead, iv); | 131 | req = esp_tmp_req(aead, iv); |
134 | 132 | ||
@@ -224,12 +222,9 @@ int esp6_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info | |||
224 | u8 *vaddr; | 222 | u8 *vaddr; |
225 | int nfrags; | 223 | int nfrags; |
226 | struct page *page; | 224 | struct page *page; |
227 | struct ip_esp_hdr *esph; | ||
228 | struct sk_buff *trailer; | 225 | struct sk_buff *trailer; |
229 | int tailen = esp->tailen; | 226 | int tailen = esp->tailen; |
230 | 227 | ||
231 | esph = ip_esp_hdr(skb); | ||
232 | |||
233 | if (!skb_cloned(skb)) { | 228 | if (!skb_cloned(skb)) { |
234 | if (tailen <= skb_availroom(skb)) { | 229 | if (tailen <= skb_availroom(skb)) { |
235 | nfrags = 1; | 230 | nfrags = 1; |
diff --git a/net/key/af_key.c b/net/key/af_key.c index daa4e90dc4db..ce9b8565d825 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c | |||
@@ -2589,7 +2589,7 @@ static int pfkey_migrate(struct sock *sk, struct sk_buff *skb, | |||
2589 | } | 2589 | } |
2590 | 2590 | ||
2591 | return xfrm_migrate(&sel, dir, XFRM_POLICY_TYPE_MAIN, m, i, | 2591 | return xfrm_migrate(&sel, dir, XFRM_POLICY_TYPE_MAIN, m, i, |
2592 | kma ? &k : NULL, net); | 2592 | kma ? &k : NULL, net, NULL); |
2593 | 2593 | ||
2594 | out: | 2594 | out: |
2595 | return err; | 2595 | return err; |
@@ -3488,7 +3488,8 @@ static int set_ipsecrequest(struct sk_buff *skb, | |||
3488 | #ifdef CONFIG_NET_KEY_MIGRATE | 3488 | #ifdef CONFIG_NET_KEY_MIGRATE |
3489 | static int pfkey_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, | 3489 | static int pfkey_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, |
3490 | const struct xfrm_migrate *m, int num_bundles, | 3490 | const struct xfrm_migrate *m, int num_bundles, |
3491 | const struct xfrm_kmaddress *k) | 3491 | const struct xfrm_kmaddress *k, |
3492 | const struct xfrm_encap_tmpl *encap) | ||
3492 | { | 3493 | { |
3493 | int i; | 3494 | int i; |
3494 | int sasize_sel; | 3495 | int sasize_sel; |
@@ -3598,7 +3599,8 @@ err: | |||
3598 | #else | 3599 | #else |
3599 | static int pfkey_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, | 3600 | static int pfkey_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, |
3600 | const struct xfrm_migrate *m, int num_bundles, | 3601 | const struct xfrm_migrate *m, int num_bundles, |
3601 | const struct xfrm_kmaddress *k) | 3602 | const struct xfrm_kmaddress *k, |
3603 | const struct xfrm_encap_tmpl *encap) | ||
3602 | { | 3604 | { |
3603 | return -ENOPROTOOPT; | 3605 | return -ENOPROTOOPT; |
3604 | } | 3606 | } |
diff --git a/net/xfrm/xfrm_device.c b/net/xfrm/xfrm_device.c index 574e6f32f94f..6d4a60d1bf19 100644 --- a/net/xfrm/xfrm_device.c +++ b/net/xfrm/xfrm_device.c | |||
@@ -138,7 +138,7 @@ ok: | |||
138 | } | 138 | } |
139 | EXPORT_SYMBOL_GPL(xfrm_dev_offload_ok); | 139 | EXPORT_SYMBOL_GPL(xfrm_dev_offload_ok); |
140 | 140 | ||
141 | int xfrm_dev_register(struct net_device *dev) | 141 | static int xfrm_dev_register(struct net_device *dev) |
142 | { | 142 | { |
143 | if ((dev->features & NETIF_F_HW_ESP) && !dev->xfrmdev_ops) | 143 | if ((dev->features & NETIF_F_HW_ESP) && !dev->xfrmdev_ops) |
144 | return NOTIFY_BAD; | 144 | return NOTIFY_BAD; |
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index af8e38f47b5b..a3dc7ab0b7ed 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
@@ -3279,11 +3279,6 @@ static int xfrm_migrate_check(const struct xfrm_migrate *m, int num_migrate) | |||
3279 | return -EINVAL; | 3279 | return -EINVAL; |
3280 | 3280 | ||
3281 | for (i = 0; i < num_migrate; i++) { | 3281 | for (i = 0; i < num_migrate; i++) { |
3282 | if (xfrm_addr_equal(&m[i].old_daddr, &m[i].new_daddr, | ||
3283 | m[i].old_family) && | ||
3284 | xfrm_addr_equal(&m[i].old_saddr, &m[i].new_saddr, | ||
3285 | m[i].old_family)) | ||
3286 | return -EINVAL; | ||
3287 | if (xfrm_addr_any(&m[i].new_daddr, m[i].new_family) || | 3282 | if (xfrm_addr_any(&m[i].new_daddr, m[i].new_family) || |
3288 | xfrm_addr_any(&m[i].new_saddr, m[i].new_family)) | 3283 | xfrm_addr_any(&m[i].new_saddr, m[i].new_family)) |
3289 | return -EINVAL; | 3284 | return -EINVAL; |
@@ -3307,7 +3302,8 @@ static int xfrm_migrate_check(const struct xfrm_migrate *m, int num_migrate) | |||
3307 | 3302 | ||
3308 | int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, | 3303 | int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, |
3309 | struct xfrm_migrate *m, int num_migrate, | 3304 | struct xfrm_migrate *m, int num_migrate, |
3310 | struct xfrm_kmaddress *k, struct net *net) | 3305 | struct xfrm_kmaddress *k, struct net *net, |
3306 | struct xfrm_encap_tmpl *encap) | ||
3311 | { | 3307 | { |
3312 | int i, err, nx_cur = 0, nx_new = 0; | 3308 | int i, err, nx_cur = 0, nx_new = 0; |
3313 | struct xfrm_policy *pol = NULL; | 3309 | struct xfrm_policy *pol = NULL; |
@@ -3330,7 +3326,8 @@ int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, | |||
3330 | if ((x = xfrm_migrate_state_find(mp, net))) { | 3326 | if ((x = xfrm_migrate_state_find(mp, net))) { |
3331 | x_cur[nx_cur] = x; | 3327 | x_cur[nx_cur] = x; |
3332 | nx_cur++; | 3328 | nx_cur++; |
3333 | if ((xc = xfrm_state_migrate(x, mp))) { | 3329 | xc = xfrm_state_migrate(x, mp, encap); |
3330 | if (xc) { | ||
3334 | x_new[nx_new] = xc; | 3331 | x_new[nx_new] = xc; |
3335 | nx_new++; | 3332 | nx_new++; |
3336 | } else { | 3333 | } else { |
@@ -3351,7 +3348,7 @@ int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, | |||
3351 | } | 3348 | } |
3352 | 3349 | ||
3353 | /* Stage 5 - announce */ | 3350 | /* Stage 5 - announce */ |
3354 | km_migrate(sel, dir, type, m, num_migrate, k); | 3351 | km_migrate(sel, dir, type, m, num_migrate, k, encap); |
3355 | 3352 | ||
3356 | xfrm_pol_put(pol); | 3353 | xfrm_pol_put(pol); |
3357 | 3354 | ||
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 2e291bc5f1fc..4a28f669c915 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
@@ -1309,7 +1309,8 @@ out: | |||
1309 | EXPORT_SYMBOL(xfrm_state_add); | 1309 | EXPORT_SYMBOL(xfrm_state_add); |
1310 | 1310 | ||
1311 | #ifdef CONFIG_XFRM_MIGRATE | 1311 | #ifdef CONFIG_XFRM_MIGRATE |
1312 | static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig) | 1312 | static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, |
1313 | struct xfrm_encap_tmpl *encap) | ||
1313 | { | 1314 | { |
1314 | struct net *net = xs_net(orig); | 1315 | struct net *net = xs_net(orig); |
1315 | struct xfrm_state *x = xfrm_state_alloc(net); | 1316 | struct xfrm_state *x = xfrm_state_alloc(net); |
@@ -1351,8 +1352,14 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig) | |||
1351 | } | 1352 | } |
1352 | x->props.calgo = orig->props.calgo; | 1353 | x->props.calgo = orig->props.calgo; |
1353 | 1354 | ||
1354 | if (orig->encap) { | 1355 | if (encap || orig->encap) { |
1355 | x->encap = kmemdup(orig->encap, sizeof(*x->encap), GFP_KERNEL); | 1356 | if (encap) |
1357 | x->encap = kmemdup(encap, sizeof(*x->encap), | ||
1358 | GFP_KERNEL); | ||
1359 | else | ||
1360 | x->encap = kmemdup(orig->encap, sizeof(*x->encap), | ||
1361 | GFP_KERNEL); | ||
1362 | |||
1356 | if (!x->encap) | 1363 | if (!x->encap) |
1357 | goto error; | 1364 | goto error; |
1358 | } | 1365 | } |
@@ -1442,11 +1449,12 @@ struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *n | |||
1442 | EXPORT_SYMBOL(xfrm_migrate_state_find); | 1449 | EXPORT_SYMBOL(xfrm_migrate_state_find); |
1443 | 1450 | ||
1444 | struct xfrm_state *xfrm_state_migrate(struct xfrm_state *x, | 1451 | struct xfrm_state *xfrm_state_migrate(struct xfrm_state *x, |
1445 | struct xfrm_migrate *m) | 1452 | struct xfrm_migrate *m, |
1453 | struct xfrm_encap_tmpl *encap) | ||
1446 | { | 1454 | { |
1447 | struct xfrm_state *xc; | 1455 | struct xfrm_state *xc; |
1448 | 1456 | ||
1449 | xc = xfrm_state_clone(x); | 1457 | xc = xfrm_state_clone(x, encap); |
1450 | if (!xc) | 1458 | if (!xc) |
1451 | return NULL; | 1459 | return NULL; |
1452 | 1460 | ||
@@ -1958,7 +1966,8 @@ EXPORT_SYMBOL(km_policy_expired); | |||
1958 | #ifdef CONFIG_XFRM_MIGRATE | 1966 | #ifdef CONFIG_XFRM_MIGRATE |
1959 | int km_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, | 1967 | int km_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, |
1960 | const struct xfrm_migrate *m, int num_migrate, | 1968 | const struct xfrm_migrate *m, int num_migrate, |
1961 | const struct xfrm_kmaddress *k) | 1969 | const struct xfrm_kmaddress *k, |
1970 | const struct xfrm_encap_tmpl *encap) | ||
1962 | { | 1971 | { |
1963 | int err = -EINVAL; | 1972 | int err = -EINVAL; |
1964 | int ret; | 1973 | int ret; |
@@ -1967,7 +1976,8 @@ int km_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, | |||
1967 | rcu_read_lock(); | 1976 | rcu_read_lock(); |
1968 | list_for_each_entry_rcu(km, &xfrm_km_list, list) { | 1977 | list_for_each_entry_rcu(km, &xfrm_km_list, list) { |
1969 | if (km->migrate) { | 1978 | if (km->migrate) { |
1970 | ret = km->migrate(sel, dir, type, m, num_migrate, k); | 1979 | ret = km->migrate(sel, dir, type, m, num_migrate, k, |
1980 | encap); | ||
1971 | if (!ret) | 1981 | if (!ret) |
1972 | err = ret; | 1982 | err = ret; |
1973 | } | 1983 | } |
@@ -2025,13 +2035,9 @@ int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen | |||
2025 | if (optlen <= 0 || optlen > PAGE_SIZE) | 2035 | if (optlen <= 0 || optlen > PAGE_SIZE) |
2026 | return -EMSGSIZE; | 2036 | return -EMSGSIZE; |
2027 | 2037 | ||
2028 | data = kmalloc(optlen, GFP_KERNEL); | 2038 | data = memdup_user(optval, optlen); |
2029 | if (!data) | 2039 | if (IS_ERR(data)) |
2030 | return -ENOMEM; | 2040 | return PTR_ERR(data); |
2031 | |||
2032 | err = -EFAULT; | ||
2033 | if (copy_from_user(data, optval, optlen)) | ||
2034 | goto out; | ||
2035 | 2041 | ||
2036 | err = -EINVAL; | 2042 | err = -EINVAL; |
2037 | rcu_read_lock(); | 2043 | rcu_read_lock(); |
@@ -2049,7 +2055,6 @@ int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen | |||
2049 | err = 0; | 2055 | err = 0; |
2050 | } | 2056 | } |
2051 | 2057 | ||
2052 | out: | ||
2053 | kfree(data); | 2058 | kfree(data); |
2054 | return err; | 2059 | return err; |
2055 | } | 2060 | } |
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 38614df33ec8..6197c7231bc7 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
@@ -2243,6 +2243,7 @@ static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
2243 | int err; | 2243 | int err; |
2244 | int n = 0; | 2244 | int n = 0; |
2245 | struct net *net = sock_net(skb->sk); | 2245 | struct net *net = sock_net(skb->sk); |
2246 | struct xfrm_encap_tmpl *encap = NULL; | ||
2246 | 2247 | ||
2247 | if (attrs[XFRMA_MIGRATE] == NULL) | 2248 | if (attrs[XFRMA_MIGRATE] == NULL) |
2248 | return -EINVAL; | 2249 | return -EINVAL; |
@@ -2260,9 +2261,18 @@ static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
2260 | if (!n) | 2261 | if (!n) |
2261 | return 0; | 2262 | return 0; |
2262 | 2263 | ||
2263 | xfrm_migrate(&pi->sel, pi->dir, type, m, n, kmp, net); | 2264 | if (attrs[XFRMA_ENCAP]) { |
2265 | encap = kmemdup(nla_data(attrs[XFRMA_ENCAP]), | ||
2266 | sizeof(*encap), GFP_KERNEL); | ||
2267 | if (!encap) | ||
2268 | return 0; | ||
2269 | } | ||
2264 | 2270 | ||
2265 | return 0; | 2271 | err = xfrm_migrate(&pi->sel, pi->dir, type, m, n, kmp, net, encap); |
2272 | |||
2273 | kfree(encap); | ||
2274 | |||
2275 | return err; | ||
2266 | } | 2276 | } |
2267 | #else | 2277 | #else |
2268 | static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh, | 2278 | static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh, |
@@ -2304,17 +2314,20 @@ static int copy_to_user_kmaddress(const struct xfrm_kmaddress *k, struct sk_buff | |||
2304 | return nla_put(skb, XFRMA_KMADDRESS, sizeof(uk), &uk); | 2314 | return nla_put(skb, XFRMA_KMADDRESS, sizeof(uk), &uk); |
2305 | } | 2315 | } |
2306 | 2316 | ||
2307 | static inline size_t xfrm_migrate_msgsize(int num_migrate, int with_kma) | 2317 | static inline size_t xfrm_migrate_msgsize(int num_migrate, int with_kma, |
2318 | int with_encp) | ||
2308 | { | 2319 | { |
2309 | return NLMSG_ALIGN(sizeof(struct xfrm_userpolicy_id)) | 2320 | return NLMSG_ALIGN(sizeof(struct xfrm_userpolicy_id)) |
2310 | + (with_kma ? nla_total_size(sizeof(struct xfrm_kmaddress)) : 0) | 2321 | + (with_kma ? nla_total_size(sizeof(struct xfrm_kmaddress)) : 0) |
2322 | + (with_encp ? nla_total_size(sizeof(struct xfrm_encap_tmpl)) : 0) | ||
2311 | + nla_total_size(sizeof(struct xfrm_user_migrate) * num_migrate) | 2323 | + nla_total_size(sizeof(struct xfrm_user_migrate) * num_migrate) |
2312 | + userpolicy_type_attrsize(); | 2324 | + userpolicy_type_attrsize(); |
2313 | } | 2325 | } |
2314 | 2326 | ||
2315 | static int build_migrate(struct sk_buff *skb, const struct xfrm_migrate *m, | 2327 | static int build_migrate(struct sk_buff *skb, const struct xfrm_migrate *m, |
2316 | int num_migrate, const struct xfrm_kmaddress *k, | 2328 | int num_migrate, const struct xfrm_kmaddress *k, |
2317 | const struct xfrm_selector *sel, u8 dir, u8 type) | 2329 | const struct xfrm_selector *sel, |
2330 | const struct xfrm_encap_tmpl *encap, u8 dir, u8 type) | ||
2318 | { | 2331 | { |
2319 | const struct xfrm_migrate *mp; | 2332 | const struct xfrm_migrate *mp; |
2320 | struct xfrm_userpolicy_id *pol_id; | 2333 | struct xfrm_userpolicy_id *pol_id; |
@@ -2336,6 +2349,11 @@ static int build_migrate(struct sk_buff *skb, const struct xfrm_migrate *m, | |||
2336 | if (err) | 2349 | if (err) |
2337 | goto out_cancel; | 2350 | goto out_cancel; |
2338 | } | 2351 | } |
2352 | if (encap) { | ||
2353 | err = nla_put(skb, XFRMA_ENCAP, sizeof(*encap), encap); | ||
2354 | if (err) | ||
2355 | goto out_cancel; | ||
2356 | } | ||
2339 | err = copy_to_user_policy_type(type, skb); | 2357 | err = copy_to_user_policy_type(type, skb); |
2340 | if (err) | 2358 | if (err) |
2341 | goto out_cancel; | 2359 | goto out_cancel; |
@@ -2355,17 +2373,19 @@ out_cancel: | |||
2355 | 2373 | ||
2356 | static int xfrm_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, | 2374 | static int xfrm_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, |
2357 | const struct xfrm_migrate *m, int num_migrate, | 2375 | const struct xfrm_migrate *m, int num_migrate, |
2358 | const struct xfrm_kmaddress *k) | 2376 | const struct xfrm_kmaddress *k, |
2377 | const struct xfrm_encap_tmpl *encap) | ||
2359 | { | 2378 | { |
2360 | struct net *net = &init_net; | 2379 | struct net *net = &init_net; |
2361 | struct sk_buff *skb; | 2380 | struct sk_buff *skb; |
2362 | 2381 | ||
2363 | skb = nlmsg_new(xfrm_migrate_msgsize(num_migrate, !!k), GFP_ATOMIC); | 2382 | skb = nlmsg_new(xfrm_migrate_msgsize(num_migrate, !!k, !!encap), |
2383 | GFP_ATOMIC); | ||
2364 | if (skb == NULL) | 2384 | if (skb == NULL) |
2365 | return -ENOMEM; | 2385 | return -ENOMEM; |
2366 | 2386 | ||
2367 | /* build migrate */ | 2387 | /* build migrate */ |
2368 | if (build_migrate(skb, m, num_migrate, k, sel, dir, type) < 0) | 2388 | if (build_migrate(skb, m, num_migrate, k, sel, encap, dir, type) < 0) |
2369 | BUG(); | 2389 | BUG(); |
2370 | 2390 | ||
2371 | return xfrm_nlmsg_multicast(net, skb, 0, XFRMNLGRP_MIGRATE); | 2391 | return xfrm_nlmsg_multicast(net, skb, 0, XFRMNLGRP_MIGRATE); |
@@ -2373,7 +2393,8 @@ static int xfrm_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, | |||
2373 | #else | 2393 | #else |
2374 | static int xfrm_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, | 2394 | static int xfrm_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, |
2375 | const struct xfrm_migrate *m, int num_migrate, | 2395 | const struct xfrm_migrate *m, int num_migrate, |
2376 | const struct xfrm_kmaddress *k) | 2396 | const struct xfrm_kmaddress *k, |
2397 | const struct xfrm_encap_tmpl *encap) | ||
2377 | { | 2398 | { |
2378 | return -ENOPROTOOPT; | 2399 | return -ENOPROTOOPT; |
2379 | } | 2400 | } |