All of lore.kernel.org
 help / color / mirror / Atom feed
From: Petr Tesarik <petrtesarik@huaweicloud.com>
To: Jonathan Corbet <corbet@lwn.net>,
	Thomas Gleixner <tglx@linutronix.de>,
	Ingo Molnar <mingo@redhat.com>, Borislav Petkov <bp@alien8.de>,
	Dave Hansen <dave.hansen@linux.intel.com>,
	x86@kernel.org (maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT)),
	"H. Peter Anvin" <hpa@zytor.com>,
	Andy Lutomirski <luto@kernel.org>,
	Oleg Nesterov <oleg@redhat.com>,
	Peter Zijlstra <peterz@infradead.org>, Xin Li <xin3.li@intel.com>,
	Arnd Bergmann <arnd@arndb.de>,
	Andrew Morton <akpm@linux-foundation.org>,
	Rick Edgecombe <rick.p.edgecombe@intel.com>,
	Kees Cook <keescook@chromium.org>,
	"Masami Hiramatsu (Google)" <mhiramat@kernel.org>,
	Pengfei Xu <pengfei.xu@intel.com>,
	Josh Poimboeuf <jpoimboe@kernel.org>,
	Ze Gao <zegao2021@gmail.com>,
	"Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>,
	Kai Huang <kai.huang@intel.com>,
	David Woodhouse <dwmw@amazon.co.uk>,
	Brian Gerst <brgerst@gmail.com>, Jason Gunthorpe <jgg@ziepe.ca>,
	Joerg Roedel <jroedel@suse.de>,
	"Mike Rapoport (IBM)" <rppt@kernel.org>,
	Tina Zhang <tina.zhang@intel.com>,
	Jacob Pan <jacob.jun.pan@linux.intel.com>,
	linux-doc@vger.kernel.org (open list:DOCUMENTATION),
	linux-kernel@vger.kernel.org (open list)
Cc: Roberto Sassu <roberto.sassu@huaweicloud.com>,
	petr@tesarici.cz,
	Petr Tesarik <petr.tesarik1@huawei-partners.com>
Subject: [PATCH v1 1/8] sbm: x86: page table arch hooks
Date: Wed, 14 Feb 2024 12:35:09 +0100	[thread overview]
Message-ID: <20240214113516.2307-2-petrtesarik@huaweicloud.com> (raw)
In-Reply-To: <20240214113516.2307-1-petrtesarik@huaweicloud.com>

From: Petr Tesarik <petr.tesarik1@huawei-partners.com>

Add arch hooks for the x86 architecture and select CONFIG_HAVE_ARCH_SBM.

Implement arch_sbm_init(): Allocate an arch-specific state page and store
it as SBM instance private data. Set up mappings for kernel text, static
data, current task and current thread stack into the.

Implement arch_sbm_map_readonly() and arch_sbm_map_writable(): Set the PTE
value, allocating additional page tables as necessary.

Implement arch_sbm_destroy(): Walk the page table hierarchy and free all
page tables, including the page global directory.

Provide a trivial implementation of arch_sbm_exec() to avoid build
failures, but do not switch to the constructed page tables yet.

Signed-off-by: Petr Tesarik <petr.tesarik1@huawei-partners.com>
---
 arch/x86/Kconfig             |   1 +
 arch/x86/include/asm/sbm.h   |  29 ++++
 arch/x86/kernel/Makefile     |   2 +
 arch/x86/kernel/sbm/Makefile |  10 ++
 arch/x86/kernel/sbm/core.c   | 248 +++++++++++++++++++++++++++++++++++
 5 files changed, 290 insertions(+)
 create mode 100644 arch/x86/include/asm/sbm.h
 create mode 100644 arch/x86/kernel/sbm/Makefile
 create mode 100644 arch/x86/kernel/sbm/core.c

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 5edec175b9bf..41fa4ab84c15 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -188,6 +188,7 @@ config X86
 	select HAVE_ARCH_MMAP_RND_COMPAT_BITS	if MMU && COMPAT
 	select HAVE_ARCH_COMPAT_MMAP_BASES	if MMU && COMPAT
 	select HAVE_ARCH_PREL32_RELOCATIONS
+	select HAVE_ARCH_SBM
 	select HAVE_ARCH_SECCOMP_FILTER
 	select HAVE_ARCH_THREAD_STRUCT_WHITELIST
 	select HAVE_ARCH_STACKLEAK
diff --git a/arch/x86/include/asm/sbm.h b/arch/x86/include/asm/sbm.h
new file mode 100644
index 000000000000..01c8d357550b
--- /dev/null
+++ b/arch/x86/include/asm/sbm.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2023-2024 Huawei Technologies Duesseldorf GmbH
+ *
+ * Author: Petr Tesarik <petr.tesarik1@huawei-partners.com>
+ *
+ * SandBox Mode (SBM) declarations for the x86 architecture.
+ */
+#ifndef __ASM_SBM_H
+#define __ASM_SBM_H
+
+#if defined(CONFIG_HAVE_ARCH_SBM) && defined(CONFIG_SANDBOX_MODE)
+
+#include <asm/pgtable_types.h>
+
+/**
+ * struct x86_sbm_state - Run-time state of the environment.
+ * @pgd:         Sandbox mode page global directory.
+ *
+ * One instance of this union is allocated for each sandbox and stored as SBM
+ * instance private data.
+ */
+struct x86_sbm_state {
+	pgd_t *pgd;
+};
+
+#endif /* defined(CONFIG_HAVE_ARCH_SBM) && defined(CONFIG_SANDBOX_MODE) */
+
+#endif /* __ASM_SBM_H */
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 0000325ab98f..4ad63b7d13ee 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -150,6 +150,8 @@ obj-$(CONFIG_X86_CET)			+= cet.o
 
 obj-$(CONFIG_X86_USER_SHADOW_STACK)	+= shstk.o
 
+obj-$(CONFIG_SANDBOX_MODE)		+= sbm/
+
 ###
 # 64 bit specific files
 ifeq ($(CONFIG_X86_64),y)
diff --git a/arch/x86/kernel/sbm/Makefile b/arch/x86/kernel/sbm/Makefile
new file mode 100644
index 000000000000..92d368b526cd
--- /dev/null
+++ b/arch/x86/kernel/sbm/Makefile
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright (C) 2023-2024 Huawei Technologies Duesseldorf GmbH
+#
+# Author: Petr Tesarik <petr.tesarik1@huawei-partners.com>
+#
+# Makefile for the x86 SandBox Mode (SBM) implementation.
+#
+
+obj-y := core.o
diff --git a/arch/x86/kernel/sbm/core.c b/arch/x86/kernel/sbm/core.c
new file mode 100644
index 000000000000..b775e3b387b1
--- /dev/null
+++ b/arch/x86/kernel/sbm/core.c
@@ -0,0 +1,248 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2023-2024 Huawei Technologies Duesseldorf GmbH
+ *
+ * Author: Petr Tesarik <petr.tesarik1@huawei-partners.com>
+ *
+ * SandBox Mode (SBM) implementation for the x86 architecture.
+ */
+
+#include <asm/pgtable.h>
+#include <asm/sbm.h>
+#include <asm/sections.h>
+#include <linux/mm.h>
+#include <linux/sbm.h>
+#include <linux/sched/task_stack.h>
+
+#define GFP_SBM_PGTABLE	(GFP_KERNEL | __GFP_ZERO)
+#define PGD_ORDER	get_order(sizeof(pgd_t) * PTRS_PER_PGD)
+
+static inline phys_addr_t page_to_ptval(struct page *page)
+{
+	return PFN_PHYS(page_to_pfn(page)) | _PAGE_TABLE;
+}
+
+static int map_page(struct x86_sbm_state *state, unsigned long addr,
+		    unsigned long pfn, pgprot_t prot)
+{
+	struct page *page;
+	pgd_t *pgdp;
+	p4d_t *p4dp;
+	pud_t *pudp;
+	pmd_t *pmdp;
+	pte_t *ptep;
+
+	pgdp = pgd_offset_pgd(state->pgd, addr);
+	if (pgd_none(*pgdp)) {
+		page = alloc_page(GFP_KERNEL | __GFP_ZERO);
+		if (!page)
+			return -ENOMEM;
+		set_pgd(pgdp, __pgd(page_to_ptval(page)));
+		p4dp = (p4d_t *)page_address(page) + p4d_index(addr);
+	} else
+		p4dp = p4d_offset(pgdp, addr);
+
+	if (p4d_none(*p4dp)) {
+		page = alloc_page(GFP_SBM_PGTABLE);
+		if (!page)
+			return -ENOMEM;
+		set_p4d(p4dp, __p4d(page_to_ptval(page)));
+		pudp = (pud_t *)page_address(page) + pud_index(addr);
+	} else
+		pudp = pud_offset(p4dp, addr);
+
+	if (pud_none(*pudp)) {
+		page = alloc_page(GFP_SBM_PGTABLE);
+		if (!page)
+			return -ENOMEM;
+		set_pud(pudp, __pud(page_to_ptval(page)));
+		pmdp = (pmd_t *)page_address(page) + pmd_index(addr);
+	} else
+		pmdp = pmd_offset(pudp, addr);
+
+	if (pmd_none(*pmdp)) {
+		page = alloc_page(GFP_SBM_PGTABLE);
+		if (!page)
+			return -ENOMEM;
+		set_pmd(pmdp, __pmd(page_to_ptval(page)));
+		ptep = (pte_t *)page_address(page) + pte_index(addr);
+	} else
+		ptep = pte_offset_kernel(pmdp, addr);
+
+	set_pte(ptep, pfn_pte(pfn, prot));
+	return 0;
+}
+
+static int map_range(struct x86_sbm_state *state, unsigned long start,
+		     unsigned long end, pgprot_t prot)
+{
+	unsigned long pfn;
+	int err;
+
+	start = PAGE_ALIGN_DOWN(start);
+	while (start < end) {
+		if (is_vmalloc_or_module_addr((void *)start))
+			pfn = vmalloc_to_pfn((void *)start);
+		else
+			pfn = PHYS_PFN(__pa(start));
+		err = map_page(state, start, pfn, prot);
+		if (err)
+			return err;
+		start += PAGE_SIZE;
+	}
+
+	return 0;
+}
+
+int arch_sbm_map_readonly(struct sbm *sbm, const struct sbm_buf *buf)
+{
+	return map_range(sbm->private, (unsigned long)buf->sbm_ptr,
+			 (unsigned long)buf->sbm_ptr + buf->size,
+			 PAGE_READONLY);
+}
+
+int arch_sbm_map_writable(struct sbm *sbm, const struct sbm_buf *buf)
+{
+	return map_range(sbm->private, (unsigned long)buf->sbm_ptr,
+			 (unsigned long)buf->sbm_ptr + buf->size,
+			 PAGE_SHARED);
+}
+
+/* Map kernel text, data, rodata, BSS and static per-cpu sections. */
+static int map_kernel(struct x86_sbm_state *state)
+{
+	int __maybe_unused cpu;
+	int err;
+
+	err = map_range(state, (unsigned long)_stext, (unsigned long)_etext,
+			PAGE_READONLY_EXEC);
+	if (err)
+		return err;
+
+	err = map_range(state, (unsigned long)__entry_text_start,
+			(unsigned long)__entry_text_end, PAGE_KERNEL_ROX);
+	if (err)
+		return err;
+
+	err = map_range(state, (unsigned long)_sdata, (unsigned long)_edata,
+			PAGE_READONLY);
+	if (err)
+		return err;
+	err = map_range(state, (unsigned long)__bss_start,
+			(unsigned long)__bss_stop, PAGE_READONLY);
+	if (err)
+		return err;
+	err = map_range(state, (unsigned long)__start_rodata,
+			(unsigned long)__end_rodata, PAGE_READONLY);
+	if (err)
+		return err;
+
+#ifdef CONFIG_SMP
+	for_each_possible_cpu(cpu) {
+		unsigned long off = per_cpu_offset(cpu);
+
+		err = map_range(state, (unsigned long)__per_cpu_start + off,
+				(unsigned long)__per_cpu_end + off,
+				PAGE_READONLY);
+		if (err)
+			return err;
+	}
+#endif
+
+	return 0;
+}
+
+int arch_sbm_init(struct sbm *sbm)
+{
+	struct x86_sbm_state *state;
+	unsigned long stack;
+	int err;
+
+	BUILD_BUG_ON(sizeof(*state) > PAGE_SIZE);
+	state = (struct x86_sbm_state *)__get_free_page(GFP_KERNEL);
+	if (!state)
+		return -ENOMEM;
+	sbm->private = state;
+
+	state->pgd = (pgd_t *)__get_free_pages(GFP_SBM_PGTABLE, PGD_ORDER);
+	if (!state->pgd)
+		return -ENOMEM;
+
+	err = map_kernel(state);
+	if (err)
+		return err;
+
+	err = map_range(state, (unsigned long)current,
+			(unsigned long)(current + 1), PAGE_READONLY);
+	if (err)
+		return err;
+
+	stack = (unsigned long)task_stack_page(current);
+	err = map_range(state, stack, stack + THREAD_SIZE, PAGE_READONLY);
+	if (err)
+		return err;
+
+	return 0;
+}
+
+static void free_pmd(pmd_t *pmd)
+{
+	pmd_t *pmdp;
+
+	for (pmdp = pmd; pmdp < pmd + PTRS_PER_PMD; ++pmdp)
+		if (!pmd_none(*pmdp))
+			free_page(pmd_page_vaddr(*pmdp));
+	if (PTRS_PER_PMD > 1)
+		free_page((unsigned long)pmd);
+}
+
+static void free_pud(pud_t *pud)
+{
+	pud_t *pudp;
+
+	for (pudp = pud; pudp < pud + PTRS_PER_PUD; ++pudp)
+		if (!pud_none(*pudp))
+			free_pmd(pmd_offset(pudp, 0));
+	if (PTRS_PER_PUD > 1)
+		free_page((unsigned long)pud);
+}
+
+static void free_p4d(p4d_t *p4d)
+{
+	p4d_t *p4dp;
+
+	for (p4dp = p4d; p4dp < p4d + PTRS_PER_P4D; ++p4dp)
+		if (!p4d_none(*p4dp))
+			free_pud(pud_offset(p4dp, 0));
+	if (PTRS_PER_P4D > 1)
+		free_page((unsigned long)p4d);
+}
+
+static void free_pgd(pgd_t *pgd)
+{
+	pgd_t *pgdp;
+
+	for (pgdp = pgd; pgdp < pgd + PTRS_PER_PGD; ++pgdp)
+		if (!pgd_none(*pgdp))
+			free_p4d(p4d_offset(pgdp, 0));
+}
+
+void arch_sbm_destroy(struct sbm *sbm)
+{
+	struct x86_sbm_state *state = sbm->private;
+
+	if (!state)
+		return;
+
+	if (state->pgd) {
+		free_pgd(state->pgd);
+		free_pages((unsigned long)state->pgd, PGD_ORDER);
+	}
+	free_page((unsigned long)state);
+	sbm->private = NULL;
+}
+
+int arch_sbm_exec(struct sbm *sbm, sbm_func func, void *args)
+{
+	return func(args);
+}
-- 
2.34.1


  reply	other threads:[~2024-02-14 11:36 UTC|newest]

Thread overview: 63+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-02-14 11:35 [PATCH v1 0/8] x86_64 SandBox Mode arch hooks Petr Tesarik
2024-02-14 11:35 ` Petr Tesarik [this message]
2024-02-14 11:35 ` [PATCH v1 2/8] sbm: x86: execute target function on sandbox mode stack Petr Tesarik
2024-02-14 11:35 ` [PATCH v1 3/8] sbm: x86: map system data structures into the sandbox Petr Tesarik
2024-02-14 11:35 ` [PATCH v1 4/8] sbm: x86: allocate and map an exception stack Petr Tesarik
2024-02-14 11:35 ` [PATCH v1 5/8] sbm: x86: handle sandbox mode faults Petr Tesarik
2024-02-14 11:35 ` [PATCH v1 6/8] sbm: x86: switch to sandbox mode pages in arch_sbm_exec() Petr Tesarik
2024-02-14 11:35 ` [PATCH v1 7/8] sbm: documentation of the x86-64 SandBox Mode implementation Petr Tesarik
2024-02-14 18:37   ` Xin Li
2024-02-14 19:16     ` Petr Tesařík
2024-02-14 11:35 ` [PATCH v1 8/8] sbm: x86: lazy TLB flushing Petr Tesarik
2024-02-14 14:52 ` [PATCH v1 0/8] x86_64 SandBox Mode arch hooks Dave Hansen
2024-02-14 15:28   ` H. Peter Anvin
2024-02-14 16:41     ` Petr Tesařík
2024-02-14 17:29       ` H. Peter Anvin
2024-02-14 19:14         ` Petr Tesařík
2024-02-14 18:14       ` Edgecombe, Rick P
2024-02-14 18:32         ` Petr Tesařík
2024-02-14 19:19           ` Edgecombe, Rick P
2024-02-14 19:35             ` Petr Tesařík
2024-02-14 18:22   ` Petr Tesařík
2024-02-14 18:42     ` Dave Hansen
2024-02-14 19:33       ` Petr Tesařík
2024-02-14 20:16         ` Dave Hansen
2024-02-16 15:24           ` [RFC 0/8] PGP key parser using SandBox Mode Petr Tesarik
2024-02-16 15:24             ` [RFC 1/8] mpi: Introduce mpi_key_length() Petr Tesarik
2024-02-16 15:24             ` [RFC 2/8] rsa: add parser of raw format Petr Tesarik
2024-02-16 15:24             ` [RFC 3/8] PGPLIB: PGP definitions (RFC 4880) Petr Tesarik
2024-02-16 15:24             ` [RFC 4/8] PGPLIB: Basic packet parser Petr Tesarik
2024-02-16 15:24             ` [RFC 5/8] PGPLIB: Signature parser Petr Tesarik
2024-02-16 15:24             ` [RFC 6/8] KEYS: PGP data parser Petr Tesarik
2024-02-16 16:44               ` Matthew Wilcox
2024-02-16 16:53                 ` Roberto Sassu
2024-02-16 17:08                   ` H. Peter Anvin
2024-02-16 17:13                     ` Roberto Sassu
2024-02-20 10:55                     ` Petr Tesarik
2024-02-21 14:02                       ` H. Peter Anvin
2024-02-22  7:53                         ` Petr Tesařík
2024-02-16 18:44                   ` Matthew Wilcox
2024-02-16 19:54                     ` Roberto Sassu
2024-02-28 17:58                       ` Roberto Sassu
2024-02-16 15:24             ` [RFC 7/8] KEYS: Run PGP key parser in a sandbox Petr Tesarik
2024-02-18  6:07               ` kernel test robot
2024-02-18  8:02               ` kernel test robot
2024-02-16 15:24             ` [RFC 8/8] KEYS: Add intentional fault injection Petr Tesarik
2024-02-16 15:38             ` [RFC 0/8] PGP key parser using SandBox Mode Dave Hansen
2024-02-16 16:08               ` Petr Tesařík
2024-02-16 17:21                 ` Jonathan Corbet
2024-02-16 18:24                   ` Roberto Sassu
2024-02-22 13:12           ` [RFC 0/5] PoC: convert AppArmor parser to " Petr Tesarik
2024-02-22 13:12             ` [RFC 1/5] sbm: x86: fix SBM error entry path Petr Tesarik
2024-02-22 13:12             ` [RFC 2/5] sbm: enhance buffer mapping API Petr Tesarik
2024-02-22 13:12             ` [RFC 3/5] sbm: x86: infrastructure to fix up sandbox faults Petr Tesarik
2024-02-22 13:12             ` [RFC 4/5] sbm: fix up calls to dynamic memory allocators Petr Tesarik
2024-02-22 15:51               ` Dave Hansen
2024-02-22 17:57                 ` Petr Tesařík
2024-02-22 18:03                   ` Dave Hansen
2024-02-22 13:12             ` [RFC 5/5] apparmor: parse profiles in sandbox mode Petr Tesarik
2024-02-14 18:52     ` [PATCH v1 0/8] x86_64 SandBox Mode arch hooks Xin Li
2024-02-15  6:59       ` Petr Tesařík
2024-02-15  8:16         ` H. Peter Anvin
2024-02-15  9:30           ` Petr Tesařík
2024-02-15  9:37             ` Roberto Sassu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240214113516.2307-2-petrtesarik@huaweicloud.com \
    --to=petrtesarik@huaweicloud.com \
    --cc=akpm@linux-foundation.org \
    --cc=arnd@arndb.de \
    --cc=bp@alien8.de \
    --cc=brgerst@gmail.com \
    --cc=corbet@lwn.net \
    --cc=dave.hansen@linux.intel.com \
    --cc=dwmw@amazon.co.uk \
    --cc=hpa@zytor.com \
    --cc=jacob.jun.pan@linux.intel.com \
    --cc=jgg@ziepe.ca \
    --cc=jpoimboe@kernel.org \
    --cc=jroedel@suse.de \
    --cc=kai.huang@intel.com \
    --cc=keescook@chromium.org \
    --cc=kirill.shutemov@linux.intel.com \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=luto@kernel.org \
    --cc=mhiramat@kernel.org \
    --cc=mingo@redhat.com \
    --cc=oleg@redhat.com \
    --cc=pengfei.xu@intel.com \
    --cc=peterz@infradead.org \
    --cc=petr.tesarik1@huawei-partners.com \
    --cc=petr@tesarici.cz \
    --cc=rick.p.edgecombe@intel.com \
    --cc=roberto.sassu@huaweicloud.com \
    --cc=rppt@kernel.org \
    --cc=tglx@linutronix.de \
    --cc=tina.zhang@intel.com \
    --cc=x86@kernel.org \
    --cc=xin3.li@intel.com \
    --cc=zegao2021@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.