--- /dev/null
+From foo@baz Sat Mar 12 21:30:16 PST 2016
+Date: Sat, 12 Mar 2016 21:30:16 -0800
+To: Greg KH <gregkh@linuxfoundation.org>
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Subject: Revert: "crypto: af_alg - Disallow bind/setkey/... after accept(2)"
+
+This reverts commit 5a707f0972e1c9d8a4a921ddae79d0f9dc36a341 which is
+commit c840ac6af3f8713a71b4d2363419145760bd6044 upstream.
+
+It's been widely reported that this patch breaks existing userspace
+applications when backported to the stable kernel releases. As no fix
+seems to be forthcoming, just revert it to let systems work again.
+
+Reported-by: "J. Paul Reed" <preed@sigkill.com>
+Cc: Dmitry Vyukov <dvyukov@google.com>
+Cc: 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, 8 insertions(+), 35 deletions(-)
+
+--- a/crypto/af_alg.c
++++ b/crypto/af_alg.c
+@@ -125,23 +125,6 @@ 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;
+@@ -149,7 +132,6 @@ 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;
+@@ -175,22 +157,16 @@ 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 err;
++ return 0;
+ }
+
+ static int alg_setkey(struct sock *sk, char __user *ukey,
+@@ -223,15 +199,11 @@ 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 = -EBUSY;
++ int err = -ENOPROTOOPT;
+
+ lock_sock(sk);
+- if (ask->refcnt)
+- goto unlock;
+-
+ type = ask->type;
+
+- err = -ENOPROTOOPT;
+ if (level != SOL_ALG || !type)
+ goto unlock;
+
+@@ -280,8 +252,7 @@ int af_alg_accept(struct sock *sk, struc
+
+ sk2->sk_family = PF_ALG;
+
+- if (!ask->refcnt++)
+- sock_hold(sk);
++ 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,8 +30,6 @@ struct alg_sock {
+
+ struct sock *parent;
+
+- unsigned int refcnt;
+-
+ const struct af_alg_type *type;
+ void *private;
+ };
+@@ -66,7 +64,6 @@ 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,
+@@ -83,6 +80,11 @@ 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);