Received: by 2002:a25:8b91:0:0:0:0:0 with SMTP id j17csp649025ybl; Fri, 31 Jan 2020 05:37:06 -0800 (PST) X-Google-Smtp-Source: APXvYqw+rxCETz06aua8xJFfhYXWK4pAhD0V/Ev42sj9+Zhb/+OH3hOZwPXJoDV1TILIwYcBBV45 X-Received: by 2002:aca:ac10:: with SMTP id v16mr5975717oie.123.1580477826469; Fri, 31 Jan 2020 05:37:06 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1580477826; cv=none; d=google.com; s=arc-20160816; b=hJVSTHhiHlPCA4k8sze0VEfrhDy2W+eYxygfQBAoZdNBecjSOw0Jv9Z5Aw7815Eog8 1Qz7vDcgUe0Y5f1DMRXqm/84mTOXV2tXV3hX2euyG8nYkcQk/3Q5cb4nUV2J7zJ+8hHZ oAklOKtIQ05kDFajeo8eP+9jfnj6zVOpnj9qLVV3f1R+aOOI5eiZusz97YfEQZbmw3zb 4TWVak/nf0JX96vVc0ffqHVT4YRAvFqyWNqibytC42jz17TjbNgXh2qWeogsSYXwWD7S QyWGArm61qBpbcb1AYjl0UhfLZwFWraTdkOBxtFFT4Sv0zkjnXsjWSCXZjcQ3nRacR+L y8zw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:date:cc:to:subject:from:message-id :dkim-signature; bh=0GVLbwhgWrQll+nMyleiz2tV3H81Ve5iFhb2AKQrvIo=; b=HWR9diAN5H+7hI4Gsi7q6O/IwWElBFHh1iIGhB/5HspvWtRVS0QVIO8GNsr2FSG/DD 99zUEyf9zP4+qHygnkN5J4Sz40a6A5AACn4EgAwHiVWl4oSinOj1sOs8qmkE13X0NpyU DVqpL11YqQIkVZSCNkZk3KHlcWckug1pJuiO/iZ/GS5FiyWW+DH8/xIMgLg6jjWzwMzl Axpbh/rUSLYxfBBQgGcn6BbX1zLRUdGOpW1FdpgHY1yyDp5oDL+tEIDGT6xVHyUgs/0O 5aFPX9ejb3Kv/ynwOx/sW1FVcsc/u0YWiMi00zo9MGNyOfXm2skwgWZ7EQTJXtJMCh3n cPJA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@c-s.fr header.s=mail header.b=r9fnEh+E; 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 p26si4580625oto.240.2020.01.31.05.36.54; Fri, 31 Jan 2020 05:37:06 -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=r9fnEh+E; 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 S1728693AbgAaNew (ORCPT + 99 others); Fri, 31 Jan 2020 08:34:52 -0500 Received: from pegase1.c-s.fr ([93.17.236.30]:13131 "EHLO pegase1.c-s.fr" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728566AbgAaNev (ORCPT ); Fri, 31 Jan 2020 08:34:51 -0500 Received: from localhost (mailhub1-int [192.168.12.234]) by localhost (Postfix) with ESMTP id 488J9h34hLz9vCRj; Fri, 31 Jan 2020 14:34:48 +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=r9fnEh+E; 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 pK71aHW6bdoa; Fri, 31 Jan 2020 14:34:48 +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 488J9h1sFVz9vCRQ; Fri, 31 Jan 2020 14:34:48 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=c-s.fr; s=mail; t=1580477688; bh=0GVLbwhgWrQll+nMyleiz2tV3H81Ve5iFhb2AKQrvIo=; h=From:Subject:To:Cc:Date:From; b=r9fnEh+E1reOH09ShTyRt0il/RuQM00HwHRGiNjYNyJRSC6NRP5MwzTSpXN8RVHqj 2yNtUBheyo8ogzV08A91B3Kgrg9E/1qJJaVLl6OY8A9/5Xs8Fw7KSzGfLuO9CwFswN AnuSNlEmEX0GxdST6AVQ+AG1wze7xXl6hLckwxwU= Received: from localhost (localhost [127.0.0.1]) by messagerie.si.c-s.fr (Postfix) with ESMTP id 8D93B8B8AA; Fri, 31 Jan 2020 14:34:49 +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 t-zHJjyrAIsu; Fri, 31 Jan 2020 14:34:49 +0100 (CET) Received: from po14934vm.idsi0.si.c-s.fr (po15451.idsi0.si.c-s.fr [172.25.230.105]) by messagerie.si.c-s.fr (Postfix) with ESMTP id 636508B8A2; Fri, 31 Jan 2020 14:34:49 +0100 (CET) Received: by po14934vm.idsi0.si.c-s.fr (Postfix, from userid 0) id 416F865288; Fri, 31 Jan 2020 13:34:49 +0000 (UTC) Message-Id: <84be5ad6a996adf5693260749dcb4d8c69182073.1580477672.git.christophe.leroy@c-s.fr> From: Christophe Leroy Subject: [PATCH v2 1/7] powerpc/mm: Implement set_memory() routines To: Benjamin Herrenschmidt , Paul Mackerras , Michael Ellerman , ruscur@russell.cc Cc: linux-kernel@vger.kernel.org, linuxppc-dev@lists.ozlabs.org Date: Fri, 31 Jan 2020 13:34:49 +0000 (UTC) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The set_memory_{ro/rw/nx/x}() functions are required for STRICT_MODULE_RWX, and are generally useful primitives to have. This implementation is designed to be completely generic across powerpc's many MMUs. It's possible that this could be optimised to be faster for specific MMUs, but the focus is on having a generic and safe implementation for now. This implementation does not handle cases where the caller is attempting to change the mapping of the page it is executing from, or if another CPU is concurrently using the page being altered. These cases likely shouldn't happen, but a more complex implementation with MMU-specific code could safely handle them, so that is left as a TODO for now. Signed-off-by: Russell Currey Signed-off-by: Christophe Leroy --- v2: - use integers instead of pointers for action - drop action check, nobody should call change_memory_attr() directly. Should it happen, the function will just do nothing. - Renamed confusing 'pte_val' var to 'pte' as pte_val() is already a function. --- arch/powerpc/Kconfig | 1 + arch/powerpc/include/asm/set_memory.h | 32 ++++++++++++ arch/powerpc/mm/Makefile | 1 + arch/powerpc/mm/pageattr.c | 74 +++++++++++++++++++++++++++ 4 files changed, 108 insertions(+) create mode 100644 arch/powerpc/include/asm/set_memory.h create mode 100644 arch/powerpc/mm/pageattr.c diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index a8fdb36a841e..ae6a27d07406 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -129,6 +129,7 @@ config PPC select ARCH_HAS_PTE_SPECIAL select ARCH_HAS_MEMBARRIER_CALLBACKS select ARCH_HAS_SCALED_CPUTIME if VIRT_CPU_ACCOUNTING_NATIVE && PPC_BOOK3S_64 + select ARCH_HAS_SET_MEMORY select ARCH_HAS_STRICT_KERNEL_RWX if ((PPC_BOOK3S_64 || PPC32) && !HIBERNATION) select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST select ARCH_HAS_UACCESS_FLUSHCACHE diff --git a/arch/powerpc/include/asm/set_memory.h b/arch/powerpc/include/asm/set_memory.h new file mode 100644 index 000000000000..c3621030a3fb --- /dev/null +++ b/arch/powerpc/include/asm/set_memory.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_POWERPC_SET_MEMORY_H +#define _ASM_POWERPC_SET_MEMORY_H + +#define SET_MEMORY_RO 0 +#define SET_MEMORY_RW 1 +#define SET_MEMORY_NX 2 +#define SET_MEMORY_X 3 + +int change_memory_attr(unsigned long addr, int numpages, int action); + +static inline int set_memory_ro(unsigned long addr, int numpages) +{ + return change_memory_attr(addr, numpages, SET_MEMORY_RO); +} + +static inline int set_memory_rw(unsigned long addr, int numpages) +{ + return change_memory_attr(addr, numpages, SET_MEMORY_RW); +} + +static inline int set_memory_nx(unsigned long addr, int numpages) +{ + return change_memory_attr(addr, numpages, SET_MEMORY_NX); +} + +static inline int set_memory_x(unsigned long addr, int numpages) +{ + return change_memory_attr(addr, numpages, SET_MEMORY_X); +} + +#endif diff --git a/arch/powerpc/mm/Makefile b/arch/powerpc/mm/Makefile index 5e147986400d..d0a0bcbc9289 100644 --- a/arch/powerpc/mm/Makefile +++ b/arch/powerpc/mm/Makefile @@ -20,3 +20,4 @@ obj-$(CONFIG_HIGHMEM) += highmem.o obj-$(CONFIG_PPC_COPRO_BASE) += copro_fault.o obj-$(CONFIG_PPC_PTDUMP) += ptdump/ obj-$(CONFIG_KASAN) += kasan/ +obj-$(CONFIG_ARCH_HAS_SET_MEMORY) += pageattr.o diff --git a/arch/powerpc/mm/pageattr.c b/arch/powerpc/mm/pageattr.c new file mode 100644 index 000000000000..0cb5294732b7 --- /dev/null +++ b/arch/powerpc/mm/pageattr.c @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * MMU-generic set_memory implementation for powerpc + * + * Copyright 2019, IBM Corporation. + */ + +#include +#include + +#include +#include +#include + + +/* + * Updates the attributes of a page in three steps: + * + * 1. invalidate the page table entry + * 2. flush the TLB + * 3. install the new entry with the updated attributes + * + * This is unsafe if the caller is attempting to change the mapping of the + * page it is executing from, or if another CPU is concurrently using the + * page being altered. + * + * TODO make the implementation resistant to this. + */ +static int change_page_attr(pte_t *ptep, unsigned long addr, void *data) +{ + int action = (int)data; + pte_t pte; + + spin_lock(&init_mm.page_table_lock); + + /* invalidate the PTE so it's safe to modify */ + pte = ptep_get_and_clear(&init_mm, addr, ptep); + flush_tlb_kernel_range(addr, addr + PAGE_SIZE); + + /* modify the PTE bits as desired, then apply */ + switch (action) { + case SET_MEMORY_RO: + pte = pte_wrprotect(pte); + break; + case SET_MEMORY_RW: + pte = pte_mkwrite(pte); + break; + case SET_MEMORY_NX: + pte = pte_exprotect(pte); + break; + case SET_MEMORY_X: + pte = pte_mkexec(pte); + break; + default: + break; + } + + set_pte_at(&init_mm, addr, ptep, pte); + spin_unlock(&init_mm.page_table_lock); + + return 0; +} + +int change_memory_attr(unsigned long addr, int numpages, int action) +{ + unsigned long start = ALIGN_DOWN(addr, PAGE_SIZE); + unsigned long sz = numpages * PAGE_SIZE; + + if (!numpages) + return 0; + + return apply_to_page_range(&init_mm, start, sz, change_page_attr, (void *)action); +} -- 2.25.0