Skip to content

Commit

Permalink
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/gi…
Browse files Browse the repository at this point in the history
…t/klassert/ipsec

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: David S. Miller <[email protected]>
  • Loading branch information
davem330 committed Jul 5, 2019
2 parents 9d1bc24 + 56c5ee1 commit 114b5b3
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 81 deletions.
8 changes: 6 additions & 2 deletions net/key/af_key.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions net/xfrm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ config XFRM_ALGO
tristate
select XFRM
select CRYPTO
select CRYPTO_HASH
select CRYPTO_BLKCIPHER

if INET
config XFRM_USER
Expand Down
98 changes: 28 additions & 70 deletions net/xfrm/xfrm_interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -156,72 +156,19 @@ 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;
struct xfrmi_net *xfrmn = net_generic(net, xfrmi_net_id);

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)
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand Down
15 changes: 7 additions & 8 deletions net/xfrm/xfrm_policy.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);

Expand Down
19 changes: 19 additions & 0 deletions net/xfrm/xfrm_user.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
27 changes: 26 additions & 1 deletion tools/testing/selftests/net/xfrm_policy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,29 @@ check_exceptions()
return $lret
}

check_hthresh_repeat()
{
local log=$1
i=0

for i in $(seq 1 10);do
ip -net ns1 xfrm policy update src e000:0001::0000 dst ff01::0014:0000:0001 dir in tmpl src :: dst :: proto esp mode tunnel priority 100 action allow || break
ip -net ns1 xfrm policy set hthresh6 0 28 || break

ip -net ns1 xfrm policy update src e000:0001::0000 dst ff01::01 dir in tmpl src :: dst :: proto esp mode tunnel priority 100 action allow || break
ip -net ns1 xfrm policy set hthresh6 0 28 || break
done

if [ $i -ne 10 ] ;then
echo "FAIL: $log" 1>&2
ret=1
return 1
fi

echo "PASS: $log"
return 0
}

#check for needed privileges
if [ "$(id -u)" -ne 0 ];then
echo "SKIP: Need root privileges"
Expand Down Expand Up @@ -404,7 +427,9 @@ for n in ns3 ns4;do
ip -net $n xfrm policy set hthresh4 32 32 hthresh6 128 128
sleep $((RANDOM%5))
done
check_exceptions "exceptions and block policies after hresh change to normal"
check_exceptions "exceptions and block policies after htresh change to normal"

check_hthresh_repeat "policies with repeated htresh change"

for i in 1 2 3 4;do ip netns del ns$i;done

Expand Down

0 comments on commit 114b5b3

Please sign in to comment.