Module Name: src Committed By: christos Date: Sat Aug 8 19:08:48 UTC 2020
Modified Files: src/sys/arch/i386/i386: trap.c src/sys/arch/x86/include: cpu.h src/sys/arch/x86/x86: cpu.c src/sys/compat/netbsd32: netbsd32_mod.c Log Message: PR/55547: Dan Plassche: Fix BSD/OS binary emulation. Centralize lcall sniffer and recognize the BSD/OS flavor. To generate a diff of this commit: cvs rdiff -u -r1.304 -r1.305 src/sys/arch/i386/i386/trap.c cvs rdiff -u -r1.128 -r1.129 src/sys/arch/x86/include/cpu.h cvs rdiff -u -r1.196 -r1.197 src/sys/arch/x86/x86/cpu.c cvs rdiff -u -r1.22 -r1.23 src/sys/compat/netbsd32/netbsd32_mod.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/i386/i386/trap.c diff -u src/sys/arch/i386/i386/trap.c:1.304 src/sys/arch/i386/i386/trap.c:1.305 --- src/sys/arch/i386/i386/trap.c:1.304 Mon Jul 13 20:45:52 2020 +++ src/sys/arch/i386/i386/trap.c Sat Aug 8 15:08:48 2020 @@ -1,5 +1,5 @@ -/* $NetBSD: trap.c,v 1.304 2020/07/14 00:45:52 yamaguchi Exp $ */ +/* $NetBSD: trap.c,v 1.305 2020/08/08 19:08:48 christos Exp $ */ /*- * Copyright (c) 1998, 2000, 2005, 2006, 2007, 2008 The NetBSD Foundation, Inc. @@ -69,7 +69,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.304 2020/07/14 00:45:52 yamaguchi Exp $"); +__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.305 2020/08/08 19:08:48 christos Exp $"); #include "opt_ddb.h" #include "opt_kgdb.h" @@ -447,19 +447,15 @@ kernelfault: /* NOTREACHED */ case T_PROTFLT|T_USER: /* protection fault */ -#if defined(COMPAT_10) +#if defined(COMPAT_10) || defined(COMPAT_NOMID) { - static const char lcall[7] = { 0x9a, 0, 0, 0, 0, 7, 0 }; - const size_t sz = sizeof(lcall); - char tmp[sizeof(lcall)]; - +#define LCALLSZ 7 /* Check for the osyscall lcall instruction. */ - if (frame->tf_eip < VM_MAXUSER_ADDRESS - sz && - copyin((void *)frame->tf_eip, tmp, sz) == 0 && - memcmp(tmp, lcall, sz) == 0) { + if (frame->tf_eip < VM_MAXUSER_ADDRESS - LCALLSZ && + x86_cpu_is_lcall((const void *)frame->tf_eip)) { /* Advance past the lcall. */ - frame->tf_eip += sz; + frame->tf_eip += LCALLSZ; /* Do the syscall. */ p->p_md.md_syscall(frame); Index: src/sys/arch/x86/include/cpu.h diff -u src/sys/arch/x86/include/cpu.h:1.128 src/sys/arch/x86/include/cpu.h:1.129 --- src/sys/arch/x86/include/cpu.h:1.128 Sun Jul 19 09:55:09 2020 +++ src/sys/arch/x86/include/cpu.h Sat Aug 8 15:08:48 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: cpu.h,v 1.128 2020/07/19 13:55:09 maxv Exp $ */ +/* $NetBSD: cpu.h,v 1.129 2020/08/08 19:08:48 christos Exp $ */ /* * Copyright (c) 1990 The Regents of the University of California. @@ -564,6 +564,7 @@ extern void (*x86_delay)(unsigned int); /* cpu.c */ void cpu_probe_features(struct cpu_info *); +int x86_cpu_is_lcall(const void *); /* vm_machdep.c */ void cpu_proc_fork(struct proc *, struct proc *); Index: src/sys/arch/x86/x86/cpu.c diff -u src/sys/arch/x86/x86/cpu.c:1.196 src/sys/arch/x86/x86/cpu.c:1.197 --- src/sys/arch/x86/x86/cpu.c:1.196 Tue Jul 28 10:49:55 2020 +++ src/sys/arch/x86/x86/cpu.c Sat Aug 8 15:08:48 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: cpu.c,v 1.196 2020/07/28 14:49:55 fcambus Exp $ */ +/* $NetBSD: cpu.c,v 1.197 2020/08/08 19:08:48 christos Exp $ */ /* * Copyright (c) 2000-2020 NetBSD Foundation, Inc. @@ -62,7 +62,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.196 2020/07/28 14:49:55 fcambus Exp $"); +__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.197 2020/08/08 19:08:48 christos Exp $"); #include "opt_ddb.h" #include "opt_mpbios.h" /* for MPDEBUG */ @@ -1451,3 +1451,26 @@ cpu_kick(struct cpu_info *ci) { x86_send_ipi(ci, X86_IPI_AST); } + +int +x86_cpu_is_lcall(const void *ip) +{ + static const uint8_t lcall[] = { 0x9a, 0, 0, 0, 0 }; + int error; + const size_t sz = sizeof(lcall) + 2; + uint8_t tmp[sizeof(lcall) + 2]; + + if ((error = copyin(ip, tmp, sz)) != 0) + return error; + + if (memcmp(tmp, lcall, sizeof(lcall)) != 0 || tmp[sz - 1] != 0) + return EINVAL; + + switch (tmp[sz - 2]) { + case (uint8_t)0x07: /* NetBSD */ + case (uint8_t)0x87: /* BSD/OS */ + return 0; + default: + return EINVAL; + } +} Index: src/sys/compat/netbsd32/netbsd32_mod.c diff -u src/sys/compat/netbsd32/netbsd32_mod.c:1.22 src/sys/compat/netbsd32/netbsd32_mod.c:1.23 --- src/sys/compat/netbsd32/netbsd32_mod.c:1.22 Sat Mar 21 12:17:08 2020 +++ src/sys/compat/netbsd32/netbsd32_mod.c Sat Aug 8 15:08:48 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: netbsd32_mod.c,v 1.22 2020/03/21 16:17:08 pgoyette Exp $ */ +/* $NetBSD: netbsd32_mod.c,v 1.23 2020/08/08 19:08:48 christos Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. @@ -59,7 +59,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: netbsd32_mod.c,v 1.22 2020/03/21 16:17:08 pgoyette Exp $"); +__KERNEL_RCSID(0, "$NetBSD: netbsd32_mod.c,v 1.23 2020/08/08 19:08:48 christos Exp $"); #ifdef _KERNEL_OPT #include "opt_execfmt.h" @@ -131,29 +131,28 @@ static struct execsw netbsd32_execsw[] = }; #if defined(__amd64__) +#include <x86/cpu.h> /* This code was moved here, from $SRC/arch/amd64/amd64/trap.c */ static int amd64_oosyscall_handle(struct proc *p, struct trapframe *frame) { - - static const char lcall[7] = { 0x9a, 0, 0, 0, 0, 7, 0 }; - const size_t sz = sizeof(lcall); - char tmp[sizeof(lcall) /* Avoids VLA */]; + int error = EPASSTHROUGH; +#define LCALLSZ 7 /* Check for the oosyscall lcall instruction. */ if (p->p_emul == &emul_netbsd32 && - frame->tf_rip < VM_MAXUSER_ADDRESS32 - sz && - copyin((void *)frame->tf_rip, tmp, sz) == 0 && - memcmp(tmp, lcall, sz) == 0) { - + frame->tf_rip < VM_MAXUSER_ADDRESS32 - LCALLSZ && + (error = x86_cpu_is_lcall((void *)frame->tf_rip)) == 0) + { /* Advance past the lcall and save instruction size. */ - frame->tf_rip += sz; - frame->tf_err = sz; + frame->tf_rip += LCALLSZ; + frame->tf_err = LCALLSZ; return 0; - } else - return EPASSTHROUGH; + } + + return error; } #endif /* defined(__amd64__) */