Re: [PATCH] x86: entry_32.S: change ESPFIX test to not touch PT_OLDSS(%esp)

From: Andy Lutomirski
Date: Mon Mar 09 2015 - 15:13:53 EST


On Mon, Mar 9, 2015 at 10:44 AM, H. Peter Anvin <hpa@xxxxxxxxx> wrote:
> On 03/09/2015 09:44 AM, Linus Torvalds wrote:
>>
>> And remember: those zero-cost out-of-order branches turn quite
>> expensive if they *ever* mispredict. Even a 5% mispredict rate is
>> likely to mean "it's better to have a data dependency chain".
>>
>> So it could easily go either way. I'm not convinced the old code is bad at all.
>>
>
> I'm inclined to side with Linus here. I'm hesitant to change this based
> on pure speculation.
>
> To answer Andy's question: I do believe we need espfix for V86 mode as well.
>

I think we don't. Did I screw up my test?

--Andy

> -hpa
>
>



--
Andy Lutomirski
AMA Capital Management, LLC
/*
* vm86 regs test.
* Copyright (c) 2014-2015 Andrew Lutomirski.
*
* This tests that vm86 regs work as expected.
*
* GPL v2.
*/

#define _GNU_SOURCE

#include <time.h>
#include <stdlib.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <sys/mman.h>
#include <sys/signal.h>
#include <sys/ucontext.h>
#include <asm/ldt.h>
#include <err.h>
#include <setjmp.h>
#include <stddef.h>
#include <stdbool.h>
#include <sys/user.h>
#include <errno.h>

#include <asm/vm86.h>

static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
int flags)
{
struct sigaction sa;

memset(&sa, 0, sizeof(sa));
sa.sa_sigaction = handler;
sa.sa_flags = SA_SIGINFO | flags;
sigemptyset(&sa.sa_mask);
if (sigaction(sig, &sa, 0))
err(1, "sigaction");
}

static void sigsegv_vm86(int sig, siginfo_t *info, void *ctx_void)
{
ucontext_t *ctx = (ucontext_t*)ctx_void;

printf("Back from vm86. EIP = %lx\n",
(unsigned long)ctx->uc_mcontext.gregs[REG_EIP]);

}

static void test_vm86(unsigned short cs, unsigned short ss)
{
struct vm86plus_struct v86, req_v86;
long ret;

memset(&v86, 0, sizeof(v86));

v86.regs.eip = 0;
v86.regs.cs = cs;
v86.regs.ss = ss;
v86.regs.esp = 0xbaadf00d;

req_v86 = v86;

printf("[RUN]\tcs = 0x%hx, ss = 0x%hx\n", cs, ss);

ret = syscall(SYS_vm86, VM86_ENTER, &v86);

if (ret == -1 && errno == ENOSYS) {
printf("[SKIP]\tvm86 not supported\n");
return;
}

printf("[OK]\tSurvived vm86 roundtrip. esp = %lx, should be %lx\n", v86.regs.esp, req_v86.regs.esp);
}

int main(void)
{
sethandler(SIGSEGV, sigsegv_vm86, SA_ONSTACK);
test_vm86(0, 0);
test_vm86(0, 3);
test_vm86(3, 0);
test_vm86(3, 3);
return 0;
}