diff options
| -rw-r--r-- | net/xfrm/xfrm_user.c | 76 |
1 files changed, 47 insertions, 29 deletions
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 52c7fce54641..2cbbe5e93a7b 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
| @@ -483,9 +483,9 @@ struct xfrm_dump_info { | |||
| 483 | 483 | ||
| 484 | static int copy_sec_ctx(struct xfrm_sec_ctx *s, struct sk_buff *skb) | 484 | static int copy_sec_ctx(struct xfrm_sec_ctx *s, struct sk_buff *skb) |
| 485 | { | 485 | { |
| 486 | int ctx_size = sizeof(struct xfrm_sec_ctx) + s->ctx_len; | ||
| 487 | struct xfrm_user_sec_ctx *uctx; | 486 | struct xfrm_user_sec_ctx *uctx; |
| 488 | struct nlattr *attr; | 487 | struct nlattr *attr; |
| 488 | int ctx_size = sizeof(*uctx) + s->ctx_len; | ||
| 489 | 489 | ||
| 490 | attr = nla_reserve(skb, XFRMA_SEC_CTX, ctx_size); | 490 | attr = nla_reserve(skb, XFRMA_SEC_CTX, ctx_size); |
| 491 | if (attr == NULL) | 491 | if (attr == NULL) |
| @@ -502,23 +502,11 @@ static int copy_sec_ctx(struct xfrm_sec_ctx *s, struct sk_buff *skb) | |||
| 502 | return 0; | 502 | return 0; |
| 503 | } | 503 | } |
| 504 | 504 | ||
| 505 | static int dump_one_state(struct xfrm_state *x, int count, void *ptr) | 505 | /* Don't change this without updating xfrm_sa_len! */ |
| 506 | static int copy_to_user_state_extra(struct xfrm_state *x, | ||
| 507 | struct xfrm_usersa_info *p, | ||
| 508 | struct sk_buff *skb) | ||
| 506 | { | 509 | { |
| 507 | struct xfrm_dump_info *sp = ptr; | ||
| 508 | struct sk_buff *in_skb = sp->in_skb; | ||
| 509 | struct sk_buff *skb = sp->out_skb; | ||
| 510 | struct xfrm_usersa_info *p; | ||
| 511 | struct nlmsghdr *nlh; | ||
| 512 | |||
| 513 | if (sp->this_idx < sp->start_idx) | ||
| 514 | goto out; | ||
| 515 | |||
| 516 | nlh = nlmsg_put(skb, NETLINK_CB(in_skb).pid, sp->nlmsg_seq, | ||
| 517 | XFRM_MSG_NEWSA, sizeof(*p), sp->nlmsg_flags); | ||
| 518 | if (nlh == NULL) | ||
| 519 | return -EMSGSIZE; | ||
| 520 | |||
| 521 | p = nlmsg_data(nlh); | ||
| 522 | copy_to_user_state(x, p); | 510 | copy_to_user_state(x, p); |
| 523 | 511 | ||
| 524 | if (x->aalg) | 512 | if (x->aalg) |
| @@ -540,6 +528,35 @@ static int dump_one_state(struct xfrm_state *x, int count, void *ptr) | |||
| 540 | if (x->lastused) | 528 | if (x->lastused) |
| 541 | NLA_PUT_U64(skb, XFRMA_LASTUSED, x->lastused); | 529 | NLA_PUT_U64(skb, XFRMA_LASTUSED, x->lastused); |
| 542 | 530 | ||
| 531 | return 0; | ||
| 532 | |||
| 533 | nla_put_failure: | ||
| 534 | return -EMSGSIZE; | ||
| 535 | } | ||
| 536 | |||
| 537 | static int dump_one_state(struct xfrm_state *x, int count, void *ptr) | ||
| 538 | { | ||
| 539 | struct xfrm_dump_info *sp = ptr; | ||
| 540 | struct sk_buff *in_skb = sp->in_skb; | ||
| 541 | struct sk_buff *skb = sp->out_skb; | ||
| 542 | struct xfrm_usersa_info *p; | ||
| 543 | struct nlmsghdr *nlh; | ||
| 544 | int err; | ||
| 545 | |||
| 546 | if (sp->this_idx < sp->start_idx) | ||
| 547 | goto out; | ||
| 548 | |||
| 549 | nlh = nlmsg_put(skb, NETLINK_CB(in_skb).pid, sp->nlmsg_seq, | ||
| 550 | XFRM_MSG_NEWSA, sizeof(*p), sp->nlmsg_flags); | ||
| 551 | if (nlh == NULL) | ||
| 552 | return -EMSGSIZE; | ||
| 553 | |||
| 554 | p = nlmsg_data(nlh); | ||
| 555 | |||
| 556 | err = copy_to_user_state_extra(x, p, skb); | ||
| 557 | if (err) | ||
| 558 | goto nla_put_failure; | ||
| 559 | |||
| 543 | nlmsg_end(skb, nlh); | 560 | nlmsg_end(skb, nlh); |
| 544 | out: | 561 | out: |
| 545 | sp->this_idx++; | 562 | sp->this_idx++; |
| @@ -547,7 +564,7 @@ out: | |||
| 547 | 564 | ||
| 548 | nla_put_failure: | 565 | nla_put_failure: |
| 549 | nlmsg_cancel(skb, nlh); | 566 | nlmsg_cancel(skb, nlh); |
| 550 | return -EMSGSIZE; | 567 | return err; |
| 551 | } | 568 | } |
| 552 | 569 | ||
| 553 | static int xfrm_dump_sa(struct sk_buff *skb, struct netlink_callback *cb) | 570 | static int xfrm_dump_sa(struct sk_buff *skb, struct netlink_callback *cb) |
| @@ -1973,6 +1990,14 @@ static inline size_t xfrm_sa_len(struct xfrm_state *x) | |||
| 1973 | l += nla_total_size(sizeof(*x->calg)); | 1990 | l += nla_total_size(sizeof(*x->calg)); |
| 1974 | if (x->encap) | 1991 | if (x->encap) |
| 1975 | l += nla_total_size(sizeof(*x->encap)); | 1992 | l += nla_total_size(sizeof(*x->encap)); |
| 1993 | if (x->security) | ||
| 1994 | l += nla_total_size(sizeof(struct xfrm_user_sec_ctx) + | ||
| 1995 | x->security->ctx_len); | ||
| 1996 | if (x->coaddr) | ||
| 1997 | l += nla_total_size(sizeof(*x->coaddr)); | ||
| 1998 | |||
| 1999 | /* Must count this as this may become non-zero behind our back. */ | ||
| 2000 | l += nla_total_size(sizeof(x->lastused)); | ||
| 1976 | 2001 | ||
| 1977 | return l; | 2002 | return l; |
| 1978 | } | 2003 | } |
| @@ -2018,23 +2043,16 @@ static int xfrm_notify_sa(struct xfrm_state *x, struct km_event *c) | |||
| 2018 | p = nla_data(attr); | 2043 | p = nla_data(attr); |
| 2019 | } | 2044 | } |
| 2020 | 2045 | ||
| 2021 | copy_to_user_state(x, p); | 2046 | if (copy_to_user_state_extra(x, p, skb)) |
| 2022 | 2047 | goto nla_put_failure; | |
| 2023 | if (x->aalg) | ||
| 2024 | NLA_PUT(skb, XFRMA_ALG_AUTH, alg_len(x->aalg), x->aalg); | ||
| 2025 | if (x->ealg) | ||
| 2026 | NLA_PUT(skb, XFRMA_ALG_CRYPT, alg_len(x->ealg), x->ealg); | ||
| 2027 | if (x->calg) | ||
| 2028 | NLA_PUT(skb, XFRMA_ALG_COMP, sizeof(*(x->calg)), x->calg); | ||
| 2029 | |||
| 2030 | if (x->encap) | ||
| 2031 | NLA_PUT(skb, XFRMA_ENCAP, sizeof(*x->encap), x->encap); | ||
| 2032 | 2048 | ||
| 2033 | nlmsg_end(skb, nlh); | 2049 | nlmsg_end(skb, nlh); |
| 2034 | 2050 | ||
| 2035 | return nlmsg_multicast(xfrm_nl, skb, 0, XFRMNLGRP_SA, GFP_ATOMIC); | 2051 | return nlmsg_multicast(xfrm_nl, skb, 0, XFRMNLGRP_SA, GFP_ATOMIC); |
| 2036 | 2052 | ||
| 2037 | nla_put_failure: | 2053 | nla_put_failure: |
| 2054 | /* Somebody screwed up with xfrm_sa_len! */ | ||
| 2055 | WARN_ON(1); | ||
| 2038 | kfree_skb(skb); | 2056 | kfree_skb(skb); |
| 2039 | return -1; | 2057 | return -1; |
| 2040 | } | 2058 | } |
