aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2007-10-09 16:30:57 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:55:02 -0400
commit68325d3b12ad5bce650c2883bb878257f197efff (patch)
treec6d15e03e017599b07742d0a8453e4ee8ee253e3
parent658b219e9379d75fbdc578b9630b598098471258 (diff)
[XFRM] user: Move attribute copying code into copy_to_user_state_extra
Here's a good example of code duplication leading to code rot. The notification patch did its own netlink message creation for xfrm states. It duplicated code that was already in dump_one_state. Guess what, the next time (and the time after) when someone updated dump_one_state the notification path got zilch. This patch moves that code from dump_one_state to copy_to_user_state_extra and uses it in xfrm_notify_sa too. Unfortunately whoever updates this still needs to update xfrm_sa_len since the notification path wants to know the exact size for allocation. At least I've added a comment saying so and if someone still forgest, we'll have a WARN_ON telling us so. I also changed the security size calculation to use xfrm_user_sec_ctx since that's what we actually put into the skb. However it makes no practical difference since it has the same size as xfrm_sec_ctx. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/xfrm/xfrm_user.c76
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
484static int copy_sec_ctx(struct xfrm_sec_ctx *s, struct sk_buff *skb) 484static 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
505static int dump_one_state(struct xfrm_state *x, int count, void *ptr) 505/* Don't change this without updating xfrm_sa_len! */
506static 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
533nla_put_failure:
534 return -EMSGSIZE;
535}
536
537static 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);
544out: 561out:
545 sp->this_idx++; 562 sp->this_idx++;
@@ -547,7 +564,7 @@ out:
547 564
548nla_put_failure: 565nla_put_failure:
549 nlmsg_cancel(skb, nlh); 566 nlmsg_cancel(skb, nlh);
550 return -EMSGSIZE; 567 return err;
551} 568}
552 569
553static int xfrm_dump_sa(struct sk_buff *skb, struct netlink_callback *cb) 570static 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
2037nla_put_failure: 2053nla_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}