diff options
Diffstat (limited to 'net/xfrm/xfrm_user.c')
-rw-r--r-- | net/xfrm/xfrm_user.c | 244 |
1 files changed, 176 insertions, 68 deletions
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 61291965c5f6..c658cb3bc7c3 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
@@ -119,6 +119,25 @@ static inline int verify_sec_ctx_len(struct nlattr **attrs) | |||
119 | return 0; | 119 | return 0; |
120 | } | 120 | } |
121 | 121 | ||
122 | static inline int verify_replay(struct xfrm_usersa_info *p, | ||
123 | struct nlattr **attrs) | ||
124 | { | ||
125 | struct nlattr *rt = attrs[XFRMA_REPLAY_ESN_VAL]; | ||
126 | |||
127 | if ((p->flags & XFRM_STATE_ESN) && !rt) | ||
128 | return -EINVAL; | ||
129 | |||
130 | if (!rt) | ||
131 | return 0; | ||
132 | |||
133 | if (p->id.proto != IPPROTO_ESP) | ||
134 | return -EINVAL; | ||
135 | |||
136 | if (p->replay_window != 0) | ||
137 | return -EINVAL; | ||
138 | |||
139 | return 0; | ||
140 | } | ||
122 | 141 | ||
123 | static int verify_newsa_info(struct xfrm_usersa_info *p, | 142 | static int verify_newsa_info(struct xfrm_usersa_info *p, |
124 | struct nlattr **attrs) | 143 | struct nlattr **attrs) |
@@ -214,6 +233,8 @@ static int verify_newsa_info(struct xfrm_usersa_info *p, | |||
214 | goto out; | 233 | goto out; |
215 | if ((err = verify_sec_ctx_len(attrs))) | 234 | if ((err = verify_sec_ctx_len(attrs))) |
216 | goto out; | 235 | goto out; |
236 | if ((err = verify_replay(p, attrs))) | ||
237 | goto out; | ||
217 | 238 | ||
218 | err = -EINVAL; | 239 | err = -EINVAL; |
219 | switch (p->mode) { | 240 | switch (p->mode) { |
@@ -234,7 +255,7 @@ out: | |||
234 | } | 255 | } |
235 | 256 | ||
236 | static int attach_one_algo(struct xfrm_algo **algpp, u8 *props, | 257 | static int attach_one_algo(struct xfrm_algo **algpp, u8 *props, |
237 | struct xfrm_algo_desc *(*get_byname)(char *, int), | 258 | struct xfrm_algo_desc *(*get_byname)(const char *, int), |
238 | struct nlattr *rta) | 259 | struct nlattr *rta) |
239 | { | 260 | { |
240 | struct xfrm_algo *p, *ualg; | 261 | struct xfrm_algo *p, *ualg; |
@@ -345,6 +366,50 @@ static int attach_aead(struct xfrm_algo_aead **algpp, u8 *props, | |||
345 | return 0; | 366 | return 0; |
346 | } | 367 | } |
347 | 368 | ||
369 | static inline int xfrm_replay_verify_len(struct xfrm_replay_state_esn *replay_esn, | ||
370 | struct nlattr *rp) | ||
371 | { | ||
372 | struct xfrm_replay_state_esn *up; | ||
373 | |||
374 | if (!replay_esn || !rp) | ||
375 | return 0; | ||
376 | |||
377 | up = nla_data(rp); | ||
378 | |||
379 | if (xfrm_replay_state_esn_len(replay_esn) != | ||
380 | xfrm_replay_state_esn_len(up)) | ||
381 | return -EINVAL; | ||
382 | |||
383 | return 0; | ||
384 | } | ||
385 | |||
386 | static int xfrm_alloc_replay_state_esn(struct xfrm_replay_state_esn **replay_esn, | ||
387 | struct xfrm_replay_state_esn **preplay_esn, | ||
388 | struct nlattr *rta) | ||
389 | { | ||
390 | struct xfrm_replay_state_esn *p, *pp, *up; | ||
391 | |||
392 | if (!rta) | ||
393 | return 0; | ||
394 | |||
395 | up = nla_data(rta); | ||
396 | |||
397 | p = kmemdup(up, xfrm_replay_state_esn_len(up), GFP_KERNEL); | ||
398 | if (!p) | ||
399 | return -ENOMEM; | ||
400 | |||
401 | pp = kmemdup(up, xfrm_replay_state_esn_len(up), GFP_KERNEL); | ||
402 | if (!pp) { | ||
403 | kfree(p); | ||
404 | return -ENOMEM; | ||
405 | } | ||
406 | |||
407 | *replay_esn = p; | ||
408 | *preplay_esn = pp; | ||
409 | |||
410 | return 0; | ||
411 | } | ||
412 | |||
348 | static inline int xfrm_user_sec_ctx_size(struct xfrm_sec_ctx *xfrm_ctx) | 413 | static inline int xfrm_user_sec_ctx_size(struct xfrm_sec_ctx *xfrm_ctx) |
349 | { | 414 | { |
350 | int len = 0; | 415 | int len = 0; |
@@ -380,10 +445,20 @@ static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info * | |||
380 | static void xfrm_update_ae_params(struct xfrm_state *x, struct nlattr **attrs) | 445 | static void xfrm_update_ae_params(struct xfrm_state *x, struct nlattr **attrs) |
381 | { | 446 | { |
382 | struct nlattr *rp = attrs[XFRMA_REPLAY_VAL]; | 447 | struct nlattr *rp = attrs[XFRMA_REPLAY_VAL]; |
448 | struct nlattr *re = attrs[XFRMA_REPLAY_ESN_VAL]; | ||
383 | struct nlattr *lt = attrs[XFRMA_LTIME_VAL]; | 449 | struct nlattr *lt = attrs[XFRMA_LTIME_VAL]; |
384 | struct nlattr *et = attrs[XFRMA_ETIMER_THRESH]; | 450 | struct nlattr *et = attrs[XFRMA_ETIMER_THRESH]; |
385 | struct nlattr *rt = attrs[XFRMA_REPLAY_THRESH]; | 451 | struct nlattr *rt = attrs[XFRMA_REPLAY_THRESH]; |
386 | 452 | ||
453 | if (re) { | ||
454 | struct xfrm_replay_state_esn *replay_esn; | ||
455 | replay_esn = nla_data(re); | ||
456 | memcpy(x->replay_esn, replay_esn, | ||
457 | xfrm_replay_state_esn_len(replay_esn)); | ||
458 | memcpy(x->preplay_esn, replay_esn, | ||
459 | xfrm_replay_state_esn_len(replay_esn)); | ||
460 | } | ||
461 | |||
387 | if (rp) { | 462 | if (rp) { |
388 | struct xfrm_replay_state *replay; | 463 | struct xfrm_replay_state *replay; |
389 | replay = nla_data(rp); | 464 | replay = nla_data(rp); |
@@ -459,7 +534,7 @@ static struct xfrm_state *xfrm_state_construct(struct net *net, | |||
459 | 534 | ||
460 | xfrm_mark_get(attrs, &x->mark); | 535 | xfrm_mark_get(attrs, &x->mark); |
461 | 536 | ||
462 | err = xfrm_init_state(x); | 537 | err = __xfrm_init_state(x, false); |
463 | if (err) | 538 | if (err) |
464 | goto error; | 539 | goto error; |
465 | 540 | ||
@@ -467,16 +542,19 @@ static struct xfrm_state *xfrm_state_construct(struct net *net, | |||
467 | security_xfrm_state_alloc(x, nla_data(attrs[XFRMA_SEC_CTX]))) | 542 | security_xfrm_state_alloc(x, nla_data(attrs[XFRMA_SEC_CTX]))) |
468 | goto error; | 543 | goto error; |
469 | 544 | ||
545 | if ((err = xfrm_alloc_replay_state_esn(&x->replay_esn, &x->preplay_esn, | ||
546 | attrs[XFRMA_REPLAY_ESN_VAL]))) | ||
547 | goto error; | ||
548 | |||
470 | x->km.seq = p->seq; | 549 | x->km.seq = p->seq; |
471 | x->replay_maxdiff = net->xfrm.sysctl_aevent_rseqth; | 550 | x->replay_maxdiff = net->xfrm.sysctl_aevent_rseqth; |
472 | /* sysctl_xfrm_aevent_etime is in 100ms units */ | 551 | /* sysctl_xfrm_aevent_etime is in 100ms units */ |
473 | x->replay_maxage = (net->xfrm.sysctl_aevent_etime*HZ)/XFRM_AE_ETH_M; | 552 | x->replay_maxage = (net->xfrm.sysctl_aevent_etime*HZ)/XFRM_AE_ETH_M; |
474 | x->preplay.bitmap = 0; | ||
475 | x->preplay.seq = x->replay.seq+x->replay_maxdiff; | ||
476 | x->preplay.oseq = x->replay.oseq +x->replay_maxdiff; | ||
477 | 553 | ||
478 | /* override default values from above */ | 554 | if ((err = xfrm_init_replay(x))) |
555 | goto error; | ||
479 | 556 | ||
557 | /* override default values from above */ | ||
480 | xfrm_update_ae_params(x, attrs); | 558 | xfrm_update_ae_params(x, attrs); |
481 | 559 | ||
482 | return x; | 560 | return x; |
@@ -497,9 +575,9 @@ static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
497 | struct xfrm_state *x; | 575 | struct xfrm_state *x; |
498 | int err; | 576 | int err; |
499 | struct km_event c; | 577 | struct km_event c; |
500 | uid_t loginuid = NETLINK_CB(skb).loginuid; | 578 | uid_t loginuid = audit_get_loginuid(current); |
501 | u32 sessionid = NETLINK_CB(skb).sessionid; | 579 | u32 sessionid = audit_get_sessionid(current); |
502 | u32 sid = NETLINK_CB(skb).sid; | 580 | u32 sid; |
503 | 581 | ||
504 | err = verify_newsa_info(p, attrs); | 582 | err = verify_newsa_info(p, attrs); |
505 | if (err) | 583 | if (err) |
@@ -515,6 +593,7 @@ static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
515 | else | 593 | else |
516 | err = xfrm_state_update(x); | 594 | err = xfrm_state_update(x); |
517 | 595 | ||
596 | security_task_getsecid(current, &sid); | ||
518 | xfrm_audit_state_add(x, err ? 0 : 1, loginuid, sessionid, sid); | 597 | xfrm_audit_state_add(x, err ? 0 : 1, loginuid, sessionid, sid); |
519 | 598 | ||
520 | if (err < 0) { | 599 | if (err < 0) { |
@@ -575,9 +654,9 @@ static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
575 | int err = -ESRCH; | 654 | int err = -ESRCH; |
576 | struct km_event c; | 655 | struct km_event c; |
577 | struct xfrm_usersa_id *p = nlmsg_data(nlh); | 656 | struct xfrm_usersa_id *p = nlmsg_data(nlh); |
578 | uid_t loginuid = NETLINK_CB(skb).loginuid; | 657 | uid_t loginuid = audit_get_loginuid(current); |
579 | u32 sessionid = NETLINK_CB(skb).sessionid; | 658 | u32 sessionid = audit_get_sessionid(current); |
580 | u32 sid = NETLINK_CB(skb).sid; | 659 | u32 sid; |
581 | 660 | ||
582 | x = xfrm_user_state_lookup(net, p, attrs, &err); | 661 | x = xfrm_user_state_lookup(net, p, attrs, &err); |
583 | if (x == NULL) | 662 | if (x == NULL) |
@@ -602,6 +681,7 @@ static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
602 | km_state_notify(x, &c); | 681 | km_state_notify(x, &c); |
603 | 682 | ||
604 | out: | 683 | out: |
684 | security_task_getsecid(current, &sid); | ||
605 | xfrm_audit_state_delete(x, err ? 0 : 1, loginuid, sessionid, sid); | 685 | xfrm_audit_state_delete(x, err ? 0 : 1, loginuid, sessionid, sid); |
606 | xfrm_state_put(x); | 686 | xfrm_state_put(x); |
607 | return err; | 687 | return err; |
@@ -705,6 +785,10 @@ static int copy_to_user_state_extra(struct xfrm_state *x, | |||
705 | if (xfrm_mark_put(skb, &x->mark)) | 785 | if (xfrm_mark_put(skb, &x->mark)) |
706 | goto nla_put_failure; | 786 | goto nla_put_failure; |
707 | 787 | ||
788 | if (x->replay_esn) | ||
789 | NLA_PUT(skb, XFRMA_REPLAY_ESN_VAL, | ||
790 | xfrm_replay_state_esn_len(x->replay_esn), x->replay_esn); | ||
791 | |||
708 | if (x->security && copy_sec_ctx(x->security, skb) < 0) | 792 | if (x->security && copy_sec_ctx(x->security, skb) < 0) |
709 | goto nla_put_failure; | 793 | goto nla_put_failure; |
710 | 794 | ||
@@ -813,7 +897,7 @@ static int build_spdinfo(struct sk_buff *skb, struct net *net, | |||
813 | u32 *f; | 897 | u32 *f; |
814 | 898 | ||
815 | nlh = nlmsg_put(skb, pid, seq, XFRM_MSG_NEWSPDINFO, sizeof(u32), 0); | 899 | nlh = nlmsg_put(skb, pid, seq, XFRM_MSG_NEWSPDINFO, sizeof(u32), 0); |
816 | if (nlh == NULL) /* shouldnt really happen ... */ | 900 | if (nlh == NULL) /* shouldn't really happen ... */ |
817 | return -EMSGSIZE; | 901 | return -EMSGSIZE; |
818 | 902 | ||
819 | f = nlmsg_data(nlh); | 903 | f = nlmsg_data(nlh); |
@@ -873,7 +957,7 @@ static int build_sadinfo(struct sk_buff *skb, struct net *net, | |||
873 | u32 *f; | 957 | u32 *f; |
874 | 958 | ||
875 | nlh = nlmsg_put(skb, pid, seq, XFRM_MSG_NEWSADINFO, sizeof(u32), 0); | 959 | nlh = nlmsg_put(skb, pid, seq, XFRM_MSG_NEWSADINFO, sizeof(u32), 0); |
876 | if (nlh == NULL) /* shouldnt really happen ... */ | 960 | if (nlh == NULL) /* shouldn't really happen ... */ |
877 | return -EMSGSIZE; | 961 | return -EMSGSIZE; |
878 | 962 | ||
879 | f = nlmsg_data(nlh); | 963 | f = nlmsg_data(nlh); |
@@ -1265,9 +1349,9 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1265 | struct km_event c; | 1349 | struct km_event c; |
1266 | int err; | 1350 | int err; |
1267 | int excl; | 1351 | int excl; |
1268 | uid_t loginuid = NETLINK_CB(skb).loginuid; | 1352 | uid_t loginuid = audit_get_loginuid(current); |
1269 | u32 sessionid = NETLINK_CB(skb).sessionid; | 1353 | u32 sessionid = audit_get_sessionid(current); |
1270 | u32 sid = NETLINK_CB(skb).sid; | 1354 | u32 sid; |
1271 | 1355 | ||
1272 | err = verify_newpolicy_info(p); | 1356 | err = verify_newpolicy_info(p); |
1273 | if (err) | 1357 | if (err) |
@@ -1280,12 +1364,13 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1280 | if (!xp) | 1364 | if (!xp) |
1281 | return err; | 1365 | return err; |
1282 | 1366 | ||
1283 | /* shouldnt excl be based on nlh flags?? | 1367 | /* shouldn't excl be based on nlh flags?? |
1284 | * Aha! this is anti-netlink really i.e more pfkey derived | 1368 | * Aha! this is anti-netlink really i.e more pfkey derived |
1285 | * in netlink excl is a flag and you wouldnt need | 1369 | * in netlink excl is a flag and you wouldnt need |
1286 | * a type XFRM_MSG_UPDPOLICY - JHS */ | 1370 | * a type XFRM_MSG_UPDPOLICY - JHS */ |
1287 | excl = nlh->nlmsg_type == XFRM_MSG_NEWPOLICY; | 1371 | excl = nlh->nlmsg_type == XFRM_MSG_NEWPOLICY; |
1288 | err = xfrm_policy_insert(p->dir, xp, excl); | 1372 | err = xfrm_policy_insert(p->dir, xp, excl); |
1373 | security_task_getsecid(current, &sid); | ||
1289 | xfrm_audit_policy_add(xp, err ? 0 : 1, loginuid, sessionid, sid); | 1374 | xfrm_audit_policy_add(xp, err ? 0 : 1, loginuid, sessionid, sid); |
1290 | 1375 | ||
1291 | if (err) { | 1376 | if (err) { |
@@ -1522,10 +1607,11 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1522 | NETLINK_CB(skb).pid); | 1607 | NETLINK_CB(skb).pid); |
1523 | } | 1608 | } |
1524 | } else { | 1609 | } else { |
1525 | uid_t loginuid = NETLINK_CB(skb).loginuid; | 1610 | uid_t loginuid = audit_get_loginuid(current); |
1526 | u32 sessionid = NETLINK_CB(skb).sessionid; | 1611 | u32 sessionid = audit_get_sessionid(current); |
1527 | u32 sid = NETLINK_CB(skb).sid; | 1612 | u32 sid; |
1528 | 1613 | ||
1614 | security_task_getsecid(current, &sid); | ||
1529 | xfrm_audit_policy_delete(xp, err ? 0 : 1, loginuid, sessionid, | 1615 | xfrm_audit_policy_delete(xp, err ? 0 : 1, loginuid, sessionid, |
1530 | sid); | 1616 | sid); |
1531 | 1617 | ||
@@ -1553,9 +1639,9 @@ static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1553 | struct xfrm_audit audit_info; | 1639 | struct xfrm_audit audit_info; |
1554 | int err; | 1640 | int err; |
1555 | 1641 | ||
1556 | audit_info.loginuid = NETLINK_CB(skb).loginuid; | 1642 | audit_info.loginuid = audit_get_loginuid(current); |
1557 | audit_info.sessionid = NETLINK_CB(skb).sessionid; | 1643 | audit_info.sessionid = audit_get_sessionid(current); |
1558 | audit_info.secid = NETLINK_CB(skb).sid; | 1644 | security_task_getsecid(current, &audit_info.secid); |
1559 | err = xfrm_state_flush(net, p->proto, &audit_info); | 1645 | err = xfrm_state_flush(net, p->proto, &audit_info); |
1560 | if (err) { | 1646 | if (err) { |
1561 | if (err == -ESRCH) /* empty table */ | 1647 | if (err == -ESRCH) /* empty table */ |
@@ -1572,17 +1658,21 @@ static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1572 | return 0; | 1658 | return 0; |
1573 | } | 1659 | } |
1574 | 1660 | ||
1575 | static inline size_t xfrm_aevent_msgsize(void) | 1661 | static inline size_t xfrm_aevent_msgsize(struct xfrm_state *x) |
1576 | { | 1662 | { |
1663 | size_t replay_size = x->replay_esn ? | ||
1664 | xfrm_replay_state_esn_len(x->replay_esn) : | ||
1665 | sizeof(struct xfrm_replay_state); | ||
1666 | |||
1577 | return NLMSG_ALIGN(sizeof(struct xfrm_aevent_id)) | 1667 | return NLMSG_ALIGN(sizeof(struct xfrm_aevent_id)) |
1578 | + nla_total_size(sizeof(struct xfrm_replay_state)) | 1668 | + nla_total_size(replay_size) |
1579 | + nla_total_size(sizeof(struct xfrm_lifetime_cur)) | 1669 | + nla_total_size(sizeof(struct xfrm_lifetime_cur)) |
1580 | + nla_total_size(sizeof(struct xfrm_mark)) | 1670 | + nla_total_size(sizeof(struct xfrm_mark)) |
1581 | + nla_total_size(4) /* XFRM_AE_RTHR */ | 1671 | + nla_total_size(4) /* XFRM_AE_RTHR */ |
1582 | + nla_total_size(4); /* XFRM_AE_ETHR */ | 1672 | + nla_total_size(4); /* XFRM_AE_ETHR */ |
1583 | } | 1673 | } |
1584 | 1674 | ||
1585 | static int build_aevent(struct sk_buff *skb, struct xfrm_state *x, struct km_event *c) | 1675 | static int build_aevent(struct sk_buff *skb, struct xfrm_state *x, const struct km_event *c) |
1586 | { | 1676 | { |
1587 | struct xfrm_aevent_id *id; | 1677 | struct xfrm_aevent_id *id; |
1588 | struct nlmsghdr *nlh; | 1678 | struct nlmsghdr *nlh; |
@@ -1600,7 +1690,13 @@ static int build_aevent(struct sk_buff *skb, struct xfrm_state *x, struct km_eve | |||
1600 | id->reqid = x->props.reqid; | 1690 | id->reqid = x->props.reqid; |
1601 | id->flags = c->data.aevent; | 1691 | id->flags = c->data.aevent; |
1602 | 1692 | ||
1603 | NLA_PUT(skb, XFRMA_REPLAY_VAL, sizeof(x->replay), &x->replay); | 1693 | if (x->replay_esn) |
1694 | NLA_PUT(skb, XFRMA_REPLAY_ESN_VAL, | ||
1695 | xfrm_replay_state_esn_len(x->replay_esn), | ||
1696 | x->replay_esn); | ||
1697 | else | ||
1698 | NLA_PUT(skb, XFRMA_REPLAY_VAL, sizeof(x->replay), &x->replay); | ||
1699 | |||
1604 | NLA_PUT(skb, XFRMA_LTIME_VAL, sizeof(x->curlft), &x->curlft); | 1700 | NLA_PUT(skb, XFRMA_LTIME_VAL, sizeof(x->curlft), &x->curlft); |
1605 | 1701 | ||
1606 | if (id->flags & XFRM_AE_RTHR) | 1702 | if (id->flags & XFRM_AE_RTHR) |
@@ -1633,16 +1729,16 @@ static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1633 | struct xfrm_aevent_id *p = nlmsg_data(nlh); | 1729 | struct xfrm_aevent_id *p = nlmsg_data(nlh); |
1634 | struct xfrm_usersa_id *id = &p->sa_id; | 1730 | struct xfrm_usersa_id *id = &p->sa_id; |
1635 | 1731 | ||
1636 | r_skb = nlmsg_new(xfrm_aevent_msgsize(), GFP_ATOMIC); | ||
1637 | if (r_skb == NULL) | ||
1638 | return -ENOMEM; | ||
1639 | |||
1640 | mark = xfrm_mark_get(attrs, &m); | 1732 | mark = xfrm_mark_get(attrs, &m); |
1641 | 1733 | ||
1642 | x = xfrm_state_lookup(net, mark, &id->daddr, id->spi, id->proto, id->family); | 1734 | x = xfrm_state_lookup(net, mark, &id->daddr, id->spi, id->proto, id->family); |
1643 | if (x == NULL) { | 1735 | if (x == NULL) |
1644 | kfree_skb(r_skb); | ||
1645 | return -ESRCH; | 1736 | return -ESRCH; |
1737 | |||
1738 | r_skb = nlmsg_new(xfrm_aevent_msgsize(x), GFP_ATOMIC); | ||
1739 | if (r_skb == NULL) { | ||
1740 | xfrm_state_put(x); | ||
1741 | return -ENOMEM; | ||
1646 | } | 1742 | } |
1647 | 1743 | ||
1648 | /* | 1744 | /* |
@@ -1674,9 +1770,10 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1674 | struct xfrm_mark m; | 1770 | struct xfrm_mark m; |
1675 | struct xfrm_aevent_id *p = nlmsg_data(nlh); | 1771 | struct xfrm_aevent_id *p = nlmsg_data(nlh); |
1676 | struct nlattr *rp = attrs[XFRMA_REPLAY_VAL]; | 1772 | struct nlattr *rp = attrs[XFRMA_REPLAY_VAL]; |
1773 | struct nlattr *re = attrs[XFRMA_REPLAY_ESN_VAL]; | ||
1677 | struct nlattr *lt = attrs[XFRMA_LTIME_VAL]; | 1774 | struct nlattr *lt = attrs[XFRMA_LTIME_VAL]; |
1678 | 1775 | ||
1679 | if (!lt && !rp) | 1776 | if (!lt && !rp && !re) |
1680 | return err; | 1777 | return err; |
1681 | 1778 | ||
1682 | /* pedantic mode - thou shalt sayeth replaceth */ | 1779 | /* pedantic mode - thou shalt sayeth replaceth */ |
@@ -1692,6 +1789,10 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1692 | if (x->km.state != XFRM_STATE_VALID) | 1789 | if (x->km.state != XFRM_STATE_VALID) |
1693 | goto out; | 1790 | goto out; |
1694 | 1791 | ||
1792 | err = xfrm_replay_verify_len(x->replay_esn, rp); | ||
1793 | if (err) | ||
1794 | goto out; | ||
1795 | |||
1695 | spin_lock_bh(&x->lock); | 1796 | spin_lock_bh(&x->lock); |
1696 | xfrm_update_ae_params(x, attrs); | 1797 | xfrm_update_ae_params(x, attrs); |
1697 | spin_unlock_bh(&x->lock); | 1798 | spin_unlock_bh(&x->lock); |
@@ -1720,9 +1821,9 @@ static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1720 | if (err) | 1821 | if (err) |
1721 | return err; | 1822 | return err; |
1722 | 1823 | ||
1723 | audit_info.loginuid = NETLINK_CB(skb).loginuid; | 1824 | audit_info.loginuid = audit_get_loginuid(current); |
1724 | audit_info.sessionid = NETLINK_CB(skb).sessionid; | 1825 | audit_info.sessionid = audit_get_sessionid(current); |
1725 | audit_info.secid = NETLINK_CB(skb).sid; | 1826 | security_task_getsecid(current, &audit_info.secid); |
1726 | err = xfrm_policy_flush(net, type, &audit_info); | 1827 | err = xfrm_policy_flush(net, type, &audit_info); |
1727 | if (err) { | 1828 | if (err) { |
1728 | if (err == -ESRCH) /* empty table */ | 1829 | if (err == -ESRCH) /* empty table */ |
@@ -1789,9 +1890,11 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1789 | 1890 | ||
1790 | err = 0; | 1891 | err = 0; |
1791 | if (up->hard) { | 1892 | if (up->hard) { |
1792 | uid_t loginuid = NETLINK_CB(skb).loginuid; | 1893 | uid_t loginuid = audit_get_loginuid(current); |
1793 | uid_t sessionid = NETLINK_CB(skb).sessionid; | 1894 | u32 sessionid = audit_get_sessionid(current); |
1794 | u32 sid = NETLINK_CB(skb).sid; | 1895 | u32 sid; |
1896 | |||
1897 | security_task_getsecid(current, &sid); | ||
1795 | xfrm_policy_delete(xp, p->dir); | 1898 | xfrm_policy_delete(xp, p->dir); |
1796 | xfrm_audit_policy_delete(xp, 1, loginuid, sessionid, sid); | 1899 | xfrm_audit_policy_delete(xp, 1, loginuid, sessionid, sid); |
1797 | 1900 | ||
@@ -1830,9 +1933,11 @@ static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1830 | km_state_expired(x, ue->hard, current->pid); | 1933 | km_state_expired(x, ue->hard, current->pid); |
1831 | 1934 | ||
1832 | if (ue->hard) { | 1935 | if (ue->hard) { |
1833 | uid_t loginuid = NETLINK_CB(skb).loginuid; | 1936 | uid_t loginuid = audit_get_loginuid(current); |
1834 | uid_t sessionid = NETLINK_CB(skb).sessionid; | 1937 | u32 sessionid = audit_get_sessionid(current); |
1835 | u32 sid = NETLINK_CB(skb).sid; | 1938 | u32 sid; |
1939 | |||
1940 | security_task_getsecid(current, &sid); | ||
1836 | __xfrm_state_delete(x); | 1941 | __xfrm_state_delete(x); |
1837 | xfrm_audit_state_delete(x, 1, loginuid, sessionid, sid); | 1942 | xfrm_audit_state_delete(x, 1, loginuid, sessionid, sid); |
1838 | } | 1943 | } |
@@ -1986,7 +2091,7 @@ static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1986 | #endif | 2091 | #endif |
1987 | 2092 | ||
1988 | #ifdef CONFIG_XFRM_MIGRATE | 2093 | #ifdef CONFIG_XFRM_MIGRATE |
1989 | static int copy_to_user_migrate(struct xfrm_migrate *m, struct sk_buff *skb) | 2094 | static int copy_to_user_migrate(const struct xfrm_migrate *m, struct sk_buff *skb) |
1990 | { | 2095 | { |
1991 | struct xfrm_user_migrate um; | 2096 | struct xfrm_user_migrate um; |
1992 | 2097 | ||
@@ -2004,7 +2109,7 @@ static int copy_to_user_migrate(struct xfrm_migrate *m, struct sk_buff *skb) | |||
2004 | return nla_put(skb, XFRMA_MIGRATE, sizeof(um), &um); | 2109 | return nla_put(skb, XFRMA_MIGRATE, sizeof(um), &um); |
2005 | } | 2110 | } |
2006 | 2111 | ||
2007 | static int copy_to_user_kmaddress(struct xfrm_kmaddress *k, struct sk_buff *skb) | 2112 | static int copy_to_user_kmaddress(const struct xfrm_kmaddress *k, struct sk_buff *skb) |
2008 | { | 2113 | { |
2009 | struct xfrm_user_kmaddress uk; | 2114 | struct xfrm_user_kmaddress uk; |
2010 | 2115 | ||
@@ -2025,11 +2130,11 @@ static inline size_t xfrm_migrate_msgsize(int num_migrate, int with_kma) | |||
2025 | + userpolicy_type_attrsize(); | 2130 | + userpolicy_type_attrsize(); |
2026 | } | 2131 | } |
2027 | 2132 | ||
2028 | static int build_migrate(struct sk_buff *skb, struct xfrm_migrate *m, | 2133 | static int build_migrate(struct sk_buff *skb, const struct xfrm_migrate *m, |
2029 | int num_migrate, struct xfrm_kmaddress *k, | 2134 | int num_migrate, const struct xfrm_kmaddress *k, |
2030 | struct xfrm_selector *sel, u8 dir, u8 type) | 2135 | const struct xfrm_selector *sel, u8 dir, u8 type) |
2031 | { | 2136 | { |
2032 | struct xfrm_migrate *mp; | 2137 | const struct xfrm_migrate *mp; |
2033 | struct xfrm_userpolicy_id *pol_id; | 2138 | struct xfrm_userpolicy_id *pol_id; |
2034 | struct nlmsghdr *nlh; | 2139 | struct nlmsghdr *nlh; |
2035 | int i; | 2140 | int i; |
@@ -2061,9 +2166,9 @@ nlmsg_failure: | |||
2061 | return -EMSGSIZE; | 2166 | return -EMSGSIZE; |
2062 | } | 2167 | } |
2063 | 2168 | ||
2064 | static int xfrm_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, | 2169 | static int xfrm_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, |
2065 | struct xfrm_migrate *m, int num_migrate, | 2170 | const struct xfrm_migrate *m, int num_migrate, |
2066 | struct xfrm_kmaddress *k) | 2171 | const struct xfrm_kmaddress *k) |
2067 | { | 2172 | { |
2068 | struct net *net = &init_net; | 2173 | struct net *net = &init_net; |
2069 | struct sk_buff *skb; | 2174 | struct sk_buff *skb; |
@@ -2079,9 +2184,9 @@ static int xfrm_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, | |||
2079 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_MIGRATE, GFP_ATOMIC); | 2184 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_MIGRATE, GFP_ATOMIC); |
2080 | } | 2185 | } |
2081 | #else | 2186 | #else |
2082 | static int xfrm_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, | 2187 | static int xfrm_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, |
2083 | struct xfrm_migrate *m, int num_migrate, | 2188 | const struct xfrm_migrate *m, int num_migrate, |
2084 | struct xfrm_kmaddress *k) | 2189 | const struct xfrm_kmaddress *k) |
2085 | { | 2190 | { |
2086 | return -ENOPROTOOPT; | 2191 | return -ENOPROTOOPT; |
2087 | } | 2192 | } |
@@ -2137,6 +2242,7 @@ static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = { | |||
2137 | [XFRMA_KMADDRESS] = { .len = sizeof(struct xfrm_user_kmaddress) }, | 2242 | [XFRMA_KMADDRESS] = { .len = sizeof(struct xfrm_user_kmaddress) }, |
2138 | [XFRMA_MARK] = { .len = sizeof(struct xfrm_mark) }, | 2243 | [XFRMA_MARK] = { .len = sizeof(struct xfrm_mark) }, |
2139 | [XFRMA_TFCPAD] = { .type = NLA_U32 }, | 2244 | [XFRMA_TFCPAD] = { .type = NLA_U32 }, |
2245 | [XFRMA_REPLAY_ESN_VAL] = { .len = sizeof(struct xfrm_replay_state_esn) }, | ||
2140 | }; | 2246 | }; |
2141 | 2247 | ||
2142 | static struct xfrm_link { | 2248 | static struct xfrm_link { |
@@ -2220,7 +2326,7 @@ static inline size_t xfrm_expire_msgsize(void) | |||
2220 | + nla_total_size(sizeof(struct xfrm_mark)); | 2326 | + nla_total_size(sizeof(struct xfrm_mark)); |
2221 | } | 2327 | } |
2222 | 2328 | ||
2223 | static int build_expire(struct sk_buff *skb, struct xfrm_state *x, struct km_event *c) | 2329 | static int build_expire(struct sk_buff *skb, struct xfrm_state *x, const struct km_event *c) |
2224 | { | 2330 | { |
2225 | struct xfrm_user_expire *ue; | 2331 | struct xfrm_user_expire *ue; |
2226 | struct nlmsghdr *nlh; | 2332 | struct nlmsghdr *nlh; |
@@ -2242,7 +2348,7 @@ nla_put_failure: | |||
2242 | return -EMSGSIZE; | 2348 | return -EMSGSIZE; |
2243 | } | 2349 | } |
2244 | 2350 | ||
2245 | static int xfrm_exp_state_notify(struct xfrm_state *x, struct km_event *c) | 2351 | static int xfrm_exp_state_notify(struct xfrm_state *x, const struct km_event *c) |
2246 | { | 2352 | { |
2247 | struct net *net = xs_net(x); | 2353 | struct net *net = xs_net(x); |
2248 | struct sk_buff *skb; | 2354 | struct sk_buff *skb; |
@@ -2259,12 +2365,12 @@ static int xfrm_exp_state_notify(struct xfrm_state *x, struct km_event *c) | |||
2259 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC); | 2365 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC); |
2260 | } | 2366 | } |
2261 | 2367 | ||
2262 | static int xfrm_aevent_state_notify(struct xfrm_state *x, struct km_event *c) | 2368 | static int xfrm_aevent_state_notify(struct xfrm_state *x, const struct km_event *c) |
2263 | { | 2369 | { |
2264 | struct net *net = xs_net(x); | 2370 | struct net *net = xs_net(x); |
2265 | struct sk_buff *skb; | 2371 | struct sk_buff *skb; |
2266 | 2372 | ||
2267 | skb = nlmsg_new(xfrm_aevent_msgsize(), GFP_ATOMIC); | 2373 | skb = nlmsg_new(xfrm_aevent_msgsize(x), GFP_ATOMIC); |
2268 | if (skb == NULL) | 2374 | if (skb == NULL) |
2269 | return -ENOMEM; | 2375 | return -ENOMEM; |
2270 | 2376 | ||
@@ -2274,7 +2380,7 @@ static int xfrm_aevent_state_notify(struct xfrm_state *x, struct km_event *c) | |||
2274 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_AEVENTS, GFP_ATOMIC); | 2380 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_AEVENTS, GFP_ATOMIC); |
2275 | } | 2381 | } |
2276 | 2382 | ||
2277 | static int xfrm_notify_sa_flush(struct km_event *c) | 2383 | static int xfrm_notify_sa_flush(const struct km_event *c) |
2278 | { | 2384 | { |
2279 | struct net *net = c->net; | 2385 | struct net *net = c->net; |
2280 | struct xfrm_usersa_flush *p; | 2386 | struct xfrm_usersa_flush *p; |
@@ -2318,6 +2424,8 @@ static inline size_t xfrm_sa_len(struct xfrm_state *x) | |||
2318 | l += nla_total_size(sizeof(*x->encap)); | 2424 | l += nla_total_size(sizeof(*x->encap)); |
2319 | if (x->tfcpad) | 2425 | if (x->tfcpad) |
2320 | l += nla_total_size(sizeof(x->tfcpad)); | 2426 | l += nla_total_size(sizeof(x->tfcpad)); |
2427 | if (x->replay_esn) | ||
2428 | l += nla_total_size(xfrm_replay_state_esn_len(x->replay_esn)); | ||
2321 | if (x->security) | 2429 | if (x->security) |
2322 | l += nla_total_size(sizeof(struct xfrm_user_sec_ctx) + | 2430 | l += nla_total_size(sizeof(struct xfrm_user_sec_ctx) + |
2323 | x->security->ctx_len); | 2431 | x->security->ctx_len); |
@@ -2330,7 +2438,7 @@ static inline size_t xfrm_sa_len(struct xfrm_state *x) | |||
2330 | return l; | 2438 | return l; |
2331 | } | 2439 | } |
2332 | 2440 | ||
2333 | static int xfrm_notify_sa(struct xfrm_state *x, struct km_event *c) | 2441 | static int xfrm_notify_sa(struct xfrm_state *x, const struct km_event *c) |
2334 | { | 2442 | { |
2335 | struct net *net = xs_net(x); | 2443 | struct net *net = xs_net(x); |
2336 | struct xfrm_usersa_info *p; | 2444 | struct xfrm_usersa_info *p; |
@@ -2387,7 +2495,7 @@ nla_put_failure: | |||
2387 | return -1; | 2495 | return -1; |
2388 | } | 2496 | } |
2389 | 2497 | ||
2390 | static int xfrm_send_state_notify(struct xfrm_state *x, struct km_event *c) | 2498 | static int xfrm_send_state_notify(struct xfrm_state *x, const struct km_event *c) |
2391 | { | 2499 | { |
2392 | 2500 | ||
2393 | switch (c->event) { | 2501 | switch (c->event) { |
@@ -2546,7 +2654,7 @@ static inline size_t xfrm_polexpire_msgsize(struct xfrm_policy *xp) | |||
2546 | } | 2654 | } |
2547 | 2655 | ||
2548 | static int build_polexpire(struct sk_buff *skb, struct xfrm_policy *xp, | 2656 | static int build_polexpire(struct sk_buff *skb, struct xfrm_policy *xp, |
2549 | int dir, struct km_event *c) | 2657 | int dir, const struct km_event *c) |
2550 | { | 2658 | { |
2551 | struct xfrm_user_polexpire *upe; | 2659 | struct xfrm_user_polexpire *upe; |
2552 | struct nlmsghdr *nlh; | 2660 | struct nlmsghdr *nlh; |
@@ -2576,7 +2684,7 @@ nlmsg_failure: | |||
2576 | return -EMSGSIZE; | 2684 | return -EMSGSIZE; |
2577 | } | 2685 | } |
2578 | 2686 | ||
2579 | static int xfrm_exp_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c) | 2687 | static int xfrm_exp_policy_notify(struct xfrm_policy *xp, int dir, const struct km_event *c) |
2580 | { | 2688 | { |
2581 | struct net *net = xp_net(xp); | 2689 | struct net *net = xp_net(xp); |
2582 | struct sk_buff *skb; | 2690 | struct sk_buff *skb; |
@@ -2591,7 +2699,7 @@ static int xfrm_exp_policy_notify(struct xfrm_policy *xp, int dir, struct km_eve | |||
2591 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC); | 2699 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC); |
2592 | } | 2700 | } |
2593 | 2701 | ||
2594 | static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *c) | 2702 | static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, const struct km_event *c) |
2595 | { | 2703 | { |
2596 | struct net *net = xp_net(xp); | 2704 | struct net *net = xp_net(xp); |
2597 | struct xfrm_userpolicy_info *p; | 2705 | struct xfrm_userpolicy_info *p; |
@@ -2656,7 +2764,7 @@ nlmsg_failure: | |||
2656 | return -1; | 2764 | return -1; |
2657 | } | 2765 | } |
2658 | 2766 | ||
2659 | static int xfrm_notify_policy_flush(struct km_event *c) | 2767 | static int xfrm_notify_policy_flush(const struct km_event *c) |
2660 | { | 2768 | { |
2661 | struct net *net = c->net; | 2769 | struct net *net = c->net; |
2662 | struct nlmsghdr *nlh; | 2770 | struct nlmsghdr *nlh; |
@@ -2681,7 +2789,7 @@ nlmsg_failure: | |||
2681 | return -1; | 2789 | return -1; |
2682 | } | 2790 | } |
2683 | 2791 | ||
2684 | static int xfrm_send_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c) | 2792 | static int xfrm_send_policy_notify(struct xfrm_policy *xp, int dir, const struct km_event *c) |
2685 | { | 2793 | { |
2686 | 2794 | ||
2687 | switch (c->event) { | 2795 | switch (c->event) { |