From patchwork Wed Mar 3 15:55:19 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benjamin Berg X-Patchwork-Id: 1446947 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.infradead.org (client-ip=2001:8b0:10b:1:d65d:64ff:fe57:4e05; helo=desiato.infradead.org; envelope-from=linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; secure) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=desiato.20200630 header.b=oGTsVEu9; dkim-atps=neutral Received: from desiato.infradead.org (desiato.infradead.org [IPv6:2001:8b0:10b:1:d65d:64ff:fe57:4e05]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4DrV2L1qF1z9sRf for ; Thu, 4 Mar 2021 10:04:58 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=desiato.20200630; h=Sender:Content-Transfer-Encoding :Content-Type:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:Cc:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=2Ur9flApFQpML4OwGvNONm/D1Q314kmdspezHfaIoYY=; b=oGTsVEu9GDlszoPGBWSksRuid 1RKPXbbk6Dz2vPzxTmCzUa/PR4cCAgnRVP7NobhDYxnsQrB9tJIZH98bFK2L9L0g7jBoIUPgZOSm1 +1fP+rgPHTBVKOQoNKWbKz2OJW4XhrM7tqglhzBOiqIS0+J/Z1NKmoRhdV9IuXperIm4Vn1jHteEq lUnmJ5huTHxyHQz//a5cODtn6NPZ9izamRNTVVurezZ8ZV0Uo+L/2wsgFH7O2YHKin1q2A/supjVK JQeShwvMjcRbS1JsK76cIP1jCb2PnlkMUMfkIneh3j2zjAJ8BqdP4xqBQpw4kM+z5DOWeR6OgqWtt jiTCknB9A==; Received: from localhost ([::1] helo=desiato.infradead.org) by desiato.infradead.org with esmtp (Exim 4.94 #2 (Red Hat Linux)) id 1lHaXy-006rfz-94; Wed, 03 Mar 2021 23:04:50 +0000 Received: from s3.sipsolutions.net ([2a01:4f8:191:4433::2] helo=sipsolutions.net) by desiato.infradead.org with esmtps (Exim 4.94 #2 (Red Hat Linux)) id 1lHTw7-005VVw-33 for linux-um@lists.infradead.org; Wed, 03 Mar 2021 16:01:21 +0000 Received: by sipsolutions.net with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.94) (envelope-from ) id 1lHTr0-00BFLI-TS; Wed, 03 Mar 2021 16:56:03 +0100 From: Benjamin Berg To: linux-um@lists.infradead.org Cc: Benjamin Berg Subject: [PATCH 23/27] um: Add helper functions to get/set state for SECCOMP Date: Wed, 3 Mar 2021 16:55:19 +0100 Message-Id: <20210303155523.124277-24-benjamin@sipsolutions.net> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210303155523.124277-1-benjamin@sipsolutions.net> References: <20210303155523.124277-1-benjamin@sipsolutions.net> MIME-Version: 1.0 X-Spam-Note: CRM114 invocation failed X-Spam-Score: 0.4 (/) X-Spam-Report: Spam detection software, running on the system "desiato.infradead.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: 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. Content analysis details: (0.4 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.0 SPF_NONE SPF: sender does not publish an SPF Record 0.4 KHOP_HELO_FCRDNS Relay HELO differs from its IP's reverse DNS X-BeenThere: linux-um@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-um" Errors-To: linux-um-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org 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 --- 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 #include +#include +#include +#include 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(®s->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), + ®s->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 +#include + 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__