| 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); |