Received: by 2002:ac0:a5a7:0:0:0:0:0 with SMTP id m36-v6csp2578926imm; Thu, 16 Aug 2018 11:50:21 -0700 (PDT) X-Google-Smtp-Source: AA+uWPxw/oJg/5Gu0AjGBhGHNU6o1MGDgmd9GZvTp6CUbUx4E2alDvKUGFkEH2z/3VEciKr+p4Tf X-Received: by 2002:a63:ef10:: with SMTP id u16-v6mr30466612pgh.269.1534445421640; Thu, 16 Aug 2018 11:50:21 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1534445421; cv=none; d=google.com; s=arc-20160816; b=H/eZgtaW6FTGECsY3j0nUIAVNP47KYpF5aX0v8a6jFKBFoBKEXqCaUmfWjImSsBBMq NOAx+a9GIMCPlknNLdJ2XeJHPgGGEblokse4XvKbYVr/i16tc9mjpOw7pG3evnBCRA9C bRg1GflHMfRV4IpVPjmIh5VJOntBPkzt+ZFCIz3IV7TNycwq5fBzU0IPD4nwFE3jvuc6 gjPlY+/J8E6zhW0ZcpvPauyMiSMR8JTAPWc43+dHeiza3zBzoOftVoYNRtjesPtw3P6w WPLOejl8rZiru9kjMiK6SS0UrFe8Hsqb7AboNl1nbLlXtmxMZfufdl1ciot6HHSjW0fU wBjw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:user-agent:references :in-reply-to:message-id:date:subject:cc:to:from :arc-authentication-results; bh=wt8AXYDlriFAoJqsOZRvq++Qc6qhBW5VoNUt17NsNDs=; b=w87Z2oQ6X6C2kgR2kQsGL8q3ZRE90mO73cnMeGZH6v1VEB9US0Gxxb2lZMmnRhprSh TYXIbH6SFWm1D5PRlwmva5SSvattMk8wAxcgskCPyqGxR6M3YzZ2CQH2vVfCzRFBfbjK wSQwEV3OKE63SZT+HCUeAhyr14WZSIhXaoKUNLJqQnjzd4YWdNR+PfvHr9T5QGKVzX+p 8rhS5vQlWsTaE0vXgKyg1BJ3ikDcrhcvOouaTw3VtHclEaJDlkdVLNbkG3nqysqbUllc TsqQG5w5PVy6Pres0BQSzOjYWNEcU57nqTsMKBODvbsUpey7FPe95Lg3XWE4QM+aZ+Ep kGiQ== ARC-Authentication-Results: i=1; mx.google.com; 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 Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id f27-v6si43408pgb.302.2018.08.16.11.50.05; Thu, 16 Aug 2018 11:50:21 -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; 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 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728371AbeHPVm0 (ORCPT + 99 others); Thu, 16 Aug 2018 17:42:26 -0400 Received: from mail.linuxfoundation.org ([140.211.169.12]:56048 "EHLO mail.linuxfoundation.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728344AbeHPVmZ (ORCPT ); Thu, 16 Aug 2018 17:42:25 -0400 Received: from localhost (unknown [194.244.16.108]) by mail.linuxfoundation.org (Postfix) with ESMTPSA id 6B6DFCB7; Thu, 16 Aug 2018 18:42:17 +0000 (UTC) From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Liu Chao , Eric Biggers , Herbert Xu Subject: [PATCH 3.18 13/15] crypto: blkcipher - fix crash flushing dcache in error path Date: Thu, 16 Aug 2018 20:41:50 +0200 Message-Id: <20180816171634.055296313@linuxfoundation.org> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180816171633.546734046@linuxfoundation.org> References: <20180816171633.546734046@linuxfoundation.org> User-Agent: quilt/0.65 X-stable: review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 3.18-stable review patch. If anyone has any objections, please let me know. ------------------ From: Eric Biggers commit 0868def3e4100591e7a1fdbf3eed1439cc8f7ca3 upstream. Like the skcipher_walk case: scatterwalk_done() is only meant to be called after a nonzero number of bytes have been processed, since scatterwalk_pagedone() will flush the dcache of the *previous* page. But in the error case of blkcipher_walk_done(), e.g. if the input wasn't an integer number of blocks, scatterwalk_done() was actually called after advancing 0 bytes. This caused a crash ("BUG: unable to handle kernel paging request") during '!PageSlab(page)' on architectures like arm and arm64 that define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE, provided that the input was page-aligned as in that case walk->offset == 0. Fix it by reorganizing blkcipher_walk_done() to skip the scatterwalk_advance() and scatterwalk_done() if an error has occurred. This bug was found by syzkaller fuzzing. Reproducer, assuming ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE: #include #include #include int main() { struct sockaddr_alg addr = { .salg_type = "skcipher", .salg_name = "ecb(aes-generic)", }; char buffer[4096] __attribute__((aligned(4096))) = { 0 }; int fd; fd = socket(AF_ALG, SOCK_SEQPACKET, 0); bind(fd, (void *)&addr, sizeof(addr)); setsockopt(fd, SOL_ALG, ALG_SET_KEY, buffer, 16); fd = accept(fd, NULL, NULL); write(fd, buffer, 15); read(fd, buffer, 15); } Reported-by: Liu Chao Fixes: 5cde0af2a982 ("[CRYPTO] cipher: Added block cipher type") Cc: # v2.6.19+ Signed-off-by: Eric Biggers Signed-off-by: Herbert Xu Signed-off-by: Greg Kroah-Hartman --- crypto/blkcipher.c | 54 +++++++++++++++++++++++++---------------------------- 1 file changed, 26 insertions(+), 28 deletions(-) --- a/crypto/blkcipher.c +++ b/crypto/blkcipher.c @@ -70,19 +70,18 @@ static inline u8 *blkcipher_get_spot(u8 return max(start, end_page); } -static inline unsigned int blkcipher_done_slow(struct blkcipher_walk *walk, - unsigned int bsize) +static inline void blkcipher_done_slow(struct blkcipher_walk *walk, + unsigned int bsize) { u8 *addr; addr = (u8 *)ALIGN((unsigned long)walk->buffer, walk->alignmask + 1); addr = blkcipher_get_spot(addr, bsize); scatterwalk_copychunks(addr, &walk->out, bsize, 1); - return bsize; } -static inline unsigned int blkcipher_done_fast(struct blkcipher_walk *walk, - unsigned int n) +static inline void blkcipher_done_fast(struct blkcipher_walk *walk, + unsigned int n) { if (walk->flags & BLKCIPHER_WALK_COPY) { blkcipher_map_dst(walk); @@ -96,49 +95,48 @@ static inline unsigned int blkcipher_don scatterwalk_advance(&walk->in, n); scatterwalk_advance(&walk->out, n); - - return n; } int blkcipher_walk_done(struct blkcipher_desc *desc, struct blkcipher_walk *walk, int err) { - unsigned int nbytes = 0; + unsigned int n; /* bytes processed */ + bool more; - if (likely(err >= 0)) { - unsigned int n = walk->nbytes - err; + if (unlikely(err < 0)) + goto finish; - if (likely(!(walk->flags & BLKCIPHER_WALK_SLOW))) - n = blkcipher_done_fast(walk, n); - else if (WARN_ON(err)) { + n = walk->nbytes - err; + walk->total -= n; + more = (walk->total != 0); + + if (likely(!(walk->flags & BLKCIPHER_WALK_SLOW))) { + blkcipher_done_fast(walk, n); + } else { + if (WARN_ON(err)) { + /* unexpected case; didn't process all bytes */ err = -EINVAL; - goto err; - } else - n = blkcipher_done_slow(walk, n); - - nbytes = walk->total - n; - err = 0; + goto finish; + } + blkcipher_done_slow(walk, n); } - scatterwalk_done(&walk->in, 0, nbytes); - scatterwalk_done(&walk->out, 1, nbytes); - -err: - walk->total = nbytes; - walk->nbytes = nbytes; + scatterwalk_done(&walk->in, 0, more); + scatterwalk_done(&walk->out, 1, more); - if (nbytes) { + if (more) { crypto_yield(desc->flags); return blkcipher_walk_next(desc, walk); } - + err = 0; +finish: + walk->nbytes = 0; if (walk->iv != desc->info) memcpy(desc->info, walk->iv, walk->ivsize); if (walk->buffer != walk->page) kfree(walk->buffer); if (walk->page) free_page((unsigned long)walk->page); - return err; } EXPORT_SYMBOL_GPL(blkcipher_walk_done);