]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 14 Feb 2016 21:30:29 +0000 (13:30 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 14 Feb 2016 21:30:29 +0000 (13:30 -0800)
added patches:
crypto-af_alg-disallow-bind-setkey-...-after-accept-2.patch
crypto-af_alg-fix-socket-double-free-when-accept-fails.patch

queue-3.10/crypto-af_alg-disallow-bind-setkey-...-after-accept-2.patch [new file with mode: 0644]
queue-3.10/crypto-af_alg-fix-socket-double-free-when-accept-fails.patch [new file with mode: 0644]
queue-3.10/series

diff --git a/queue-3.10/crypto-af_alg-disallow-bind-setkey-...-after-accept-2.patch b/queue-3.10/crypto-af_alg-disallow-bind-setkey-...-after-accept-2.patch
new file mode 100644 (file)
index 0000000..83ad308
--- /dev/null
@@ -0,0 +1,145 @@
+From c840ac6af3f8713a71b4d2363419145760bd6044 Mon Sep 17 00:00:00 2001
+From: Herbert Xu <herbert@gondor.apana.org.au>
+Date: Wed, 30 Dec 2015 11:47:53 +0800
+Subject: crypto: af_alg - Disallow bind/setkey/... after accept(2)
+
+From: Herbert Xu <herbert@gondor.apana.org.au>
+
+commit c840ac6af3f8713a71b4d2363419145760bd6044 upstream.
+
+Each af_alg parent socket obtained by socket(2) corresponds to a
+tfm object once bind(2) has succeeded.  An accept(2) call on that
+parent socket creates a context which then uses the tfm object.
+
+Therefore as long as any child sockets created by accept(2) exist
+the parent socket must not be modified or freed.
+
+This patch guarantees this by using locks and a reference count
+on the parent socket.  Any attempt to modify the parent socket will
+fail with EBUSY.
+
+Reported-by: Dmitry Vyukov <dvyukov@google.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ crypto/af_alg.c         |   35 ++++++++++++++++++++++++++++++++---
+ include/crypto/if_alg.h |    8 +++-----
+ 2 files changed, 35 insertions(+), 8 deletions(-)
+
+--- a/crypto/af_alg.c
++++ b/crypto/af_alg.c
+@@ -125,6 +125,23 @@ int af_alg_release(struct socket *sock)
+ }
+ EXPORT_SYMBOL_GPL(af_alg_release);
++void af_alg_release_parent(struct sock *sk)
++{
++      struct alg_sock *ask = alg_sk(sk);
++      bool last;
++
++      sk = ask->parent;
++      ask = alg_sk(sk);
++
++      lock_sock(sk);
++      last = !--ask->refcnt;
++      release_sock(sk);
++
++      if (last)
++              sock_put(sk);
++}
++EXPORT_SYMBOL_GPL(af_alg_release_parent);
++
+ static int alg_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
+ {
+       struct sock *sk = sock->sk;
+@@ -132,6 +149,7 @@ static int alg_bind(struct socket *sock,
+       struct sockaddr_alg *sa = (void *)uaddr;
+       const struct af_alg_type *type;
+       void *private;
++      int err;
+       if (sock->state == SS_CONNECTED)
+               return -EINVAL;
+@@ -157,16 +175,22 @@ static int alg_bind(struct socket *sock,
+               return PTR_ERR(private);
+       }
++      err = -EBUSY;
+       lock_sock(sk);
++      if (ask->refcnt)
++              goto unlock;
+       swap(ask->type, type);
+       swap(ask->private, private);
++      err = 0;
++
++unlock:
+       release_sock(sk);
+       alg_do_release(type, private);
+-      return 0;
++      return err;
+ }
+ static int alg_setkey(struct sock *sk, char __user *ukey,
+@@ -199,11 +223,15 @@ static int alg_setsockopt(struct socket
+       struct sock *sk = sock->sk;
+       struct alg_sock *ask = alg_sk(sk);
+       const struct af_alg_type *type;
+-      int err = -ENOPROTOOPT;
++      int err = -EBUSY;
+       lock_sock(sk);
++      if (ask->refcnt)
++              goto unlock;
++
+       type = ask->type;
++      err = -ENOPROTOOPT;
+       if (level != SOL_ALG || !type)
+               goto unlock;
+@@ -254,7 +282,8 @@ int af_alg_accept(struct sock *sk, struc
+       sk2->sk_family = PF_ALG;
+-      sock_hold(sk);
++      if (!ask->refcnt++)
++              sock_hold(sk);
+       alg_sk(sk2)->parent = sk;
+       alg_sk(sk2)->type = type;
+--- a/include/crypto/if_alg.h
++++ b/include/crypto/if_alg.h
+@@ -30,6 +30,8 @@ struct alg_sock {
+       struct sock *parent;
++      unsigned int refcnt;
++
+       const struct af_alg_type *type;
+       void *private;
+ };
+@@ -64,6 +66,7 @@ int af_alg_register_type(const struct af
+ int af_alg_unregister_type(const struct af_alg_type *type);
+ int af_alg_release(struct socket *sock);
++void af_alg_release_parent(struct sock *sk);
+ int af_alg_accept(struct sock *sk, struct socket *newsock);
+ int af_alg_make_sg(struct af_alg_sgl *sgl, void __user *addr, int len,
+@@ -80,11 +83,6 @@ static inline struct alg_sock *alg_sk(st
+       return (struct alg_sock *)sk;
+ }
+-static inline void af_alg_release_parent(struct sock *sk)
+-{
+-      sock_put(alg_sk(sk)->parent);
+-}
+-
+ static inline void af_alg_init_completion(struct af_alg_completion *completion)
+ {
+       init_completion(&completion->completion);
diff --git a/queue-3.10/crypto-af_alg-fix-socket-double-free-when-accept-fails.patch b/queue-3.10/crypto-af_alg-fix-socket-double-free-when-accept-fails.patch
new file mode 100644 (file)
index 0000000..d97dabe
--- /dev/null
@@ -0,0 +1,37 @@
+From a383292c86663bbc31ac62cc0c04fc77504636a6 Mon Sep 17 00:00:00 2001
+From: Herbert Xu <herbert@gondor.apana.org.au>
+Date: Wed, 30 Dec 2015 20:24:17 +0800
+Subject: crypto: af_alg - Fix socket double-free when accept fails
+
+From: Herbert Xu <herbert@gondor.apana.org.au>
+
+commit a383292c86663bbc31ac62cc0c04fc77504636a6 upstream.
+
+When we fail an accept(2) call we will end up freeing the socket
+twice, once due to the direct sk_free call and once again through
+newsock.
+
+This patch fixes this by removing the sk_free call.
+
+Reported-by: Dmitry Vyukov <dvyukov@google.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ crypto/af_alg.c |    4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+--- a/crypto/af_alg.c
++++ b/crypto/af_alg.c
+@@ -275,10 +275,8 @@ int af_alg_accept(struct sock *sk, struc
+       security_sk_clone(sk, sk2);
+       err = type->accept(ask->private, sk2);
+-      if (err) {
+-              sk_free(sk2);
++      if (err)
+               goto unlock;
+-      }
+       sk2->sk_family = PF_ALG;
index 06cf64ad3a963c7e72751717dc228bcd47d828b0..df54d690b5d50ece3fc962798c3854a4507b37ac 100644 (file)
@@ -52,3 +52,5 @@ usb-serial-option-adding-support-for-telit-le922.patch
 usb-option-fix-cinterion-ahxx-enumeration.patch
 tty-fix-unsafe-ldisc-reference-via-ioctl-tiocgetd.patch
 ext4-fix-handling-of-extended-tv_sec.patch
+crypto-af_alg-disallow-bind-setkey-...-after-accept-2.patch
+crypto-af_alg-fix-socket-double-free-when-accept-fails.patch