From a133d93054fa063fb3bd328abdc3d09a7e687afe Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Sat, 6 May 2017 23:42:21 +0800 Subject: [PATCH 1/6] xfrm: use memdup_user Use memdup_user() helper instead of open-coding to simplify the code. Signed-off-by: Geliang Tang Signed-off-by: Steffen Klassert --- net/xfrm/xfrm_state.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index fc3c5aa38754..5780cdad2260 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -2023,13 +2023,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(); @@ -2047,7 +2043,6 @@ int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen err = 0; } -out: kfree(data); return err; } From 24d472e4e497c29d2eb8fcbe6d9b373b66804e01 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Thu, 18 May 2017 15:51:38 +0000 Subject: [PATCH 2/6] xfrm: Make function xfrm_dev_register static Fixes the following sparse warning: net/xfrm/xfrm_device.c:141:5: warning: symbol 'xfrm_dev_register' was not declared. Should it be static? Signed-off-by: Wei Yongjun Signed-off-by: Steffen Klassert --- net/xfrm/xfrm_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/xfrm/xfrm_device.c b/net/xfrm/xfrm_device.c index 8ec8a3fcf8d4..50ec73399b48 100644 --- a/net/xfrm/xfrm_device.c +++ b/net/xfrm/xfrm_device.c @@ -138,7 +138,7 @@ ok: } 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; From 67df58a3e5535d8ffeb48a41ec0b38859cc284b8 Mon Sep 17 00:00:00 2001 From: Sabrina Dubroca Date: Wed, 3 May 2017 16:57:57 +0200 Subject: [PATCH 3/6] ah: use crypto_memneq to check the ICV Signed-off-by: Sabrina Dubroca Signed-off-by: Steffen Klassert --- net/ipv4/ah4.c | 5 +++-- net/ipv6/ah6.c | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c index 22377c8ff14b..207350b30f88 100644 --- a/net/ipv4/ah4.c +++ b/net/ipv4/ah4.c @@ -1,5 +1,6 @@ #define pr_fmt(fmt) "IPsec: " fmt +#include #include #include #include @@ -277,7 +278,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; @@ -413,7 +414,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; diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index dda6035e3b84..ac747b13a8dc 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c @@ -25,6 +25,7 @@ #define pr_fmt(fmt) "IPv6: " fmt +#include #include #include #include @@ -481,7 +482,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; @@ -627,7 +628,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; From d49c9dc1c84878b0c044af7519a80ccb814b3f9f Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 19 May 2017 09:55:56 -0700 Subject: [PATCH 4/6] ipv6: remove unused variables in esp6 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resolves warnings: net/ipv6/esp6.c: In function ‘esp_ssg_unref’: net/ipv6/esp6.c:121:10: warning: variable ‘seqhi’ set but not used [-Wunused-but-set-variable] net/ipv6/esp6.c: In function ‘esp6_output_head’: net/ipv6/esp6.c:227:21: warning: variable ‘esph’ set but not used [-Wunused-but-set-variable] Signed-off-by: Stephen Hemminger Signed-off-by: Steffen Klassert --- net/ipv6/esp6.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index 1fe99ba8066c..53b6b870b935 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c @@ -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; @@ -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); @@ -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; From 4ab47d47af20addd6ecee1ece0205b1fbf483942 Mon Sep 17 00:00:00 2001 From: Antony Antony Date: Tue, 6 Jun 2017 12:12:13 +0200 Subject: [PATCH 5/6] xfrm: extend MIGRATE with UDP encapsulation port Add UDP encapsulation port to XFRM_MSG_MIGRATE using an optional netlink attribute XFRMA_ENCAP. The devices that support IKE MOBIKE extension (RFC-4555 Section 3.8) could go to sleep for a few minutes and wake up. When it wake up the NAT mapping could have expired, the device send a MOBIKE UPDATE_SA message to migrate the IPsec SA. The change could be a change UDP encapsulation port, IP address, or both. Reported-by: Paul Wouters Signed-off-by: Antony Antony Reviewed-by: Richard Guy Briggs Signed-off-by: Steffen Klassert --- include/net/xfrm.h | 6 ++++-- net/key/af_key.c | 2 +- net/xfrm/xfrm_policy.c | 11 ++++------- net/xfrm/xfrm_state.c | 18 +++++++++++++----- net/xfrm/xfrm_user.c | 14 ++++++++++++-- 5 files changed, 34 insertions(+), 17 deletions(-) diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 6793a30c66b1..1cc71726e581 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -1688,10 +1688,12 @@ int km_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, const struct xfrm_kmaddress *k); 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); diff --git a/net/key/af_key.c b/net/key/af_key.c index c1950bb14735..3b130cbdc463 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -2602,7 +2602,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; diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index b00a1d5a7f52..d47f055ca90e 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -3315,11 +3315,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; @@ -3343,7 +3338,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; @@ -3366,7 +3362,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 { diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 5780cdad2260..b76e6730b165 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -1309,7 +1309,8 @@ out: 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); @@ -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; } @@ -1440,11 +1447,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; diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 38614df33ec8..fb98892f7d89 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -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; @@ -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, From 8bafd73093f2f431f5a363f8057abc0ccc118853 Mon Sep 17 00:00:00 2001 From: Antony Antony Date: Tue, 6 Jun 2017 12:12:14 +0200 Subject: [PATCH 6/6] xfrm: add UDP encapsulation port in migrate message Add XFRMA_ENCAP, UDP encapsulation port, to km_migrate announcement to userland. Only add if XFRMA_ENCAP was in user migrate request. Signed-off-by: Antony Antony Reviewed-by: Richard Guy Briggs Signed-off-by: Steffen Klassert --- include/net/xfrm.h | 6 ++++-- net/key/af_key.c | 6 ++++-- net/xfrm/xfrm_policy.c | 2 +- net/xfrm/xfrm_state.c | 6 ++++-- net/xfrm/xfrm_user.c | 23 +++++++++++++++++------ 5 files changed, 30 insertions(+), 13 deletions(-) diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 1cc71726e581..34420d9708a0 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -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); }; @@ -1685,7 +1686,8 @@ 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, diff --git a/net/key/af_key.c b/net/key/af_key.c index 3b130cbdc463..d539bb7df01d 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -3508,7 +3508,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; @@ -3618,7 +3619,8 @@ err: #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; } diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index d47f055ca90e..e6141891d23c 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -3384,7 +3384,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); diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index b76e6730b165..f2421c668449 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -1964,7 +1964,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; @@ -1973,7 +1974,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; } diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index fb98892f7d89..6197c7231bc7 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -2314,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; @@ -2346,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; @@ -2365,17 +2373,19 @@ out_cancel: 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); @@ -2383,7 +2393,8 @@ static int xfrm_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, #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; }