All of lore.kernel.org
 help / color / mirror / Atom feed
From: benjamin@sipsolutions.net
To: linux-um@lists.infradead.org
Cc: Benjamin Berg <benjamin@sipsolutions.net>
Subject: [PATCH v2 28/28] um: Delay flushing syscalls until the thread is restarted
Date: Tue, 22 Nov 2022 11:07:59 +0100	[thread overview]
Message-ID: <20221122100759.208290-29-benjamin@sipsolutions.net> (raw)
In-Reply-To: <20221122100759.208290-1-benjamin@sipsolutions.net>

From: Benjamin Berg <benjamin@sipsolutions.net>

This way we can avoid doing two extra context switches when managing
processes using seccomp.

Signed-off-by: Benjamin Berg <benjamin@sipsolutions.net>
---
 arch/um/include/shared/os.h        |  1 +
 arch/um/include/shared/skas/skas.h |  1 +
 arch/um/kernel/skas/process.c      |  8 ++++
 arch/um/kernel/tlb.c               | 10 +----
 arch/um/os-Linux/skas/mem.c        | 71 ++++++++++++++++--------------
 arch/um/os-Linux/skas/process.c    | 26 ++++++++++-
 6 files changed, 75 insertions(+), 42 deletions(-)

diff --git a/arch/um/include/shared/os.h b/arch/um/include/shared/os.h
index 07683f45d7e1..aa888d4870d9 100644
--- a/arch/um/include/shared/os.h
+++ b/arch/um/include/shared/os.h
@@ -273,6 +273,7 @@ int syscall_stub_flush(struct mm_id *mm_idp);
 struct stub_syscall *syscall_stub_alloc(struct mm_id *mm_idp,
 					unsigned long data_len,
 					unsigned long *data_addr);
+void syscall_stub_dump_error(struct mm_id *mm_idp);
 
 void map(struct mm_id *mm_idp, unsigned long virt,
 	 unsigned long len, int prot, int phys_fd,
diff --git a/arch/um/include/shared/skas/skas.h b/arch/um/include/shared/skas/skas.h
index f10599995d4d..bc672d607101 100644
--- a/arch/um/include/shared/skas/skas.h
+++ b/arch/um/include/shared/skas/skas.h
@@ -21,5 +21,6 @@ extern void new_thread_handler(void);
 extern void handle_syscall(struct uml_pt_regs *regs);
 extern long execute_syscall_skas(void *r);
 extern unsigned long current_stub_stack(void);
+extern struct mm_id *current_mm_id(void);
 
 #endif
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
index f2ac134c9752..c7345c83e07b 100644
--- a/arch/um/kernel/skas/process.c
+++ b/arch/um/kernel/skas/process.c
@@ -53,3 +53,11 @@ unsigned long current_stub_stack(void)
 
 	return current->mm->context.id.stack;
 }
+
+struct mm_id *current_mm_id(void)
+{
+	if (current->mm == NULL)
+		return NULL;
+
+	return &current->mm->context.id;
+}
diff --git a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c
index c15cac380fcd..bda516cb1186 100644
--- a/arch/um/kernel/tlb.c
+++ b/arch/um/kernel/tlb.c
@@ -460,7 +460,7 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long address)
 	pmd_t *pmd;
 	pte_t *pte;
 	struct mm_struct *mm = vma->vm_mm;
-	int r, w, x, prot, err = 0;
+	int r, w, x, prot;
 	struct mm_id *mm_id;
 
 	address &= PAGE_MASK;
@@ -508,14 +508,6 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long address)
 	} else if (pte_newprot(*pte))
 		protect(mm_id, address, PAGE_SIZE, prot);
 
-	err = syscall_stub_flush(mm_id);
-	if (err) {
-		if (err == -ENOMEM)
-			report_enomem();
-
-		goto kill;
-	}
-
 	*pte = pte_mkuptodate(*pte);
 
 	return;
diff --git a/arch/um/os-Linux/skas/mem.c b/arch/um/os-Linux/skas/mem.c
index 619035151bc6..68155aadea09 100644
--- a/arch/um/os-Linux/skas/mem.c
+++ b/arch/um/os-Linux/skas/mem.c
@@ -25,6 +25,44 @@ extern char __syscall_stub_start[];
 extern void wait_stub_done(int pid);
 void wait_stub_done_seccomp(int pid, struct stub_data *data, int running);
 
+void syscall_stub_dump_error(struct mm_id *mm_idp)
+{
+	struct stub_data *proc_data = (void *)mm_idp->stack;
+	struct stub_syscall *sc;
+	int n;
+
+	if (proc_data->syscall_data_len < 0 ||
+	    proc_data->syscall_data_len > (long) mm_idp->syscall_data_len - sizeof(*sc))
+		panic("Syscall data was corrupted by stub (len is: %d, expected maximum: %d)!",
+		      proc_data->syscall_data_len,
+		      mm_idp->syscall_data_len);
+
+	sc = (void *) (((unsigned long) &proc_data->syscall_data) +
+		       proc_data->syscall_data_len);
+
+	printk(UM_KERN_ERR "%s : length = %d, last offset = %d",
+	       __func__, mm_idp->syscall_data_len,
+	       proc_data->syscall_data_len);
+	printk(UM_KERN_ERR "%s : syscall %ld failed, return value = 0x%lx, expected return value = 0x%lx\n",
+	       __func__, sc->syscall, proc_data->err,
+	       sc->expected_result);
+
+	printk(UM_KERN_ERR "    syscall parameters: 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n",
+	       sc->arg[0], sc->arg[1], sc->arg[2],
+	       sc->arg[3], sc->arg[4], sc->arg[5]);
+
+	n = sc->cmd_len - sizeof(*sc);
+	if (n > 0) {
+		printk(UM_KERN_ERR "    syscall data 0x%lx + %d",
+		       STUB_DATA + ((unsigned long) (&sc->data) &
+				    (UM_KERN_PAGE_SIZE - 1)),
+		       n);
+		print_hex_dump(UM_KERN_ERR,
+			       "    syscall data: ", 0,
+			       16, 4, sc->data, n, 0);
+	}
+}
+
 static inline unsigned long *check_init_stack(struct mm_id *mm_idp,
 					      unsigned long *stack)
 {
@@ -90,38 +128,7 @@ static inline long do_syscall_stub(struct mm_id *mm_idp)
 	 * otherwise it will be zero (but we do not need to rely on that).
 	 */
 	if (proc_data->err) {
-		struct stub_syscall *sc;
-
-		if (proc_data->syscall_data_len < 0 ||
-		    proc_data->syscall_data_len > (long) mm_idp->syscall_data_len - sizeof(*sc))
-			panic("Syscall data was corrupted by stub (len is: %d, expected maximum: %d)!",
-			      proc_data->syscall_data_len,
-			      mm_idp->syscall_data_len);
-
-		sc = (void *) (((unsigned long) &proc_data->syscall_data) +
-			       proc_data->syscall_data_len);
-
-		printk(UM_KERN_ERR "%s : length = %d, last offset = %d",
-		       __func__, mm_idp->syscall_data_len,
-		       proc_data->syscall_data_len);
-		printk(UM_KERN_ERR "%s : syscall %ld failed, return value = 0x%lx, expected return value = 0x%lx\n",
-		       __func__, sc->syscall, proc_data->err,
-		       sc->expected_result);
-
-		printk(UM_KERN_ERR "    syscall parameters: 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n",
-		       sc->arg[0], sc->arg[1], sc->arg[2],
-		       sc->arg[3], sc->arg[4], sc->arg[5]);
-
-		n = sc->cmd_len - sizeof(*sc);
-		if (n > 0) {
-			printk(UM_KERN_ERR "    syscall data 0x%lx + %d",
-			       STUB_DATA + ((unsigned long) (&sc->data) &
-					    (UM_KERN_PAGE_SIZE - 1)),
-			       n);
-			print_hex_dump(UM_KERN_ERR,
-				       "    syscall data: ", 0,
-				       16, 4, sc->data, n, 0);
-		}
+		syscall_stub_dump_error(mm_idp);
 
 		/* Store error code in case someone tries to add more syscalls */
 		mm_idp->syscall_data_len = proc_data->err;
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index 55868eb35727..39941d14bb51 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -530,7 +530,8 @@ void userspace(struct uml_pt_regs *regs, unsigned long *aux_fp_regs)
 			fatal_sigsegv();
 
 		if (using_seccomp) {
-			struct stub_data *proc_data = (void *)current_stub_stack();
+			struct mm_id *mm_id = current_mm_id();
+			struct stub_data *proc_data = (void *) mm_id->stack;
 			int ret;
 
 			ret = set_stub_state(regs, proc_data, singlestepping());
@@ -544,6 +545,10 @@ void userspace(struct uml_pt_regs *regs, unsigned long *aux_fp_regs)
 			if (proc_data->restart_wait != 0)
 				panic("Programming error: Flag to only run syscalls in child was not cleared!");
 
+			/* Mark pending syscalls for flushing */
+			proc_data->syscall_data_len = mm_id->syscall_data_len;
+			mm_id->syscall_data_len = 0;
+
 			proc_data->signal = 0;
 			proc_data->futex = FUTEX_IN_CHILD;
 			CATCH_EINTR(syscall(__NR_futex, &proc_data->futex,
@@ -556,6 +561,13 @@ void userspace(struct uml_pt_regs *regs, unsigned long *aux_fp_regs)
 
 			sig = proc_data->signal;
 
+			if (sig == SIGTRAP && proc_data->err != 0) {
+				printk(UM_KERN_ERR "%s - Error flushing stub syscalls",
+				       __func__);
+				syscall_stub_dump_error(mm_id);
+				fatal_sigsegv();
+			}
+
 			ret = get_stub_state(regs, proc_data);
 			if (ret) {
 				printk(UM_KERN_ERR "%s - failed to get regs: %d",
@@ -586,6 +598,14 @@ void userspace(struct uml_pt_regs *regs, unsigned long *aux_fp_regs)
 				GET_FAULTINFO_FROM_MC(regs->faultinfo, mcontext);
 			}
 		} else {
+			/* With ptrace, we need to explicitly flush all pending syscalls. */
+			err = syscall_stub_flush(current_mm_id());
+			if (err) {
+				printk(UM_KERN_ERR "%s - Error flushing stub syscalls: %d",
+				       __func__, -err);
+				fatal_sigsegv();
+			}
+
 			/*
 			 * This can legitimately fail if the process loads a
 			 * bogus value into a segment register.  It will
@@ -760,6 +780,10 @@ int copy_context_skas0(struct mm_id *id, struct mm_id *from)
 
 	child_data->child_err = -ESRCH;
 
+	err = syscall_stub_flush(from);
+	if (err)
+		return err;
+
 	if (using_seccomp) {
 		err = set_stub_state(&thread_regs, data, 0);
 		if (err)
-- 
2.38.1


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um

      parent reply	other threads:[~2022-11-22 10:26 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-11-22 10:07 [PATCH v2 00/28] Implement SECCOMP based userland benjamin
2022-11-22 10:07 ` [PATCH v2 01/28] um: Switch printk calls to adhere to correct coding style benjamin
2022-11-22 10:07 ` [PATCH v2 02/28] um: Declare fix_range_common as a static function benjamin
2022-11-22 10:07 ` [PATCH v2 03/28] um: Drop support for hosts without SYSEMU_SINGLESTEP support benjamin
2022-11-22 10:07 ` [PATCH v2 04/28] um: Drop NULL check from start_userspace benjamin
2022-11-22 10:07 ` [PATCH v2 05/28] um: Make errors to stop ptraced child fatal during startup benjamin
2022-11-22 10:07 ` [PATCH v2 06/28] um: Don't use vfprintf() for os_info() benjamin
2022-11-22 10:07 ` [PATCH v2 07/28] um: Do not use printk in SIGWINCH helper thread benjamin
2022-11-22 10:07 ` [PATCH v2 08/28] um: Reap winch thread if it fails benjamin
2022-11-22 10:07 ` [PATCH v2 09/28] um: Do not use printk in userspace trampoline benjamin
2022-11-22 10:07 ` [PATCH v2 10/28] um: Always inline stub functions benjamin
2022-11-22 10:07 ` [PATCH v2 11/28] um: Rely on PTRACE_SETREGSET to set FS/GS base registers benjamin
2022-11-22 10:07 ` [PATCH v2 12/28] um: Remove unused register save/restore functions benjamin
2022-11-22 10:07 ` [PATCH v2 13/28] um: Mark 32bit syscall helpers as clobbering memory benjamin
2022-11-22 10:07 ` [PATCH v2 14/28] um: Remove stub-data.h include from common-offsets.h benjamin
2022-11-22 10:07 ` [PATCH v2 15/28] um: Create signal stack memory assignment in stub_data benjamin
2022-11-22 10:07 ` [PATCH v2 16/28] um: Add generic stub_syscall6 function benjamin
2022-11-22 10:07 ` [PATCH v2 17/28] um: Rework syscall handling benjamin
2022-11-22 10:07 ` [PATCH v2 18/28] um: Store full CSGSFS and SS register from mcontext benjamin
2022-11-22 10:07 ` [PATCH v2 19/28] um: Pass full mm_id to functions creating helper processes benjamin
2022-11-22 10:07 ` [PATCH v2 20/28] um: Move faultinfo extraction into userspace routine benjamin
2022-11-22 10:07 ` [PATCH v2 21/28] um: Use struct uml_pt_regs for copy_context_skas0 benjamin
2022-11-22 10:07 ` [PATCH v2 22/28] um: Add UML_SECCOMP configuration option benjamin
2022-11-22 10:07 ` [PATCH v2 23/28] um: Add stub side of SECCOMP/futex based process handling benjamin
2022-11-22 10:07 ` [PATCH v2 24/28] um: Add helper functions to get/set state for SECCOMP benjamin
2022-11-22 10:07 ` [PATCH v2 25/28] um: Add SECCOMP support detection and initialization benjamin
2022-11-22 10:07 ` [PATCH v2 26/28] um: Die if a child dies unexpectedly in seccomp mode benjamin
2022-11-22 10:07 ` [PATCH v2 27/28] um: Implement kernel side of SECCOMP based process handling benjamin
2022-11-22 10:07 ` benjamin [this message]

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=20221122100759.208290-29-benjamin@sipsolutions.net \
    --to=benjamin@sipsolutions.net \
    --cc=linux-um@lists.infradead.org \
    /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.