linux-um.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
From: Benjamin Berg <benjamin@sipsolutions.net>
To: linux-um@lists.infradead.org
Cc: Benjamin Berg <benjamin@sipsolutions.net>
Subject: [PATCH 23/27] um: Add helper functions to get/set state for SECCOMP
Date: Wed,  3 Mar 2021 16:55:19 +0100	[thread overview]
Message-ID: <20210303155523.124277-24-benjamin@sipsolutions.net> (raw)
In-Reply-To: <20210303155523.124277-1-benjamin@sipsolutions.net>

When not using ptrace, we need to both save and restore registers
through the mcontext as provided by the host kernel to our signal
handlers.

Add corresponding functions to store the state to an mcontext and
helpers to access the mcontext of the subprocess through the stub data.

Signed-off-by: Benjamin Berg <benjamin@sipsolutions.net>
---
 arch/x86/um/os-Linux/mcontext.c      | 100 +++++++++++++++++++++++++++
 arch/x86/um/shared/sysdep/mcontext.h |   9 +++
 2 files changed, 109 insertions(+)

diff --git a/arch/x86/um/os-Linux/mcontext.c b/arch/x86/um/os-Linux/mcontext.c
index 81b9d1f9f4e6..506ce0aa7108 100644
--- a/arch/x86/um/os-Linux/mcontext.c
+++ b/arch/x86/um/os-Linux/mcontext.c
@@ -3,6 +3,9 @@
 #define __FRAME_OFFSETS
 #include <asm/ptrace.h>
 #include <sysdep/ptrace.h>
+#include <string.h>
+#include <signal.h>
+#include <sysdep/mcontext.h>
 
 void get_regs_from_mc(struct uml_pt_regs *regs, mcontext_t *mc)
 {
@@ -16,6 +19,10 @@ void get_regs_from_mc(struct uml_pt_regs *regs, mcontext_t *mc)
 	COPY2(UESP, ESP); /* sic */
 	COPY(EBX); COPY(EDX); COPY(ECX); COPY(EAX);
 	COPY(EIP); COPY_SEG_CPL3(CS); COPY(EFL); COPY_SEG_CPL3(SS);
+#undef COPY2
+#undef COPY
+#undef COPY_SEG
+#undef COPY_SEG_CPL3
 #else
 #define COPY2(X,Y) regs->gp[X/sizeof(unsigned long)] = mc->gregs[REG_##Y]
 #define COPY(X) regs->gp[X/sizeof(unsigned long)] = mc->gregs[REG_##X]
@@ -27,5 +34,98 @@ void get_regs_from_mc(struct uml_pt_regs *regs, mcontext_t *mc)
 	COPY2(EFLAGS, EFL);
 	COPY2(CS, CSGSFS);
 	regs->gp[SS / sizeof(unsigned long)] = mc->gregs[REG_CSGSFS] >> 48;
+#undef COPY2
+#undef COPY
 #endif
 }
+
+#ifdef CONFIG_UML_SECCOMP
+/* Same thing, but the copy macros are turned around. */
+void get_mc_from_regs(struct uml_pt_regs *regs, mcontext_t *mc, int single_stepping)
+{
+#ifdef __i386__
+#define COPY2(X,Y) mc->gregs[REG_##Y] = regs->gp[X]
+#define COPY(X) mc->gregs[REG_##X] = regs->gp[X]
+#define COPY_SEG(X) mc->gregs[REG_##X] = mc->gregs[REG_##X] & 0xffff;
+#define COPY_SEG_CPL3(X) mc->gregs[REG_##X] = (regs->gp[X] & 0xffff) | 3;
+	COPY_SEG(GS); COPY_SEG(FS); COPY_SEG(ES); COPY_SEG(DS);
+	COPY(EDI); COPY(ESI); COPY(EBP);
+	COPY2(UESP, ESP); /* sic */
+	COPY(EBX); COPY(EDX); COPY(ECX); COPY(EAX);
+	COPY(EIP); COPY_SEG_CPL3(CS); COPY(EFL); COPY_SEG_CPL3(SS);
+#else
+#define COPY2(X,Y) mc->gregs[REG_##Y] = regs->gp[X/sizeof(unsigned long)]
+#define COPY(X) mc->gregs[REG_##X] = regs->gp[X/sizeof(unsigned long)]
+	COPY(R8); COPY(R9); COPY(R10); COPY(R11);
+	COPY(R12); COPY(R13); COPY(R14); COPY(R15);
+	COPY(RDI); COPY(RSI); COPY(RBP); COPY(RBX);
+	COPY(RDX); COPY(RAX); COPY(RCX); COPY(RSP);
+	COPY(RIP);
+	COPY2(EFLAGS, EFL);
+	mc->gregs[REG_CSGSFS] = mc->gregs[REG_CSGSFS] & 0xffffffffffffl;
+	mc->gregs[REG_CSGSFS] |= (regs->gp[SS / sizeof(unsigned long)] & 0xffff) << 48;
+#endif
+
+	if (single_stepping)
+		mc->gregs[REG_EFL] |= X86_EFLAGS_TF;
+	else
+		mc->gregs[REG_EFL] &= ~X86_EFLAGS_TF;
+}
+
+void get_stub_state(struct uml_pt_regs *regs, struct stub_data *data)
+{
+	mcontext_t *mcontext;
+
+	if (data->mctx_offset > sizeof(data->sigstack) - sizeof(*mcontext))
+		panic("%s - Invalid mcontext offset from child!\n", __func__);
+
+	mcontext = (void *)&data->sigstack[data->mctx_offset];
+
+	get_regs_from_mc(regs, mcontext);
+	/* Copy floating point registers. As fpregs is a pointer, we need to make some
+	 * assumptions here in order to dereference it.
+	 * As such, assume it is on the same memory page.
+	 */
+	memcpy(&regs->fp,
+	       (void *) (((unsigned long) mcontext->fpregs & (UM_KERN_PAGE_SIZE - 1)) +
+			 (unsigned long) data),
+	       sizeof(*mcontext->fpregs));
+
+	/* We do not need to read the x86_64 FS_BASE/GS_BASE registers as
+	 * we do not permit userspace to set them directly.
+	 */
+}
+
+void set_stub_state(struct uml_pt_regs *regs, struct stub_data *data, int single_stepping)
+{
+	mcontext_t *mcontext = (void *)&data->sigstack[data->mctx_offset];
+
+	get_mc_from_regs(regs, mcontext, single_stepping);
+
+	/* Copy floating point registers (note that mc->fpregs is a userspace address) */
+	memcpy((void *) ((unsigned long) mcontext->fpregs - STUB_DATA +
+			 (unsigned long) data),
+	       &regs->fp, sizeof(*mcontext->fpregs));
+
+#ifdef __i386__
+	/*
+	 * On x86, we need to sync the GDT entries for the thread local storage.
+	 */
+	#error "Not implemented"
+#else
+	/*
+	 * On x86_64, we need to sync back the FS_BASE/GS_BASE registers
+	 * using the arch specific data.
+	 */
+	data->arch_data.sync = 0;
+
+	if (data->arch_data.fs_base != regs->gp[FS_BASE / sizeof(unsigned long)])
+		data->arch_data.sync |= 0x1;
+	if (data->arch_data.gs_base != regs->gp[GS_BASE / sizeof(unsigned long)])
+		data->arch_data.sync |= 0x2;
+
+	data->arch_data.fs_base = regs->gp[FS_BASE / sizeof(unsigned long)];
+	data->arch_data.gs_base = regs->gp[GS_BASE / sizeof(unsigned long)];
+#endif
+}
+#endif
diff --git a/arch/x86/um/shared/sysdep/mcontext.h b/arch/x86/um/shared/sysdep/mcontext.h
index b724c54da316..63334c36c269 100644
--- a/arch/x86/um/shared/sysdep/mcontext.h
+++ b/arch/x86/um/shared/sysdep/mcontext.h
@@ -6,7 +6,16 @@
 #ifndef __SYS_SIGCONTEXT_X86_H
 #define __SYS_SIGCONTEXT_X86_H
 
+#include <linux/kconfig.h>
+#include <stub-data.h>
+
 extern void get_regs_from_mc(struct uml_pt_regs *, mcontext_t *);
+extern void get_mc_from_regs(struct uml_pt_regs *regs, mcontext_t *mc,
+			     int single_stepping);
+
+extern void get_stub_state(struct uml_pt_regs *regs, struct stub_data *data);
+extern void set_stub_state(struct uml_pt_regs *regs, struct stub_data *data,
+			   int single_stepping);
 
 #ifdef __i386__
 
-- 
2.29.2


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


  parent reply	other threads:[~2021-03-03 16:01 UTC|newest]

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

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=20210303155523.124277-24-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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).