Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1329765
| From | Ben Hutchings <ben@decadent.org.uk> |
|---|---|
| Newsgroups | linux.kernel |
| Subject | [PATCH 3.2 73/87] crypto: algif_hash - Require setkey before accept(2) |
| Date | 2016-02-09 01:20 +0100 |
| Message-ID | <r04cb-4m5-23@gated-at.bofh.it> (permalink) |
| References | <r03SN-3V2-7@gated-at.bofh.it> |
| Organization | linux.* mail to news gateway |
3.2.77-rc1 review patch. If anyone has any objections, please let me know.
------------------
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>
[bwh: Backported to 3.2:
- Add struct kiocb * parameter to {recv,send}msg ops
- Adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
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 kiocb *unused, struct socket *sock,
struct msghdr *msg, size_t ignored)
{
@@ -246,22 +251,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 kiocb *unused, struct socket *sock,
+ struct msghdr *msg, size_t size)
+{
+ int err;
+
+ err = hash_check_key(sock);
+ if (err)
+ return err;
+
+ return hash_sendmsg(unused, 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 kiocb *unused, 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(unused, 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;
@@ -269,15 +403,40 @@ static void hash_sock_destruct(struct so
sock_kfree_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)
@@ -297,7 +456,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);
@@ -306,12 +465,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
};
Back to linux.kernel | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread
[PATCH 3.2 00/87] 3.2.77-rc1 review Ben Hutchings <ben@decadent.org.uk> - 2016-02-09 01:20 +0100
[PATCH 3.2 79/87] crypto: af_alg - Forbid bind(2) when nokey child sockets are present Ben Hutchings <ben@decadent.org.uk> - 2016-02-09 01:20 +0100
[PATCH 3.2 17/87] asix: silence log message from oversize packet Ben Hutchings <ben@decadent.org.uk> - 2016-02-09 01:20 +0100
[PATCH 3.2 73/87] crypto: algif_hash - Require setkey before accept(2) Ben Hutchings <ben@decadent.org.uk> - 2016-02-09 01:20 +0100
[PATCH 3.2 18/87] futex: Drop refcount if requeue_pi() acquired the rtmutex Ben Hutchings <ben@decadent.org.uk> - 2016-02-09 01:20 +0100
[PATCH 3.2 60/87] crypto: af_alg - Fix socket double-free when accept fails Ben Hutchings <ben@decadent.org.uk> - 2016-02-09 01:20 +0100
[PATCH 3.2 72/87] crypto: hash - Add crypto_ahash_has_setkey Ben Hutchings <ben@decadent.org.uk> - 2016-02-09 01:20 +0100
[PATCH 3.2 70/87] crypto: af_alg - Add nokey compatibility path Ben Hutchings <ben@decadent.org.uk> - 2016-02-09 01:20 +0100
[PATCH 3.2 57/87] ALSA: timer: Harden slave timer list handling Ben Hutchings <ben@decadent.org.uk> - 2016-02-09 01:20 +0100
[PATCH 3.2 61/87] ALSA: hrtimer: Fix stall by hrtimer_cancel() Ben Hutchings <ben@decadent.org.uk> - 2016-02-09 01:20 +0100
[PATCH 3.2 82/87] crypto: algif_skcipher - Load TX SG list after waiting Ben Hutchings <ben@decadent.org.uk> - 2016-02-09 01:20 +0100
[PATCH 3.2 11/87] rtlwifi: fix memory leak for USB device Ben Hutchings <ben@decadent.org.uk> - 2016-02-09 01:20 +0100
[PATCH 3.2 64/87] ALSA: control: Avoid kernel warnings from tlv ioctl with numid 0 Ben Hutchings <ben@decadent.org.uk> - 2016-02-09 01:20 +0100
[PATCH 3.2 01/87] [media] gspca: ov534/topro: prevent a division by 0 Ben Hutchings <ben@decadent.org.uk> - 2016-02-09 01:20 +0100
[PATCH 3.2 08/87] mtd: nand: fix ONFI parameter page layout Ben Hutchings <ben@decadent.org.uk> - 2016-02-09 01:30 +0100
[PATCH 3.2 80/87] crypto: algif_hash - Fix race condition in hash_check_key Ben Hutchings <ben@decadent.org.uk> - 2016-02-09 01:30 +0100
[PATCH 3.2 04/87] SCSI: initio: remove duplicate module device table Ben Hutchings <ben@decadent.org.uk> - 2016-02-09 01:30 +0100
[PATCH 3.2 87/87] [media] usbvision: fix crash on detecting device with invalid configuration Ben Hutchings <ben@decadent.org.uk> - 2016-02-09 01:30 +0100
[PATCH 3.2 15/87] powerpc: Make value-returning atomics fully ordered Ben Hutchings <ben@decadent.org.uk> - 2016-02-09 01:30 +0100
[PATCH 3.2 10/87] xhci: refuse loading if nousb is used Ben Hutchings <ben@decadent.org.uk> - 2016-02-09 01:30 +0100
[PATCH 3.2 05/87] KVM: x86: expose MSR_TSC_AUX to userspace Ben Hutchings <ben@decadent.org.uk> - 2016-02-09 01:30 +0100
[PATCH 3.2 86/87] [media] usbvision fix overflow of interfaces array Ben Hutchings <ben@decadent.org.uk> - 2016-02-09 01:30 +0100
[PATCH 3.2 85/87] [media] usbvision: fix leak of usb_dev on failure paths in usbvision_probe() Ben Hutchings <ben@decadent.org.uk> - 2016-02-09 01:30 +0100
[PATCH 3.2 07/87] ath9k_htc: check for underflow in ath9k_htc_rx_msg() Ben Hutchings <ben@decadent.org.uk> - 2016-02-09 01:30 +0100
[PATCH 3.2 13/87] wlcore/wl12xx: spi: fix oops on firmware load Ben Hutchings <ben@decadent.org.uk> - 2016-02-09 01:30 +0100
[PATCH 3.2 14/87] EDAC: Robustify workqueues destruction Ben Hutchings <ben@decadent.org.uk> - 2016-02-09 01:30 +0100
[PATCH 3.2 19/87] ALSA: fm801: propagate TUNER_ONLY bit when autodetected Ben Hutchings <ben@decadent.org.uk> - 2016-02-09 01:30 +0100
[PATCH 3.2 84/87] [media] usbvision-video: fix memory leak of alt_max_pkt_size Ben Hutchings <ben@decadent.org.uk> - 2016-02-09 01:30 +0100
[PATCH 3.2 12/87] wlcore: SPI - fix spi transfer_list Ben Hutchings <ben@decadent.org.uk> - 2016-02-09 01:30 +0100
[PATCH 3.2 16/87] powerpc: Make {cmp}xchg* and their atomic_ versions fully ordered Ben Hutchings <ben@decadent.org.uk> - 2016-02-09 01:30 +0100
[PATCH 3.2 78/87] crypto: algif_skcipher - Remove custom release parent function Ben Hutchings <ben@decadent.org.uk> - 2016-02-09 01:30 +0100
[PATCH 3.2 03/87] [media] rc: allow rc modules to be loaded if rc-main is not a module Ben Hutchings <ben@decadent.org.uk> - 2016-02-09 01:30 +0100
Re: [PATCH 3.2 00/87] 3.2.77-rc1 review Guenter Roeck <linux@roeck-us.net> - 2016-02-09 05:00 +0100
Re: [PATCH 3.2 00/87] 3.2.77-rc1 review Ben Hutchings <ben@decadent.org.uk> - 2016-02-10 02:10 +0100
csiph-web