Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 114b5b35 authored by David S. Miller's avatar David S. Miller
Browse files


Steffen Klassert says:

====================
pull request (net): ipsec 2019-07-05

1)  Fix xfrm selector prefix length validation for
    inter address family tunneling.
    From Anirudh Gupta.

2) Fix a memleak in pfkey.
   From Jeremy Sowden.

3) Fix SA selector validation to allow empty selectors again.
   From Nicolas Dichtel.

4) Select crypto ciphers for xfrm_algo, this fixes some
   randconfig builds. From Arnd Bergmann.

5) Remove a duplicated assignment in xfrm_bydst_resize.
   From Cong Wang.

6) Fix a hlist corruption on hash rebuild.
   From Florian Westphal.

7) Fix a memory leak when creating xfrm interfaces.
   From Nicolas Dichtel.

Please pull or let me know if there are problems.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 9d1bc24b 56c5ee1a
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -2438,8 +2438,10 @@ static int key_pol_get_resp(struct sock *sk, struct xfrm_policy *xp, const struc
		goto out;
	}
	err = pfkey_xfrm_policy2msg(out_skb, xp, dir);
	if (err < 0)
	if (err < 0) {
		kfree_skb(out_skb);
		goto out;
	}

	out_hdr = (struct sadb_msg *) out_skb->data;
	out_hdr->sadb_msg_version = hdr->sadb_msg_version;
@@ -2690,8 +2692,10 @@ static int dump_sp(struct xfrm_policy *xp, int dir, int count, void *ptr)
		return PTR_ERR(out_skb);

	err = pfkey_xfrm_policy2msg(out_skb, xp, dir);
	if (err < 0)
	if (err < 0) {
		kfree_skb(out_skb);
		return err;
	}

	out_hdr = (struct sadb_msg *) out_skb->data;
	out_hdr->sadb_msg_version = pfk->dump.msg_version;
+2 −0
Original line number Diff line number Diff line
@@ -15,6 +15,8 @@ config XFRM_ALGO
	tristate
	select XFRM
	select CRYPTO
	select CRYPTO_HASH
	select CRYPTO_BLKCIPHER

if INET
config XFRM_USER
+28 −70
Original line number Diff line number Diff line
@@ -133,7 +133,7 @@ static void xfrmi_dev_free(struct net_device *dev)
	free_percpu(dev->tstats);
}

static int xfrmi_create2(struct net_device *dev)
static int xfrmi_create(struct net_device *dev)
{
	struct xfrm_if *xi = netdev_priv(dev);
	struct net *net = dev_net(dev);
@@ -156,54 +156,7 @@ static int xfrmi_create2(struct net_device *dev)
	return err;
}

static struct xfrm_if *xfrmi_create(struct net *net, struct xfrm_if_parms *p)
{
	struct net_device *dev;
	struct xfrm_if *xi;
	char name[IFNAMSIZ];
	int err;

	if (p->name[0]) {
		strlcpy(name, p->name, IFNAMSIZ);
	} else {
		err = -EINVAL;
		goto failed;
	}

	dev = alloc_netdev(sizeof(*xi), name, NET_NAME_UNKNOWN, xfrmi_dev_setup);
	if (!dev) {
		err = -EAGAIN;
		goto failed;
	}

	dev_net_set(dev, net);

	xi = netdev_priv(dev);
	xi->p = *p;
	xi->net = net;
	xi->dev = dev;
	xi->phydev = dev_get_by_index(net, p->link);
	if (!xi->phydev) {
		err = -ENODEV;
		goto failed_free;
	}

	err = xfrmi_create2(dev);
	if (err < 0)
		goto failed_dev_put;

	return xi;

failed_dev_put:
	dev_put(xi->phydev);
failed_free:
	free_netdev(dev);
failed:
	return ERR_PTR(err);
}

static struct xfrm_if *xfrmi_locate(struct net *net, struct xfrm_if_parms *p,
				   int create)
static struct xfrm_if *xfrmi_locate(struct net *net, struct xfrm_if_parms *p)
{
	struct xfrm_if __rcu **xip;
	struct xfrm_if *xi;
@@ -211,17 +164,11 @@ static struct xfrm_if *xfrmi_locate(struct net *net, struct xfrm_if_parms *p,

	for (xip = &xfrmn->xfrmi[0];
	     (xi = rtnl_dereference(*xip)) != NULL;
	     xip = &xi->next) {
		if (xi->p.if_id == p->if_id) {
			if (create)
				return ERR_PTR(-EEXIST);

	     xip = &xi->next)
		if (xi->p.if_id == p->if_id)
			return xi;
		}
	}
	if (!create)
		return ERR_PTR(-ENODEV);
	return xfrmi_create(net, p);

	return NULL;
}

static void xfrmi_dev_uninit(struct net_device *dev)
@@ -686,21 +633,33 @@ static int xfrmi_newlink(struct net *src_net, struct net_device *dev,
			struct netlink_ext_ack *extack)
{
	struct net *net = dev_net(dev);
	struct xfrm_if_parms *p;
	struct xfrm_if_parms p;
	struct xfrm_if *xi;
	int err;

	xi = netdev_priv(dev);
	p = &xi->p;

	xfrmi_netlink_parms(data, p);
	xfrmi_netlink_parms(data, &p);

	if (!tb[IFLA_IFNAME])
		return -EINVAL;

	nla_strlcpy(p->name, tb[IFLA_IFNAME], IFNAMSIZ);
	nla_strlcpy(p.name, tb[IFLA_IFNAME], IFNAMSIZ);

	xi = xfrmi_locate(net, p, 1);
	return PTR_ERR_OR_ZERO(xi);
	xi = xfrmi_locate(net, &p);
	if (xi)
		return -EEXIST;

	xi = netdev_priv(dev);
	xi->p = p;
	xi->net = net;
	xi->dev = dev;
	xi->phydev = dev_get_by_index(net, p.link);
	if (!xi->phydev)
		return -ENODEV;

	err = xfrmi_create(dev);
	if (err < 0)
		dev_put(xi->phydev);
	return err;
}

static void xfrmi_dellink(struct net_device *dev, struct list_head *head)
@@ -717,9 +676,8 @@ static int xfrmi_changelink(struct net_device *dev, struct nlattr *tb[],

	xfrmi_netlink_parms(data, &xi->p);

	xi = xfrmi_locate(net, &xi->p, 0);

	if (IS_ERR_OR_NULL(xi)) {
	xi = xfrmi_locate(net, &xi->p);
	if (!xi) {
		xi = netdev_priv(dev);
	} else {
		if (xi->dev != dev)
+7 −8
Original line number Diff line number Diff line
@@ -582,9 +582,6 @@ static void xfrm_bydst_resize(struct net *net, int dir)
	spin_lock_bh(&net->xfrm.xfrm_policy_lock);
	write_seqcount_begin(&xfrm_policy_hash_generation);

	odst = rcu_dereference_protected(net->xfrm.policy_bydst[dir].table,
				lockdep_is_held(&net->xfrm.xfrm_policy_lock));

	odst = rcu_dereference_protected(net->xfrm.policy_bydst[dir].table,
				lockdep_is_held(&net->xfrm.xfrm_policy_lock));

@@ -1280,13 +1277,17 @@ static void xfrm_hash_rebuild(struct work_struct *work)

		hlist_for_each_entry_safe(policy, n,
					  &net->xfrm.policy_inexact[dir],
					  bydst_inexact_list)
					  bydst_inexact_list) {
			hlist_del_rcu(&policy->bydst);
			hlist_del_init(&policy->bydst_inexact_list);
		}

		hmask = net->xfrm.policy_bydst[dir].hmask;
		odst = net->xfrm.policy_bydst[dir].table;
		for (i = hmask; i >= 0; i--)
			INIT_HLIST_HEAD(odst + i);
		for (i = hmask; i >= 0; i--) {
			hlist_for_each_entry_safe(policy, n, odst + i, bydst)
				hlist_del_rcu(&policy->bydst);
		}
		if ((dir & XFRM_POLICY_MASK) == XFRM_POLICY_OUT) {
			/* dir out => dst = remote, src = local */
			net->xfrm.policy_bydst[dir].dbits4 = rbits4;
@@ -1315,8 +1316,6 @@ static void xfrm_hash_rebuild(struct work_struct *work)
		chain = policy_hash_bysel(net, &policy->selector,
					  policy->family, dir);

		hlist_del_rcu(&policy->bydst);

		if (!chain) {
			void *p = xfrm_policy_inexact_insert(policy, dir, 0);

+19 −0
Original line number Diff line number Diff line
@@ -151,6 +151,25 @@ static int verify_newsa_info(struct xfrm_usersa_info *p,

	err = -EINVAL;
	switch (p->family) {
	case AF_INET:
		break;

	case AF_INET6:
#if IS_ENABLED(CONFIG_IPV6)
		break;
#else
		err = -EAFNOSUPPORT;
		goto out;
#endif

	default:
		goto out;
	}

	switch (p->sel.family) {
	case AF_UNSPEC:
		break;

	case AF_INET:
		if (p->sel.prefixlen_d > 32 || p->sel.prefixlen_s > 32)
			goto out;
Loading