diff options
| -rw-r--r-- | include/linux/pfkeyv2.h | 13 | ||||
| -rw-r--r-- | include/linux/xfrm.h | 10 | ||||
| -rw-r--r-- | include/net/xfrm.h | 15 | ||||
| -rw-r--r-- | net/key/af_key.c | 86 | ||||
| -rw-r--r-- | net/xfrm/xfrm_policy.c | 5 | ||||
| -rw-r--r-- | net/xfrm/xfrm_state.c | 5 | ||||
| -rw-r--r-- | net/xfrm/xfrm_user.c | 57 |
7 files changed, 154 insertions, 37 deletions
diff --git a/include/linux/pfkeyv2.h b/include/linux/pfkeyv2.h index 700725ddcaae..01b262959f2e 100644 --- a/include/linux/pfkeyv2.h +++ b/include/linux/pfkeyv2.h | |||
| @@ -226,6 +226,15 @@ struct sadb_x_sec_ctx { | |||
| 226 | } __attribute__((packed)); | 226 | } __attribute__((packed)); |
| 227 | /* sizeof(struct sadb_sec_ctx) = 8 */ | 227 | /* sizeof(struct sadb_sec_ctx) = 8 */ |
| 228 | 228 | ||
| 229 | /* Used by MIGRATE to pass addresses IKE will use to perform | ||
| 230 | * negotiation with the peer */ | ||
| 231 | struct sadb_x_kmaddress { | ||
| 232 | uint16_t sadb_x_kmaddress_len; | ||
| 233 | uint16_t sadb_x_kmaddress_exttype; | ||
| 234 | uint32_t sadb_x_kmaddress_reserved; | ||
| 235 | } __attribute__((packed)); | ||
| 236 | /* sizeof(struct sadb_x_kmaddress) == 8 */ | ||
| 237 | |||
| 229 | /* Message types */ | 238 | /* Message types */ |
| 230 | #define SADB_RESERVED 0 | 239 | #define SADB_RESERVED 0 |
| 231 | #define SADB_GETSPI 1 | 240 | #define SADB_GETSPI 1 |
| @@ -346,7 +355,9 @@ struct sadb_x_sec_ctx { | |||
| 346 | #define SADB_X_EXT_NAT_T_DPORT 22 | 355 | #define SADB_X_EXT_NAT_T_DPORT 22 |
| 347 | #define SADB_X_EXT_NAT_T_OA 23 | 356 | #define SADB_X_EXT_NAT_T_OA 23 |
| 348 | #define SADB_X_EXT_SEC_CTX 24 | 357 | #define SADB_X_EXT_SEC_CTX 24 |
| 349 | #define SADB_EXT_MAX 24 | 358 | /* Used with MIGRATE to pass @ to IKE for negotiation */ |
| 359 | #define SADB_X_EXT_KMADDRESS 25 | ||
| 360 | #define SADB_EXT_MAX 25 | ||
| 350 | 361 | ||
| 351 | /* Identity Extension values */ | 362 | /* Identity Extension values */ |
| 352 | #define SADB_IDENTTYPE_RESERVED 0 | 363 | #define SADB_IDENTTYPE_RESERVED 0 |
diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h index fb0c215a3051..4bc1e6b86cb2 100644 --- a/include/linux/xfrm.h +++ b/include/linux/xfrm.h | |||
| @@ -279,6 +279,7 @@ enum xfrm_attr_type_t { | |||
| 279 | XFRMA_POLICY_TYPE, /* struct xfrm_userpolicy_type */ | 279 | XFRMA_POLICY_TYPE, /* struct xfrm_userpolicy_type */ |
| 280 | XFRMA_MIGRATE, | 280 | XFRMA_MIGRATE, |
| 281 | XFRMA_ALG_AEAD, /* struct xfrm_algo_aead */ | 281 | XFRMA_ALG_AEAD, /* struct xfrm_algo_aead */ |
| 282 | XFRMA_KMADDRESS, /* struct xfrm_user_kmaddress */ | ||
| 282 | __XFRMA_MAX | 283 | __XFRMA_MAX |
| 283 | 284 | ||
| 284 | #define XFRMA_MAX (__XFRMA_MAX - 1) | 285 | #define XFRMA_MAX (__XFRMA_MAX - 1) |
| @@ -415,6 +416,15 @@ struct xfrm_user_report { | |||
| 415 | struct xfrm_selector sel; | 416 | struct xfrm_selector sel; |
| 416 | }; | 417 | }; |
| 417 | 418 | ||
| 419 | /* Used by MIGRATE to pass addresses IKE should use to perform | ||
| 420 | * SA negotiation with the peer */ | ||
| 421 | struct xfrm_user_kmaddress { | ||
| 422 | xfrm_address_t local; | ||
| 423 | xfrm_address_t remote; | ||
| 424 | __u32 reserved; | ||
| 425 | __u16 family; | ||
| 426 | }; | ||
| 427 | |||
| 418 | struct xfrm_user_migrate { | 428 | struct xfrm_user_migrate { |
| 419 | xfrm_address_t old_daddr; | 429 | xfrm_address_t old_daddr; |
| 420 | xfrm_address_t old_saddr; | 430 | xfrm_address_t old_saddr; |
diff --git a/include/net/xfrm.h b/include/net/xfrm.h index b98d2056f27f..11c890ad8ebb 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h | |||
| @@ -492,6 +492,13 @@ struct xfrm_policy | |||
| 492 | struct xfrm_tmpl xfrm_vec[XFRM_MAX_DEPTH]; | 492 | struct xfrm_tmpl xfrm_vec[XFRM_MAX_DEPTH]; |
| 493 | }; | 493 | }; |
| 494 | 494 | ||
| 495 | struct xfrm_kmaddress { | ||
| 496 | xfrm_address_t local; | ||
| 497 | xfrm_address_t remote; | ||
| 498 | u32 reserved; | ||
| 499 | u16 family; | ||
| 500 | }; | ||
| 501 | |||
| 495 | struct xfrm_migrate { | 502 | struct xfrm_migrate { |
| 496 | xfrm_address_t old_daddr; | 503 | xfrm_address_t old_daddr; |
| 497 | xfrm_address_t old_saddr; | 504 | xfrm_address_t old_saddr; |
| @@ -531,7 +538,7 @@ struct xfrm_mgr | |||
| 531 | int (*new_mapping)(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport); | 538 | int (*new_mapping)(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport); |
| 532 | int (*notify_policy)(struct xfrm_policy *x, int dir, struct km_event *c); | 539 | int (*notify_policy)(struct xfrm_policy *x, int dir, struct km_event *c); |
| 533 | int (*report)(u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr); | 540 | int (*report)(u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr); |
| 534 | int (*migrate)(struct xfrm_selector *sel, u8 dir, u8 type, struct xfrm_migrate *m, int num_bundles); | 541 | int (*migrate)(struct xfrm_selector *sel, u8 dir, u8 type, struct xfrm_migrate *m, int num_bundles, struct xfrm_kmaddress *k); |
| 535 | }; | 542 | }; |
| 536 | 543 | ||
| 537 | extern int xfrm_register_km(struct xfrm_mgr *km); | 544 | extern int xfrm_register_km(struct xfrm_mgr *km); |
| @@ -1432,12 +1439,14 @@ extern int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *xdst, | |||
| 1432 | 1439 | ||
| 1433 | #ifdef CONFIG_XFRM_MIGRATE | 1440 | #ifdef CONFIG_XFRM_MIGRATE |
| 1434 | extern int km_migrate(struct xfrm_selector *sel, u8 dir, u8 type, | 1441 | extern int km_migrate(struct xfrm_selector *sel, u8 dir, u8 type, |
| 1435 | struct xfrm_migrate *m, int num_bundles); | 1442 | struct xfrm_migrate *m, int num_bundles, |
| 1443 | struct xfrm_kmaddress *k); | ||
| 1436 | extern struct xfrm_state * xfrm_migrate_state_find(struct xfrm_migrate *m); | 1444 | extern struct xfrm_state * xfrm_migrate_state_find(struct xfrm_migrate *m); |
| 1437 | extern struct xfrm_state * xfrm_state_migrate(struct xfrm_state *x, | 1445 | extern struct xfrm_state * xfrm_state_migrate(struct xfrm_state *x, |
| 1438 | struct xfrm_migrate *m); | 1446 | struct xfrm_migrate *m); |
| 1439 | extern int xfrm_migrate(struct xfrm_selector *sel, u8 dir, u8 type, | 1447 | extern int xfrm_migrate(struct xfrm_selector *sel, u8 dir, u8 type, |
| 1440 | struct xfrm_migrate *m, int num_bundles); | 1448 | struct xfrm_migrate *m, int num_bundles, |
| 1449 | struct xfrm_kmaddress *k); | ||
| 1441 | #endif | 1450 | #endif |
| 1442 | 1451 | ||
| 1443 | extern wait_queue_head_t km_waitq; | 1452 | extern wait_queue_head_t km_waitq; |
diff --git a/net/key/af_key.c b/net/key/af_key.c index 7ae641df70bd..362fe317e1f3 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c | |||
| @@ -398,6 +398,7 @@ static u8 sadb_ext_min_len[] = { | |||
| 398 | [SADB_X_EXT_NAT_T_DPORT] = (u8) sizeof(struct sadb_x_nat_t_port), | 398 | [SADB_X_EXT_NAT_T_DPORT] = (u8) sizeof(struct sadb_x_nat_t_port), |
| 399 | [SADB_X_EXT_NAT_T_OA] = (u8) sizeof(struct sadb_address), | 399 | [SADB_X_EXT_NAT_T_OA] = (u8) sizeof(struct sadb_address), |
| 400 | [SADB_X_EXT_SEC_CTX] = (u8) sizeof(struct sadb_x_sec_ctx), | 400 | [SADB_X_EXT_SEC_CTX] = (u8) sizeof(struct sadb_x_sec_ctx), |
| 401 | [SADB_X_EXT_KMADDRESS] = (u8) sizeof(struct sadb_x_kmaddress), | ||
| 401 | }; | 402 | }; |
| 402 | 403 | ||
| 403 | /* Verify sadb_address_{len,prefixlen} against sa_family. */ | 404 | /* Verify sadb_address_{len,prefixlen} against sa_family. */ |
| @@ -2384,24 +2385,21 @@ static int pfkey_sockaddr_pair_size(sa_family_t family) | |||
| 2384 | return PFKEY_ALIGN8(pfkey_sockaddr_len(family) * 2); | 2385 | return PFKEY_ALIGN8(pfkey_sockaddr_len(family) * 2); |
| 2385 | } | 2386 | } |
| 2386 | 2387 | ||
| 2387 | static int parse_sockaddr_pair(struct sadb_x_ipsecrequest *rq, | 2388 | static int parse_sockaddr_pair(struct sockaddr *sa, int ext_len, |
| 2388 | xfrm_address_t *saddr, xfrm_address_t *daddr, | 2389 | xfrm_address_t *saddr, xfrm_address_t *daddr, |
| 2389 | u16 *family) | 2390 | u16 *family) |
| 2390 | { | 2391 | { |
| 2391 | u8 *sa = (u8 *) (rq + 1); | ||
| 2392 | int af, socklen; | 2392 | int af, socklen; |
| 2393 | 2393 | ||
| 2394 | if (rq->sadb_x_ipsecrequest_len < | 2394 | if (ext_len < pfkey_sockaddr_pair_size(sa->sa_family)) |
| 2395 | pfkey_sockaddr_pair_size(((struct sockaddr *)sa)->sa_family)) | ||
| 2396 | return -EINVAL; | 2395 | return -EINVAL; |
| 2397 | 2396 | ||
| 2398 | af = pfkey_sockaddr_extract((struct sockaddr *) sa, | 2397 | af = pfkey_sockaddr_extract(sa, saddr); |
| 2399 | saddr); | ||
| 2400 | if (!af) | 2398 | if (!af) |
| 2401 | return -EINVAL; | 2399 | return -EINVAL; |
| 2402 | 2400 | ||
| 2403 | socklen = pfkey_sockaddr_len(af); | 2401 | socklen = pfkey_sockaddr_len(af); |
| 2404 | if (pfkey_sockaddr_extract((struct sockaddr *) (sa + socklen), | 2402 | if (pfkey_sockaddr_extract((struct sockaddr *) (((u8 *)sa) + socklen), |
| 2405 | daddr) != af) | 2403 | daddr) != af) |
| 2406 | return -EINVAL; | 2404 | return -EINVAL; |
| 2407 | 2405 | ||
| @@ -2421,7 +2419,9 @@ static int ipsecrequests_to_migrate(struct sadb_x_ipsecrequest *rq1, int len, | |||
| 2421 | return -EINVAL; | 2419 | return -EINVAL; |
| 2422 | 2420 | ||
| 2423 | /* old endoints */ | 2421 | /* old endoints */ |
| 2424 | err = parse_sockaddr_pair(rq1, &m->old_saddr, &m->old_daddr, | 2422 | err = parse_sockaddr_pair((struct sockaddr *)(rq1 + 1), |
| 2423 | rq1->sadb_x_ipsecrequest_len, | ||
| 2424 | &m->old_saddr, &m->old_daddr, | ||
| 2425 | &m->old_family); | 2425 | &m->old_family); |
| 2426 | if (err) | 2426 | if (err) |
| 2427 | return err; | 2427 | return err; |
| @@ -2434,7 +2434,9 @@ static int ipsecrequests_to_migrate(struct sadb_x_ipsecrequest *rq1, int len, | |||
| 2434 | return -EINVAL; | 2434 | return -EINVAL; |
| 2435 | 2435 | ||
| 2436 | /* new endpoints */ | 2436 | /* new endpoints */ |
| 2437 | err = parse_sockaddr_pair(rq2, &m->new_saddr, &m->new_daddr, | 2437 | err = parse_sockaddr_pair((struct sockaddr *)(rq2 + 1), |
| 2438 | rq2->sadb_x_ipsecrequest_len, | ||
| 2439 | &m->new_saddr, &m->new_daddr, | ||
| 2438 | &m->new_family); | 2440 | &m->new_family); |
| 2439 | if (err) | 2441 | if (err) |
| 2440 | return err; | 2442 | return err; |
| @@ -2460,29 +2462,40 @@ static int pfkey_migrate(struct sock *sk, struct sk_buff *skb, | |||
| 2460 | int i, len, ret, err = -EINVAL; | 2462 | int i, len, ret, err = -EINVAL; |
| 2461 | u8 dir; | 2463 | u8 dir; |
| 2462 | struct sadb_address *sa; | 2464 | struct sadb_address *sa; |
| 2465 | struct sadb_x_kmaddress *kma; | ||
| 2463 | struct sadb_x_policy *pol; | 2466 | struct sadb_x_policy *pol; |
| 2464 | struct sadb_x_ipsecrequest *rq; | 2467 | struct sadb_x_ipsecrequest *rq; |
| 2465 | struct xfrm_selector sel; | 2468 | struct xfrm_selector sel; |
| 2466 | struct xfrm_migrate m[XFRM_MAX_DEPTH]; | 2469 | struct xfrm_migrate m[XFRM_MAX_DEPTH]; |
| 2470 | struct xfrm_kmaddress k; | ||
| 2467 | 2471 | ||
| 2468 | if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC - 1], | 2472 | if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC - 1], |
| 2469 | ext_hdrs[SADB_EXT_ADDRESS_DST - 1]) || | 2473 | ext_hdrs[SADB_EXT_ADDRESS_DST - 1]) || |
| 2470 | !ext_hdrs[SADB_X_EXT_POLICY - 1]) { | 2474 | !ext_hdrs[SADB_X_EXT_POLICY - 1]) { |
| 2471 | err = -EINVAL; | 2475 | err = -EINVAL; |
| 2472 | goto out; | 2476 | goto out; |
| 2473 | } | 2477 | } |
| 2474 | 2478 | ||
| 2479 | kma = ext_hdrs[SADB_X_EXT_KMADDRESS - 1]; | ||
| 2475 | pol = ext_hdrs[SADB_X_EXT_POLICY - 1]; | 2480 | pol = ext_hdrs[SADB_X_EXT_POLICY - 1]; |
| 2476 | if (!pol) { | ||
| 2477 | err = -EINVAL; | ||
| 2478 | goto out; | ||
| 2479 | } | ||
| 2480 | 2481 | ||
| 2481 | if (pol->sadb_x_policy_dir >= IPSEC_DIR_MAX) { | 2482 | if (pol->sadb_x_policy_dir >= IPSEC_DIR_MAX) { |
| 2482 | err = -EINVAL; | 2483 | err = -EINVAL; |
| 2483 | goto out; | 2484 | goto out; |
| 2484 | } | 2485 | } |
| 2485 | 2486 | ||
| 2487 | if (kma) { | ||
| 2488 | /* convert sadb_x_kmaddress to xfrm_kmaddress */ | ||
| 2489 | k.reserved = kma->sadb_x_kmaddress_reserved; | ||
| 2490 | ret = parse_sockaddr_pair((struct sockaddr *)(kma + 1), | ||
| 2491 | 8*(kma->sadb_x_kmaddress_len) - sizeof(*kma), | ||
| 2492 | &k.local, &k.remote, &k.family); | ||
| 2493 | if (ret < 0) { | ||
| 2494 | err = ret; | ||
| 2495 | goto out; | ||
| 2496 | } | ||
| 2497 | } | ||
| 2498 | |||
| 2486 | dir = pol->sadb_x_policy_dir - 1; | 2499 | dir = pol->sadb_x_policy_dir - 1; |
| 2487 | memset(&sel, 0, sizeof(sel)); | 2500 | memset(&sel, 0, sizeof(sel)); |
| 2488 | 2501 | ||
| @@ -2527,7 +2540,8 @@ static int pfkey_migrate(struct sock *sk, struct sk_buff *skb, | |||
| 2527 | goto out; | 2540 | goto out; |
| 2528 | } | 2541 | } |
| 2529 | 2542 | ||
| 2530 | return xfrm_migrate(&sel, dir, XFRM_POLICY_TYPE_MAIN, m, i); | 2543 | return xfrm_migrate(&sel, dir, XFRM_POLICY_TYPE_MAIN, m, i, |
| 2544 | kma ? &k : NULL); | ||
| 2531 | 2545 | ||
| 2532 | out: | 2546 | out: |
| 2533 | return err; | 2547 | return err; |
| @@ -3319,6 +3333,32 @@ static int set_sadb_address(struct sk_buff *skb, int sasize, int type, | |||
| 3319 | return 0; | 3333 | return 0; |
| 3320 | } | 3334 | } |
| 3321 | 3335 | ||
| 3336 | |||
| 3337 | static int set_sadb_kmaddress(struct sk_buff *skb, struct xfrm_kmaddress *k) | ||
| 3338 | { | ||
| 3339 | struct sadb_x_kmaddress *kma; | ||
| 3340 | u8 *sa; | ||
| 3341 | int family = k->family; | ||
| 3342 | int socklen = pfkey_sockaddr_len(family); | ||
| 3343 | int size_req; | ||
| 3344 | |||
| 3345 | size_req = (sizeof(struct sadb_x_kmaddress) + | ||
| 3346 | pfkey_sockaddr_pair_size(family)); | ||
| 3347 | |||
| 3348 | kma = (struct sadb_x_kmaddress *)skb_put(skb, size_req); | ||
| 3349 | memset(kma, 0, size_req); | ||
| 3350 | kma->sadb_x_kmaddress_len = size_req / 8; | ||
| 3351 | kma->sadb_x_kmaddress_exttype = SADB_X_EXT_KMADDRESS; | ||
| 3352 | kma->sadb_x_kmaddress_reserved = k->reserved; | ||
| 3353 | |||
| 3354 | sa = (u8 *)(kma + 1); | ||
| 3355 | if (!pfkey_sockaddr_fill(&k->local, 0, (struct sockaddr *)sa, family) || | ||
| 3356 | !pfkey_sockaddr_fill(&k->remote, 0, (struct sockaddr *)(sa+socklen), family)) | ||
| 3357 | return -EINVAL; | ||
| 3358 | |||
| 3359 | return 0; | ||
| 3360 | } | ||
| 3361 | |||
| 3322 | static int set_ipsecrequest(struct sk_buff *skb, | 3362 | static int set_ipsecrequest(struct sk_buff *skb, |
| 3323 | uint8_t proto, uint8_t mode, int level, | 3363 | uint8_t proto, uint8_t mode, int level, |
| 3324 | uint32_t reqid, uint8_t family, | 3364 | uint32_t reqid, uint8_t family, |
| @@ -3351,7 +3391,8 @@ static int set_ipsecrequest(struct sk_buff *skb, | |||
| 3351 | 3391 | ||
| 3352 | #ifdef CONFIG_NET_KEY_MIGRATE | 3392 | #ifdef CONFIG_NET_KEY_MIGRATE |
| 3353 | static int pfkey_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, | 3393 | static int pfkey_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, |
| 3354 | struct xfrm_migrate *m, int num_bundles) | 3394 | struct xfrm_migrate *m, int num_bundles, |
| 3395 | struct xfrm_kmaddress *k) | ||
| 3355 | { | 3396 | { |
| 3356 | int i; | 3397 | int i; |
| 3357 | int sasize_sel; | 3398 | int sasize_sel; |
| @@ -3368,6 +3409,12 @@ static int pfkey_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, | |||
| 3368 | if (num_bundles <= 0 || num_bundles > XFRM_MAX_DEPTH) | 3409 | if (num_bundles <= 0 || num_bundles > XFRM_MAX_DEPTH) |
| 3369 | return -EINVAL; | 3410 | return -EINVAL; |
| 3370 | 3411 | ||
| 3412 | if (k != NULL) { | ||
| 3413 | /* addresses for KM */ | ||
| 3414 | size += PFKEY_ALIGN8(sizeof(struct sadb_x_kmaddress) + | ||
| 3415 | pfkey_sockaddr_pair_size(k->family)); | ||
| 3416 | } | ||
| 3417 | |||
| 3371 | /* selector */ | 3418 | /* selector */ |
| 3372 | sasize_sel = pfkey_sockaddr_size(sel->family); | 3419 | sasize_sel = pfkey_sockaddr_size(sel->family); |
| 3373 | if (!sasize_sel) | 3420 | if (!sasize_sel) |
| @@ -3404,6 +3451,10 @@ static int pfkey_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, | |||
| 3404 | hdr->sadb_msg_seq = 0; | 3451 | hdr->sadb_msg_seq = 0; |
| 3405 | hdr->sadb_msg_pid = 0; | 3452 | hdr->sadb_msg_pid = 0; |
| 3406 | 3453 | ||
| 3454 | /* Addresses to be used by KM for negotiation, if ext is available */ | ||
| 3455 | if (k != NULL && (set_sadb_kmaddress(skb, k) < 0)) | ||
| 3456 | return -EINVAL; | ||
| 3457 | |||
| 3407 | /* selector src */ | 3458 | /* selector src */ |
| 3408 | set_sadb_address(skb, sasize_sel, SADB_EXT_ADDRESS_SRC, sel); | 3459 | set_sadb_address(skb, sasize_sel, SADB_EXT_ADDRESS_SRC, sel); |
| 3409 | 3460 | ||
| @@ -3449,7 +3500,8 @@ err: | |||
| 3449 | } | 3500 | } |
| 3450 | #else | 3501 | #else |
| 3451 | static int pfkey_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, | 3502 | static int pfkey_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, |
| 3452 | struct xfrm_migrate *m, int num_bundles) | 3503 | struct xfrm_migrate *m, int num_bundles, |
| 3504 | struct xfrm_kmaddress *k) | ||
| 3453 | { | 3505 | { |
| 3454 | return -ENOPROTOOPT; | 3506 | return -ENOPROTOOPT; |
| 3455 | } | 3507 | } |
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index b7ec08025ffb..832b47c1de80 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
| @@ -2679,7 +2679,8 @@ static int xfrm_migrate_check(struct xfrm_migrate *m, int num_migrate) | |||
| 2679 | } | 2679 | } |
| 2680 | 2680 | ||
| 2681 | int xfrm_migrate(struct xfrm_selector *sel, u8 dir, u8 type, | 2681 | int xfrm_migrate(struct xfrm_selector *sel, u8 dir, u8 type, |
| 2682 | struct xfrm_migrate *m, int num_migrate) | 2682 | struct xfrm_migrate *m, int num_migrate, |
| 2683 | struct xfrm_kmaddress *k) | ||
| 2683 | { | 2684 | { |
| 2684 | int i, err, nx_cur = 0, nx_new = 0; | 2685 | int i, err, nx_cur = 0, nx_new = 0; |
| 2685 | struct xfrm_policy *pol = NULL; | 2686 | struct xfrm_policy *pol = NULL; |
| @@ -2723,7 +2724,7 @@ int xfrm_migrate(struct xfrm_selector *sel, u8 dir, u8 type, | |||
| 2723 | } | 2724 | } |
| 2724 | 2725 | ||
| 2725 | /* Stage 5 - announce */ | 2726 | /* Stage 5 - announce */ |
| 2726 | km_migrate(sel, dir, type, m, num_migrate); | 2727 | km_migrate(sel, dir, type, m, num_migrate, k); |
| 2727 | 2728 | ||
| 2728 | xfrm_pol_put(pol); | 2729 | xfrm_pol_put(pol); |
| 2729 | 2730 | ||
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 747fd8c291a7..508337f97249 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
| @@ -1814,7 +1814,8 @@ EXPORT_SYMBOL(km_policy_expired); | |||
| 1814 | 1814 | ||
| 1815 | #ifdef CONFIG_XFRM_MIGRATE | 1815 | #ifdef CONFIG_XFRM_MIGRATE |
| 1816 | int km_migrate(struct xfrm_selector *sel, u8 dir, u8 type, | 1816 | int km_migrate(struct xfrm_selector *sel, u8 dir, u8 type, |
| 1817 | struct xfrm_migrate *m, int num_migrate) | 1817 | struct xfrm_migrate *m, int num_migrate, |
| 1818 | struct xfrm_kmaddress *k) | ||
| 1818 | { | 1819 | { |
| 1819 | int err = -EINVAL; | 1820 | int err = -EINVAL; |
| 1820 | int ret; | 1821 | int ret; |
| @@ -1823,7 +1824,7 @@ int km_migrate(struct xfrm_selector *sel, u8 dir, u8 type, | |||
| 1823 | read_lock(&xfrm_km_lock); | 1824 | read_lock(&xfrm_km_lock); |
| 1824 | list_for_each_entry(km, &xfrm_km_list, list) { | 1825 | list_for_each_entry(km, &xfrm_km_list, list) { |
| 1825 | if (km->migrate) { | 1826 | if (km->migrate) { |
| 1826 | ret = km->migrate(sel, dir, type, m, num_migrate); | 1827 | ret = km->migrate(sel, dir, type, m, num_migrate, k); |
| 1827 | if (!ret) | 1828 | if (!ret) |
| 1828 | err = ret; | 1829 | err = ret; |
| 1829 | } | 1830 | } |
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 76f75df21e15..4a8a1abb59ee 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
| @@ -1710,12 +1710,23 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
| 1710 | 1710 | ||
| 1711 | #ifdef CONFIG_XFRM_MIGRATE | 1711 | #ifdef CONFIG_XFRM_MIGRATE |
| 1712 | static int copy_from_user_migrate(struct xfrm_migrate *ma, | 1712 | static int copy_from_user_migrate(struct xfrm_migrate *ma, |
| 1713 | struct xfrm_kmaddress *k, | ||
| 1713 | struct nlattr **attrs, int *num) | 1714 | struct nlattr **attrs, int *num) |
| 1714 | { | 1715 | { |
| 1715 | struct nlattr *rt = attrs[XFRMA_MIGRATE]; | 1716 | struct nlattr *rt = attrs[XFRMA_MIGRATE]; |
| 1716 | struct xfrm_user_migrate *um; | 1717 | struct xfrm_user_migrate *um; |
| 1717 | int i, num_migrate; | 1718 | int i, num_migrate; |
| 1718 | 1719 | ||
| 1720 | if (k != NULL) { | ||
| 1721 | struct xfrm_user_kmaddress *uk; | ||
| 1722 | |||
| 1723 | uk = nla_data(attrs[XFRMA_KMADDRESS]); | ||
| 1724 | memcpy(&k->local, &uk->local, sizeof(k->local)); | ||
| 1725 | memcpy(&k->remote, &uk->remote, sizeof(k->remote)); | ||
| 1726 | k->family = uk->family; | ||
| 1727 | k->reserved = uk->reserved; | ||
| 1728 | } | ||
| 1729 | |||
| 1719 | um = nla_data(rt); | 1730 | um = nla_data(rt); |
| 1720 | num_migrate = nla_len(rt) / sizeof(*um); | 1731 | num_migrate = nla_len(rt) / sizeof(*um); |
| 1721 | 1732 | ||
| @@ -1745,6 +1756,7 @@ static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
| 1745 | { | 1756 | { |
| 1746 | struct xfrm_userpolicy_id *pi = nlmsg_data(nlh); | 1757 | struct xfrm_userpolicy_id *pi = nlmsg_data(nlh); |
| 1747 | struct xfrm_migrate m[XFRM_MAX_DEPTH]; | 1758 | struct xfrm_migrate m[XFRM_MAX_DEPTH]; |
| 1759 | struct xfrm_kmaddress km, *kmp; | ||
| 1748 | u8 type; | 1760 | u8 type; |
| 1749 | int err; | 1761 | int err; |
| 1750 | int n = 0; | 1762 | int n = 0; |
| @@ -1752,19 +1764,20 @@ static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
| 1752 | if (attrs[XFRMA_MIGRATE] == NULL) | 1764 | if (attrs[XFRMA_MIGRATE] == NULL) |
| 1753 | return -EINVAL; | 1765 | return -EINVAL; |
| 1754 | 1766 | ||
| 1767 | kmp = attrs[XFRMA_KMADDRESS] ? &km : NULL; | ||
| 1768 | |||
| 1755 | err = copy_from_user_policy_type(&type, attrs); | 1769 | err = copy_from_user_policy_type(&type, attrs); |
| 1756 | if (err) | 1770 | if (err) |
| 1757 | return err; | 1771 | return err; |
| 1758 | 1772 | ||
| 1759 | err = copy_from_user_migrate((struct xfrm_migrate *)m, | 1773 | err = copy_from_user_migrate((struct xfrm_migrate *)m, kmp, attrs, &n); |
| 1760 | attrs, &n); | ||
| 1761 | if (err) | 1774 | if (err) |
| 1762 | return err; | 1775 | return err; |
| 1763 | 1776 | ||
| 1764 | if (!n) | 1777 | if (!n) |
| 1765 | return 0; | 1778 | return 0; |
| 1766 | 1779 | ||
| 1767 | xfrm_migrate(&pi->sel, pi->dir, type, m, n); | 1780 | xfrm_migrate(&pi->sel, pi->dir, type, m, n, kmp); |
| 1768 | 1781 | ||
| 1769 | return 0; | 1782 | return 0; |
| 1770 | } | 1783 | } |
| @@ -1795,16 +1808,30 @@ static int copy_to_user_migrate(struct xfrm_migrate *m, struct sk_buff *skb) | |||
| 1795 | return nla_put(skb, XFRMA_MIGRATE, sizeof(um), &um); | 1808 | return nla_put(skb, XFRMA_MIGRATE, sizeof(um), &um); |
| 1796 | } | 1809 | } |
| 1797 | 1810 | ||
| 1798 | static inline size_t xfrm_migrate_msgsize(int num_migrate) | 1811 | static int copy_to_user_kmaddress(struct xfrm_kmaddress *k, struct sk_buff *skb) |
| 1812 | { | ||
| 1813 | struct xfrm_user_kmaddress uk; | ||
| 1814 | |||
| 1815 | memset(&uk, 0, sizeof(uk)); | ||
| 1816 | uk.family = k->family; | ||
| 1817 | uk.reserved = k->reserved; | ||
| 1818 | memcpy(&uk.local, &k->local, sizeof(uk.local)); | ||
| 1819 | memcpy(&uk.remote, &k->local, sizeof(uk.remote)); | ||
| 1820 | |||
| 1821 | return nla_put(skb, XFRMA_KMADDRESS, sizeof(uk), &uk); | ||
| 1822 | } | ||
| 1823 | |||
| 1824 | static inline size_t xfrm_migrate_msgsize(int num_migrate, int with_kma) | ||
| 1799 | { | 1825 | { |
| 1800 | return NLMSG_ALIGN(sizeof(struct xfrm_userpolicy_id)) | 1826 | return NLMSG_ALIGN(sizeof(struct xfrm_userpolicy_id)) |
| 1801 | + nla_total_size(sizeof(struct xfrm_user_migrate) * num_migrate) | 1827 | + (with_kma ? nla_total_size(sizeof(struct xfrm_kmaddress)) : 0) |
| 1802 | + userpolicy_type_attrsize(); | 1828 | + nla_total_size(sizeof(struct xfrm_user_migrate) * num_migrate) |
| 1829 | + userpolicy_type_attrsize(); | ||
| 1803 | } | 1830 | } |
| 1804 | 1831 | ||
| 1805 | static int build_migrate(struct sk_buff *skb, struct xfrm_migrate *m, | 1832 | static int build_migrate(struct sk_buff *skb, struct xfrm_migrate *m, |
| 1806 | int num_migrate, struct xfrm_selector *sel, | 1833 | int num_migrate, struct xfrm_kmaddress *k, |
| 1807 | u8 dir, u8 type) | 1834 | struct xfrm_selector *sel, u8 dir, u8 type) |
| 1808 | { | 1835 | { |
| 1809 | struct xfrm_migrate *mp; | 1836 | struct xfrm_migrate *mp; |
| 1810 | struct xfrm_userpolicy_id *pol_id; | 1837 | struct xfrm_userpolicy_id *pol_id; |
| @@ -1821,6 +1848,9 @@ static int build_migrate(struct sk_buff *skb, struct xfrm_migrate *m, | |||
| 1821 | memcpy(&pol_id->sel, sel, sizeof(pol_id->sel)); | 1848 | memcpy(&pol_id->sel, sel, sizeof(pol_id->sel)); |
| 1822 | pol_id->dir = dir; | 1849 | pol_id->dir = dir; |
| 1823 | 1850 | ||
| 1851 | if (k != NULL && (copy_to_user_kmaddress(k, skb) < 0)) | ||
| 1852 | goto nlmsg_failure; | ||
| 1853 | |||
| 1824 | if (copy_to_user_policy_type(type, skb) < 0) | 1854 | if (copy_to_user_policy_type(type, skb) < 0) |
| 1825 | goto nlmsg_failure; | 1855 | goto nlmsg_failure; |
| 1826 | 1856 | ||
| @@ -1836,23 +1866,25 @@ nlmsg_failure: | |||
| 1836 | } | 1866 | } |
| 1837 | 1867 | ||
| 1838 | static int xfrm_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, | 1868 | static int xfrm_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, |
| 1839 | struct xfrm_migrate *m, int num_migrate) | 1869 | struct xfrm_migrate *m, int num_migrate, |
| 1870 | struct xfrm_kmaddress *k) | ||
| 1840 | { | 1871 | { |
| 1841 | struct sk_buff *skb; | 1872 | struct sk_buff *skb; |
| 1842 | 1873 | ||
| 1843 | skb = nlmsg_new(xfrm_migrate_msgsize(num_migrate), GFP_ATOMIC); | 1874 | skb = nlmsg_new(xfrm_migrate_msgsize(num_migrate, !!k), GFP_ATOMIC); |
| 1844 | if (skb == NULL) | 1875 | if (skb == NULL) |
| 1845 | return -ENOMEM; | 1876 | return -ENOMEM; |
| 1846 | 1877 | ||
| 1847 | /* build migrate */ | 1878 | /* build migrate */ |
| 1848 | if (build_migrate(skb, m, num_migrate, sel, dir, type) < 0) | 1879 | if (build_migrate(skb, m, num_migrate, k, sel, dir, type) < 0) |
| 1849 | BUG(); | 1880 | BUG(); |
| 1850 | 1881 | ||
| 1851 | return nlmsg_multicast(xfrm_nl, skb, 0, XFRMNLGRP_MIGRATE, GFP_ATOMIC); | 1882 | return nlmsg_multicast(xfrm_nl, skb, 0, XFRMNLGRP_MIGRATE, GFP_ATOMIC); |
| 1852 | } | 1883 | } |
| 1853 | #else | 1884 | #else |
| 1854 | static int xfrm_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, | 1885 | static int xfrm_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, |
| 1855 | struct xfrm_migrate *m, int num_migrate) | 1886 | struct xfrm_migrate *m, int num_migrate, |
| 1887 | struct xfrm_kmaddress *k) | ||
| 1856 | { | 1888 | { |
| 1857 | return -ENOPROTOOPT; | 1889 | return -ENOPROTOOPT; |
| 1858 | } | 1890 | } |
| @@ -1901,6 +1933,7 @@ static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = { | |||
| 1901 | [XFRMA_COADDR] = { .len = sizeof(xfrm_address_t) }, | 1933 | [XFRMA_COADDR] = { .len = sizeof(xfrm_address_t) }, |
| 1902 | [XFRMA_POLICY_TYPE] = { .len = sizeof(struct xfrm_userpolicy_type)}, | 1934 | [XFRMA_POLICY_TYPE] = { .len = sizeof(struct xfrm_userpolicy_type)}, |
| 1903 | [XFRMA_MIGRATE] = { .len = sizeof(struct xfrm_user_migrate) }, | 1935 | [XFRMA_MIGRATE] = { .len = sizeof(struct xfrm_user_migrate) }, |
| 1936 | [XFRMA_KMADDRESS] = { .len = sizeof(struct xfrm_user_kmaddress) }, | ||
| 1904 | }; | 1937 | }; |
| 1905 | 1938 | ||
| 1906 | static struct xfrm_link { | 1939 | static struct xfrm_link { |
