FAILED: patch "[PATCH] crypto: algif_skcipher - Require setkey before accept(2)" failed to apply to 3.14-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 3.14-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
Quoted 1 line
From
dd504589577d8e8e70f51f997ad487a4cb6c026fMon Sep 17 00:00:00 2001
From: Herbert Xu <[email protected]>
Date: Fri, 25 Dec 2015 15:40:05 +0800
Subject: [PATCH] crypto: algif_skcipher - Require setkey before accept(2)
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 <[email protected]>
Signed-off-by Herbert Xu <[email protected]>
Tested-by Dmitry Vyukov <[email protected]>
crypto/algif_skcipher.c +41 -7
@@ -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_ops = {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 *private, struct sock *sk) {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 *private, struct sock *sk) 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);