]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.11-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 3 Jul 2017 11:51:43 +0000 (13:51 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 3 Jul 2017 11:51:43 +0000 (13:51 +0200)
added patches:
xfrm-fix-stack-access-out-of-bounds-with-config_xfrm_sub_policy.patch
xfrm-move-xfrm_garbage_collect-out-of-xfrm_policy_flush.patch
xfrm-null-dereference-on-allocation-failure.patch
xfrm-oops-on-error-in-pfkey_msg2xfrm_state.patch
xfrm6-fix-ipv6-payload_len-in-xfrm6_transport_finish.patch

queue-4.11/series
queue-4.11/xfrm-fix-stack-access-out-of-bounds-with-config_xfrm_sub_policy.patch [new file with mode: 0644]
queue-4.11/xfrm-move-xfrm_garbage_collect-out-of-xfrm_policy_flush.patch [new file with mode: 0644]
queue-4.11/xfrm-null-dereference-on-allocation-failure.patch [new file with mode: 0644]
queue-4.11/xfrm-oops-on-error-in-pfkey_msg2xfrm_state.patch [new file with mode: 0644]
queue-4.11/xfrm6-fix-ipv6-payload_len-in-xfrm6_transport_finish.patch [new file with mode: 0644]

index 4577d94273dffec01bc626af5faeb2e925182739..8393b1d7b0e93d3fb80aaca3aeef93fb54b5cc01 100644 (file)
@@ -52,3 +52,8 @@ x86-mm-fix-boot-crash-caused-by-incorrect-loop-count-calculation-in-sync_global_
 pinctrl-amd-use-regular-interrupt-instead-of-chained.patch
 mm-vmalloc.c-huge-vmap-fail-gracefully-on-unexpected-huge-vmap-mappings.patch
 xen-blkback-don-t-free-be-structure-too-early.patch
+xfrm6-fix-ipv6-payload_len-in-xfrm6_transport_finish.patch
+xfrm-move-xfrm_garbage_collect-out-of-xfrm_policy_flush.patch
+xfrm-fix-stack-access-out-of-bounds-with-config_xfrm_sub_policy.patch
+xfrm-null-dereference-on-allocation-failure.patch
+xfrm-oops-on-error-in-pfkey_msg2xfrm_state.patch
diff --git a/queue-4.11/xfrm-fix-stack-access-out-of-bounds-with-config_xfrm_sub_policy.patch b/queue-4.11/xfrm-fix-stack-access-out-of-bounds-with-config_xfrm_sub_policy.patch
new file mode 100644 (file)
index 0000000..22f9878
--- /dev/null
@@ -0,0 +1,121 @@
+From 9b3eb54106cf6acd03f07cf0ab01c13676a226c2 Mon Sep 17 00:00:00 2001
+From: Sabrina Dubroca <sd@queasysnail.net>
+Date: Wed, 3 May 2017 16:43:19 +0200
+Subject: xfrm: fix stack access out of bounds with CONFIG_XFRM_SUB_POLICY
+
+From: Sabrina Dubroca <sd@queasysnail.net>
+
+commit 9b3eb54106cf6acd03f07cf0ab01c13676a226c2 upstream.
+
+When CONFIG_XFRM_SUB_POLICY=y, xfrm_dst stores a copy of the flowi for
+that dst. Unfortunately, the code that allocates and fills this copy
+doesn't care about what type of flowi (flowi, flowi4, flowi6) gets
+passed. In multiple code paths (from raw_sendmsg, from TCP when
+replying to a FIN, in vxlan, geneve, and gre), the flowi that gets
+passed to xfrm is actually an on-stack flowi4, so we end up reading
+stuff from the stack past the end of the flowi4 struct.
+
+Since xfrm_dst->origin isn't used anywhere following commit
+ca116922afa8 ("xfrm: Eliminate "fl" and "pol" args to
+xfrm_bundle_ok()."), just get rid of it.  xfrm_dst->partner isn't used
+either, so get rid of that too.
+
+Fixes: 9d6ec938019c ("ipv4: Use flowi4 in public route lookup interfaces.")
+Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
+Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ include/net/xfrm.h     |   10 ----------
+ net/xfrm/xfrm_policy.c |   47 -----------------------------------------------
+ 2 files changed, 57 deletions(-)
+
+--- a/include/net/xfrm.h
++++ b/include/net/xfrm.h
+@@ -945,10 +945,6 @@ struct xfrm_dst {
+       struct flow_cache_object flo;
+       struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX];
+       int num_pols, num_xfrms;
+-#ifdef CONFIG_XFRM_SUB_POLICY
+-      struct flowi *origin;
+-      struct xfrm_selector *partner;
+-#endif
+       u32 xfrm_genid;
+       u32 policy_genid;
+       u32 route_mtu_cached;
+@@ -964,12 +960,6 @@ static inline void xfrm_dst_destroy(stru
+       dst_release(xdst->route);
+       if (likely(xdst->u.dst.xfrm))
+               xfrm_state_put(xdst->u.dst.xfrm);
+-#ifdef CONFIG_XFRM_SUB_POLICY
+-      kfree(xdst->origin);
+-      xdst->origin = NULL;
+-      kfree(xdst->partner);
+-      xdst->partner = NULL;
+-#endif
+ }
+ #endif
+--- a/net/xfrm/xfrm_policy.c
++++ b/net/xfrm/xfrm_policy.c
+@@ -1793,43 +1793,6 @@ free_dst:
+       goto out;
+ }
+-#ifdef CONFIG_XFRM_SUB_POLICY
+-static int xfrm_dst_alloc_copy(void **target, const void *src, int size)
+-{
+-      if (!*target) {
+-              *target = kmalloc(size, GFP_ATOMIC);
+-              if (!*target)
+-                      return -ENOMEM;
+-      }
+-
+-      memcpy(*target, src, size);
+-      return 0;
+-}
+-#endif
+-
+-static int xfrm_dst_update_parent(struct dst_entry *dst,
+-                                const struct xfrm_selector *sel)
+-{
+-#ifdef CONFIG_XFRM_SUB_POLICY
+-      struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
+-      return xfrm_dst_alloc_copy((void **)&(xdst->partner),
+-                                 sel, sizeof(*sel));
+-#else
+-      return 0;
+-#endif
+-}
+-
+-static int xfrm_dst_update_origin(struct dst_entry *dst,
+-                                const struct flowi *fl)
+-{
+-#ifdef CONFIG_XFRM_SUB_POLICY
+-      struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
+-      return xfrm_dst_alloc_copy((void **)&(xdst->origin), fl, sizeof(*fl));
+-#else
+-      return 0;
+-#endif
+-}
+-
+ static int xfrm_expand_policies(const struct flowi *fl, u16 family,
+                               struct xfrm_policy **pols,
+                               int *num_pols, int *num_xfrms)
+@@ -1901,16 +1864,6 @@ xfrm_resolve_and_create_bundle(struct xf
+       xdst = (struct xfrm_dst *)dst;
+       xdst->num_xfrms = err;
+-      if (num_pols > 1)
+-              err = xfrm_dst_update_parent(dst, &pols[1]->selector);
+-      else
+-              err = xfrm_dst_update_origin(dst, fl);
+-      if (unlikely(err)) {
+-              dst_free(dst);
+-              XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTBUNDLECHECKERROR);
+-              return ERR_PTR(err);
+-      }
+-
+       xdst->num_pols = num_pols;
+       memcpy(xdst->pols, pols, sizeof(struct xfrm_policy *) * num_pols);
+       xdst->policy_genid = atomic_read(&pols[0]->genid);
diff --git a/queue-4.11/xfrm-move-xfrm_garbage_collect-out-of-xfrm_policy_flush.patch b/queue-4.11/xfrm-move-xfrm_garbage_collect-out-of-xfrm_policy_flush.patch
new file mode 100644 (file)
index 0000000..4a1b58f
--- /dev/null
@@ -0,0 +1,79 @@
+From 138437f591dd9a42d53c6fed1a3c85e02678851c Mon Sep 17 00:00:00 2001
+From: Hangbin Liu <liuhangbin@gmail.com>
+Date: Sun, 11 Jun 2017 09:44:20 +0800
+Subject: xfrm: move xfrm_garbage_collect out of xfrm_policy_flush
+
+From: Hangbin Liu <liuhangbin@gmail.com>
+
+commit 138437f591dd9a42d53c6fed1a3c85e02678851c upstream.
+
+Now we will force to do garbage collection if any policy removed in
+xfrm_policy_flush(). But during xfrm_net_exit(). We call flow_cache_fini()
+first and set set fc->percpu to NULL. Then after we call xfrm_policy_fini()
+-> frxm_policy_flush() -> flow_cache_flush(), we will get NULL pointer
+dereference when check percpu_empty. The code path looks like:
+
+flow_cache_fini()
+  - fc->percpu = NULL
+xfrm_policy_fini()
+  - xfrm_policy_flush()
+    - xfrm_garbage_collect()
+      - flow_cache_flush()
+        - flow_cache_percpu_empty()
+         - fcp = per_cpu_ptr(fc->percpu, cpu)
+
+To reproduce, just add ipsec in netns and then remove the netns.
+
+v2:
+As Xin Long suggested, since only two other places need to call it. move
+xfrm_garbage_collect() outside xfrm_policy_flush().
+
+v3:
+Fix subject mismatch after v2 fix.
+
+Fixes: 35db06912189 ("xfrm: do the garbage collection after flushing policy")
+Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
+Reviewed-by: Xin Long <lucien.xin@gmail.com>
+Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/key/af_key.c       |    2 ++
+ net/xfrm/xfrm_policy.c |    4 ----
+ net/xfrm/xfrm_user.c   |    1 +
+ 3 files changed, 3 insertions(+), 4 deletions(-)
+
+--- a/net/key/af_key.c
++++ b/net/key/af_key.c
+@@ -2755,6 +2755,8 @@ static int pfkey_spdflush(struct sock *s
+       int err, err2;
+       err = xfrm_policy_flush(net, XFRM_POLICY_TYPE_MAIN, true);
++      if (!err)
++              xfrm_garbage_collect(net);
+       err2 = unicast_flush_resp(sk, hdr);
+       if (err || err2) {
+               if (err == -ESRCH) /* empty table - old silent behavior */
+--- a/net/xfrm/xfrm_policy.c
++++ b/net/xfrm/xfrm_policy.c
+@@ -1006,10 +1006,6 @@ int xfrm_policy_flush(struct net *net, u
+               err = -ESRCH;
+ out:
+       spin_unlock_bh(&net->xfrm.xfrm_policy_lock);
+-
+-      if (cnt)
+-              xfrm_garbage_collect(net);
+-
+       return err;
+ }
+ EXPORT_SYMBOL(xfrm_policy_flush);
+--- a/net/xfrm/xfrm_user.c
++++ b/net/xfrm/xfrm_user.c
+@@ -1999,6 +1999,7 @@ static int xfrm_flush_policy(struct sk_b
+                       return 0;
+               return err;
+       }
++      xfrm_garbage_collect(net);
+       c.data.type = type;
+       c.event = nlh->nlmsg_type;
diff --git a/queue-4.11/xfrm-null-dereference-on-allocation-failure.patch b/queue-4.11/xfrm-null-dereference-on-allocation-failure.patch
new file mode 100644 (file)
index 0000000..5289ed6
--- /dev/null
@@ -0,0 +1,34 @@
+From e747f64336fc15e1c823344942923195b800aa1e Mon Sep 17 00:00:00 2001
+From: Dan Carpenter <dan.carpenter@oracle.com>
+Date: Wed, 14 Jun 2017 13:35:37 +0300
+Subject: xfrm: NULL dereference on allocation failure
+
+From: Dan Carpenter <dan.carpenter@oracle.com>
+
+commit e747f64336fc15e1c823344942923195b800aa1e upstream.
+
+The default error code in pfkey_msg2xfrm_state() is -ENOBUFS.  We
+added a new call to security_xfrm_state_alloc() which sets "err" to zero
+so there several places where we can return ERR_PTR(0) if kmalloc()
+fails.  The caller is expecting error pointers so it leads to a NULL
+dereference.
+
+Fixes: df71837d5024 ("[LSM-IPSec]: Security association restriction.")
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/key/af_key.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/net/key/af_key.c
++++ b/net/key/af_key.c
+@@ -1157,6 +1157,7 @@ static struct xfrm_state * pfkey_msg2xfr
+                       goto out;
+       }
++      err = -ENOBUFS;
+       key = ext_hdrs[SADB_EXT_KEY_AUTH - 1];
+       if (sa->sadb_sa_auth) {
+               int keysize = 0;
diff --git a/queue-4.11/xfrm-oops-on-error-in-pfkey_msg2xfrm_state.patch b/queue-4.11/xfrm-oops-on-error-in-pfkey_msg2xfrm_state.patch
new file mode 100644 (file)
index 0000000..ce4f8be
--- /dev/null
@@ -0,0 +1,71 @@
+From 1e3d0c2c70cd3edb5deed186c5f5c75f2b84a633 Mon Sep 17 00:00:00 2001
+From: Dan Carpenter <dan.carpenter@oracle.com>
+Date: Wed, 14 Jun 2017 13:34:05 +0300
+Subject: xfrm: Oops on error in pfkey_msg2xfrm_state()
+
+From: Dan Carpenter <dan.carpenter@oracle.com>
+
+commit 1e3d0c2c70cd3edb5deed186c5f5c75f2b84a633 upstream.
+
+There are some missing error codes here so we accidentally return NULL
+instead of an error pointer.  It results in a NULL pointer dereference.
+
+Fixes: df71837d5024 ("[LSM-IPSec]: Security association restriction.")
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/key/af_key.c |   16 ++++++++++++----
+ 1 file changed, 12 insertions(+), 4 deletions(-)
+
+--- a/net/key/af_key.c
++++ b/net/key/af_key.c
+@@ -1169,8 +1169,10 @@ static struct xfrm_state * pfkey_msg2xfr
+               if (key)
+                       keysize = (key->sadb_key_bits + 7) / 8;
+               x->aalg = kmalloc(sizeof(*x->aalg) + keysize, GFP_KERNEL);
+-              if (!x->aalg)
++              if (!x->aalg) {
++                      err = -ENOMEM;
+                       goto out;
++              }
+               strcpy(x->aalg->alg_name, a->name);
+               x->aalg->alg_key_len = 0;
+               if (key) {
+@@ -1189,8 +1191,10 @@ static struct xfrm_state * pfkey_msg2xfr
+                               goto out;
+                       }
+                       x->calg = kmalloc(sizeof(*x->calg), GFP_KERNEL);
+-                      if (!x->calg)
++                      if (!x->calg) {
++                              err = -ENOMEM;
+                               goto out;
++                      }
+                       strcpy(x->calg->alg_name, a->name);
+                       x->props.calgo = sa->sadb_sa_encrypt;
+               } else {
+@@ -1204,8 +1208,10 @@ static struct xfrm_state * pfkey_msg2xfr
+                       if (key)
+                               keysize = (key->sadb_key_bits + 7) / 8;
+                       x->ealg = kmalloc(sizeof(*x->ealg) + keysize, GFP_KERNEL);
+-                      if (!x->ealg)
++                      if (!x->ealg) {
++                              err = -ENOMEM;
+                               goto out;
++                      }
+                       strcpy(x->ealg->alg_name, a->name);
+                       x->ealg->alg_key_len = 0;
+                       if (key) {
+@@ -1250,8 +1256,10 @@ static struct xfrm_state * pfkey_msg2xfr
+               struct xfrm_encap_tmpl *natt;
+               x->encap = kmalloc(sizeof(*x->encap), GFP_KERNEL);
+-              if (!x->encap)
++              if (!x->encap) {
++                      err = -ENOMEM;
+                       goto out;
++              }
+               natt = x->encap;
+               n_type = ext_hdrs[SADB_X_EXT_NAT_T_TYPE-1];
diff --git a/queue-4.11/xfrm6-fix-ipv6-payload_len-in-xfrm6_transport_finish.patch b/queue-4.11/xfrm6-fix-ipv6-payload_len-in-xfrm6_transport_finish.patch
new file mode 100644 (file)
index 0000000..64dc1b5
--- /dev/null
@@ -0,0 +1,40 @@
+From 7c88e21aefcf86fb41b48b2e04528db5a30fbe18 Mon Sep 17 00:00:00 2001
+From: Yossi Kuperman <yossiku@mellanox.com>
+Date: Thu, 22 Jun 2017 11:37:10 +0300
+Subject: xfrm6: Fix IPv6 payload_len in xfrm6_transport_finish
+
+From: Yossi Kuperman <yossiku@mellanox.com>
+
+commit 7c88e21aefcf86fb41b48b2e04528db5a30fbe18 upstream.
+
+IPv6 payload length indicates the size of the payload, including any
+extension headers.
+
+In xfrm6_transport_finish, ipv6_hdr(skb)->payload_len is set to the
+payload size only, regardless of the presence of any extension headers.
+After ESP GRO transport mode decapsulation, ipv6_rcv trims the packet
+according to the wrong payload_len, thus corrupting the packet.
+
+Set payload_len to account for extension headers as well.
+
+Fixes: 7785bba299a8 ("esp: Add a software GRO codepath")
+Signed-off-by: Yossi Kuperman <yossiku@mellanox.com>
+Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/ipv6/xfrm6_input.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/ipv6/xfrm6_input.c
++++ b/net/ipv6/xfrm6_input.c
+@@ -43,8 +43,8 @@ int xfrm6_transport_finish(struct sk_buf
+               return 1;
+ #endif
+-      ipv6_hdr(skb)->payload_len = htons(skb->len);
+       __skb_push(skb, skb->data - skb_network_header(skb));
++      ipv6_hdr(skb)->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
+       if (xo && (xo->flags & XFRM_GRO)) {
+               skb_mac_header_rebuild(skb);