From patchwork Tue Jul 17 13:49:17 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ram Pai X-Patchwork-Id: 10529519 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 206C860545 for ; Tue, 17 Jul 2018 13:51:05 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 04E0B29203 for ; Tue, 17 Jul 2018 13:51:05 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id EC8A129221; Tue, 17 Jul 2018 13:51:04 +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.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, MAILING_LIST_MULTI, RCVD_IN_DNSWL_NONE, T_DKIM_INVALID autolearn=unavailable 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 2AF0B29203 for ; Tue, 17 Jul 2018 13:51:04 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 689AF6B0274; Tue, 17 Jul 2018 09:50:35 -0400 (EDT) Delivered-To: linux-mm-outgoing@kvack.org Received: by kanga.kvack.org (Postfix, from userid 40) id 634D76B0275; Tue, 17 Jul 2018 09:50:35 -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 4D8056B0276; Tue, 17 Jul 2018 09:50:35 -0400 (EDT) X-Original-To: linux-mm@kvack.org X-Delivered-To: linux-mm@kvack.org Received: from mail-qt0-f200.google.com (mail-qt0-f200.google.com [209.85.216.200]) by kanga.kvack.org (Postfix) with ESMTP id 126816B0274 for ; Tue, 17 Jul 2018 09:50:35 -0400 (EDT) Received: by mail-qt0-f200.google.com with SMTP id i10-v6so751140qtp.13 for ; Tue, 17 Jul 2018 06:50:35 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:dkim-signature:sender:from:to:cc:subject:date :message-id:in-reply-to:references; bh=Esg25II181BR9ikSNz2Y/vIgtoBkJlb9Lkp/0J415fM=; b=WCYPbbmXM2NvCFucpvDlDFQTinc+2NG5QpnU+2RLr12Y5jJGhBcvIRu9OFeCPtW4nW 7gNUGqZZNK3Qcxyop1s6rxnegNcqFPx+IZrjRAaSrOs4mFN/WcMuJkahtJE4EcPTXCbY UlZztyJY+ytv9HZJmq2PndEknpRnB7aT9jHS7QK6+YJpCTZJge1MTPibJMQCLS7CCZv3 msdKwf7Q/Zfv2Jne9ld1BH4ToAheTwEtgrJTdbv+QvMQaDtIrmuF10V48Keyt9H7DueZ s+eLnDby/66MNqnpS8F7Hd6fNS3aLn+lVJv5w/Spk79oSqqxFc8CgYoBc+vtliM5X0bi 2lMg== X-Gm-Message-State: AOUpUlFkWnqKXEKK4FzjPbY74mJUdGNKG2zsaMZDv3xaPNCcKnXyZEgr raJhhK3x1xf6ni88hq9XO1dtQ40ykTQ9xumHg/JbEB0WKPVNIwec/sxJaBwD79dmLxsGzaOHTl0 F8Nngf1E9kkEPBdzFaRubXUneOvoxZMUGtHICxXGdMjxHMWUYge3R7EcXDW9V5YPQLZwutikpOB /YZvEuZ9O39i1kH5RMnei3YbOHSp1UduXYz2WOAo+ke0MRKwvH/H1wZs4Lcz3ePz0OmiAn22Nk5 P+wtzISppKNBgXdr9o1WWjkGVmyxjoemnm51EkremDtf4avtmT9DX8xGsI6NiuyEl0IxU4YDuoI CRYVetEqYKtH2fB7Ij1MTJM2iW0WZSZ0kkwXC2npqg50OA1EOzcHQDczJ0qu3t4QcJb3q1q/mg= = X-Received: by 2002:ac8:29ef:: with SMTP id 44-v6mr1516443qtt.174.1531835434768; Tue, 17 Jul 2018 06:50:34 -0700 (PDT) X-Received: by 2002:ac8:29ef:: with SMTP id 44-v6mr1516344qtt.174.1531835433363; Tue, 17 Jul 2018 06:50:33 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1531835433; cv=none; d=google.com; s=arc-20160816; b=v/6dJuJY7OVdhrmZuJdzyOkCkyPOfx1UyWVJaCgORvv61LXUOPrnCDjNwyc7S49Dvh TaKc06pf7NgTtSlxLBPUu9550uxOrPK6enLuIBDBoh5Omf8w9XW+P3WKiMalScGQYXVN 1LOxgXdzpOe+82OKEJyWF0M/NG0d/96lcnGGTkVo7Jrmebto+JVXP87LTq0IsaOO6xZh y/f2yoVXbHsWx1GZegLKHjyqCBmpd+2eEqn0v2zjnP2bA+Uk0l/JfAJTuAluIT7O51WW iPywic2TC1L6DXoD3szCcnWX15ZZWR/IkqCYKfdHoPQG0Z4bwnthVuVTuPmbPdBYFAj9 8P6w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=references:in-reply-to:message-id:date:subject:cc:to:from:sender :dkim-signature:arc-authentication-results; bh=Esg25II181BR9ikSNz2Y/vIgtoBkJlb9Lkp/0J415fM=; b=BJR07ZwMbl8SXuCgYb0SuyGt4mscmFjXVRF+JFPz+QUzjTufB0e2C+xoYLChYVLQSg RdT8P+oWPlBBNsoDAFDtrH4ax/XJmxWEESMLuy4AQoEtd043VEh9RN7m+sg3pXzmN7az yjH5X5Symczh/P4LMlat2juTcc/6FwpJDURUpcFDZKh/2IoTbkS2wFp8UBb5WMX+3mei hEM1hv1OY+CXw05JFHgJfs66V5mha1eQiZZRvNcF633RUNZbUudBWxbMIO67bkWVf7IA tYnVBf5Er1vyRKabt680hyqsurmOLCfHhiORUBMGIcL8CUmwb/VQLOdr2m9Z3LyEZX36 ShQw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=l75obiFb; spf=pass (google.com: domain of ram.n.pai@gmail.com designates 209.85.220.65 as permitted sender) smtp.mailfrom=ram.n.pai@gmail.com; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=ibm.com Received: from mail-sor-f65.google.com (mail-sor-f65.google.com. [209.85.220.65]) by mx.google.com with SMTPS id i67-v6sor492496qtb.137.2018.07.17.06.50.33 for (Google Transport Security); Tue, 17 Jul 2018 06:50:33 -0700 (PDT) Received-SPF: pass (google.com: domain of ram.n.pai@gmail.com designates 209.85.220.65 as permitted sender) client-ip=209.85.220.65; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=l75obiFb; spf=pass (google.com: domain of ram.n.pai@gmail.com designates 209.85.220.65 as permitted sender) smtp.mailfrom=ram.n.pai@gmail.com; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=ibm.com 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=Esg25II181BR9ikSNz2Y/vIgtoBkJlb9Lkp/0J415fM=; b=l75obiFbnBV/LoWQesrgtml7Zo8klrHUkfFks9G6PwgCh4fswmbiE6cKZ2X28dPiTQ 11ViY2Oen5xvnXhSdQATFxQEMriQkad6/NXta2K6DrfaTy6JCVuFbq73x6tZEYvs6A8e 8uP8Df1Aju+ELgK8HtO72w2EXBvn53UZacyijpYMspQ52WJXMA1zTVaq3wKdIt9JHNBo QGKr2ADp1BtCLhn+DqkUusu0RL8umEW6KuZApHKLQ+Z4898Q2rHYB4lNaKGSkx5hM2zP ObKGFFQOGbAwecTJFhjzJkxCmtS9QZgfMQ1OFFqJ/wX9S30/0ytSjjAqg70q4kE2B7L0 11Pg== X-Google-Smtp-Source: AAOMgpfsKKFAq5ykcKLHdpEjBONnra+K0W/rVD8mv+sx+cV2dWKXvQJ5ozbmwJnAbGZE0i56Hsi4pg== X-Received: by 2002:ac8:2a76:: with SMTP id l51-v6mr1607646qtl.342.1531835432997; Tue, 17 Jul 2018 06:50:32 -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 s83-v6sm640937qki.20.2018.07.17.06.50.30 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 17 Jul 2018 06:50:32 -0700 (PDT) From: Ram Pai To: shuahkh@osg.samsung.com, linux-kselftest@vger.kernel.org Cc: mpe@ellerman.id.au, linuxppc-dev@lists.ozlabs.org, linux-mm@kvack.org, x86@kernel.org, linux-arch@vger.kernel.org, mingo@redhat.com, dave.hansen@intel.com, mhocko@kernel.org, bauerman@linux.vnet.ibm.com, linuxram@us.ibm.com, fweimer@redhat.com, msuchanek@suse.de, aneesh.kumar@linux.vnet.ibm.com Subject: [PATCH v14 14/22] selftests/vm: Introduce generic abstractions Date: Tue, 17 Jul 2018 06:49:17 -0700 Message-Id: <1531835365-32387-15-git-send-email-linuxram@us.ibm.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1531835365-32387-1-git-send-email-linuxram@us.ibm.com> References: <1531835365-32387-1-git-send-email-linuxram@us.ibm.com> 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 Introduce generic abstractions and provide architecture specific implementation for the abstractions. cc: Dave Hansen cc: Florian Weimer Signed-off-by: Ram Pai Signed-off-by: Thiago Jung Bauermann --- tools/testing/selftests/vm/pkey-helpers.h | 16 ++++- tools/testing/selftests/vm/pkey-powerpc.h | 93 ++++++++++++++++++++++++++ tools/testing/selftests/vm/pkey-x86.h | 15 ++++ tools/testing/selftests/vm/protection_keys.c | 52 ++++++++------ 4 files changed, 153 insertions(+), 23 deletions(-) create mode 100644 tools/testing/selftests/vm/pkey-powerpc.h diff --git a/tools/testing/selftests/vm/pkey-helpers.h b/tools/testing/selftests/vm/pkey-helpers.h index 52a1152..321bbbd 100644 --- a/tools/testing/selftests/vm/pkey-helpers.h +++ b/tools/testing/selftests/vm/pkey-helpers.h @@ -74,8 +74,13 @@ static inline void sigsafe_printf(const char *format, ...) } \ } while (0) +__attribute__((noinline)) int read_ptr(int *ptr); +void expected_pkey_fault(int pkey); + #if defined(__i386__) || defined(__x86_64__) /* arch */ #include "pkey-x86.h" +#elif defined(__powerpc64__) /* arch */ +#include "pkey-powerpc.h" #else /* arch */ #error Architecture not supported #endif /* arch */ @@ -186,7 +191,16 @@ static inline int open_hugepage_file(int flag) static inline int get_start_key(void) { - return 1; + return 0; +} + +static inline u32 *siginfo_get_pkey_ptr(siginfo_t *si) +{ +#ifdef si_pkey + return &si->si_pkey; +#else + return (u32 *)(((u8 *)si) + si_pkey_offset); +#endif } #endif /* _PKEYS_HELPER_H */ diff --git a/tools/testing/selftests/vm/pkey-powerpc.h b/tools/testing/selftests/vm/pkey-powerpc.h new file mode 100644 index 0000000..b0d1abe --- /dev/null +++ b/tools/testing/selftests/vm/pkey-powerpc.h @@ -0,0 +1,93 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef _PKEYS_POWERPC_H +#define _PKEYS_POWERPC_H + +#ifndef SYS_mprotect_key +# define SYS_mprotect_key 386 +#endif +#ifndef SYS_pkey_alloc +# define SYS_pkey_alloc 384 +# define SYS_pkey_free 385 +#endif +#define REG_IP_IDX PT_NIP +#define REG_TRAPNO PT_TRAP +#define gregs gp_regs +#define fpregs fp_regs +#define si_pkey_offset 0x20 + +#ifndef PKEY_DISABLE_ACCESS +# define PKEY_DISABLE_ACCESS 0x3 /* disable read and write */ +#endif + +#ifndef PKEY_DISABLE_WRITE +# define PKEY_DISABLE_WRITE 0x2 +#endif + +#define NR_PKEYS 32 +#define NR_RESERVED_PKEYS_4K 27 /* pkey-0, pkey-1, exec-only-pkey + and 24 other keys that cannot be + represented in the PTE */ +#define NR_RESERVED_PKEYS_64K 3 /* pkey-0, pkey-1 and exec-only-pkey */ +#define PKEY_BITS_PER_PKEY 2 +#define HPAGE_SIZE (1UL << 24) +#define PAGE_SIZE (1UL << 16) +#define pkey_reg_t u64 +#define PKEY_REG_FMT "%016lx" +#define HUGEPAGE_FILE "/sys/kernel/mm/hugepages/hugepages-16384kB/nr_hugepages" + +static inline u32 pkey_bit_position(int pkey) +{ + return (NR_PKEYS - pkey - 1) * PKEY_BITS_PER_PKEY; +} + +static inline pkey_reg_t __read_pkey_reg(void) +{ + pkey_reg_t pkey_reg; + + asm volatile("mfspr %0, 0xd" : "=r" (pkey_reg)); + + return pkey_reg; +} + +static inline void __write_pkey_reg(pkey_reg_t pkey_reg) +{ + pkey_reg_t eax = pkey_reg; + + dprintf4("%s() changing "PKEY_REG_FMT" to "PKEY_REG_FMT"\n", + __func__, __read_pkey_reg(), pkey_reg); + + asm volatile("mtspr 0xd, %0" : : "r" ((unsigned long)(eax)) : "memory"); + + dprintf4("%s() pkey register after changing "PKEY_REG_FMT" to " + PKEY_REG_FMT"\n", __func__, __read_pkey_reg(), + pkey_reg); +} + +static inline int cpu_has_pku(void) +{ + return 1; +} + +static inline int arch_reserved_keys(void) +{ + if (sysconf(_SC_PAGESIZE) == 4096) + return NR_RESERVED_PKEYS_4K; + else + return NR_RESERVED_PKEYS_64K; +} + +void expect_fault_on_read_execonly_key(void *p1, int pkey) +{ + /* powerpc does not allow userspace to change permissions of exec-only + * keys since those keys are not allocated by userspace. The signal + * handler wont be able to reset the permissions, which means the code + * will infinitely continue to segfault here. + */ + return; +} + +/* 8-bytes of instruction * 16384bytes = 1 page */ +#define __page_o_noops() asm(".rept 16384 ; nop; .endr") + +#endif /* _PKEYS_POWERPC_H */ diff --git a/tools/testing/selftests/vm/pkey-x86.h b/tools/testing/selftests/vm/pkey-x86.h index d5fa299..f5d0ff2 100644 --- a/tools/testing/selftests/vm/pkey-x86.h +++ b/tools/testing/selftests/vm/pkey-x86.h @@ -42,6 +42,7 @@ #endif #define NR_PKEYS 16 +#define NR_RESERVED_PKEYS 2 /* pkey-0 and exec-only-pkey */ #define PKEY_BITS_PER_PKEY 2 #define HPAGE_SIZE (1UL<<21) #define PAGE_SIZE 4096 @@ -161,4 +162,18 @@ int pkey_reg_xstate_offset(void) return xstate_offset; } +static inline int arch_reserved_keys(void) +{ + return NR_RESERVED_PKEYS; +} + +void expect_fault_on_read_execonly_key(void *p1, int pkey) +{ + int ptr_contents; + + ptr_contents = read_ptr(p1); + dprintf2("ptr (%p) contents@%d: %x\n", p1, __LINE__, ptr_contents); + expected_pkey_fault(pkey); +} + #endif /* _PKEYS_X86_H */ diff --git a/tools/testing/selftests/vm/protection_keys.c b/tools/testing/selftests/vm/protection_keys.c index 304f74f..18e1bb7 100644 --- a/tools/testing/selftests/vm/protection_keys.c +++ b/tools/testing/selftests/vm/protection_keys.c @@ -197,17 +197,18 @@ void dump_mem(void *dumpme, int len_bytes) int pkey_faults; int last_si_pkey = -1; +void pkey_access_allow(int pkey); void signal_handler(int signum, siginfo_t *si, void *vucontext) { ucontext_t *uctxt = vucontext; int trapno; unsigned long ip; char *fpregs; +#if defined(__i386__) || defined(__x86_64__) /* arch */ pkey_reg_t *pkey_reg_ptr; - u64 siginfo_pkey; +#endif /* defined(__i386__) || defined(__x86_64__) */ + u32 siginfo_pkey; u32 *si_pkey_ptr; - int pkey_reg_offset; - fpregset_t fpregset; dprint_in_signal = 1; dprintf1(">>>>===============SIGSEGV============================\n"); @@ -217,12 +218,14 @@ void signal_handler(int signum, siginfo_t *si, void *vucontext) trapno = uctxt->uc_mcontext.gregs[REG_TRAPNO]; ip = uctxt->uc_mcontext.gregs[REG_IP_IDX]; - fpregset = uctxt->uc_mcontext.fpregs; - fpregs = (void *)fpregset; + fpregs = (char *) uctxt->uc_mcontext.fpregs; dprintf2("%s() trapno: %d ip: 0x%016lx info->si_code: %s/%d\n", __func__, trapno, ip, si_code_str(si->si_code), si->si_code); + +#if defined(__i386__) || defined(__x86_64__) /* arch */ + #ifdef __i386__ /* * 32-bit has some extra padding so that userspace can tell whether @@ -230,20 +233,21 @@ void signal_handler(int signum, siginfo_t *si, void *vucontext) * state. We just assume that it is here. */ fpregs += 0x70; -#endif - pkey_reg_offset = pkey_reg_xstate_offset(); - pkey_reg_ptr = (void *)(&fpregs[pkey_reg_offset]); +#endif /* __i386__ */ - dprintf1("siginfo: %p\n", si); - dprintf1(" fpregs: %p\n", fpregs); + pkey_reg_ptr = (void *)(&fpregs[pkey_reg_xstate_offset()]); /* - * If we got a PKEY fault, we *HAVE* to have at least one bit set in + * If we got a key fault, we *HAVE* to have at least one bit set in * here. */ dprintf1("pkey_reg_xstate_offset: %d\n", pkey_reg_xstate_offset()); if (DEBUG_LEVEL > 4) dump_mem(pkey_reg_ptr - 128, 256); pkey_assert(*pkey_reg_ptr); +#endif /* defined(__i386__) || defined(__x86_64__) */ + + dprintf1("siginfo: %p\n", si); + dprintf1(" fpregs: %p\n", fpregs); if ((si->si_code == SEGV_MAPERR) || (si->si_code == SEGV_ACCERR) || @@ -252,22 +256,28 @@ void signal_handler(int signum, siginfo_t *si, void *vucontext) exit(4); } - si_pkey_ptr = (u32 *)(((u8 *)si) + si_pkey_offset); + si_pkey_ptr = siginfo_get_pkey_ptr(si); dprintf1("si_pkey_ptr: %p\n", si_pkey_ptr); - dump_mem((u8 *)si_pkey_ptr - 8, 24); + dump_mem(si_pkey_ptr - 8, 24); siginfo_pkey = *si_pkey_ptr; pkey_assert(siginfo_pkey < NR_PKEYS); last_si_pkey = siginfo_pkey; - dprintf1("signal pkey_reg from xsave: "PKEY_REG_FMT"\n", *pkey_reg_ptr); /* * need __read_pkey_reg() version so we do not do shadow_pkey_reg * checking */ dprintf1("signal pkey_reg from pkey_reg: "PKEY_REG_FMT"\n", __read_pkey_reg()); - dprintf1("pkey from siginfo: %jx\n", siginfo_pkey); - *(u64 *)pkey_reg_ptr = 0x00000000; +#if defined(__i386__) || defined(__x86_64__) /* arch */ + dprintf1("signal pkey_reg from xsave: "PKEY_REG_FMT"\n", *pkey_reg_ptr); + *(u64 *)pkey_reg_ptr &= clear_pkey_flags(siginfo_pkey, + PKEY_DISABLE_ACCESS | PKEY_DISABLE_WRITE); +#elif __powerpc64__ + pkey_access_allow(siginfo_pkey); +#endif + shadow_pkey_reg &= clear_pkey_flags(siginfo_pkey, + PKEY_DISABLE_ACCESS | PKEY_DISABLE_WRITE); dprintf1("WARNING: set PKEY_REG=0 to allow faulting instruction " "to continue\n"); pkey_faults++; @@ -1328,9 +1338,8 @@ void test_executing_on_unreadable_memory(int *ptr, u16 pkey) madvise(p1, PAGE_SIZE, MADV_DONTNEED); lots_o_noops_around_write(&scratch); do_not_expect_pkey_fault("executing on PROT_EXEC memory"); - ptr_contents = read_ptr(p1); - dprintf2("ptr (%p) contents@%d: %x\n", p1, __LINE__, ptr_contents); - expected_pkey_fault(pkey); + + expect_fault_on_read_execonly_key(p1, pkey); } void test_implicit_mprotect_exec_only_memory(int *ptr, u16 pkey) @@ -1357,9 +1366,8 @@ void test_implicit_mprotect_exec_only_memory(int *ptr, u16 pkey) madvise(p1, PAGE_SIZE, MADV_DONTNEED); lots_o_noops_around_write(&scratch); do_not_expect_pkey_fault("executing on PROT_EXEC memory"); - ptr_contents = read_ptr(p1); - dprintf2("ptr (%p) contents@%d: %x\n", p1, __LINE__, ptr_contents); - expected_pkey_fault(UNKNOWN_PKEY); + + expect_fault_on_read_execonly_key(p1, UNKNOWN_PKEY); /* * Put the memory back to non-PROT_EXEC. Should clear the