diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/xfrm/xfrm_state.c | 6 | ||||
-rw-r--r-- | net/xfrm/xfrm_user.c | 28 |
2 files changed, 33 insertions, 1 deletions
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index f05371556cce..3da89c01ea71 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
@@ -78,6 +78,7 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x) | |||
78 | kfree(x->ealg); | 78 | kfree(x->ealg); |
79 | kfree(x->calg); | 79 | kfree(x->calg); |
80 | kfree(x->encap); | 80 | kfree(x->encap); |
81 | kfree(x->coaddr); | ||
81 | if (x->mode) | 82 | if (x->mode) |
82 | xfrm_put_mode(x->mode); | 83 | xfrm_put_mode(x->mode); |
83 | if (x->type) { | 84 | if (x->type) { |
@@ -603,6 +604,11 @@ out: | |||
603 | if (likely(x1->km.state == XFRM_STATE_VALID)) { | 604 | if (likely(x1->km.state == XFRM_STATE_VALID)) { |
604 | if (x->encap && x1->encap) | 605 | if (x->encap && x1->encap) |
605 | memcpy(x1->encap, x->encap, sizeof(*x1->encap)); | 606 | memcpy(x1->encap, x->encap, sizeof(*x1->encap)); |
607 | if (x->coaddr && x1->coaddr) { | ||
608 | memcpy(x1->coaddr, x->coaddr, sizeof(*x1->coaddr)); | ||
609 | } | ||
610 | if (!use_spi && memcmp(&x1->sel, &x->sel, sizeof(x1->sel))) | ||
611 | memcpy(&x1->sel, &x->sel, sizeof(x1->sel)); | ||
606 | memcpy(&x1->lft, &x->lft, sizeof(x1->lft)); | 612 | memcpy(&x1->lft, &x->lft, sizeof(x1->lft)); |
607 | x1->km.dying = 0; | 613 | x1->km.dying = 0; |
608 | 614 | ||
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index b5f8ab71aa54..939808de9e20 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
@@ -187,11 +187,14 @@ static int verify_newsa_info(struct xfrm_usersa_info *p, | |||
187 | goto out; | 187 | goto out; |
188 | if ((err = verify_sec_ctx_len(xfrma))) | 188 | if ((err = verify_sec_ctx_len(xfrma))) |
189 | goto out; | 189 | goto out; |
190 | if ((err = verify_one_addr(xfrma, XFRMA_COADDR, NULL))) | ||
191 | goto out; | ||
190 | 192 | ||
191 | err = -EINVAL; | 193 | err = -EINVAL; |
192 | switch (p->mode) { | 194 | switch (p->mode) { |
193 | case XFRM_MODE_TRANSPORT: | 195 | case XFRM_MODE_TRANSPORT: |
194 | case XFRM_MODE_TUNNEL: | 196 | case XFRM_MODE_TUNNEL: |
197 | case XFRM_MODE_ROUTEOPTIMIZATION: | ||
195 | break; | 198 | break; |
196 | 199 | ||
197 | default: | 200 | default: |
@@ -276,6 +279,24 @@ static int attach_sec_ctx(struct xfrm_state *x, struct rtattr *u_arg) | |||
276 | return security_xfrm_state_alloc(x, uctx); | 279 | return security_xfrm_state_alloc(x, uctx); |
277 | } | 280 | } |
278 | 281 | ||
282 | static int attach_one_addr(xfrm_address_t **addrpp, struct rtattr *u_arg) | ||
283 | { | ||
284 | struct rtattr *rta = u_arg; | ||
285 | xfrm_address_t *p, *uaddrp; | ||
286 | |||
287 | if (!rta) | ||
288 | return 0; | ||
289 | |||
290 | uaddrp = RTA_DATA(rta); | ||
291 | p = kmalloc(sizeof(*p), GFP_KERNEL); | ||
292 | if (!p) | ||
293 | return -ENOMEM; | ||
294 | |||
295 | memcpy(p, uaddrp, sizeof(*p)); | ||
296 | *addrpp = p; | ||
297 | return 0; | ||
298 | } | ||
299 | |||
279 | static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p) | 300 | static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p) |
280 | { | 301 | { |
281 | memcpy(&x->id, &p->id, sizeof(x->id)); | 302 | memcpy(&x->id, &p->id, sizeof(x->id)); |
@@ -365,7 +386,8 @@ static struct xfrm_state *xfrm_state_construct(struct xfrm_usersa_info *p, | |||
365 | goto error; | 386 | goto error; |
366 | if ((err = attach_encap_tmpl(&x->encap, xfrma[XFRMA_ENCAP-1]))) | 387 | if ((err = attach_encap_tmpl(&x->encap, xfrma[XFRMA_ENCAP-1]))) |
367 | goto error; | 388 | goto error; |
368 | 389 | if ((err = attach_one_addr(&x->coaddr, xfrma[XFRMA_COADDR-1]))) | |
390 | goto error; | ||
369 | err = xfrm_init_state(x); | 391 | err = xfrm_init_state(x); |
370 | if (err) | 392 | if (err) |
371 | goto error; | 393 | goto error; |
@@ -569,6 +591,10 @@ static int dump_one_state(struct xfrm_state *x, int count, void *ptr) | |||
569 | uctx->ctx_len = x->security->ctx_len; | 591 | uctx->ctx_len = x->security->ctx_len; |
570 | memcpy(uctx + 1, x->security->ctx_str, x->security->ctx_len); | 592 | memcpy(uctx + 1, x->security->ctx_str, x->security->ctx_len); |
571 | } | 593 | } |
594 | |||
595 | if (x->coaddr) | ||
596 | RTA_PUT(skb, XFRMA_COADDR, sizeof(*x->coaddr), x->coaddr); | ||
597 | |||
572 | nlh->nlmsg_len = skb->tail - b; | 598 | nlh->nlmsg_len = skb->tail - b; |
573 | out: | 599 | out: |
574 | sp->this_idx++; | 600 | sp->this_idx++; |