From patchwork Mon Nov 27 07:12:12 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 10075959 X-Patchwork-Delegate: herbert@gondor.apana.org.au Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 93043602BD for ; Mon, 27 Nov 2017 07:15:15 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 794F71FFDA for ; Mon, 27 Nov 2017 07:15:15 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6E12528C79; Mon, 27 Nov 2017 07:15:15 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E502128CE3 for ; Mon, 27 Nov 2017 07:15:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751156AbdK0HPN (ORCPT ); Mon, 27 Nov 2017 02:15:13 -0500 Received: from mail-pg0-f65.google.com ([74.125.83.65]:45271 "EHLO mail-pg0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750838AbdK0HPM (ORCPT ); Mon, 27 Nov 2017 02:15:12 -0500 Received: by mail-pg0-f65.google.com with SMTP id 207so18285012pgc.12; Sun, 26 Nov 2017 23:15:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=6P+fb0ALmOXdKBl4FcceaIIMd7lZDNLpkBzmIBXGmhw=; b=lmEcOWJqxQjsRDQKZzpdT86kncQGF2GtLkAk4KmEfSNKHaZ90v28lcsObt0b8i9kLI UEJtHNfEIE9RuvmqHXONhyYSde39hiUKB6f9iCGA8AQz7quUi7+nhj3KqtMqvnd36Xk7 id5Rnojz/6Lw4MglVfYOQy+yqsfcjfrw0kagwCBPIgNIIPKSEAHhVzqbmqkyBSsZsymG jJvUATiQL+ZuAm81u8x2FcKZ8HjLKOs9Ty97Lfqe0z63a+eaNaQWBmlHtz1z8S2zf/5B OQFrSH8rLGWUUfSX5AFn7rycS39vNZjtlsdINVYShY/VsPkH9hK/0+/F9unJd51Aqw/9 UpaA== 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; bh=6P+fb0ALmOXdKBl4FcceaIIMd7lZDNLpkBzmIBXGmhw=; b=hkKNR27mj07czaF3bzGwogFfJmjV5E6fUFktxXCBGyaXX98QngfCv2T0hcLMxkzua3 +YHHGDMOH1Qk5W0d+7+4XRdDKeN+wst98Ezwwvegw5+bE+W45viCJbD95t3/Z2XxWjHZ xCERrqiydJMw7hTffn0pin08Tr7FB7/1VfTMfLbt0qWUxGDdzWjNvyAD6pwR3zw7IURC uViKVgQbzoHFKArrVG9AiLOGL+N0vA2/hI+7OmyGrStVIu5QHhmDmt4OdrO+3C5cHPJe TTR+Vlzhj04ApwYNl+mgkeBqEBgGxUOiyDn89Dy72HbK4yqh4T4O/0rNSSDAuI0HKexC cciw== X-Gm-Message-State: AJaThX61NL6m4EwUreohJm5VP+7DAoVCi66YYj88rjoB6kyXO00qrcBe ooBF++eaxEd+5f4Eg6kmSIR8Tqjy X-Google-Smtp-Source: AGs4zMZFQRNcOP5WjItg9k9kZt5QUMblWm3uEaC7PUZ8gNKQyMBR3GIjvBORAmzhQor2sWXF4XOKEQ== X-Received: by 10.99.108.66 with SMTP id h63mr36031619pgc.362.1511766911329; Sun, 26 Nov 2017 23:15:11 -0800 (PST) Received: from zzz.localdomain (c-67-185-97-198.hsd1.wa.comcast.net. [67.185.97.198]) by smtp.gmail.com with ESMTPSA id x6sm46297909pff.55.2017.11.26.23.15.10 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 26 Nov 2017 23:15:10 -0800 (PST) From: Eric Biggers To: keyrings@vger.kernel.org, David Howells Cc: linux-crypto@vger.kernel.org, Alexander Potapenko , Eric Biggers , stable@vger.kernel.org Subject: [PATCH] ASN.1: fix out-of-bounds read when parsing indefinite length item Date: Sun, 26 Nov 2017 23:12:12 -0800 Message-Id: <20171127071212.25243-1-ebiggers3@gmail.com> X-Mailer: git-send-email 2.15.0 Sender: linux-crypto-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-crypto@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Eric Biggers In asn1_ber_decoder(), indefinitely-sized ASN.1 items were being passed to the action functions before their lengths had been computed, using the bogus length of 0x80 (ASN1_INDEFINITE_LENGTH). This resulted in reading data past the end of the input buffer, when given a specially crafted message. Fix it by rearranging the code so that the indefinite length is resolved before the action is called. This bug was originally found by fuzzing the X.509 parser in userspace using libFuzzer from the LLVM project. KASAN report (cleaned up slightly): BUG: KASAN: slab-out-of-bounds in memcpy ./include/linux/string.h:341 [inline] BUG: KASAN: slab-out-of-bounds in x509_fabricate_name.constprop.1+0x1a4/0x940 crypto/asymmetric_keys/x509_cert_parser.c:366 Read of size 128 at addr ffff880035dd9eaf by task keyctl/195 CPU: 1 PID: 195 Comm: keyctl Not tainted 4.14.0-09238-g1d3b78bbc6e9 #26 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.11.0-20171110_100015-anatol 04/01/2014 Call Trace: __dump_stack lib/dump_stack.c:17 [inline] dump_stack+0xd1/0x175 lib/dump_stack.c:53 print_address_description+0x78/0x260 mm/kasan/report.c:252 kasan_report_error mm/kasan/report.c:351 [inline] kasan_report+0x23f/0x350 mm/kasan/report.c:409 memcpy+0x1f/0x50 mm/kasan/kasan.c:302 memcpy ./include/linux/string.h:341 [inline] x509_fabricate_name.constprop.1+0x1a4/0x940 crypto/asymmetric_keys/x509_cert_parser.c:366 asn1_ber_decoder+0xb4a/0x1fd0 lib/asn1_decoder.c:447 x509_cert_parse+0x1c7/0x620 crypto/asymmetric_keys/x509_cert_parser.c:89 x509_key_preparse+0x61/0x750 crypto/asymmetric_keys/x509_public_key.c:174 asymmetric_key_preparse+0xa4/0x150 crypto/asymmetric_keys/asymmetric_type.c:388 key_create_or_update+0x4d4/0x10a0 security/keys/key.c:850 SYSC_add_key security/keys/keyctl.c:122 [inline] SyS_add_key+0xe8/0x290 security/keys/keyctl.c:62 entry_SYSCALL_64_fastpath+0x1f/0x96 Allocated by task 195: __do_kmalloc_node mm/slab.c:3675 [inline] __kmalloc_node+0x47/0x60 mm/slab.c:3682 kvmalloc ./include/linux/mm.h:540 [inline] SYSC_add_key security/keys/keyctl.c:104 [inline] SyS_add_key+0x19e/0x290 security/keys/keyctl.c:62 entry_SYSCALL_64_fastpath+0x1f/0x96 Fixes: 42d5ec27f873 ("X.509: Add an ASN.1 decoder") Reported-by: Alexander Potapenko Cc: # v3.7+ Signed-off-by: Eric Biggers --- lib/asn1_decoder.c | 47 ++++++++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/lib/asn1_decoder.c b/lib/asn1_decoder.c index 1ef0cec38d78..d77cdfc4b554 100644 --- a/lib/asn1_decoder.c +++ b/lib/asn1_decoder.c @@ -313,42 +313,47 @@ int asn1_ber_decoder(const struct asn1_decoder *decoder, /* Decide how to handle the operation */ switch (op) { - case ASN1_OP_MATCH_ANY_ACT: - case ASN1_OP_MATCH_ANY_ACT_OR_SKIP: - case ASN1_OP_COND_MATCH_ANY_ACT: - case ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP: - ret = actions[machine[pc + 1]](context, hdr, tag, data + dp, len); - if (ret < 0) - return ret; - goto skip_data; - - case ASN1_OP_MATCH_ACT: - case ASN1_OP_MATCH_ACT_OR_SKIP: - case ASN1_OP_COND_MATCH_ACT_OR_SKIP: - ret = actions[machine[pc + 2]](context, hdr, tag, data + dp, len); - if (ret < 0) - return ret; - goto skip_data; - case ASN1_OP_MATCH: case ASN1_OP_MATCH_OR_SKIP: + case ASN1_OP_MATCH_ACT: + case ASN1_OP_MATCH_ACT_OR_SKIP: case ASN1_OP_MATCH_ANY: case ASN1_OP_MATCH_ANY_OR_SKIP: + case ASN1_OP_MATCH_ANY_ACT: + case ASN1_OP_MATCH_ANY_ACT_OR_SKIP: case ASN1_OP_COND_MATCH_OR_SKIP: + case ASN1_OP_COND_MATCH_ACT_OR_SKIP: case ASN1_OP_COND_MATCH_ANY: case ASN1_OP_COND_MATCH_ANY_OR_SKIP: - skip_data: + case ASN1_OP_COND_MATCH_ANY_ACT: + case ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP: + if (!(flags & FLAG_CONS)) { if (flags & FLAG_INDEFINITE_LENGTH) { + size_t tmp = dp; + ret = asn1_find_indefinite_length( - data, datalen, &dp, &len, &errmsg); + data, datalen, &tmp, &len, &errmsg); if (ret < 0) goto error; - } else { - dp += len; } pr_debug("- LEAF: %zu\n", len); } + + if (op & ASN1_OP_MATCH__ACT) { + unsigned char act; + + if (op & ASN1_OP_MATCH__ANY) + act = machine[pc + 1]; + else + act = machine[pc + 2]; + ret = actions[act](context, hdr, tag, data + dp, len); + if (ret < 0) + return ret; + } + + if (!(flags & FLAG_CONS)) + dp += len; pc += asn1_op_lengths[op]; goto next_op;