diff options
Diffstat (limited to 'net')
-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 | } |