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-next

Steffen Klassert says:

====================
pull request (net-next): ipsec-next 2017-06-23

1) Use memdup_user to spmlify xfrm_user_policy.
   From Geliang Tang.

2) Make xfrm_dev_register static to silence a sparse warning.
   From Wei Yongjun.

3) Use crypto_memneq to check the ICV in the AH protocol.
   From Sabrina Dubroca.

4) Remove some unused variables in esp6.
   From Stephen Hemminger.

5) Extend XFRM MIGRATE to allow to change the UDP encapsulation port.
   From Antony Antony.

6) Include the UDP encapsulation port to km_migrate announcements.
   From Antony Antony.

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

Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
davem330 committed Jun 23, 2017
2 parents 408cf83 + 8bafd73 commit 93bbbfb
Show file tree
Hide file tree
Showing 9 changed files with 74 additions and 48 deletions.
12 changes: 8 additions & 4 deletions include/net/xfrm.h
Original file line number Diff line number Diff line change
Expand Up @@ -631,7 +631,8 @@ struct xfrm_mgr {
u8 dir, u8 type,
const struct xfrm_migrate *m,
int num_bundles,
const struct xfrm_kmaddress *k);
const struct xfrm_kmaddress *k,
const struct xfrm_encap_tmpl *encap);
bool (*is_alive)(const struct km_event *c);
};

Expand Down Expand Up @@ -1675,13 +1676,16 @@ int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol);
#ifdef CONFIG_XFRM_MIGRATE
int km_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
const struct xfrm_migrate *m, int num_bundles,
const struct xfrm_kmaddress *k);
const struct xfrm_kmaddress *k,
const struct xfrm_encap_tmpl *encap);
struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *net);
struct xfrm_state *xfrm_state_migrate(struct xfrm_state *x,
struct xfrm_migrate *m);
struct xfrm_migrate *m,
struct xfrm_encap_tmpl *encap);
int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
struct xfrm_migrate *m, int num_bundles,
struct xfrm_kmaddress *k, struct net *net);
struct xfrm_kmaddress *k, struct net *net,
struct xfrm_encap_tmpl *encap);
#endif

int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport);
Expand Down
5 changes: 3 additions & 2 deletions net/ipv4/ah4.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#define pr_fmt(fmt) "IPsec: " fmt

#include <crypto/algapi.h>
#include <crypto/hash.h>
#include <linux/err.h>
#include <linux/module.h>
Expand Down Expand Up @@ -279,7 +280,7 @@ static void ah_input_done(struct crypto_async_request *base, int err)
auth_data = ah_tmp_auth(work_iph, ihl);
icv = ah_tmp_icv(ahp->ahash, auth_data, ahp->icv_trunc_len);

err = memcmp(icv, auth_data, ahp->icv_trunc_len) ? -EBADMSG: 0;
err = crypto_memneq(icv, auth_data, ahp->icv_trunc_len) ? -EBADMSG : 0;
if (err)
goto out;

Expand Down Expand Up @@ -417,7 +418,7 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
goto out_free;
}

err = memcmp(icv, auth_data, ahp->icv_trunc_len) ? -EBADMSG: 0;
err = crypto_memneq(icv, auth_data, ahp->icv_trunc_len) ? -EBADMSG : 0;
if (err)
goto out_free;

Expand Down
5 changes: 3 additions & 2 deletions net/ipv6/ah6.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

#define pr_fmt(fmt) "IPv6: " fmt

#include <crypto/algapi.h>
#include <crypto/hash.h>
#include <linux/module.h>
#include <linux/slab.h>
Expand Down Expand Up @@ -483,7 +484,7 @@ static void ah6_input_done(struct crypto_async_request *base, int err)
auth_data = ah_tmp_auth(work_iph, hdr_len);
icv = ah_tmp_icv(ahp->ahash, auth_data, ahp->icv_trunc_len);

err = memcmp(icv, auth_data, ahp->icv_trunc_len) ? -EBADMSG : 0;
err = crypto_memneq(icv, auth_data, ahp->icv_trunc_len) ? -EBADMSG : 0;
if (err)
goto out;

Expand Down Expand Up @@ -631,7 +632,7 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
goto out_free;
}

err = memcmp(icv, auth_data, ahp->icv_trunc_len) ? -EBADMSG : 0;
err = crypto_memneq(icv, auth_data, ahp->icv_trunc_len) ? -EBADMSG : 0;
if (err)
goto out_free;

Expand Down
5 changes: 0 additions & 5 deletions net/ipv6/esp6.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,6 @@ static inline struct scatterlist *esp_req_sg(struct crypto_aead *aead,

static void esp_ssg_unref(struct xfrm_state *x, void *tmp)
{
__be32 *seqhi;
struct crypto_aead *aead = x->data;
int seqhilen = 0;
u8 *iv;
Expand All @@ -128,7 +127,6 @@ static void esp_ssg_unref(struct xfrm_state *x, void *tmp)
if (x->props.flags & XFRM_STATE_ESN)
seqhilen += sizeof(__be32);

seqhi = esp_tmp_seqhi(tmp);
iv = esp_tmp_iv(aead, tmp, seqhilen);
req = esp_tmp_req(aead, iv);

Expand Down Expand Up @@ -224,12 +222,9 @@ int esp6_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info
u8 *vaddr;
int nfrags;
struct page *page;
struct ip_esp_hdr *esph;
struct sk_buff *trailer;
int tailen = esp->tailen;

esph = ip_esp_hdr(skb);

if (!skb_cloned(skb)) {
if (tailen <= skb_availroom(skb)) {
nfrags = 1;
Expand Down
8 changes: 5 additions & 3 deletions net/key/af_key.c
Original file line number Diff line number Diff line change
Expand Up @@ -2589,7 +2589,7 @@ static int pfkey_migrate(struct sock *sk, struct sk_buff *skb,
}

return xfrm_migrate(&sel, dir, XFRM_POLICY_TYPE_MAIN, m, i,
kma ? &k : NULL, net);
kma ? &k : NULL, net, NULL);

out:
return err;
Expand Down Expand Up @@ -3488,7 +3488,8 @@ static int set_ipsecrequest(struct sk_buff *skb,
#ifdef CONFIG_NET_KEY_MIGRATE
static int pfkey_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
const struct xfrm_migrate *m, int num_bundles,
const struct xfrm_kmaddress *k)
const struct xfrm_kmaddress *k,
const struct xfrm_encap_tmpl *encap)
{
int i;
int sasize_sel;
Expand Down Expand Up @@ -3598,7 +3599,8 @@ static int pfkey_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
#else
static int pfkey_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
const struct xfrm_migrate *m, int num_bundles,
const struct xfrm_kmaddress *k)
const struct xfrm_kmaddress *k,
const struct xfrm_encap_tmpl *encap)
{
return -ENOPROTOOPT;
}
Expand Down
2 changes: 1 addition & 1 deletion net/xfrm/xfrm_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ bool xfrm_dev_offload_ok(struct sk_buff *skb, struct xfrm_state *x)
}
EXPORT_SYMBOL_GPL(xfrm_dev_offload_ok);

int xfrm_dev_register(struct net_device *dev)
static int xfrm_dev_register(struct net_device *dev)
{
if ((dev->features & NETIF_F_HW_ESP) && !dev->xfrmdev_ops)
return NOTIFY_BAD;
Expand Down
13 changes: 5 additions & 8 deletions net/xfrm/xfrm_policy.c
Original file line number Diff line number Diff line change
Expand Up @@ -3279,11 +3279,6 @@ static int xfrm_migrate_check(const struct xfrm_migrate *m, int num_migrate)
return -EINVAL;

for (i = 0; i < num_migrate; i++) {
if (xfrm_addr_equal(&m[i].old_daddr, &m[i].new_daddr,
m[i].old_family) &&
xfrm_addr_equal(&m[i].old_saddr, &m[i].new_saddr,
m[i].old_family))
return -EINVAL;
if (xfrm_addr_any(&m[i].new_daddr, m[i].new_family) ||
xfrm_addr_any(&m[i].new_saddr, m[i].new_family))
return -EINVAL;
Expand All @@ -3307,7 +3302,8 @@ static int xfrm_migrate_check(const struct xfrm_migrate *m, int num_migrate)

int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
struct xfrm_migrate *m, int num_migrate,
struct xfrm_kmaddress *k, struct net *net)
struct xfrm_kmaddress *k, struct net *net,
struct xfrm_encap_tmpl *encap)
{
int i, err, nx_cur = 0, nx_new = 0;
struct xfrm_policy *pol = NULL;
Expand All @@ -3330,7 +3326,8 @@ int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
if ((x = xfrm_migrate_state_find(mp, net))) {
x_cur[nx_cur] = x;
nx_cur++;
if ((xc = xfrm_state_migrate(x, mp))) {
xc = xfrm_state_migrate(x, mp, encap);
if (xc) {
x_new[nx_new] = xc;
nx_new++;
} else {
Expand All @@ -3351,7 +3348,7 @@ int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
}

/* Stage 5 - announce */
km_migrate(sel, dir, type, m, num_migrate, k);
km_migrate(sel, dir, type, m, num_migrate, k, encap);

xfrm_pol_put(pol);

Expand Down
35 changes: 20 additions & 15 deletions net/xfrm/xfrm_state.c
Original file line number Diff line number Diff line change
Expand Up @@ -1309,7 +1309,8 @@ int xfrm_state_add(struct xfrm_state *x)
EXPORT_SYMBOL(xfrm_state_add);

#ifdef CONFIG_XFRM_MIGRATE
static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig)
static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig,
struct xfrm_encap_tmpl *encap)
{
struct net *net = xs_net(orig);
struct xfrm_state *x = xfrm_state_alloc(net);
Expand Down Expand Up @@ -1351,8 +1352,14 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig)
}
x->props.calgo = orig->props.calgo;

if (orig->encap) {
x->encap = kmemdup(orig->encap, sizeof(*x->encap), GFP_KERNEL);
if (encap || orig->encap) {
if (encap)
x->encap = kmemdup(encap, sizeof(*x->encap),
GFP_KERNEL);
else
x->encap = kmemdup(orig->encap, sizeof(*x->encap),
GFP_KERNEL);

if (!x->encap)
goto error;
}
Expand Down Expand Up @@ -1442,11 +1449,12 @@ struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *n
EXPORT_SYMBOL(xfrm_migrate_state_find);

struct xfrm_state *xfrm_state_migrate(struct xfrm_state *x,
struct xfrm_migrate *m)
struct xfrm_migrate *m,
struct xfrm_encap_tmpl *encap)
{
struct xfrm_state *xc;

xc = xfrm_state_clone(x);
xc = xfrm_state_clone(x, encap);
if (!xc)
return NULL;

Expand Down Expand Up @@ -1958,7 +1966,8 @@ EXPORT_SYMBOL(km_policy_expired);
#ifdef CONFIG_XFRM_MIGRATE
int km_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
const struct xfrm_migrate *m, int num_migrate,
const struct xfrm_kmaddress *k)
const struct xfrm_kmaddress *k,
const struct xfrm_encap_tmpl *encap)
{
int err = -EINVAL;
int ret;
Expand All @@ -1967,7 +1976,8 @@ int km_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
rcu_read_lock();
list_for_each_entry_rcu(km, &xfrm_km_list, list) {
if (km->migrate) {
ret = km->migrate(sel, dir, type, m, num_migrate, k);
ret = km->migrate(sel, dir, type, m, num_migrate, k,
encap);
if (!ret)
err = ret;
}
Expand Down Expand Up @@ -2025,13 +2035,9 @@ int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen
if (optlen <= 0 || optlen > PAGE_SIZE)
return -EMSGSIZE;

data = kmalloc(optlen, GFP_KERNEL);
if (!data)
return -ENOMEM;

err = -EFAULT;
if (copy_from_user(data, optval, optlen))
goto out;
data = memdup_user(optval, optlen);
if (IS_ERR(data))
return PTR_ERR(data);

err = -EINVAL;
rcu_read_lock();
Expand All @@ -2049,7 +2055,6 @@ int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen
err = 0;
}

out:
kfree(data);
return err;
}
Expand Down
37 changes: 29 additions & 8 deletions net/xfrm/xfrm_user.c
Original file line number Diff line number Diff line change
Expand Up @@ -2243,6 +2243,7 @@ static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh,
int err;
int n = 0;
struct net *net = sock_net(skb->sk);
struct xfrm_encap_tmpl *encap = NULL;

if (attrs[XFRMA_MIGRATE] == NULL)
return -EINVAL;
Expand All @@ -2260,9 +2261,18 @@ static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh,
if (!n)
return 0;

xfrm_migrate(&pi->sel, pi->dir, type, m, n, kmp, net);
if (attrs[XFRMA_ENCAP]) {
encap = kmemdup(nla_data(attrs[XFRMA_ENCAP]),
sizeof(*encap), GFP_KERNEL);
if (!encap)
return 0;
}

return 0;
err = xfrm_migrate(&pi->sel, pi->dir, type, m, n, kmp, net, encap);

kfree(encap);

return err;
}
#else
static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh,
Expand Down Expand Up @@ -2304,17 +2314,20 @@ static int copy_to_user_kmaddress(const struct xfrm_kmaddress *k, struct sk_buff
return nla_put(skb, XFRMA_KMADDRESS, sizeof(uk), &uk);
}

static inline size_t xfrm_migrate_msgsize(int num_migrate, int with_kma)
static inline size_t xfrm_migrate_msgsize(int num_migrate, int with_kma,
int with_encp)
{
return NLMSG_ALIGN(sizeof(struct xfrm_userpolicy_id))
+ (with_kma ? nla_total_size(sizeof(struct xfrm_kmaddress)) : 0)
+ (with_encp ? nla_total_size(sizeof(struct xfrm_encap_tmpl)) : 0)
+ nla_total_size(sizeof(struct xfrm_user_migrate) * num_migrate)
+ userpolicy_type_attrsize();
}

static int build_migrate(struct sk_buff *skb, const struct xfrm_migrate *m,
int num_migrate, const struct xfrm_kmaddress *k,
const struct xfrm_selector *sel, u8 dir, u8 type)
const struct xfrm_selector *sel,
const struct xfrm_encap_tmpl *encap, u8 dir, u8 type)
{
const struct xfrm_migrate *mp;
struct xfrm_userpolicy_id *pol_id;
Expand All @@ -2336,6 +2349,11 @@ static int build_migrate(struct sk_buff *skb, const struct xfrm_migrate *m,
if (err)
goto out_cancel;
}
if (encap) {
err = nla_put(skb, XFRMA_ENCAP, sizeof(*encap), encap);
if (err)
goto out_cancel;
}
err = copy_to_user_policy_type(type, skb);
if (err)
goto out_cancel;
Expand All @@ -2355,25 +2373,28 @@ static int build_migrate(struct sk_buff *skb, const struct xfrm_migrate *m,

static int xfrm_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
const struct xfrm_migrate *m, int num_migrate,
const struct xfrm_kmaddress *k)
const struct xfrm_kmaddress *k,
const struct xfrm_encap_tmpl *encap)
{
struct net *net = &init_net;
struct sk_buff *skb;

skb = nlmsg_new(xfrm_migrate_msgsize(num_migrate, !!k), GFP_ATOMIC);
skb = nlmsg_new(xfrm_migrate_msgsize(num_migrate, !!k, !!encap),
GFP_ATOMIC);
if (skb == NULL)
return -ENOMEM;

/* build migrate */
if (build_migrate(skb, m, num_migrate, k, sel, dir, type) < 0)
if (build_migrate(skb, m, num_migrate, k, sel, encap, dir, type) < 0)
BUG();

return xfrm_nlmsg_multicast(net, skb, 0, XFRMNLGRP_MIGRATE);
}
#else
static int xfrm_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
const struct xfrm_migrate *m, int num_migrate,
const struct xfrm_kmaddress *k)
const struct xfrm_kmaddress *k,
const struct xfrm_encap_tmpl *encap)
{
return -ENOPROTOOPT;
}
Expand Down

0 comments on commit 93bbbfb

Please sign in to comment.