diff options
Diffstat (limited to 'net/xfrm/xfrm_user.c')
-rw-r--r-- | net/xfrm/xfrm_user.c | 59 |
1 files changed, 53 insertions, 6 deletions
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 41f3d51ffc33..b5f8ab71aa54 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
@@ -87,6 +87,22 @@ static int verify_encap_tmpl(struct rtattr **xfrma) | |||
87 | return 0; | 87 | return 0; |
88 | } | 88 | } |
89 | 89 | ||
90 | static int verify_one_addr(struct rtattr **xfrma, enum xfrm_attr_type_t type, | ||
91 | xfrm_address_t **addrp) | ||
92 | { | ||
93 | struct rtattr *rt = xfrma[type - 1]; | ||
94 | |||
95 | if (!rt) | ||
96 | return 0; | ||
97 | |||
98 | if ((rt->rta_len - sizeof(*rt)) < sizeof(**addrp)) | ||
99 | return -EINVAL; | ||
100 | |||
101 | if (addrp) | ||
102 | *addrp = RTA_DATA(rt); | ||
103 | |||
104 | return 0; | ||
105 | } | ||
90 | 106 | ||
91 | static inline int verify_sec_ctx_len(struct rtattr **xfrma) | 107 | static inline int verify_sec_ctx_len(struct rtattr **xfrma) |
92 | { | 108 | { |
@@ -418,16 +434,48 @@ out: | |||
418 | return err; | 434 | return err; |
419 | } | 435 | } |
420 | 436 | ||
437 | static struct xfrm_state *xfrm_user_state_lookup(struct xfrm_usersa_id *p, | ||
438 | struct rtattr **xfrma, | ||
439 | int *errp) | ||
440 | { | ||
441 | struct xfrm_state *x = NULL; | ||
442 | int err; | ||
443 | |||
444 | if (xfrm_id_proto_match(p->proto, IPSEC_PROTO_ANY)) { | ||
445 | err = -ESRCH; | ||
446 | x = xfrm_state_lookup(&p->daddr, p->spi, p->proto, p->family); | ||
447 | } else { | ||
448 | xfrm_address_t *saddr = NULL; | ||
449 | |||
450 | err = verify_one_addr(xfrma, XFRMA_SRCADDR, &saddr); | ||
451 | if (err) | ||
452 | goto out; | ||
453 | |||
454 | if (!saddr) { | ||
455 | err = -EINVAL; | ||
456 | goto out; | ||
457 | } | ||
458 | |||
459 | x = xfrm_state_lookup_byaddr(&p->daddr, saddr, p->proto, | ||
460 | p->family); | ||
461 | } | ||
462 | |||
463 | out: | ||
464 | if (!x && errp) | ||
465 | *errp = err; | ||
466 | return x; | ||
467 | } | ||
468 | |||
421 | static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) | 469 | static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) |
422 | { | 470 | { |
423 | struct xfrm_state *x; | 471 | struct xfrm_state *x; |
424 | int err; | 472 | int err = -ESRCH; |
425 | struct km_event c; | 473 | struct km_event c; |
426 | struct xfrm_usersa_id *p = NLMSG_DATA(nlh); | 474 | struct xfrm_usersa_id *p = NLMSG_DATA(nlh); |
427 | 475 | ||
428 | x = xfrm_state_lookup(&p->daddr, p->spi, p->proto, p->family); | 476 | x = xfrm_user_state_lookup(p, (struct rtattr **)xfrma, &err); |
429 | if (x == NULL) | 477 | if (x == NULL) |
430 | return -ESRCH; | 478 | return err; |
431 | 479 | ||
432 | if ((err = security_xfrm_state_delete(x)) != 0) | 480 | if ((err = security_xfrm_state_delete(x)) != 0) |
433 | goto out; | 481 | goto out; |
@@ -578,10 +626,9 @@ static int xfrm_get_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) | |||
578 | struct xfrm_usersa_id *p = NLMSG_DATA(nlh); | 626 | struct xfrm_usersa_id *p = NLMSG_DATA(nlh); |
579 | struct xfrm_state *x; | 627 | struct xfrm_state *x; |
580 | struct sk_buff *resp_skb; | 628 | struct sk_buff *resp_skb; |
581 | int err; | 629 | int err = -ESRCH; |
582 | 630 | ||
583 | x = xfrm_state_lookup(&p->daddr, p->spi, p->proto, p->family); | 631 | x = xfrm_user_state_lookup(p, (struct rtattr **)xfrma, &err); |
584 | err = -ESRCH; | ||
585 | if (x == NULL) | 632 | if (x == NULL) |
586 | goto out_noput; | 633 | goto out_noput; |
587 | 634 | ||