From patchwork Mon Sep 18 18:37:23 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 9957385 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 232E560385 for ; Mon, 18 Sep 2017 18:37:37 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 168AC28C06 for ; Mon, 18 Sep 2017 18:37:37 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0B33628D30; Mon, 18 Sep 2017 18:37:37 +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=-6.3 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM, T_DKIM_INVALID 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 9693828C06 for ; Mon, 18 Sep 2017 18:37:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756849AbdIRShf (ORCPT ); Mon, 18 Sep 2017 14:37:35 -0400 Received: from mail-pg0-f67.google.com ([74.125.83.67]:38266 "EHLO mail-pg0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752898AbdIRShe (ORCPT ); Mon, 18 Sep 2017 14:37:34 -0400 Received: by mail-pg0-f67.google.com with SMTP id m30so667733pgn.5; Mon, 18 Sep 2017 11:37:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=siWTiS0CMHoGCW16Ezgtajg7nru1EgHZag7/BXnkv7E=; b=tnjWE15wCnFajSnzxbTM2lYTZpewLZYrvx99JYboslVL4whosk9lHJ/ybobF8IQbCh dr4VJcLCieUzDtEorusQhh2XLI57z41iqvdj1u5XaIj46LTP9K1uhKXyjvsk883Seasd xca/ZQTT0gwbbd3tqUpMpfSvheg/kCvpQs1NjKMa3bu9kj3Kr0Q6JE5BXsS4pcZAioLT 2KnmZjBgoHSyUkNg1DG8dJ/dIidH5i3XEAdgsaFfcv+8HREtDBdvCwAy9IBMm2FqYNAc X1gpg77XGAqLBPFfyTdq5ITvZlty/Gp+ONzsrC5Cm8omvqwVUyhvdqgdSsXBQiOBkrWO xzrA== 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=siWTiS0CMHoGCW16Ezgtajg7nru1EgHZag7/BXnkv7E=; b=E7yOfF5/F2gYL+OZF9DNte4NVuSLqy93uA/vGR9tnUSTkTE0UuwCrEUnODBB8I48OF NwkwSu4sDspKxk9GVYsmWRYFn8L7MzrPhwWcg/eSgOt2fdPrWYzFz9Yg94VV2Wjl86QE my67QRUa/TmsM3TJ9u840TDE4vWztVNSpta1nWIiYTInJiQ16xp/1sC7ou1PSdOYnKa9 Ez5HnjTPUHTY0d/DCf3Q6B8ggDxqKgBcXj2yId9ftml9uzRjuawjPk7lxUYq2O82O716 OzoT/RR+3ONoYTCnqMMD2VFgYhYq4iLMClZ2Lx60eSQW6Q4xqT4C+A38Oe1kqewCkCDT X/BQ== X-Gm-Message-State: AHPjjUh7QiZrxXggEk4/T9/yk4cJvRum3EzwJX758NsPwVLLFhR/D99w WGAWATq49BCJJD2qV0A= X-Google-Smtp-Source: ADKCNb7g9YhNdjBKemzTtMPvoJS/dGVEaIewU54R5sZh6RBPJIii+LXkTPF5eJ4kEQ2JCXfz1aXa5g== X-Received: by 10.84.128.67 with SMTP id 61mr36906736pla.387.1505759853336; Mon, 18 Sep 2017 11:37:33 -0700 (PDT) Received: from ebiggers-linuxstation.kir.corp.google.com ([100.66.174.81]) by smtp.gmail.com with ESMTPSA id s86sm92555pfi.74.2017.09.18.11.37.32 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 18 Sep 2017 11:37:32 -0700 (PDT) From: Eric Biggers To: keyrings@vger.kernel.org Cc: David Howells , Michael Halcrow , linux-security-module@vger.kernel.org, linux-kernel@vger.kernel.org, Eric Biggers , stable@vger.kernel.org Subject: [PATCH] KEYS: prevent KEYCTL_READ on negative key Date: Mon, 18 Sep 2017 11:37:23 -0700 Message-Id: <20170918183723.114253-1-ebiggers3@gmail.com> X-Mailer: git-send-email 2.14.1.690.gbb1197296e-goog Sender: owner-linux-security-module@vger.kernel.org Precedence: bulk List-ID: X-Virus-Scanned: ClamAV using ClamSMTP From: Eric Biggers Because keyctl_read_key() looks up the key with no permissions requested, it may find a negatively instantiated key. If the key is also possessed, we went ahead and called ->read() on the key. But the key payload will actually contain the ->reject_error rather than the normal payload. Thus, the kernel oopses trying to read the user_key_payload from memory address (int)-ENOKEY = 0x00000000ffffff82. Fortunately the payload data is stored inline, so it shouldn't be possible to abuse this as an arbitrary memory read primitive... Reproducer: keyctl new_session keyctl request2 user desc '' @s keyctl read $(keyctl show | awk '/user: desc/ {print $1}') It causes a crash like the following: BUG: unable to handle kernel paging request at 00000000ffffff92 IP: user_read+0x33/0xa0 PGD 36a54067 P4D 36a54067 PUD 0 Oops: 0000 [#1] SMP CPU: 0 PID: 211 Comm: keyctl Not tainted 4.14.0-rc1 #337 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-20170228_101828-anatol 04/01/2014 task: ffff90aa3b74c3c0 task.stack: ffff9878c0478000 RIP: 0010:user_read+0x33/0xa0 RSP: 0018:ffff9878c047bee8 EFLAGS: 00010246 RAX: 0000000000000001 RBX: ffff90aa3d7da340 RCX: 0000000000000017 RDX: 0000000000000000 RSI: 00000000ffffff82 RDI: ffff90aa3d7da340 RBP: ffff9878c047bf00 R08: 00000024f95da94f R09: 0000000000000000 R10: 0000000000000001 R11: 0000000000000000 R12: 0000000000000000 R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000 FS: 00007f58ece69740(0000) GS:ffff90aa3e200000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00000000ffffff92 CR3: 0000000036adc001 CR4: 00000000003606f0 Call Trace: keyctl_read_key+0xac/0xe0 SyS_keyctl+0x99/0x120 entry_SYSCALL_64_fastpath+0x1f/0xbe RIP: 0033:0x7f58ec787bb9 RSP: 002b:00007ffc8d401678 EFLAGS: 00000206 ORIG_RAX: 00000000000000fa RAX: ffffffffffffffda RBX: 00007ffc8d402800 RCX: 00007f58ec787bb9 RDX: 0000000000000000 RSI: 00000000174a63ac RDI: 000000000000000b RBP: 0000000000000004 R08: 00007ffc8d402809 R09: 0000000000000020 R10: 0000000000000000 R11: 0000000000000206 R12: 00007ffc8d402800 R13: 00007ffc8d4016e0 R14: 0000000000000000 R15: 0000000000000000 Code: e5 41 55 49 89 f5 41 54 49 89 d4 53 48 89 fb e8 a4 b4 ad ff 85 c0 74 09 80 3d b9 4c 96 00 00 74 43 48 8b b3 20 01 00 00 4d 85 ed <0f> b7 5e 10 74 29 4d 85 e4 74 24 4c 39 e3 4c 89 e2 4c 89 ef 48 RIP: user_read+0x33/0xa0 RSP: ffff9878c047bee8 CR2: 00000000ffffff92 Fixes: 61ea0c0ba904 ("KEYS: Skip key state checks when checking for possession") Cc: [v3.13+] Signed-off-by: Eric Biggers --- security/keys/keyctl.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index ab0b337c84b4..6a82090c7fc1 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c @@ -766,6 +766,11 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen) key = key_ref_to_ptr(key_ref); + if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) { + ret = -ENOKEY; + goto error2; + } + /* see if we can read it directly */ ret = key_permission(key_ref, KEY_NEED_READ); if (ret == 0)