From: <gregkh@linuxfoundation.org>
To: herbert@gondor.apana.org.au, gregkh@linuxfoundation.org
Cc: <stable@vger.kernel.org>, <stable-commits@vger.kernel.org>
Subject: Patch "crypto: algif_hash - Require setkey before accept(2)" has been added to the 4.3-stable tree
Date: Sun, 14 Feb 2016 13:30:40 -0800 [thread overview]
Message-ID: <1455485440198166@kroah.com> (raw)
This is a note to let you know that I've just added the patch titled
crypto: algif_hash - Require setkey before accept(2)
to the 4.3-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
crypto-algif_hash-require-setkey-before-accept-2.patch
and it can be found in the queue-4.3 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@vger.kernel.org> know about it.
>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
};
Patches currently in stable-queue which might be from herbert@gondor.apana.org.au are
queue-4.3/crypto-fix-test-vector-for-rsa.patch
queue-4.3/crypto-algif_skcipher-use-new-skcipher-interface.patch
queue-4.3/crypto-af_alg-disallow-bind-setkey-...-after-accept-2.patch
queue-4.3/crypto-crc32c-pclmul-use-.rodata-instead-of-.rotata.patch
queue-4.3/crypto-caam-fix-non-block-aligned-hash-calculation.patch
queue-4.3/crypto-nx-fix-timing-leak-in-gcm-and-ccm-decryption.patch
queue-4.3/crypto-skcipher-copy-iv-from-desc-even-for-0-len-walks.patch
queue-4.3/crypto-skcipher-add-crypto_skcipher_has_setkey.patch
queue-4.3/crypto-algif_skcipher-add-key-check-exception-for-cipher_null.patch
queue-4.3/crypto-algif_skcipher-require-setkey-before-accept-2.patch
queue-4.3/crypto-algif_skcipher-add-nokey-compatibility-path.patch
queue-4.3/crypto-hash-add-crypto_ahash_has_setkey.patch
queue-4.3/crypto-af_alg-add-nokey-compatibility-path.patch
queue-4.3/crypto-sun4i-ss-add-missing-statesize.patch
queue-4.3/crypto-algif_hash-require-setkey-before-accept-2.patch
queue-4.3/crypto-qat-don-t-use-userspace-pointer.patch
queue-4.3/crypto-talitos-fix-timing-leak-in-esp-icv-verification.patch
queue-4.3/crypto-algif_hash-only-export-and-import-on-sockets-with-data.patch
queue-4.3/crypto-af_alg-fix-socket-double-free-when-accept-fails.patch
reply other threads:[~2016-02-14 21:30 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1455485440198166@kroah.com \
--to=gregkh@linuxfoundation.org \
--cc=herbert@gondor.apana.org.au \
--cc=stable-commits@vger.kernel.org \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.