From patchwork Sun May 20 19:11:15 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ram Pai X-Patchwork-Id: 10413585 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 02E2A60365 for ; Sun, 20 May 2018 19:11:33 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E53CB2872E for ; Sun, 20 May 2018 19:11:32 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D82F92873D; Sun, 20 May 2018 19:11:32 +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=-2.9 required=2.0 tests=BAYES_00, MAILING_LIST_MULTI, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2838E2872E for ; Sun, 20 May 2018 19:11:31 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 6E4376B05FA; Sun, 20 May 2018 15:11:30 -0400 (EDT) Delivered-To: linux-mm-outgoing@kvack.org Received: by kanga.kvack.org (Postfix, from userid 40) id 694F56B05FC; Sun, 20 May 2018 15:11:30 -0400 (EDT) X-Original-To: int-list-linux-mm@kvack.org X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 5843A6B0637; Sun, 20 May 2018 15:11:30 -0400 (EDT) X-Original-To: linux-mm@kvack.org X-Delivered-To: linux-mm@kvack.org Received: from mail-wr0-f200.google.com (mail-wr0-f200.google.com [209.85.128.200]) by kanga.kvack.org (Postfix) with ESMTP id EECAB6B05FA for ; Sun, 20 May 2018 15:11:29 -0400 (EDT) Received: by mail-wr0-f200.google.com with SMTP id f23-v6so10074870wra.20 for ; Sun, 20 May 2018 12:11:29 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-original-authentication-results:x-gm-message-state:date:from:to :cc:subject:reply-to:references:mime-version:in-reply-to:user-agent :message-id:content-transfer-encoding:content-disposition; bh=QQEQs+bM4htdCab3yQ2hcX5zUaZ0fi1SlYqjdXq150Q=; b=WI5pn/0aSGZEGuL21AcHSO1llLGYGvxaiqgGrn+qG4BuxESSe0y3mN8Bah3sbylphU CTEB4ldc+aFBu2sODsSWX2X8XEhuAhjdEHnXb18z4cQQQdMOe0Ny/2fImV++mdF2Uezo zOmG/KDf6c26fbWDpWnHMIFa0ymNzGC9ENKYh8BM0hKpX0Yydts8XHkAjnxV323fPRFn OodpyS8c61FcY9dYnifM2KdfMT9DewS653GIKa+NYooZ/n7MIoFToGNr/RXTE/pdC8Tj 9ZMmZZVst5FJDS/C/1dT7HqcV3Fk1HiKw+xNemlHuGvgjbK8Z2BOMjn23g2wtfcLQdGM 171A== X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of linuxram@us.ibm.com designates 148.163.156.1 as permitted sender) smtp.mailfrom=linuxram@us.ibm.com; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=ibm.com X-Gm-Message-State: ALKqPwdv8QS9O0W1+cQedH9SqLe5QZT6fL2y1kf0ms++JyfC++ZH0zg5 MDV0x2BeIIj1d+C/yt8UEqZjRV7ltrej7p/CjacjkgTScbtII3FoHZNoNNT2TYpsrhHis+9KC+C UDCNxzbR4HlkOSmcQHmg7UtjpcVib4mtsCEwG9tHklUsBEhoP0Gf3YQ919ISn0EYIeA== X-Received: by 2002:a50:a985:: with SMTP id n5-v6mr20886179edc.112.1526843489464; Sun, 20 May 2018 12:11:29 -0700 (PDT) X-Google-Smtp-Source: AB8JxZp2iKkvwG+dPgyr3HeNKOop9h9H9WyO+zUI4v2GtZlQ3ElaNvsD8hD+LCTeUefhjzE6idKW X-Received: by 2002:a50:a985:: with SMTP id n5-v6mr20886132edc.112.1526843488421; Sun, 20 May 2018 12:11:28 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1526843488; cv=none; d=google.com; s=arc-20160816; b=DbUa0T3qswC6fF/A5ryjnOlCuLCfSqO83Gh7VPNu9kC5sasW3kQ913gqt+YT7Rc1eY w3b+j0Z84KX3DZ3xg+VwByFwEGhnCB9bYBUVkzPUFfIZhJhXzQWZhGewY2KNJPDbxsbK JsqMqtiHF2NdOacTxgg5cT8w8oxdpB87l02pMK2W4Pr6HXsugx6T8dzPA8+OT691D+Mc 2Zy1bH8P4E/sFd7DttB/056RkkxrQfxsvrBWomwqYH46FXOMCKpfzLzDYA4nSVWLZITD TFidx41DLPsSeW2MAv+q5B/8zfb+CA74AQf/CoJiW6xGmfLblhjwRoPk2kMSFEBOHZUb GLHw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-disposition:content-transfer-encoding:message-id:user-agent :in-reply-to:mime-version:references:reply-to:subject:cc:to:from :date:arc-authentication-results; bh=QQEQs+bM4htdCab3yQ2hcX5zUaZ0fi1SlYqjdXq150Q=; b=AoBqzhaMAel3sq7jrlrLQfzfbVTNZszOv4Yn8h9wAD3YEBmM7yNo5twwOklBUdTTaZ MBheOA8qhJgYJUkE80/c957sUC8MphQp/1+EHPGBDTH4zlGtQEuxR/I4b2nMinD0AtJr fKxhdzh6kiYJxaCaEUZ4yEZHUq3hocBG4ywevZqwEZi/EGxwAvUy7eCYIrQkGsQ95+je soxamCEhgV+p1rhsX8eqErIVwmNVm8ToQcBCfdrfWG2yLlVknJs/LSRUktE4gRSg0AQ2 eASnLrqEDFe0gfipRAngNJWqhwtb9uC/0VOuyGFlk8gB4lcrMo6QLMy/phOxCep0gi7m PggQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linuxram@us.ibm.com designates 148.163.156.1 as permitted sender) smtp.mailfrom=linuxram@us.ibm.com; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=ibm.com Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com. [148.163.156.1]) by mx.google.com with ESMTPS id u26-v6si5319807eda.395.2018.05.20.12.11.27 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 20 May 2018 12:11:28 -0700 (PDT) Received-SPF: pass (google.com: domain of linuxram@us.ibm.com designates 148.163.156.1 as permitted sender) client-ip=148.163.156.1; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linuxram@us.ibm.com designates 148.163.156.1 as permitted sender) smtp.mailfrom=linuxram@us.ibm.com; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=ibm.com Received: from pps.filterd (m0098399.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.22/8.16.0.22) with SMTP id w4KJ9FmA007174 for ; Sun, 20 May 2018 15:11:26 -0400 Received: from e06smtp13.uk.ibm.com (e06smtp13.uk.ibm.com [195.75.94.109]) by mx0a-001b2d01.pphosted.com with ESMTP id 2j31aknx0p-1 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=NOT) for ; Sun, 20 May 2018 15:11:25 -0400 Received: from localhost by e06smtp13.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Sun, 20 May 2018 20:11:23 +0100 Received: from b06cxnps4076.portsmouth.uk.ibm.com (9.149.109.198) by e06smtp13.uk.ibm.com (192.168.101.143) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; (version=TLSv1/SSLv3 cipher=AES256-GCM-SHA384 bits=256/256) Sun, 20 May 2018 20:11:20 +0100 Received: from d06av24.portsmouth.uk.ibm.com (mk.ibm.com [9.149.105.60]) by b06cxnps4076.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id w4KJBJm22425172 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Sun, 20 May 2018 19:11:19 GMT Received: from d06av24.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id B7B7842041; Sun, 20 May 2018 20:02:04 +0100 (BST) Received: from d06av24.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 8724E4203F; Sun, 20 May 2018 20:02:03 +0100 (BST) Received: from ram.oc3035372033.ibm.com (unknown [9.80.231.86]) by d06av24.portsmouth.uk.ibm.com (Postfix) with ESMTPS; Sun, 20 May 2018 20:02:03 +0100 (BST) Date: Sun, 20 May 2018 12:11:15 -0700 From: Ram Pai To: Andy Lutomirski Cc: Florian Weimer , linuxppc-dev , Linux-MM , Dave Hansen Subject: Re: pkeys on POWER: Access rights not reset on execve Reply-To: Ram Pai References: <53828769-23c4-b2e3-cf59-239936819c3e@redhat.com> <20180519011947.GJ5479@ram.oc3035372033.ibm.com> <20180519202747.GK5479@ram.oc3035372033.ibm.com> <20180520060425.GL5479@ram.oc3035372033.ibm.com> MIME-Version: 1.0 In-Reply-To: User-Agent: Mutt/1.5.20 (2009-12-10) X-TM-AS-GCONF: 00 x-cbid: 18052019-0012-0000-0000-000005D89D99 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 18052019-0013-0000-0000-00001955D88B Message-Id: <20180520191115.GM5479@ram.oc3035372033.ibm.com> Content-Disposition: inline X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2018-05-20_07:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=0 phishscore=0 bulkscore=0 spamscore=0 clxscore=1011 lowpriorityscore=0 impostorscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1709140000 definitions=main-1805200233 X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: X-Virus-Scanned: ClamAV using ClamSMTP On Sat, May 19, 2018 at 11:06:20PM -0700, Andy Lutomirski wrote: > On Sat, May 19, 2018 at 11:04 PM Ram Pai wrote: > > > On Sat, May 19, 2018 at 04:47:23PM -0700, Andy Lutomirski wrote: > On > Sat, May 19, 2018 at 1:28 PM Ram Pai wrote: > > > ...snip... > > > > > > So is it possible for two threads to each call pkey_alloc() and end up > with > > > the same key? If so, it seems entirely broken. > > > No. Two threads cannot allocate the same key; just like x86. > > > > If not, then how do you > > > intend for a multithreaded application to usefully allocate a new key? > > > Regardless, it seems like the current behavior on POWER is very > difficult > > > to work with. Can you give an example of a use case for which POWER's > > > behavior makes sense? > > > > > > For the use cases I've imagined, POWER's behavior does not make sense. > > > x86's is not ideal but is still better. Here are my two example use > cases: > > > > > > 1. A crypto library. Suppose I'm writing a TLS-terminating server, and > I > > > want it to be resistant to Heartbleed-like bugs. I could store my > private > > > keys protected by mprotect_key() and arrange for all threads and signal > > > handlers to have PKRU/AMR values that prevent any access to the memory. > > > When an explicit call is made to sign with the key, I would temporarily > > > change PKRU/AMR to allow access, compute the signature, and change > PKRU/AMR > > > back. On x86 right now, this works nicely. On POWER, it doesn't, > because > > > any thread started before my pkey_alloc() call can access the protected > > > memory, as can any signal handler. > > > > > > 2. A database using mmap() (with persistent memory or otherwise). It > would > > > be nice to be resistant to accidental corruption due to stray writes. I > > > would do more or less the same thing as (1), except that I would want > > > threads that are not actively writing to the database to be able the > > > protected memory. On x86, I need to manually convince threads that may > > > have been started before my pkey_alloc() call as well as signal > handlers to > > > update their PKRU values. On POWER, as in example (1), the error goes > the > > > other direction -- if I fail to propagate the AMR bits to all threads, > > > writes are not blocked. > > > I see the problem from an application's point of view, on powerpc. If > > the key allocated in one thread is not activated on all threads > > (existing one and future one), than other threads will not be able > > to modify the key's permissions. Hence they will not be able to control > > access/write to pages to which the key is associated. > > > As Florian suggested, I should enable the key's bit in the UAMOR value > > corresponding to existing threads, when a new key is allocated. > > > Now, looking at the implementation for x86, I see that sys_mpkey_alloc() > > makes no attempt to modify anything of any other thread. How > > does it manage to activate the key on any other thread? Is this > > magic done by the hardware? > > x86 has no equivalent concept to UAMOR. There are 16 keys no matter what. Florian, Does the following patch fix the problem for you? Just like x86 I am enabling all keys in the UAMOR register during initialization itself. Hence any key created by any thread at any time, will get activated on all threads. So any thread can change the permission on that key. Smoke tested it with your test program. Signed-off-by: Ram Pai > > --Andy diff --git a/arch/powerpc/mm/pkeys.c b/arch/powerpc/mm/pkeys.c index 0eafdf01..ab4519a 100644 --- a/arch/powerpc/mm/pkeys.c +++ b/arch/powerpc/mm/pkeys.c @@ -15,8 +15,9 @@ int pkeys_total; /* Total pkeys as per device tree */ bool pkeys_devtree_defined; /* pkey property exported by device tree */ u32 initial_allocation_mask; /* Bits set for reserved keys */ -u64 pkey_amr_uamor_mask; /* Bits in AMR/UMOR not to be touched */ +u64 pkey_amr_mask; /* Bits in AMR not to be touched */ u64 pkey_iamr_mask; /* Bits in AMR not to be touched */ +u64 pkey_uamor_mask; /* Bits in UMOR not to be touched */ #define AMR_BITS_PER_PKEY 2 #define AMR_RD_BIT 0x1UL @@ -24,6 +25,7 @@ #define IAMR_EX_BIT 0x1UL #define PKEY_REG_BITS (sizeof(u64)*8) #define pkeyshift(pkey) (PKEY_REG_BITS - ((pkey+1) * AMR_BITS_PER_PKEY)) +#define switch_off(bitmask, i) (bitmask &= ~(0x3ul << pkeyshift(i))) static void scan_pkey_feature(void) { @@ -120,19 +122,31 @@ int pkey_initialize(void) os_reserved = 0; #endif initial_allocation_mask = ~0x0; - pkey_amr_uamor_mask = ~0x0ul; + + /* register mask is in BE format */ + pkey_amr_mask = ~0x0ul; pkey_iamr_mask = ~0x0ul; - /* - * key 0, 1 are reserved. - * key 0 is the default key, which allows read/write/execute. - * key 1 is recommended not to be used. PowerISA(3.0) page 1015, - * programming note. - */ - for (i = 2; i < (pkeys_total - os_reserved); i++) { - initial_allocation_mask &= ~(0x1 << i); - pkey_amr_uamor_mask &= ~(0x3ul << pkeyshift(i)); + + for (i = 0; i < (pkeys_total - os_reserved); i++) { + if (i != 0 && i != 1) /* 0 and 1 are already allocated */ + initial_allocation_mask &= ~(0x1 << i); + pkey_amr_mask &= ~(0x3ul << pkeyshift(i)); pkey_iamr_mask &= ~(0x1ul << pkeyshift(i)); } + + pkey_uamor_mask = ~0x0ul; + switch_off(pkey_uamor_mask, 0); + /* + * key 1 is recommended not to be used. + * PowerISA(3.0) page 1015, + * @TODO: Revisit this. This is only applicable on + * pseries kernel running on powerVM. + */ + switch_off(pkey_uamor_mask, 1); + for (i = (pkeys_total - os_reserved); i < pkeys_total; i++) + switch_off(pkey_uamor_mask, i); + + printk("pkey_uamor_mask=0x%llx \n", pkey_uamor_mask); return 0; } @@ -280,7 +294,6 @@ void thread_pkey_regs_save(struct thread_struct *thread) */ thread->amr = read_amr(); thread->iamr = read_iamr(); - thread->uamor = read_uamor(); } void thread_pkey_regs_restore(struct thread_struct *new_thread, @@ -289,9 +302,6 @@ void thread_pkey_regs_restore(struct thread_struct *new_thread, if (static_branch_likely(&pkey_disabled)) return; - /* - * TODO: Just set UAMOR to zero if @new_thread hasn't used any keys yet. - */ if (old_thread->amr != new_thread->amr) write_amr(new_thread->amr); if (old_thread->iamr != new_thread->iamr) @@ -305,9 +315,9 @@ void thread_pkey_regs_init(struct thread_struct *thread) if (static_branch_likely(&pkey_disabled)) return; - thread->amr = read_amr() & pkey_amr_uamor_mask; + thread->amr = read_amr() & pkey_amr_mask; thread->iamr = read_iamr() & pkey_iamr_mask; - thread->uamor = read_uamor() & pkey_amr_uamor_mask; + thread->uamor = pkey_uamor_mask; } static inline bool pkey_allows_readwrite(int pkey)