--- /dev/null
+From 37766586c965d63758ad542325a96d5384f4a8c9 Mon Sep 17 00:00:00 2001
+From: Herbert Xu <herbert@gondor.apana.org.au>
+Date: Mon, 4 Jan 2016 13:35:18 +0900
+Subject: crypto: af_alg - Add nokey compatibility path
+
+From: Herbert Xu <herbert@gondor.apana.org.au>
+
+commit 37766586c965d63758ad542325a96d5384f4a8c9 upstream.
+
+This patch adds a compatibility path to support old applications
+that do acept(2) before setkey.
+
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ crypto/af_alg.c | 13 ++++++++++++-
+ include/crypto/if_alg.h | 2 ++
+ 2 files changed, 14 insertions(+), 1 deletion(-)
+
+--- a/crypto/af_alg.c
++++ b/crypto/af_alg.c
+@@ -76,6 +76,8 @@ int af_alg_register_type(const struct af
+ goto unlock;
+
+ type->ops->owner = THIS_MODULE;
++ if (type->ops_nokey)
++ type->ops_nokey->owner = THIS_MODULE;
+ node->type = type;
+ list_add(&node->list, &alg_types);
+ err = 0;
+@@ -267,6 +269,7 @@ int af_alg_accept(struct sock *sk, struc
+ const struct af_alg_type *type;
+ struct sock *sk2;
+ int err;
++ bool nokey;
+
+ lock_sock(sk);
+ type = ask->type;
+@@ -285,12 +288,17 @@ int af_alg_accept(struct sock *sk, struc
+ security_sk_clone(sk, sk2);
+
+ err = type->accept(ask->private, sk2);
++
++ nokey = err == -ENOKEY;
++ if (nokey && type->accept_nokey)
++ err = type->accept_nokey(ask->private, sk2);
++
+ if (err)
+ goto unlock;
+
+ sk2->sk_family = PF_ALG;
+
+- if (!ask->refcnt++)
++ if (nokey || !ask->refcnt++)
+ sock_hold(sk);
+ alg_sk(sk2)->parent = sk;
+ alg_sk(sk2)->type = type;
+@@ -298,6 +306,9 @@ int af_alg_accept(struct sock *sk, struc
+ newsock->ops = type->ops;
+ newsock->state = SS_CONNECTED;
+
++ if (nokey)
++ newsock->ops = type->ops_nokey;
++
+ err = 0;
+
+ unlock:
+--- a/include/crypto/if_alg.h
++++ b/include/crypto/if_alg.h
+@@ -52,9 +52,11 @@ struct af_alg_type {
+ void (*release)(void *private);
+ int (*setkey)(void *private, const u8 *key, unsigned int keylen);
+ int (*accept)(void *private, struct sock *sk);
++ int (*accept_nokey)(void *private, struct sock *sk);
+ int (*setauthsize)(void *private, unsigned int authsize);
+
+ struct proto_ops *ops;
++ struct proto_ops *ops_nokey;
+ struct module *owner;
+ char name[14];
+ };
--- /dev/null
+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)
+ {
+ const u32 forbidden = CRYPTO_ALG_INTERNAL;
+@@ -133,6 +150,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;
+@@ -160,16 +178,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,
+@@ -202,11 +226,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;
+
+@@ -264,7 +292,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;
+ };
+@@ -67,6 +69,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, struct iov_iter *iter, int len);
+@@ -83,11 +86,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);
--- /dev/null
+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
+@@ -285,10 +285,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;
+
--- /dev/null
+From 6de62f15b581f920ade22d758f4c338311c2f0d4 Mon Sep 17 00:00:00 2001
+From: Herbert Xu <herbert@gondor.apana.org.au>
+Date: Fri, 8 Jan 2016 21:31:04 +0800
+Subject: crypto: algif_hash - Require setkey before accept(2)
+
+From: Herbert Xu <herbert@gondor.apana.org.au>
+
+commit 6de62f15b581f920ade22d758f4c338311c2f0d4 upstream.
+
+Hash implementations that require a key may crash if you use
+them without setting a key. This patch adds the necessary checks
+so that if you do attempt to use them without a key that we return
+-ENOKEY instead of proceeding.
+
+This patch also adds a compatibility path to support old applications
+that do acept(2) before setkey.
+
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ crypto/algif_hash.c | 201 +++++++++++++++++++++++++++++++++++++++++++++++++---
+ 1 file changed, 193 insertions(+), 8 deletions(-)
+
+--- a/crypto/algif_hash.c
++++ b/crypto/algif_hash.c
+@@ -34,6 +34,11 @@ struct hash_ctx {
+ struct ahash_request req;
+ };
+
++struct algif_hash_tfm {
++ struct crypto_ahash *hash;
++ bool has_key;
++};
++
+ static int hash_sendmsg(struct socket *sock, struct msghdr *msg,
+ size_t ignored)
+ {
+@@ -235,22 +240,151 @@ static struct proto_ops algif_hash_ops =
+ .accept = hash_accept,
+ };
+
++static int hash_check_key(struct socket *sock)
++{
++ int err;
++ struct sock *psk;
++ struct alg_sock *pask;
++ struct algif_hash_tfm *tfm;
++ struct sock *sk = sock->sk;
++ struct alg_sock *ask = alg_sk(sk);
++
++ if (ask->refcnt)
++ return 0;
++
++ psk = ask->parent;
++ pask = alg_sk(ask->parent);
++ tfm = pask->private;
++
++ err = -ENOKEY;
++ lock_sock(psk);
++ if (!tfm->has_key)
++ goto unlock;
++
++ if (!pask->refcnt++)
++ sock_hold(psk);
++
++ ask->refcnt = 1;
++ sock_put(psk);
++
++ err = 0;
++
++unlock:
++ release_sock(psk);
++
++ return err;
++}
++
++static int hash_sendmsg_nokey(struct socket *sock, struct msghdr *msg,
++ size_t size)
++{
++ int err;
++
++ err = hash_check_key(sock);
++ if (err)
++ return err;
++
++ return hash_sendmsg(sock, msg, size);
++}
++
++static ssize_t hash_sendpage_nokey(struct socket *sock, struct page *page,
++ int offset, size_t size, int flags)
++{
++ int err;
++
++ err = hash_check_key(sock);
++ if (err)
++ return err;
++
++ return hash_sendpage(sock, page, offset, size, flags);
++}
++
++static int hash_recvmsg_nokey(struct socket *sock, struct msghdr *msg,
++ size_t ignored, int flags)
++{
++ int err;
++
++ err = hash_check_key(sock);
++ if (err)
++ return err;
++
++ return hash_recvmsg(sock, msg, ignored, flags);
++}
++
++static int hash_accept_nokey(struct socket *sock, struct socket *newsock,
++ int flags)
++{
++ int err;
++
++ err = hash_check_key(sock);
++ if (err)
++ return err;
++
++ return hash_accept(sock, newsock, flags);
++}
++
++static struct proto_ops algif_hash_ops_nokey = {
++ .family = PF_ALG,
++
++ .connect = sock_no_connect,
++ .socketpair = sock_no_socketpair,
++ .getname = sock_no_getname,
++ .ioctl = sock_no_ioctl,
++ .listen = sock_no_listen,
++ .shutdown = sock_no_shutdown,
++ .getsockopt = sock_no_getsockopt,
++ .mmap = sock_no_mmap,
++ .bind = sock_no_bind,
++ .setsockopt = sock_no_setsockopt,
++ .poll = sock_no_poll,
++
++ .release = af_alg_release,
++ .sendmsg = hash_sendmsg_nokey,
++ .sendpage = hash_sendpage_nokey,
++ .recvmsg = hash_recvmsg_nokey,
++ .accept = hash_accept_nokey,
++};
++
+ static void *hash_bind(const char *name, u32 type, u32 mask)
+ {
+- return crypto_alloc_ahash(name, type, mask);
++ struct algif_hash_tfm *tfm;
++ struct crypto_ahash *hash;
++
++ tfm = kzalloc(sizeof(*tfm), GFP_KERNEL);
++ if (!tfm)
++ return ERR_PTR(-ENOMEM);
++
++ hash = crypto_alloc_ahash(name, type, mask);
++ if (IS_ERR(hash)) {
++ kfree(tfm);
++ return ERR_CAST(hash);
++ }
++
++ tfm->hash = hash;
++
++ return tfm;
+ }
+
+ static void hash_release(void *private)
+ {
+- crypto_free_ahash(private);
++ struct algif_hash_tfm *tfm = private;
++
++ crypto_free_ahash(tfm->hash);
++ kfree(tfm);
+ }
+
+ static int hash_setkey(void *private, const u8 *key, unsigned int keylen)
+ {
+- return crypto_ahash_setkey(private, key, keylen);
++ struct algif_hash_tfm *tfm = private;
++ int err;
++
++ err = crypto_ahash_setkey(tfm->hash, key, keylen);
++ tfm->has_key = !err;
++
++ return err;
+ }
+
+-static void hash_sock_destruct(struct sock *sk)
++static void hash_sock_destruct_common(struct sock *sk)
+ {
+ struct alg_sock *ask = alg_sk(sk);
+ struct hash_ctx *ctx = ask->private;
+@@ -258,15 +392,40 @@ static void hash_sock_destruct(struct so
+ sock_kzfree_s(sk, ctx->result,
+ crypto_ahash_digestsize(crypto_ahash_reqtfm(&ctx->req)));
+ sock_kfree_s(sk, ctx, ctx->len);
++}
++
++static void hash_sock_destruct(struct sock *sk)
++{
++ hash_sock_destruct_common(sk);
+ af_alg_release_parent(sk);
+ }
+
+-static int hash_accept_parent(void *private, struct sock *sk)
++static void hash_release_parent_nokey(struct sock *sk)
++{
++ struct alg_sock *ask = alg_sk(sk);
++
++ if (!ask->refcnt) {
++ sock_put(ask->parent);
++ return;
++ }
++
++ af_alg_release_parent(sk);
++}
++
++static void hash_sock_destruct_nokey(struct sock *sk)
++{
++ hash_sock_destruct_common(sk);
++ hash_release_parent_nokey(sk);
++}
++
++static int hash_accept_parent_common(void *private, struct sock *sk)
+ {
+ struct hash_ctx *ctx;
+ struct alg_sock *ask = alg_sk(sk);
+- unsigned len = sizeof(*ctx) + crypto_ahash_reqsize(private);
+- unsigned ds = crypto_ahash_digestsize(private);
++ struct algif_hash_tfm *tfm = private;
++ struct crypto_ahash *hash = tfm->hash;
++ unsigned len = sizeof(*ctx) + crypto_ahash_reqsize(hash);
++ unsigned ds = crypto_ahash_digestsize(hash);
+
+ ctx = sock_kmalloc(sk, len, GFP_KERNEL);
+ if (!ctx)
+@@ -286,7 +445,7 @@ static int hash_accept_parent(void *priv
+
+ ask->private = ctx;
+
+- ahash_request_set_tfm(&ctx->req, private);
++ ahash_request_set_tfm(&ctx->req, hash);
+ ahash_request_set_callback(&ctx->req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+ af_alg_complete, &ctx->completion);
+
+@@ -295,12 +454,38 @@ static int hash_accept_parent(void *priv
+ return 0;
+ }
+
++static int hash_accept_parent(void *private, struct sock *sk)
++{
++ struct algif_hash_tfm *tfm = private;
++
++ if (!tfm->has_key && crypto_ahash_has_setkey(tfm->hash))
++ return -ENOKEY;
++
++ return hash_accept_parent_common(private, sk);
++}
++
++static int hash_accept_parent_nokey(void *private, struct sock *sk)
++{
++ int err;
++
++ err = hash_accept_parent_common(private, sk);
++ if (err)
++ goto out;
++
++ sk->sk_destruct = hash_sock_destruct_nokey;
++
++out:
++ return err;
++}
++
+ static const struct af_alg_type algif_type_hash = {
+ .bind = hash_bind,
+ .release = hash_release,
+ .setkey = hash_setkey,
+ .accept = hash_accept_parent,
++ .accept_nokey = hash_accept_parent_nokey,
+ .ops = &algif_hash_ops,
++ .ops_nokey = &algif_hash_ops_nokey,
+ .name = "hash",
+ .owner = THIS_MODULE
+ };
--- /dev/null
+From 6e8d8ecf438792ecf7a3207488fb4eebc4edb040 Mon Sep 17 00:00:00 2001
+From: Herbert Xu <herbert@gondor.apana.org.au>
+Date: Mon, 11 Jan 2016 21:29:41 +0800
+Subject: crypto: algif_skcipher - Add key check exception for cipher_null
+
+From: Herbert Xu <herbert@gondor.apana.org.au>
+
+commit 6e8d8ecf438792ecf7a3207488fb4eebc4edb040 upstream.
+
+This patch adds an exception to the key check so that cipher_null
+users may continue to use algif_skcipher without setting a key.
+
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ crypto/algif_skcipher.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/crypto/algif_skcipher.c
++++ b/crypto/algif_skcipher.c
+@@ -978,7 +978,7 @@ static int skcipher_accept_parent(void *
+ {
+ struct skcipher_tfm *tfm = private;
+
+- if (!tfm->has_key)
++ if (!tfm->has_key && crypto_skcipher_has_setkey(tfm->skcipher))
+ return -ENOKEY;
+
+ return skcipher_accept_parent_common(private, sk);
--- /dev/null
+From a0fa2d037129a9849918a92d91b79ed6c7bd2818 Mon Sep 17 00:00:00 2001
+From: Herbert Xu <herbert@gondor.apana.org.au>
+Date: Mon, 4 Jan 2016 13:36:12 +0900
+Subject: crypto: algif_skcipher - Add nokey compatibility path
+
+From: Herbert Xu <herbert@gondor.apana.org.au>
+
+commit a0fa2d037129a9849918a92d91b79ed6c7bd2818 upstream.
+
+This patch adds a compatibility path to support old applications
+that do acept(2) before setkey.
+
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ crypto/algif_skcipher.c | 149 ++++++++++++++++++++++++++++++++++++++++++++++--
+ 1 file changed, 144 insertions(+), 5 deletions(-)
+
+--- a/crypto/algif_skcipher.c
++++ b/crypto/algif_skcipher.c
+@@ -753,6 +753,99 @@ static struct proto_ops algif_skcipher_o
+ .poll = skcipher_poll,
+ };
+
++static int skcipher_check_key(struct socket *sock)
++{
++ int err;
++ struct sock *psk;
++ struct alg_sock *pask;
++ struct skcipher_tfm *tfm;
++ struct sock *sk = sock->sk;
++ struct alg_sock *ask = alg_sk(sk);
++
++ if (ask->refcnt)
++ return 0;
++
++ psk = ask->parent;
++ pask = alg_sk(ask->parent);
++ tfm = pask->private;
++
++ err = -ENOKEY;
++ lock_sock(psk);
++ if (!tfm->has_key)
++ goto unlock;
++
++ if (!pask->refcnt++)
++ sock_hold(psk);
++
++ ask->refcnt = 1;
++ sock_put(psk);
++
++ err = 0;
++
++unlock:
++ release_sock(psk);
++
++ return err;
++}
++
++static int skcipher_sendmsg_nokey(struct socket *sock, struct msghdr *msg,
++ size_t size)
++{
++ int err;
++
++ err = skcipher_check_key(sock);
++ if (err)
++ return err;
++
++ return skcipher_sendmsg(sock, msg, size);
++}
++
++static ssize_t skcipher_sendpage_nokey(struct socket *sock, struct page *page,
++ int offset, size_t size, int flags)
++{
++ int err;
++
++ err = skcipher_check_key(sock);
++ if (err)
++ return err;
++
++ return skcipher_sendpage(sock, page, offset, size, flags);
++}
++
++static int skcipher_recvmsg_nokey(struct socket *sock, struct msghdr *msg,
++ size_t ignored, int flags)
++{
++ int err;
++
++ err = skcipher_check_key(sock);
++ if (err)
++ return err;
++
++ return skcipher_recvmsg(sock, msg, ignored, flags);
++}
++
++static struct proto_ops algif_skcipher_ops_nokey = {
++ .family = PF_ALG,
++
++ .connect = sock_no_connect,
++ .socketpair = sock_no_socketpair,
++ .getname = sock_no_getname,
++ .ioctl = sock_no_ioctl,
++ .listen = sock_no_listen,
++ .shutdown = sock_no_shutdown,
++ .getsockopt = sock_no_getsockopt,
++ .mmap = sock_no_mmap,
++ .bind = sock_no_bind,
++ .accept = sock_no_accept,
++ .setsockopt = sock_no_setsockopt,
++
++ .release = af_alg_release,
++ .sendmsg = skcipher_sendmsg_nokey,
++ .sendpage = skcipher_sendpage_nokey,
++ .recvmsg = skcipher_recvmsg_nokey,
++ .poll = skcipher_poll,
++};
++
+ static void *skcipher_bind(const char *name, u32 type, u32 mask)
+ {
+ struct skcipher_tfm *tfm;
+@@ -802,7 +895,7 @@ static void skcipher_wait(struct sock *s
+ msleep(100);
+ }
+
+-static void skcipher_sock_destruct(struct sock *sk)
++static void skcipher_sock_destruct_common(struct sock *sk)
+ {
+ struct alg_sock *ask = alg_sk(sk);
+ struct skcipher_ctx *ctx = ask->private;
+@@ -814,10 +907,33 @@ static void skcipher_sock_destruct(struc
+ skcipher_free_sgl(sk);
+ sock_kzfree_s(sk, ctx->iv, crypto_skcipher_ivsize(tfm));
+ sock_kfree_s(sk, ctx, ctx->len);
++}
++
++static void skcipher_sock_destruct(struct sock *sk)
++{
++ skcipher_sock_destruct_common(sk);
+ af_alg_release_parent(sk);
+ }
+
+-static int skcipher_accept_parent(void *private, struct sock *sk)
++static void skcipher_release_parent_nokey(struct sock *sk)
++{
++ struct alg_sock *ask = alg_sk(sk);
++
++ if (!ask->refcnt) {
++ sock_put(ask->parent);
++ return;
++ }
++
++ af_alg_release_parent(sk);
++}
++
++static void skcipher_sock_destruct_nokey(struct sock *sk)
++{
++ skcipher_sock_destruct_common(sk);
++ skcipher_release_parent_nokey(sk);
++}
++
++static int skcipher_accept_parent_common(void *private, struct sock *sk)
+ {
+ struct skcipher_ctx *ctx;
+ struct alg_sock *ask = alg_sk(sk);
+@@ -825,9 +941,6 @@ static int skcipher_accept_parent(void *
+ struct crypto_skcipher *skcipher = tfm->skcipher;
+ unsigned int len = sizeof(*ctx) + crypto_skcipher_reqsize(skcipher);
+
+- if (!tfm->has_key)
+- return -ENOKEY;
+-
+ ctx = sock_kmalloc(sk, len, GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+@@ -861,12 +974,38 @@ static int skcipher_accept_parent(void *
+ return 0;
+ }
+
++static int skcipher_accept_parent(void *private, struct sock *sk)
++{
++ struct skcipher_tfm *tfm = private;
++
++ if (!tfm->has_key)
++ return -ENOKEY;
++
++ return skcipher_accept_parent_common(private, sk);
++}
++
++static int skcipher_accept_parent_nokey(void *private, struct sock *sk)
++{
++ int err;
++
++ err = skcipher_accept_parent_common(private, sk);
++ if (err)
++ goto out;
++
++ sk->sk_destruct = skcipher_sock_destruct_nokey;
++
++out:
++ return err;
++}
++
+ static const struct af_alg_type algif_type_skcipher = {
+ .bind = skcipher_bind,
+ .release = skcipher_release,
+ .setkey = skcipher_setkey,
+ .accept = skcipher_accept_parent,
++ .accept_nokey = skcipher_accept_parent_nokey,
+ .ops = &algif_skcipher_ops,
++ .ops_nokey = &algif_skcipher_ops_nokey,
+ .name = "skcipher",
+ .owner = THIS_MODULE
+ };
--- /dev/null
+From dd504589577d8e8e70f51f997ad487a4cb6c026f Mon Sep 17 00:00:00 2001
+From: Herbert Xu <herbert@gondor.apana.org.au>
+Date: Fri, 25 Dec 2015 15:40:05 +0800
+Subject: crypto: algif_skcipher - Require setkey before accept(2)
+
+From: Herbert Xu <herbert@gondor.apana.org.au>
+
+commit dd504589577d8e8e70f51f997ad487a4cb6c026f upstream.
+
+Some cipher implementations will crash if you try to use them
+without calling setkey first. This patch adds a check so that
+the accept(2) call will fail with -ENOKEY if setkey hasn't been
+done on the socket yet.
+
+Reported-by: Dmitry Vyukov <dvyukov@google.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Tested-by: Dmitry Vyukov <dvyukov@google.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ crypto/algif_skcipher.c | 48 +++++++++++++++++++++++++++++++++++++++++-------
+ 1 file changed, 41 insertions(+), 7 deletions(-)
+
+--- a/crypto/algif_skcipher.c
++++ b/crypto/algif_skcipher.c
+@@ -31,6 +31,11 @@ struct skcipher_sg_list {
+ struct scatterlist sg[0];
+ };
+
++struct skcipher_tfm {
++ struct crypto_skcipher *skcipher;
++ bool has_key;
++};
++
+ struct skcipher_ctx {
+ struct list_head tsgl;
+ struct af_alg_sgl rsgl;
+@@ -750,17 +755,41 @@ static struct proto_ops algif_skcipher_o
+
+ static void *skcipher_bind(const char *name, u32 type, u32 mask)
+ {
+- return crypto_alloc_skcipher(name, type, mask);
++ struct skcipher_tfm *tfm;
++ struct crypto_skcipher *skcipher;
++
++ tfm = kzalloc(sizeof(*tfm), GFP_KERNEL);
++ if (!tfm)
++ return ERR_PTR(-ENOMEM);
++
++ skcipher = crypto_alloc_skcipher(name, type, mask);
++ if (IS_ERR(skcipher)) {
++ kfree(tfm);
++ return ERR_CAST(skcipher);
++ }
++
++ tfm->skcipher = skcipher;
++
++ return tfm;
+ }
+
+ static void skcipher_release(void *private)
+ {
+- crypto_free_skcipher(private);
++ struct skcipher_tfm *tfm = private;
++
++ crypto_free_skcipher(tfm->skcipher);
++ kfree(tfm);
+ }
+
+ static int skcipher_setkey(void *private, const u8 *key, unsigned int keylen)
+ {
+- return crypto_skcipher_setkey(private, key, keylen);
++ struct skcipher_tfm *tfm = private;
++ int err;
++
++ err = crypto_skcipher_setkey(tfm->skcipher, key, keylen);
++ tfm->has_key = !err;
++
++ return err;
+ }
+
+ static void skcipher_wait(struct sock *sk)
+@@ -792,20 +821,25 @@ static int skcipher_accept_parent(void *
+ {
+ struct skcipher_ctx *ctx;
+ struct alg_sock *ask = alg_sk(sk);
+- unsigned int len = sizeof(*ctx) + crypto_skcipher_reqsize(private);
++ struct skcipher_tfm *tfm = private;
++ struct crypto_skcipher *skcipher = tfm->skcipher;
++ unsigned int len = sizeof(*ctx) + crypto_skcipher_reqsize(skcipher);
++
++ if (!tfm->has_key)
++ return -ENOKEY;
+
+ ctx = sock_kmalloc(sk, len, GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+- ctx->iv = sock_kmalloc(sk, crypto_skcipher_ivsize(private),
++ ctx->iv = sock_kmalloc(sk, crypto_skcipher_ivsize(skcipher),
+ GFP_KERNEL);
+ if (!ctx->iv) {
+ sock_kfree_s(sk, ctx, len);
+ return -ENOMEM;
+ }
+
+- memset(ctx->iv, 0, crypto_skcipher_ivsize(private));
++ memset(ctx->iv, 0, crypto_skcipher_ivsize(skcipher));
+
+ INIT_LIST_HEAD(&ctx->tsgl);
+ ctx->len = len;
+@@ -818,7 +852,7 @@ static int skcipher_accept_parent(void *
+
+ ask->private = ctx;
+
+- skcipher_request_set_tfm(&ctx->req, private);
++ skcipher_request_set_tfm(&ctx->req, skcipher);
+ skcipher_request_set_callback(&ctx->req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+ af_alg_complete, &ctx->completion);
+
--- /dev/null
+From a5596d6332787fd383b3b5427b41f94254430827 Mon Sep 17 00:00:00 2001
+From: Herbert Xu <herbert@gondor.apana.org.au>
+Date: Fri, 8 Jan 2016 21:28:26 +0800
+Subject: crypto: hash - Add crypto_ahash_has_setkey
+
+From: Herbert Xu <herbert@gondor.apana.org.au>
+
+commit a5596d6332787fd383b3b5427b41f94254430827 upstream.
+
+This patch adds a way for ahash users to determine whether a key
+is required by a crypto_ahash transform.
+
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ crypto/ahash.c | 5 ++++-
+ crypto/shash.c | 4 +++-
+ include/crypto/hash.h | 6 ++++++
+ 3 files changed, 13 insertions(+), 2 deletions(-)
+
+--- a/crypto/ahash.c
++++ b/crypto/ahash.c
+@@ -451,6 +451,7 @@ static int crypto_ahash_init_tfm(struct
+ struct ahash_alg *alg = crypto_ahash_alg(hash);
+
+ hash->setkey = ahash_nosetkey;
++ hash->has_setkey = false;
+ hash->export = ahash_no_export;
+ hash->import = ahash_no_import;
+
+@@ -463,8 +464,10 @@ static int crypto_ahash_init_tfm(struct
+ hash->finup = alg->finup ?: ahash_def_finup;
+ hash->digest = alg->digest;
+
+- if (alg->setkey)
++ if (alg->setkey) {
+ hash->setkey = alg->setkey;
++ hash->has_setkey = true;
++ }
+ if (alg->export)
+ hash->export = alg->export;
+ if (alg->import)
+--- a/crypto/shash.c
++++ b/crypto/shash.c
+@@ -355,8 +355,10 @@ int crypto_init_shash_ops_async(struct c
+ crt->finup = shash_async_finup;
+ crt->digest = shash_async_digest;
+
+- if (alg->setkey)
++ if (alg->setkey) {
+ crt->setkey = shash_async_setkey;
++ crt->has_setkey = true;
++ }
+ if (alg->export)
+ crt->export = shash_async_export;
+ if (alg->import)
+--- a/include/crypto/hash.h
++++ b/include/crypto/hash.h
+@@ -204,6 +204,7 @@ struct crypto_ahash {
+ unsigned int keylen);
+
+ unsigned int reqsize;
++ bool has_setkey;
+ struct crypto_tfm base;
+ };
+
+@@ -361,6 +362,11 @@ static inline void *ahash_request_ctx(st
+ int crypto_ahash_setkey(struct crypto_ahash *tfm, const u8 *key,
+ unsigned int keylen);
+
++static inline bool crypto_ahash_has_setkey(struct crypto_ahash *tfm)
++{
++ return tfm->has_setkey;
++}
++
+ /**
+ * crypto_ahash_finup() - update and finalize message digest
+ * @req: reference to the ahash_request handle that holds all information
--- /dev/null
+From a1383cd86a062fc798899ab20f0ec2116cce39cb Mon Sep 17 00:00:00 2001
+From: Herbert Xu <herbert@gondor.apana.org.au>
+Date: Mon, 11 Jan 2016 21:26:50 +0800
+Subject: crypto: skcipher - Add crypto_skcipher_has_setkey
+
+From: Herbert Xu <herbert@gondor.apana.org.au>
+
+commit a1383cd86a062fc798899ab20f0ec2116cce39cb upstream.
+
+This patch adds a way for skcipher users to determine whether a key
+is required by a transform.
+
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ crypto/skcipher.c | 2 ++
+ include/crypto/skcipher.h | 7 +++++++
+ 2 files changed, 9 insertions(+)
+
+--- a/crypto/skcipher.c
++++ b/crypto/skcipher.c
+@@ -118,6 +118,7 @@ int crypto_init_skcipher_ops_blkcipher(s
+ skcipher->decrypt = skcipher_decrypt_blkcipher;
+
+ skcipher->ivsize = crypto_blkcipher_ivsize(blkcipher);
++ skcipher->has_setkey = calg->cra_blkcipher.max_keysize;
+
+ return 0;
+ }
+@@ -210,6 +211,7 @@ int crypto_init_skcipher_ops_ablkcipher(
+ skcipher->ivsize = crypto_ablkcipher_ivsize(ablkcipher);
+ skcipher->reqsize = crypto_ablkcipher_reqsize(ablkcipher) +
+ sizeof(struct ablkcipher_request);
++ skcipher->has_setkey = calg->cra_ablkcipher.max_keysize;
+
+ return 0;
+ }
+--- a/include/crypto/skcipher.h
++++ b/include/crypto/skcipher.h
+@@ -61,6 +61,8 @@ struct crypto_skcipher {
+ unsigned int ivsize;
+ unsigned int reqsize;
+
++ bool has_setkey;
++
+ struct crypto_tfm base;
+ };
+
+@@ -305,6 +307,11 @@ static inline int crypto_skcipher_setkey
+ return tfm->setkey(tfm, key, keylen);
+ }
+
++static inline bool crypto_skcipher_has_setkey(struct crypto_skcipher *tfm)
++{
++ return tfm->has_setkey;
++}
++
+ /**
+ * crypto_skcipher_reqtfm() - obtain cipher handle from request
+ * @req: skcipher_request out of which the cipher handle is to be obtained
ext4-fix-an-endianness-bug-in-ext4_encrypted_zeroout.patch
ext4-fix-an-endianness-bug-in-ext4_encrypted_follow_link.patch
sched-fix-crash-in-sched_init_numa.patch
+crypto-algif_skcipher-require-setkey-before-accept-2.patch
+crypto-af_alg-disallow-bind-setkey-...-after-accept-2.patch
+crypto-af_alg-fix-socket-double-free-when-accept-fails.patch
+crypto-af_alg-add-nokey-compatibility-path.patch
+crypto-algif_skcipher-add-nokey-compatibility-path.patch
+crypto-hash-add-crypto_ahash_has_setkey.patch
+crypto-algif_hash-require-setkey-before-accept-2.patch
+crypto-skcipher-add-crypto_skcipher_has_setkey.patch
+crypto-algif_skcipher-add-key-check-exception-for-cipher_null.patch