Received: by 2002:ac0:a5a6:0:0:0:0:0 with SMTP id m35-v6csp2870632imm; Tue, 4 Sep 2018 11:18:09 -0700 (PDT) X-Google-Smtp-Source: ANB0Vdbh0NE3b6tHHWk5q9lkDhmYQ7gv27Un057vG5qQTZkbXHg7Tc5EACMUvTX0sHXZgcB53Uh1 X-Received: by 2002:aa7:86cb:: with SMTP id h11-v6mr35803332pfo.58.1536085089760; Tue, 04 Sep 2018 11:18:09 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1536085089; cv=none; d=google.com; s=arc-20160816; b=YjeRiSUPGn0uJGdxnWo1/KwWDG8w657HGjQKovjQnq/WzrhrjDN00QoyU8bTPqJbx0 Tiewkficmq5G9ZibIgH4aGpq2P2Pg0+LhBjCBFgfLK8C2Nyij/qlxBkSJ9C9huyD3KzG X4tNy4hRvU0PrvfcQGj5Ch9DYfb0y5biHC11aYMnPgn9buFVabrHSXjS4Enhj/Txfg9t fTsLcd3T1Flv6phwpmddC9q/kIIrmS8qldAAzeNcpAdZoUs7ObQf478MrsO7/c/+YjUE dlcv+KHbcCgDeZtU0vupPeNGErfhc3HqQP/4DmRH5DJNqI2xHRhBkD+lthC5uWWDrOHb hsIA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=nB+CR4lS0Xcd10F4octuTThVuwMrMZ6zDzWzpkfENAU=; b=jl3qvZ5AE0mNqDM224VEmUOfW5WQBd+R2JgVwHH2vu54TfljF2G8KO56GgM1b52OEf zG4nCDgR9h3BvaTt4uUlZ9jrxK163fYqsAxKZujG9UceKQ7LOGMWDDv0VKaQ9tcYozkq 6i1KmqpEf7PQzB50daUYzUygUI5BU7lkgqpr5YS/Vtrb0Phdd2uiiuexD3CnPovlCJhH DpVsLGVm1uwb1JlvPsQShNZ4DXC36bmfXgL53S6Q7Gq8Cw8//6ifBJ0CTMniqjs7JHrR /GJufDySbLfK8KAoboWNuWTELDZC4VeMCBNanD1BQk6xmBy/EM5pN+ahw09P5If4LTWy 2FUA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=mB7gQLn9; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id e6-v6si23051222plk.441.2018.09.04.11.17.54; Tue, 04 Sep 2018 11:18:09 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@chromium.org header.s=google header.b=mB7gQLn9; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=chromium.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727828AbeIDWm6 (ORCPT + 99 others); Tue, 4 Sep 2018 18:42:58 -0400 Received: from mail-pl1-f196.google.com ([209.85.214.196]:38835 "EHLO mail-pl1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727694AbeIDWmv (ORCPT ); Tue, 4 Sep 2018 18:42:51 -0400 Received: by mail-pl1-f196.google.com with SMTP id u11-v6so2010553plq.5 for ; Tue, 04 Sep 2018 11:16:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=nB+CR4lS0Xcd10F4octuTThVuwMrMZ6zDzWzpkfENAU=; b=mB7gQLn9jE8CIQ48SkjDwKzCmmooepbjeWhWNfhtqWZcUFHV13vxPfd9ht7cLaRq90 BSOUQ4Se8KZVs/NGvmfPxKBa/1mZYZZHU/SmM7/UmXPw/5pmb+/8vGTUJm4dhLUCRcaY ZRnBSJr1hYw9RMt9JbKRPJ/W70F5/0HY1+ANA= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=nB+CR4lS0Xcd10F4octuTThVuwMrMZ6zDzWzpkfENAU=; b=Uh2ZQU1aX77J0LzDTrisEX8ok5kmaPQorPnxXrFQ+dj001xUSFApj/YfFm/paIhs1K DWHbfflBaG0qjwJQkm+y6Kl32DHWlkRYDzoqSEOS+inuxA7rTqq1R5fZloQ85S51ufE9 10Y7RbMOldwYB19gD0kaaxHyeb6Hapd0wPOqVGGSsQXQzxfJO67+FHPunfLXQDacCeCd N2Y7+e+FfU6u0eAR+6CJgSITLEYq0jfl8/AoEZLHQC8qiv+IUufswM5Ai3h3miRx52RV Sode1ikrgCfdnu452WHbYjuokEhl/0dubi1wVL0+rEIhJzlGoOEzQPvyhQqrJMEvTmcR ejvQ== X-Gm-Message-State: APzg51DOluDcUV8x/2qprJF5ebxoIPE2zyblUpRSLV9Zlc0PffNYqVjB zI4VvzWn6K6RbbHKUHw6ifNK0Q== X-Received: by 2002:a17:902:64c1:: with SMTP id y1-v6mr34164880pli.45.1536084995849; Tue, 04 Sep 2018 11:16:35 -0700 (PDT) Received: from www.outflux.net (173-164-112-133-Oregon.hfc.comcastbusiness.net. [173.164.112.133]) by smtp.gmail.com with ESMTPSA id z11-v6sm31792016pff.162.2018.09.04.11.16.32 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 04 Sep 2018 11:16:32 -0700 (PDT) From: Kees Cook To: Herbert Xu Cc: Kees Cook , Eric Biggers , Ard Biesheuvel , Gilad Ben-Yossef , Antoine Tenart , Boris Brezillon , Arnaud Ebalard , Corentin Labbe , Maxime Ripard , Chen-Yu Tsai , Christian Lamparter , Philippe Ombredanne , Jonathan Cameron , linux-crypto@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [PATCH 1/2] crypto: skcipher: Allow crypto_skcipher_set_reqsize() to fail Date: Tue, 4 Sep 2018 11:16:28 -0700 Message-Id: <20180904181629.20712-2-keescook@chromium.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180904181629.20712-1-keescook@chromium.org> References: <20180904181629.20712-1-keescook@chromium.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org In the quest to remove all stack VLA usage from the kernel[1], we must put an upper limit on how large an skcipher's reqsize can grow. In order to cleanly handle this limit, crypto_skcipher_set_reqsize() must report whether the desired reqsize is allowed. This means all callers need to check the new return value and handle any cleanup now. This patch adds the return value and updates all the callers to check the result and act appropriately. A followup patch will add the new bounds checking to crypto_skcipher_set_reqsize(). [1] https://lkml.kernel.org/r/CA+55aFzCG-zNmZwX4A2FQpadafLfEzK6CC=qPXydAacU1RqZWA@mail.gmail.com Signed-off-by: Kees Cook --- crypto/cryptd.c | 7 +++++-- crypto/ctr.c | 7 +++++-- crypto/cts.c | 7 +++++-- crypto/lrw.c | 9 ++++++--- crypto/simd.c | 7 +++++-- crypto/xts.c | 11 ++++++++--- drivers/crypto/amcc/crypto4xx_core.c | 8 +++++++- drivers/crypto/cavium/nitrox/nitrox_algs.c | 9 +++++++-- drivers/crypto/ccree/cc_cipher.c | 6 ++++-- drivers/crypto/hisilicon/sec/sec_algs.c | 5 ++++- drivers/crypto/inside-secure/safexcel_cipher.c | 5 ++++- drivers/crypto/marvell/cipher.c | 4 +--- drivers/crypto/sunxi-ss/sun4i-ss-cipher.c | 4 +--- include/crypto/internal/skcipher.h | 4 +++- 14 files changed, 65 insertions(+), 28 deletions(-) diff --git a/crypto/cryptd.c b/crypto/cryptd.c index addca7bae33f..e0131907a537 100644 --- a/crypto/cryptd.c +++ b/crypto/cryptd.c @@ -563,15 +563,18 @@ static int cryptd_skcipher_init_tfm(struct crypto_skcipher *tfm) struct crypto_skcipher_spawn *spawn = &ictx->spawn; struct cryptd_skcipher_ctx *ctx = crypto_skcipher_ctx(tfm); struct crypto_skcipher *cipher; + int ret; cipher = crypto_spawn_skcipher(spawn); if (IS_ERR(cipher)) return PTR_ERR(cipher); ctx->child = cipher; - crypto_skcipher_set_reqsize( + ret = crypto_skcipher_set_reqsize( tfm, sizeof(struct cryptd_skcipher_request_ctx)); - return 0; + if (ret) + crypto_free_skcipher(ctx->child); + return ret; } static void cryptd_skcipher_exit_tfm(struct crypto_skcipher *tfm) diff --git a/crypto/ctr.c b/crypto/ctr.c index 435b75bd619e..70b8496ee569 100644 --- a/crypto/ctr.c +++ b/crypto/ctr.c @@ -319,6 +319,7 @@ static int crypto_rfc3686_init_tfm(struct crypto_skcipher *tfm) struct crypto_skcipher *cipher; unsigned long align; unsigned int reqsize; + int ret; cipher = crypto_spawn_skcipher(spawn); if (IS_ERR(cipher)) @@ -330,9 +331,11 @@ static int crypto_rfc3686_init_tfm(struct crypto_skcipher *tfm) align &= ~(crypto_tfm_ctx_alignment() - 1); reqsize = align + sizeof(struct crypto_rfc3686_req_ctx) + crypto_skcipher_reqsize(cipher); - crypto_skcipher_set_reqsize(tfm, reqsize); + ret = crypto_skcipher_set_reqsize(tfm, reqsize); + if (ret) + crypto_free_skcipher(ctx->child); - return 0; + return ret; } static void crypto_rfc3686_exit_tfm(struct crypto_skcipher *tfm) diff --git a/crypto/cts.c b/crypto/cts.c index 4e28d83ae37d..f04c29f4197f 100644 --- a/crypto/cts.c +++ b/crypto/cts.c @@ -289,6 +289,7 @@ static int crypto_cts_init_tfm(struct crypto_skcipher *tfm) unsigned reqsize; unsigned bsize; unsigned align; + int ret; cipher = crypto_spawn_skcipher(spawn); if (IS_ERR(cipher)) @@ -303,9 +304,11 @@ static int crypto_cts_init_tfm(struct crypto_skcipher *tfm) crypto_tfm_ctx_alignment()) + (align & ~(crypto_tfm_ctx_alignment() - 1)) + bsize; - crypto_skcipher_set_reqsize(tfm, reqsize); + ret = crypto_skcipher_set_reqsize(tfm, reqsize); + if (ret) + crypto_free_skcipher(ctx->child); - return 0; + return ret; } static void crypto_cts_exit_tfm(struct crypto_skcipher *tfm) diff --git a/crypto/lrw.c b/crypto/lrw.c index 393a782679c7..dc344046b637 100644 --- a/crypto/lrw.c +++ b/crypto/lrw.c @@ -426,6 +426,7 @@ static int init_tfm(struct crypto_skcipher *tfm) struct crypto_skcipher_spawn *spawn = skcipher_instance_ctx(inst); struct priv *ctx = crypto_skcipher_ctx(tfm); struct crypto_skcipher *cipher; + int ret; cipher = crypto_spawn_skcipher(spawn); if (IS_ERR(cipher)) @@ -433,10 +434,12 @@ static int init_tfm(struct crypto_skcipher *tfm) ctx->child = cipher; - crypto_skcipher_set_reqsize(tfm, crypto_skcipher_reqsize(cipher) + - sizeof(struct rctx)); + ret = crypto_skcipher_set_reqsize(tfm, + crypto_skcipher_reqsize(cipher) + sizeof(struct rctx)); + if (ret) + crypto_free_skcipher(ctx->child); - return 0; + return ret; } static void exit_tfm(struct crypto_skcipher *tfm) diff --git a/crypto/simd.c b/crypto/simd.c index ea7240be3001..bf1a27057e92 100644 --- a/crypto/simd.c +++ b/crypto/simd.c @@ -112,6 +112,7 @@ static int simd_skcipher_init(struct crypto_skcipher *tfm) struct simd_skcipher_alg *salg; struct skcipher_alg *alg; unsigned reqsize; + int ret; alg = crypto_skcipher_alg(tfm); salg = container_of(alg, struct simd_skcipher_alg, alg); @@ -127,9 +128,11 @@ static int simd_skcipher_init(struct crypto_skcipher *tfm) reqsize = sizeof(struct skcipher_request); reqsize += crypto_skcipher_reqsize(&cryptd_tfm->base); - crypto_skcipher_set_reqsize(tfm, reqsize); + ret = crypto_skcipher_set_reqsize(tfm, reqsize); + if (ret) + cryptd_free_skcipher(ctx->cryptd_tfm); - return 0; + return ret; } struct simd_skcipher_alg *simd_skcipher_create_compat(const char *algname, diff --git a/crypto/xts.c b/crypto/xts.c index ccf55fbb8bc2..d7a85abb9723 100644 --- a/crypto/xts.c +++ b/crypto/xts.c @@ -364,6 +364,7 @@ static int init_tfm(struct crypto_skcipher *tfm) struct priv *ctx = crypto_skcipher_ctx(tfm); struct crypto_skcipher *child; struct crypto_cipher *tweak; + int ret; child = crypto_spawn_skcipher(&ictx->spawn); if (IS_ERR(child)) @@ -379,10 +380,14 @@ static int init_tfm(struct crypto_skcipher *tfm) ctx->tweak = tweak; - crypto_skcipher_set_reqsize(tfm, crypto_skcipher_reqsize(child) + - sizeof(struct rctx)); + ret = crypto_skcipher_set_reqsize(tfm, + crypto_skcipher_reqsize(child) + sizeof(struct rctx)); + if (ret) { + crypto_free_cipher(ctx->tweak); + crypto_free_skcipher(ctx->child); + } - return 0; + return ret; } static void exit_tfm(struct crypto_skcipher *tfm) diff --git a/drivers/crypto/amcc/crypto4xx_core.c b/drivers/crypto/amcc/crypto4xx_core.c index 6eaec9ba0f68..de41bc35629c 100644 --- a/drivers/crypto/amcc/crypto4xx_core.c +++ b/drivers/crypto/amcc/crypto4xx_core.c @@ -951,6 +951,8 @@ static int crypto4xx_sk_init(struct crypto_skcipher *sk) struct crypto4xx_ctx *ctx = crypto_skcipher_ctx(sk); if (alg->base.cra_flags & CRYPTO_ALG_NEED_FALLBACK) { + int ret; + ctx->sw_cipher.cipher = crypto_alloc_skcipher(alg->base.cra_name, 0, CRYPTO_ALG_NEED_FALLBACK | @@ -958,9 +960,13 @@ static int crypto4xx_sk_init(struct crypto_skcipher *sk) if (IS_ERR(ctx->sw_cipher.cipher)) return PTR_ERR(ctx->sw_cipher.cipher); - crypto_skcipher_set_reqsize(sk, + ret = crypto_skcipher_set_reqsize(sk, sizeof(struct skcipher_request) + 32 + crypto_skcipher_reqsize(ctx->sw_cipher.cipher)); + if (ret) { + crypto_free_skcipher(ctx->sw_cipher.cipher); + return ret; + } } amcc_alg = container_of(alg, struct crypto4xx_alg, alg.u.cipher); diff --git a/drivers/crypto/cavium/nitrox/nitrox_algs.c b/drivers/crypto/cavium/nitrox/nitrox_algs.c index 2ae6124e5da6..f0e688d37da6 100644 --- a/drivers/crypto/cavium/nitrox/nitrox_algs.c +++ b/drivers/crypto/cavium/nitrox/nitrox_algs.c @@ -74,6 +74,7 @@ static int nitrox_skcipher_init(struct crypto_skcipher *tfm) { struct nitrox_crypto_ctx *nctx = crypto_skcipher_ctx(tfm); void *fctx; + int ret; /* get the first device */ nctx->ndev = nitrox_get_first_device(); @@ -87,9 +88,13 @@ static int nitrox_skcipher_init(struct crypto_skcipher *tfm) return -ENOMEM; } nctx->u.ctx_handle = (uintptr_t)fctx; - crypto_skcipher_set_reqsize(tfm, crypto_skcipher_reqsize(tfm) + + ret = crypto_skcipher_set_reqsize(tfm, crypto_skcipher_reqsize(tfm) + sizeof(struct nitrox_kcrypt_request)); - return 0; + if (ret) { + crypto_free_context(fctx); + nitrox_put_device(nctx->ndev); + } + return ret; } static void nitrox_skcipher_exit(struct crypto_skcipher *tfm) diff --git a/drivers/crypto/ccree/cc_cipher.c b/drivers/crypto/ccree/cc_cipher.c index 7623b29911af..ec8e9506f4c5 100644 --- a/drivers/crypto/ccree/cc_cipher.c +++ b/drivers/crypto/ccree/cc_cipher.c @@ -136,13 +136,15 @@ static int cc_cipher_init(struct crypto_tfm *tfm) skcipher_alg.base); struct device *dev = drvdata_to_dev(cc_alg->drvdata); unsigned int max_key_buf_size = cc_alg->skcipher_alg.max_keysize; - int rc = 0; + int rc; dev_dbg(dev, "Initializing context @%p for %s\n", ctx_p, crypto_tfm_alg_name(tfm)); - crypto_skcipher_set_reqsize(__crypto_skcipher_cast(tfm), + rc = crypto_skcipher_set_reqsize(__crypto_skcipher_cast(tfm), sizeof(struct cipher_req_ctx)); + if (rc) + return rc; ctx_p->cipher_mode = cc_alg->cipher_mode; ctx_p->flow_mode = cc_alg->flow_mode; diff --git a/drivers/crypto/hisilicon/sec/sec_algs.c b/drivers/crypto/hisilicon/sec/sec_algs.c index f7d6d690116e..b10ff7202718 100644 --- a/drivers/crypto/hisilicon/sec/sec_algs.c +++ b/drivers/crypto/hisilicon/sec/sec_algs.c @@ -880,10 +880,13 @@ static int sec_alg_skcipher_decrypt(struct skcipher_request *req) static int sec_alg_skcipher_init(struct crypto_skcipher *tfm) { struct sec_alg_tfm_ctx *ctx = crypto_skcipher_ctx(tfm); + int ret; mutex_init(&ctx->lock); INIT_LIST_HEAD(&ctx->backlog); - crypto_skcipher_set_reqsize(tfm, sizeof(struct sec_request)); + ret = crypto_skcipher_set_reqsize(tfm, sizeof(struct sec_request)); + if (ret) + return ret; ctx->queue = sec_queue_alloc_start_safe(); if (IS_ERR(ctx->queue)) diff --git a/drivers/crypto/inside-secure/safexcel_cipher.c b/drivers/crypto/inside-secure/safexcel_cipher.c index 3aef1d43e435..b64a245a00fb 100644 --- a/drivers/crypto/inside-secure/safexcel_cipher.c +++ b/drivers/crypto/inside-secure/safexcel_cipher.c @@ -782,9 +782,12 @@ static int safexcel_skcipher_cra_init(struct crypto_tfm *tfm) struct safexcel_alg_template *tmpl = container_of(tfm->__crt_alg, struct safexcel_alg_template, alg.skcipher.base); + int ret; - crypto_skcipher_set_reqsize(__crypto_skcipher_cast(tfm), + ret = crypto_skcipher_set_reqsize(__crypto_skcipher_cast(tfm), sizeof(struct safexcel_cipher_req)); + if (ret) + return ret; ctx->priv = tmpl->priv; diff --git a/drivers/crypto/marvell/cipher.c b/drivers/crypto/marvell/cipher.c index 0ae84ec9e21c..41a2e047beb6 100644 --- a/drivers/crypto/marvell/cipher.c +++ b/drivers/crypto/marvell/cipher.c @@ -241,10 +241,8 @@ static int mv_cesa_skcipher_cra_init(struct crypto_tfm *tfm) ctx->ops = &mv_cesa_skcipher_req_ops; - crypto_skcipher_set_reqsize(__crypto_skcipher_cast(tfm), + return crypto_skcipher_set_reqsize(__crypto_skcipher_cast(tfm), sizeof(struct mv_cesa_skcipher_req)); - - return 0; } static int mv_cesa_aes_setkey(struct crypto_skcipher *cipher, const u8 *key, diff --git a/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c b/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c index 5cf64746731a..d01fb1054b77 100644 --- a/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c +++ b/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c @@ -465,10 +465,8 @@ int sun4i_ss_cipher_init(struct crypto_tfm *tfm) alg.crypto.base); op->ss = algt->ss; - crypto_skcipher_set_reqsize(__crypto_skcipher_cast(tfm), + return crypto_skcipher_set_reqsize(__crypto_skcipher_cast(tfm), sizeof(struct sun4i_cipher_req_ctx)); - - return 0; } /* check and set the AES key, prepare the mode to be used */ diff --git a/include/crypto/internal/skcipher.h b/include/crypto/internal/skcipher.h index e42f7063f245..d2926ecae2ac 100644 --- a/include/crypto/internal/skcipher.h +++ b/include/crypto/internal/skcipher.h @@ -127,10 +127,12 @@ static inline struct crypto_skcipher *crypto_spawn_skcipher( return crypto_spawn_tfm2(&spawn->base); } -static inline void crypto_skcipher_set_reqsize( +static inline int crypto_skcipher_set_reqsize( struct crypto_skcipher *skcipher, unsigned int reqsize) { skcipher->reqsize = reqsize; + + return 0; } int crypto_register_skcipher(struct skcipher_alg *alg); -- 2.17.1