Received: by 2002:a25:8b91:0:0:0:0:0 with SMTP id j17csp307361ybl; Thu, 30 Jan 2020 22:46:58 -0800 (PST) X-Google-Smtp-Source: APXvYqxCa/DdMF1tovpNtsVa8jF1MXr5FcSPiDcyjtDIIXO1+o36HyjW5O61okTgYXJSsqdZOyZI X-Received: by 2002:aca:1c0d:: with SMTP id c13mr5229338oic.44.1580453218519; Thu, 30 Jan 2020 22:46:58 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1580453218; cv=none; d=google.com; s=arc-20160816; b=yLR17LiHkWVyEcXUKlY5/u/tId+o8L695luvlCx290MsPQ/uxrPA/WxHHaErD3UHi0 KqCz7MC/nyvA7fZbKUzWFyWHaBxgHKMANzc1HBb7v546ROWcb8vFpczAKMOYMnDQtair TnjhZ7cxndBounyxA221uRaKawB2mGXpawlLvBK9mnHVV8cgZ889vmTgR5qszLL74dhm 6k6gCVtgcyrSxgswjq+MOerOBvFeiIk7/xWjstTL+LDCsCklg2W0I+eyewkgm8xrnr43 nYLrlIrA3igkex8pHk5Gff3beYHeqMiIvryEHQbbs3v8nJzkXkQvHbNhoX7KnQdyzwDR pFqw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding :content-language:in-reply-to:mime-version:user-agent:date :message-id:from:references:cc:to:subject:dkim-signature; bh=gN9mH4xRhjR/wIE778JRs1PqDrleGT+yzJx5pXGJcHE=; b=icIvDwbkqcR5H3353QSo+xa8IBW7o3bIQuV4ZpZr8HnqInmAHCRpyiNAa3Mw/pLHEh LhFmVdMBi2rDwZyBabb5nFUntTVDpjOYq6dthLw9rwPRYVvSpfmQk9jKLZYYDg1XRHA1 cgSdLuagK0+A0MP1kuQWkx1efvLHhK4BwogNxoU04P3d4bFRNZDAdpOoaBjsgLkPbwT5 cWevxlZPMxcBr4ZMxpTdtCqWbKnSF278mUCUNCiphDDj7x1vH/Qu2pG4Nut54pFRmf+D A35oi/JtQYk3OtI6bcpxGNa63G4rSXZY81HmsLL1cjk1AEMh17TN5GSYgVivJa7FD9YN NqhQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@c-s.fr header.s=mail header.b=tsg4lMRF; 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 o206si3801729oih.143.2020.01.30.22.46.46; Thu, 30 Jan 2020 22:46:58 -0800 (PST) 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=@c-s.fr header.s=mail header.b=tsg4lMRF; 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 S1728081AbgAaGoa (ORCPT + 99 others); Fri, 31 Jan 2020 01:44:30 -0500 Received: from pegase1.c-s.fr ([93.17.236.30]:50533 "EHLO pegase1.c-s.fr" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725832AbgAaGoa (ORCPT ); Fri, 31 Jan 2020 01:44:30 -0500 Received: from localhost (mailhub1-int [192.168.12.234]) by localhost (Postfix) with ESMTP id 48874956hnz9vCRl; Fri, 31 Jan 2020 07:44:25 +0100 (CET) Authentication-Results: localhost; dkim=pass reason="1024-bit key; insecure key" header.d=c-s.fr header.i=@c-s.fr header.b=tsg4lMRF; dkim-adsp=pass; dkim-atps=neutral X-Virus-Scanned: Debian amavisd-new at c-s.fr Received: from pegase1.c-s.fr ([192.168.12.234]) by localhost (pegase1.c-s.fr [192.168.12.234]) (amavisd-new, port 10024) with ESMTP id EIcP0bne_ziW; Fri, 31 Jan 2020 07:44:25 +0100 (CET) Received: from messagerie.si.c-s.fr (messagerie.si.c-s.fr [192.168.25.192]) by pegase1.c-s.fr (Postfix) with ESMTP id 48874942hLz9vCRj; Fri, 31 Jan 2020 07:44:25 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=c-s.fr; s=mail; t=1580453065; bh=gN9mH4xRhjR/wIE778JRs1PqDrleGT+yzJx5pXGJcHE=; h=Subject:To:Cc:References:From:Date:In-Reply-To:From; b=tsg4lMRFaCATCJvjbzjaIx4gXKQgcbe+U4bqozqfnFsmYNtj1EjfZtN7ulHsIj619 RH2aVi1yXHC4c+RIVFIxoB8ug/ryd6VOgBl5xBrg3Nkcg62nramSfU7HbRjAJ5TIps XSslTDr2XCmb8v9A55k6kUe8VsporoAE7oZE0dqg= Received: from localhost (localhost [127.0.0.1]) by messagerie.si.c-s.fr (Postfix) with ESMTP id 688108B889; Fri, 31 Jan 2020 07:44:26 +0100 (CET) X-Virus-Scanned: amavisd-new at c-s.fr Received: from messagerie.si.c-s.fr ([127.0.0.1]) by localhost (messagerie.si.c-s.fr [127.0.0.1]) (amavisd-new, port 10023) with ESMTP id vgirdEoRJhzn; Fri, 31 Jan 2020 07:44:26 +0100 (CET) Received: from [172.25.230.105] (po15451.idsi0.si.c-s.fr [172.25.230.105]) by messagerie.si.c-s.fr (Postfix) with ESMTP id 2A66F8B884; Fri, 31 Jan 2020 07:44:26 +0100 (CET) Subject: Re: [PATCH] lkdtm: Test KUAP directional user access unlocks on powerpc To: Russell Currey , keescook@chromium.org, mpe@ellerman.id.au Cc: linux-kernel@vger.kernel.org, dja@axtens.net, kernel-hardening@lists.openwall.com, linuxppc-dev@lists.ozlabs.org References: <20200131053157.22463-1-ruscur@russell.cc> From: Christophe Leroy Message-ID: <1b40cea6-0675-731a-58b1-bdc65f1e495e@c-s.fr> Date: Fri, 31 Jan 2020 07:44:26 +0100 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:68.0) Gecko/20100101 Thunderbird/68.4.2 MIME-Version: 1.0 In-Reply-To: <20200131053157.22463-1-ruscur@russell.cc> Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: fr Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Le 31/01/2020 à 06:31, Russell Currey a écrit : > Kernel Userspace Access Prevention (KUAP) on powerpc supports > allowing only one access direction (Read or Write) when allowing access > to or from user memory. > > A bug was recently found that showed that these one-way unlocks never > worked, and allowing Read *or* Write would actually unlock Read *and* > Write. We should have a test case for this so we can make sure this > doesn't happen again. > > Like ACCESS_USERSPACE, the correct result is for the test to fault. > > At the time of writing this, the upstream kernel still has this bug > present, so the test will allow both accesses whereas ACCESS_USERSPACE > will correctly fault. > > Signed-off-by: Russell Currey > --- > drivers/misc/lkdtm/core.c | 3 +++ > drivers/misc/lkdtm/lkdtm.h | 3 +++ > drivers/misc/lkdtm/perms.c | 43 ++++++++++++++++++++++++++++++++++++++ > 3 files changed, 49 insertions(+) > > diff --git a/drivers/misc/lkdtm/core.c b/drivers/misc/lkdtm/core.c > index ee0d6e721441..baef3c6f48d6 100644 > --- a/drivers/misc/lkdtm/core.c > +++ b/drivers/misc/lkdtm/core.c > @@ -137,6 +137,9 @@ static const struct crashtype crashtypes[] = { > CRASHTYPE(EXEC_USERSPACE), > CRASHTYPE(EXEC_NULL), > CRASHTYPE(ACCESS_USERSPACE), > +#ifdef CONFIG_PPC_KUAP > + CRASHTYPE(ACCESS_USERSPACE_KUAP), > +#endif I'm not sure it is a good idea to build this test as a specific test for powerpc, more comments below. > CRASHTYPE(ACCESS_NULL), > CRASHTYPE(WRITE_RO), > CRASHTYPE(WRITE_RO_AFTER_INIT), > diff --git a/drivers/misc/lkdtm/lkdtm.h b/drivers/misc/lkdtm/lkdtm.h > index c56d23e37643..406a3fb32e6f 100644 > --- a/drivers/misc/lkdtm/lkdtm.h > +++ b/drivers/misc/lkdtm/lkdtm.h > @@ -57,6 +57,9 @@ void lkdtm_EXEC_RODATA(void); > void lkdtm_EXEC_USERSPACE(void); > void lkdtm_EXEC_NULL(void); > void lkdtm_ACCESS_USERSPACE(void); > +#ifdef CONFIG_PPC_KUAP > +void lkdtm_ACCESS_USERSPACE_KUAP(void); > +#endif > void lkdtm_ACCESS_NULL(void); > > /* lkdtm_refcount.c */ > diff --git a/drivers/misc/lkdtm/perms.c b/drivers/misc/lkdtm/perms.c > index 62f76d506f04..2c9aa0114333 100644 > --- a/drivers/misc/lkdtm/perms.c > +++ b/drivers/misc/lkdtm/perms.c > @@ -10,6 +10,9 @@ > #include > #include > #include > +#ifdef CONFIG_PPC_KUAP > +#include > +#endif asm/uaccess.h is already included by linux/uaccess.h > > /* Whether or not to fill the target memory area with do_nothing(). */ > #define CODE_WRITE true > @@ -200,6 +203,46 @@ void lkdtm_ACCESS_USERSPACE(void) > vm_munmap(user_addr, PAGE_SIZE); > } > > +/* Test that KUAP's directional user access unlocks work as intended */ > +#ifdef CONFIG_PPC_KUAP > +void lkdtm_ACCESS_USERSPACE_KUAP(void) > +{ > + unsigned long user_addr, tmp = 0; > + unsigned long *ptr; Should be a __user ptr because allow_write_to_user() and friends takes __user pointers. > + > + user_addr = vm_mmap(NULL, 0, PAGE_SIZE, > + PROT_READ | PROT_WRITE | PROT_EXEC, > + MAP_ANONYMOUS | MAP_PRIVATE, 0); > + if (user_addr >= TASK_SIZE) { Should use IS_ERR_VALUE() here. > + pr_warn("Failed to allocate user memory\n"); > + return; > + } > + > + if (copy_to_user((void __user *)user_addr, &tmp, sizeof(tmp))) { Should use ptr instead of casted user_addr. Why using copy_to_user() for writing an unsigned long ? put_user() should be enough. > + pr_warn("copy_to_user failed\n"); > + vm_munmap(user_addr, PAGE_SIZE); > + return; > + } > + > + ptr = (unsigned long *)user_addr; move before copy_to_user() and use there. > + > + /* Allowing "write to" should not allow "read from" */ > + allow_write_to_user(ptr, sizeof(unsigned long)); This is powerpc specific. I think we should build this around the user_access_begin()/user_access_end() generic fonctions. I'm about to propose an enhancement to this in order to allow unlocking only read or write. See discussion at https://patchwork.ozlabs.org/patch/1227926/. My plan is to propose my enhancement once powerpc implementation of user_access_begin stuff is merged. I don't know if Michael is still planning to merge the series for 5.6 (https://patchwork.ozlabs.org/patch/1228801/ - patch 1 of the series has already been merged by Linus in 5.5) > + pr_info("attempting bad read at %px with write allowed\n", ptr); > + tmp = *ptr; > + tmp += 0xc0dec0de; > + prevent_write_to_user(ptr, sizeof(unsigned long)); Does it work ? I would have thought that if the read fails the process will die and the following test won't be performed. > + > + /* Allowing "read from" should not allow "write to" */ > + allow_read_from_user(ptr, sizeof(unsigned long)); > + pr_info("attempting bad write at %px with read allowed\n", ptr); > + *ptr = tmp; > + prevent_read_from_user(ptr, sizeof(unsigned long)); > + > + vm_munmap(user_addr, PAGE_SIZE); > +} > +#endif > + > void lkdtm_ACCESS_NULL(void) > { > unsigned long tmp; > Christophe