Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756187AbcCUN2b (ORCPT ); Mon, 21 Mar 2016 09:28:31 -0400 Received: from mail-wm0-f66.google.com ([74.125.82.66]:33846 "EHLO mail-wm0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756004AbcCUN0z (ORCPT ); Mon, 21 Mar 2016 09:26:55 -0400 From: Nicolai Stange To: Herbert Xu , "David S. Miller" Cc: Tadeusz Struk , Michal Marek , Andrzej Zaborowski , Stephan Mueller , Arnd Bergmann , linux-crypto@vger.kernel.org, linux-kernel@vger.kernel.org, Nicolai Stange Subject: [PATCH RESEND v2 14/14] lib/mpi: mpi_read_raw_from_sgl(): fix out-of-bounds buffer access Date: Mon, 21 Mar 2016 14:26:15 +0100 Message-Id: <1458566775-5239-15-git-send-email-nicstange@gmail.com> X-Mailer: git-send-email 2.7.3 In-Reply-To: <1458566775-5239-1-git-send-email-nicstange@gmail.com> References: <1458566775-5239-1-git-send-email-nicstange@gmail.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3462 Lines: 81 Within the copying loop in mpi_read_raw_from_sgl(), the last input SGE's byte count gets artificially extended as follows: if (sg_is_last(sg) && (len % BYTES_PER_MPI_LIMB)) len += BYTES_PER_MPI_LIMB - (len % BYTES_PER_MPI_LIMB); Within the following byte copying loop, this causes reads beyond that SGE's allocated buffer: BUG: KASAN: slab-out-of-bounds in mpi_read_raw_from_sgl+0x331/0x650 at addr ffff8801e168d4d8 Read of size 1 by task systemd-udevd/721 [...] Call Trace: [] dump_stack+0xbc/0x117 [] ? _atomic_dec_and_lock+0x169/0x169 [] ? print_section+0x61/0xb0 [] print_trailer+0x179/0x2c0 [] object_err+0x34/0x40 [] kasan_report_error+0x307/0x8c0 [] ? kasan_unpoison_shadow+0x35/0x50 [] ? kasan_kmalloc+0x5e/0x70 [] kasan_report+0x71/0xa0 [] ? mpi_read_raw_from_sgl+0x331/0x650 [] __asan_load1+0x46/0x50 [] mpi_read_raw_from_sgl+0x331/0x650 [] rsa_verify+0x106/0x260 [] ? rsa_set_pub_key+0xf0/0xf0 [] ? sg_init_table+0x29/0x50 [] ? pkcs1pad_sg_set_buf+0xb2/0x2e0 [] pkcs1pad_verify+0x1f4/0x2b0 [] public_key_verify_signature+0x3a7/0x5e0 [] ? public_key_describe+0x80/0x80 [] ? keyring_search_aux+0x150/0x150 [] ? x509_request_asymmetric_key+0x114/0x370 [] ? kfree+0x220/0x370 [] public_key_verify_signature_2+0x32/0x50 [] verify_signature+0x7c/0xb0 [] pkcs7_validate_trust+0x42c/0x5f0 [] system_verify_data+0xca/0x170 [] ? top_trace_array+0x9b/0x9b [] ? __vfs_read+0x279/0x3d0 [] mod_verify_sig+0x1ff/0x290 [...] The exact purpose of the len extension isn't clear to me, but due to its form, I suspect that it's a leftover somehow accounting for leading zero bytes within the most significant output limb. Note however that without that len adjustement, the total number of bytes ever processed by the inner loop equals nbytes and thus, the last output limb gets written at this point. Thus the net effect of the len adjustement cited above is just to keep the inner loop running for some more iterations, namely < BYTES_PER_MPI_LIMB ones, reading some extra bytes from beyond the last SGE's buffer and discarding them afterwards. Fix this issue by purging the extension of len beyond the last input SGE's buffer length. Fixes: 2d4d1eea540b ("lib/mpi: Add mpi sgl helpers") Signed-off-by: Nicolai Stange --- lib/mpi/mpicoder.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c index 3f114d2..0c534ac 100644 --- a/lib/mpi/mpicoder.c +++ b/lib/mpi/mpicoder.c @@ -484,9 +484,6 @@ MPI mpi_read_raw_from_sgl(struct scatterlist *sgl, unsigned int nbytes) const u8 *buffer = sg_virt(sg) + lzeros; int len = sg->length - lzeros; - if (sg_is_last(sg) && (len % BYTES_PER_MPI_LIMB)) - len += BYTES_PER_MPI_LIMB - (len % BYTES_PER_MPI_LIMB); - for (x = 0; x < len; x++) { a <<= 8; a |= *buffer++; -- 2.7.3