aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2017-10-24 07:17:38 -0400
committerDavid S. Miller <davem@davemloft.net>2017-10-24 07:17:47 -0400
commit864f5af3a3525f588391cd230cb8129ad758708e (patch)
treef282338a19a9337206e237577509c31af4cf3672
parentb71d21c274eff20a9db8158882b545b141b73ab8 (diff)
parent1137b5e2529a8f5ca8ee709288ecba3e68044df2 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec
Steffen Klassert says: ==================== pull request (net): ipsec 2017-10-24 1) Fix a memleak when we don't find a inner_mode during bundle creation. From David Miller. 2) Fix a xfrm policy dump crash. We may crash on error when dumping policies via netlink. Fix this by initializing the policy walk with the cb->start method. This fix is a serious stable candidate. From Herbert Xu. Please pull or let me know if there are problems. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/xfrm/xfrm_policy.c16
-rw-r--r--net/xfrm/xfrm_user.c25
2 files changed, 23 insertions, 18 deletions
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index f06253969972..2746b62a8944 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1573,6 +1573,14 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
1573 goto put_states; 1573 goto put_states;
1574 } 1574 }
1575 1575
1576 if (!dst_prev)
1577 dst0 = dst1;
1578 else
1579 /* Ref count is taken during xfrm_alloc_dst()
1580 * No need to do dst_clone() on dst1
1581 */
1582 dst_prev->child = dst1;
1583
1576 if (xfrm[i]->sel.family == AF_UNSPEC) { 1584 if (xfrm[i]->sel.family == AF_UNSPEC) {
1577 inner_mode = xfrm_ip2inner_mode(xfrm[i], 1585 inner_mode = xfrm_ip2inner_mode(xfrm[i],
1578 xfrm_af2proto(family)); 1586 xfrm_af2proto(family));
@@ -1584,14 +1592,6 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
1584 } else 1592 } else
1585 inner_mode = xfrm[i]->inner_mode; 1593 inner_mode = xfrm[i]->inner_mode;
1586 1594
1587 if (!dst_prev)
1588 dst0 = dst1;
1589 else
1590 /* Ref count is taken during xfrm_alloc_dst()
1591 * No need to do dst_clone() on dst1
1592 */
1593 dst_prev->child = dst1;
1594
1595 xdst->route = dst; 1595 xdst->route = dst;
1596 dst_copy_metrics(dst1, dst); 1596 dst_copy_metrics(dst1, dst);
1597 1597
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index b997f1395357..e44a0fed48dd 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -1693,32 +1693,34 @@ static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr
1693 1693
1694static int xfrm_dump_policy_done(struct netlink_callback *cb) 1694static int xfrm_dump_policy_done(struct netlink_callback *cb)
1695{ 1695{
1696 struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *) &cb->args[1]; 1696 struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *)cb->args;
1697 struct net *net = sock_net(cb->skb->sk); 1697 struct net *net = sock_net(cb->skb->sk);
1698 1698
1699 xfrm_policy_walk_done(walk, net); 1699 xfrm_policy_walk_done(walk, net);
1700 return 0; 1700 return 0;
1701} 1701}
1702 1702
1703static int xfrm_dump_policy_start(struct netlink_callback *cb)
1704{
1705 struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *)cb->args;
1706
1707 BUILD_BUG_ON(sizeof(*walk) > sizeof(cb->args));
1708
1709 xfrm_policy_walk_init(walk, XFRM_POLICY_TYPE_ANY);
1710 return 0;
1711}
1712
1703static int xfrm_dump_policy(struct sk_buff *skb, struct netlink_callback *cb) 1713static int xfrm_dump_policy(struct sk_buff *skb, struct netlink_callback *cb)
1704{ 1714{
1705 struct net *net = sock_net(skb->sk); 1715 struct net *net = sock_net(skb->sk);
1706 struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *) &cb->args[1]; 1716 struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *)cb->args;
1707 struct xfrm_dump_info info; 1717 struct xfrm_dump_info info;
1708 1718
1709 BUILD_BUG_ON(sizeof(struct xfrm_policy_walk) >
1710 sizeof(cb->args) - sizeof(cb->args[0]));
1711
1712 info.in_skb = cb->skb; 1719 info.in_skb = cb->skb;
1713 info.out_skb = skb; 1720 info.out_skb = skb;
1714 info.nlmsg_seq = cb->nlh->nlmsg_seq; 1721 info.nlmsg_seq = cb->nlh->nlmsg_seq;
1715 info.nlmsg_flags = NLM_F_MULTI; 1722 info.nlmsg_flags = NLM_F_MULTI;
1716 1723
1717 if (!cb->args[0]) {
1718 cb->args[0] = 1;
1719 xfrm_policy_walk_init(walk, XFRM_POLICY_TYPE_ANY);
1720 }
1721
1722 (void) xfrm_policy_walk(net, walk, dump_one_policy, &info); 1724 (void) xfrm_policy_walk(net, walk, dump_one_policy, &info);
1723 1725
1724 return skb->len; 1726 return skb->len;
@@ -2474,6 +2476,7 @@ static const struct nla_policy xfrma_spd_policy[XFRMA_SPD_MAX+1] = {
2474 2476
2475static const struct xfrm_link { 2477static const struct xfrm_link {
2476 int (*doit)(struct sk_buff *, struct nlmsghdr *, struct nlattr **); 2478 int (*doit)(struct sk_buff *, struct nlmsghdr *, struct nlattr **);
2479 int (*start)(struct netlink_callback *);
2477 int (*dump)(struct sk_buff *, struct netlink_callback *); 2480 int (*dump)(struct sk_buff *, struct netlink_callback *);
2478 int (*done)(struct netlink_callback *); 2481 int (*done)(struct netlink_callback *);
2479 const struct nla_policy *nla_pol; 2482 const struct nla_policy *nla_pol;
@@ -2487,6 +2490,7 @@ static const struct xfrm_link {
2487 [XFRM_MSG_NEWPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_add_policy }, 2490 [XFRM_MSG_NEWPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_add_policy },
2488 [XFRM_MSG_DELPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_get_policy }, 2491 [XFRM_MSG_DELPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_get_policy },
2489 [XFRM_MSG_GETPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_get_policy, 2492 [XFRM_MSG_GETPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_get_policy,
2493 .start = xfrm_dump_policy_start,
2490 .dump = xfrm_dump_policy, 2494 .dump = xfrm_dump_policy,
2491 .done = xfrm_dump_policy_done }, 2495 .done = xfrm_dump_policy_done },
2492 [XFRM_MSG_ALLOCSPI - XFRM_MSG_BASE] = { .doit = xfrm_alloc_userspi }, 2496 [XFRM_MSG_ALLOCSPI - XFRM_MSG_BASE] = { .doit = xfrm_alloc_userspi },
@@ -2539,6 +2543,7 @@ static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
2539 2543
2540 { 2544 {
2541 struct netlink_dump_control c = { 2545 struct netlink_dump_control c = {
2546 .start = link->start,
2542 .dump = link->dump, 2547 .dump = link->dump,
2543 .done = link->done, 2548 .done = link->done,
2544 }; 2549 };