From patchwork Thu Jun 14 00:29:02 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ram Pai X-Patchwork-Id: 929145 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [203.11.71.2]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 415lDj3btWz9ry1 for ; Thu, 14 Jun 2018 10:41:41 +1000 (AEST) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=us.ibm.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="AUcm0+n0"; dkim-atps=neutral Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 415lDj21hSzF0dY for ; Thu, 14 Jun 2018 10:41:41 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dmarc=none (p=none dis=none) header.from=us.ibm.com Authentication-Results: lists.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="AUcm0+n0"; dkim-atps=neutral X-Original-To: linuxppc-dev@lists.ozlabs.org Delivered-To: linuxppc-dev@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gmail.com (client-ip=2607:f8b0:400d:c0d::242; helo=mail-qt0-x242.google.com; envelope-from=ram.n.pai@gmail.com; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=none (p=none dis=none) header.from=us.ibm.com Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="AUcm0+n0"; dkim-atps=neutral Received: from mail-qt0-x242.google.com (mail-qt0-x242.google.com [IPv6:2607:f8b0:400d:c0d::242]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 415kyb5Cl4zF0Pd for ; Thu, 14 Jun 2018 10:29:27 +1000 (AEST) Received: by mail-qt0-x242.google.com with SMTP id x34-v6so4246755qtk.5 for ; Wed, 13 Jun 2018 17:29:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=wTYFB64yxo7eSl/Yuk72Ca+jBgjcUg+rrm0rwYNJ+C8=; b=AUcm0+n0AhdZGLp34jBDrqBdHato86f1RdrNG5KzrM/+9hT2sgQFrd7T74rjoP4O9f NhxAFTwjEK/PazENaBje0J9lQ+XsqqRfJo4GeoEZ+aC6Ds4xdmLKhYOx8nX9KyBvswKp yBOSzLDMtY7Zhr7+/UbUB9CciP6w5pBH4ErLucbu4wvzCyM7kvtjQD0rmey2arp+hpQf cTB9Qt/ApjqbzG9Q4C4vev2Or/PMN72RLwmkNHeQ9IRUab8DqTI0LnkBTMDVVZ0WYwIr trooPNjX0CcZ9ec/CZg0NXHZcI3XSnJlvQb3kewG1HqSKzFUGwo4nVh9hCRW0RlXVJwV uv6w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=wTYFB64yxo7eSl/Yuk72Ca+jBgjcUg+rrm0rwYNJ+C8=; b=je3fOKf1u975Uibgn/e6NrPpdMjN5i8WigLrLkWHGJ+VdLmILzqvp9DO5ICUZvu/kk sNy2DATHmkKH0xbcF2AucaOsFW7o7rerJ4BxzMhK6QqtiSr7rH7jwXVpDk9a1EbpYyps WUGlLzf9+NzgedyueO7Pi5tYltkNw8JQnxgg6NNtlM2hF1vTTNwts4WPI2ZIx0sRQC8f 6kg+gNxhEQNziHYuTF2E5Wm7HGp008I5cQqRnKbCZ7kTWs2SRWVQULxthfsbkibDiYHt BTucDgfB2KxDJxfn3dtBXbGDIkwRoWjGiQevzP7uyhUpu0dScGIKVUUR9PoU8QfmN48p 8vvg== X-Gm-Message-State: APt69E3Et42pNEEgyTexDw9uePOMk010cl9r0py6IB4V2KlXO3k7/ynO X5nj1TLesLJcCGxhT+JBYQY= X-Google-Smtp-Source: ADUXVKI1xEU8+bUHfGqihAPya00ISwnriLdyoeKpdGP+GeStWDxylbLwTY3pbxLi++qYYS9XrSq1Gw== X-Received: by 2002:ac8:1a74:: with SMTP id q49-v6mr360036qtk.142.1528936165435; Wed, 13 Jun 2018 17:29:25 -0700 (PDT) Received: from localhost.localdomain (50-39-100-161.bvtn.or.frontiernet.net. [50.39.100.161]) by smtp.gmail.com with ESMTPSA id s12-v6sm3159581qkl.65.2018.06.13.17.29.23 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 13 Jun 2018 17:29:24 -0700 (PDT) From: Ram Pai To: mpe@ellerman.id.au Subject: [PATCH v2 4/6] powerpc/pkeys: Preallocate execute-only key Date: Wed, 13 Jun 2018 17:29:02 -0700 Message-Id: <1528936144-6696-5-git-send-email-linuxram@us.ibm.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1528936144-6696-1-git-send-email-linuxram@us.ibm.com> References: <1528936144-6696-1-git-send-email-linuxram@us.ibm.com> X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.26 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: fweimer@redhat.com, Ulrich.Weigand@de.ibm.com, linuxram@us.ibm.com, mhocko@kernel.org, dave.hansen@intel.com, aneesh.kumar@linux.vnet.ibm.com, luto@kernel.org, bauerman@linux.vnet.ibm.com, msuchanek@suse.de, linuxppc-dev@lists.ozlabs.org Errors-To: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org Sender: "Linuxppc-dev" execute-only key is allocated dynamically. This is a problem. When a thread implicitly creates a execute-only key, and resets UAMOR for that key, the UAMOR value does not percolate to all the other threads. Any other thread may ignorantly change the permissions on the key. This can cause the key to be not execute-only for that thread. Preallocate the execute-only key and ensure that no thread can change the permission of the key, by resetting the corresponding bit in UAMOR. CC: Andy Lutomirski CC: Florian Weimer CC: Thiago Jung Bauermann CC: Michael Ellerman Signed-off-by: Ram Pai --- arch/powerpc/mm/pkeys.c | 53 +++++++--------------------------------------- 1 files changed, 8 insertions(+), 45 deletions(-) diff --git a/arch/powerpc/mm/pkeys.c b/arch/powerpc/mm/pkeys.c index b681bec..1f2389f 100644 --- a/arch/powerpc/mm/pkeys.c +++ b/arch/powerpc/mm/pkeys.c @@ -25,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 EXECUTE_ONLY_KEY 2 static void scan_pkey_feature(void) { @@ -120,7 +121,8 @@ int pkey_initialize(void) #else os_reserved = 0; #endif - initial_allocation_mask = (0x1 << 0) | (0x1 << 1); + initial_allocation_mask = (0x1 << 0) | (0x1 << 1) | + (0x1 << EXECUTE_ONLY_KEY); /* register mask is in BE format */ pkey_amr_mask = ~0x0ul; @@ -130,9 +132,12 @@ int pkey_initialize(void) pkey_amr_mask &= ~(0x3ul << pkeyshift(i)); pkey_iamr_mask &= ~(0x1ul << pkeyshift(i)); } + pkey_amr_mask |= (AMR_RD_BIT|AMR_WR_BIT) << pkeyshift(EXECUTE_ONLY_KEY); pkey_uamor_mask = ~0x0ul; pkey_uamor_mask &= ~(0x3ul << pkeyshift(0)); + pkey_uamor_mask &= ~(0x3ul << pkeyshift(EXECUTE_ONLY_KEY)); + for (i = (pkeys_total - os_reserved); i < pkeys_total; i++) pkey_uamor_mask &= ~(0x3ul << pkeyshift(i)); @@ -146,8 +151,7 @@ void pkey_mm_init(struct mm_struct *mm) if (static_branch_likely(&pkey_disabled)) return; mm_pkey_allocation_map(mm) = initial_allocation_mask; - /* -1 means unallocated or invalid */ - mm->context.execute_only_pkey = -1; + mm->context.execute_only_pkey = EXECUTE_ONLY_KEY; } static inline u64 read_amr(void) @@ -326,48 +330,7 @@ static inline bool pkey_allows_readwrite(int pkey) int __execute_only_pkey(struct mm_struct *mm) { - bool need_to_set_mm_pkey = false; - int execute_only_pkey = mm->context.execute_only_pkey; - int ret; - - /* Do we need to assign a pkey for mm's execute-only maps? */ - if (execute_only_pkey == -1) { - /* Go allocate one to use, which might fail */ - execute_only_pkey = mm_pkey_alloc(mm); - if (execute_only_pkey < 0) - return -1; - need_to_set_mm_pkey = true; - } - - /* - * We do not want to go through the relatively costly dance to set AMR - * if we do not need to. Check it first and assume that if the - * execute-only pkey is readwrite-disabled than we do not have to set it - * ourselves. - */ - if (!need_to_set_mm_pkey && !pkey_allows_readwrite(execute_only_pkey)) - return execute_only_pkey; - - /* - * Set up AMR so that it denies access for everything other than - * execution. - */ - ret = __arch_set_user_pkey_access(current, execute_only_pkey, - PKEY_DISABLE_ACCESS | - PKEY_DISABLE_WRITE); - /* - * If the AMR-set operation failed somehow, just return 0 and - * effectively disable execute-only support. - */ - if (ret) { - mm_pkey_free(mm, execute_only_pkey); - return -1; - } - - /* We got one, store it and use it from here on out */ - if (need_to_set_mm_pkey) - mm->context.execute_only_pkey = execute_only_pkey; - return execute_only_pkey; + return mm->context.execute_only_pkey; } static inline bool vma_is_pkey_exec_only(struct vm_area_struct *vma)