lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Mon, 1 Jun 2015 15:54:18 -0700
From:	Andy Lutomirski <luto@...capital.net>
To:	Shuah Khan <shuahkh@....samsung.com>
Cc:	Andy Lutomirski <luto@...nel.org>, Ingo Molnar <mingo@...nel.org>,
	Jan Beulich <JBeulich@...e.com>, X86 ML <x86@...nel.org>,
	"linux-kernel@...r.kernel.org" <linux-kernel@...r.kernel.org>
Subject: Re: [PATCH] x86_32, entry, selftests: Add a selftest for kernel
 entries from vm86 mode

On Mon, Jun 1, 2015 at 9:02 AM, Shuah Khan <shuahkh@....samsung.com> wrote:
> On 05/29/2015 03:58 PM, Andy Lutomirski wrote:
>> Test a couple of special cases in 32-bit kernels for entries from
>> vm86 mode.  This will OOPS both old kernels due to a bug and and
>> 4.1-rc5 due to a regression I introduced, and it should make sure
>> that the SYSENTER-from-vm86-mode hack in the kernel keeps working.
>>
>> Tests: 394838c96013 x86/asm/entry/32: Fix user_mode() misuses
>> Tests: 7ba554b5ac69 x86/asm/entry/32: Really make user_mode() work correctly for VM86 mode
>> Signed-off-by: Andy Lutomirski <luto@...nel.org>
>> ---
>>
>> Ingo, Shuah: I think this should go in through -tip.  (In general, I think
>> new x86 tests that don't have interesting interactions with the kselftest
>> infrastructure should go in through -tip, especially tests such as this one
>> that are related to recent regressions.)
>
> No problem going through tip. Could you please make sure
>
> "make kselftest" run from top level and
> tools/testing/selftests/kselftest_install.sh
>
> don't break?

Both 'make kselftest -j12 TARGETS=x86' and
../../../tools/testing/selftests/kselftest_install.sh work for me.
(The .. thing is annoying -- would it make sense to fix it to work
from the kernel tree root?)

--Andy

>
> Once the above are verified, here is my
>
> Acked-by: Shuah Khan <shuahkh@....samsung.com>
>
> Thanks,
> -- Shuah
>
>>
>> tools/testing/selftests/x86/Makefile          |   6 +-
>>  tools/testing/selftests/x86/entry_from_vm86.c | 114 ++++++++++++++++++++++++++
>>  2 files changed, 118 insertions(+), 2 deletions(-)
>>  create mode 100644 tools/testing/selftests/x86/entry_from_vm86.c
>>
>> diff --git a/tools/testing/selftests/x86/Makefile b/tools/testing/selftests/x86/Makefile
>> index 5bdb781163d1..9b0d8baf2934 100644
>> --- a/tools/testing/selftests/x86/Makefile
>> +++ b/tools/testing/selftests/x86/Makefile
>> @@ -5,8 +5,10 @@ include ../lib.mk
>>  .PHONY: all all_32 all_64 warn_32bit_failure clean
>>
>>  TARGETS_C_BOTHBITS := sigreturn single_step_syscall
>> +TARGETS_C_32BIT_ONLY := entry_from_vm86
>>
>> -BINARIES_32 := $(TARGETS_C_BOTHBITS:%=%_32)
>> +TARGETS_C_32BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_32BIT_ONLY)
>> +BINARIES_32 := $(TARGETS_C_32BIT_ALL:%=%_32)
>>  BINARIES_64 := $(TARGETS_C_BOTHBITS:%=%_64)
>>
>>  CFLAGS := -O2 -g -std=gnu99 -pthread -Wall
>> @@ -32,7 +34,7 @@ all_64: $(BINARIES_64)
>>  clean:
>>       $(RM) $(BINARIES_32) $(BINARIES_64)
>>
>> -$(TARGETS_C_BOTHBITS:%=%_32): %_32: %.c
>> +$(TARGETS_C_32BIT_ALL:%=%_32): %_32: %.c
>>       $(CC) -m32 -o $@ $(CFLAGS) $(EXTRA_CFLAGS) $^ -lrt -ldl
>>
>>  $(TARGETS_C_BOTHBITS:%=%_64): %_64: %.c
>> diff --git a/tools/testing/selftests/x86/entry_from_vm86.c b/tools/testing/selftests/x86/entry_from_vm86.c
>> new file mode 100644
>> index 000000000000..5c38a187677b
>> --- /dev/null
>> +++ b/tools/testing/selftests/x86/entry_from_vm86.c
>> @@ -0,0 +1,114 @@
>> +/*
>> + * entry_from_vm86.c - tests kernel entries from vm86 mode
>> + * Copyright (c) 2014-2015 Andrew Lutomirski
>> + *
>> + * This exercises a few paths that need to special-case vm86 mode.
>> + *
>> + * GPL v2.
>> + */
>> +
>> +#define _GNU_SOURCE
>> +
>> +#include <assert.h>
>> +#include <stdlib.h>
>> +#include <sys/syscall.h>
>> +#include <sys/signal.h>
>> +#include <sys/ucontext.h>
>> +#include <unistd.h>
>> +#include <stdio.h>
>> +#include <string.h>
>> +#include <inttypes.h>
>> +#include <sys/mman.h>
>> +#include <err.h>
>> +#include <stddef.h>
>> +#include <stdbool.h>
>> +#include <errno.h>
>> +#include <sys/vm86.h>
>> +
>> +static unsigned long load_addr = 0x10000;
>> +static int nerrs = 0;
>> +
>> +asm (
>> +     ".pushsection .rodata\n\t"
>> +     ".type vmcode_bound, @object\n\t"
>> +     "vmcode:\n\t"
>> +     "vmcode_bound:\n\t"
>> +     ".code16\n\t"
>> +     "bound %ax, (2048)\n\t"
>> +     "int3\n\t"
>> +     "vmcode_sysenter:\n\t"
>> +     "sysenter\n\t"
>> +     ".size vmcode, . - vmcode\n\t"
>> +     "end_vmcode:\n\t"
>> +     ".code32\n\t"
>> +     ".popsection"
>> +     );
>> +
>> +extern unsigned char vmcode[], end_vmcode[];
>> +extern unsigned char vmcode_bound[], vmcode_sysenter[];
>> +
>> +static void do_test(struct vm86plus_struct *v86, unsigned long eip,
>> +                 const char *text)
>> +{
>> +     long ret;
>> +
>> +     printf("[RUN]\t%s from vm86 mode\n", text);
>> +     v86->regs.eip = eip;
>> +     ret = vm86(VM86_ENTER, v86);
>> +
>> +     if (ret == -1 && errno == ENOSYS) {
>> +             printf("[SKIP]\tvm86 not supported\n");
>> +             return;
>> +     }
>> +
>> +     if (VM86_TYPE(ret) == VM86_INTx) {
>> +             char trapname[32];
>> +             int trapno = VM86_ARG(ret);
>> +             if (trapno == 13)
>> +                     strcpy(trapname, "GP");
>> +             else if (trapno == 5)
>> +                     strcpy(trapname, "BR");
>> +             else if (trapno == 14)
>> +                     strcpy(trapname, "PF");
>> +             else
>> +                     sprintf(trapname, "%d", trapno);
>> +
>> +             printf("[OK]\tExited vm86 mode due to #%s\n", trapname);
>> +     } else if (VM86_TYPE(ret) == VM86_UNKNOWN) {
>> +             printf("[OK]\tExited vm86 mode due to unhandled GP fault\n");
>> +     } else {
>> +             printf("[OK]\tExited vm86 mode due to type %ld, arg %ld\n",
>> +                    VM86_TYPE(ret), VM86_ARG(ret));
>> +     }
>> +}
>> +
>> +int main(void)
>> +{
>> +     struct vm86plus_struct v86;
>> +     unsigned char *addr = mmap((void *)load_addr, 4096,
>> +                                PROT_READ | PROT_WRITE | PROT_EXEC,
>> +                                MAP_ANONYMOUS | MAP_PRIVATE, -1,0);
>> +     if (addr != (unsigned char *)load_addr)
>> +             err(1, "mmap");
>> +
>> +     memcpy(addr, vmcode, end_vmcode - vmcode);
>> +     addr[2048] = 2;
>> +     addr[2050] = 3;
>> +
>> +     memset(&v86, 0, sizeof(v86));
>> +
>> +     v86.regs.cs = load_addr / 16;
>> +     v86.regs.ss = load_addr / 16;
>> +     v86.regs.ds = load_addr / 16;
>> +     v86.regs.es = load_addr / 16;
>> +
>> +     assert((v86.regs.cs & 3) == 0); /* Looks like RPL = 0 */
>> +
>> +     /* #BR -- should deliver SIG??? */
>> +     do_test(&v86, vmcode_bound - vmcode, "#BR");
>> +
>> +     /* SYSENTER -- should cause #GP or #UD depending on CPU */
>> +     do_test(&v86, vmcode_sysenter - vmcode, "SYSENTER");
>> +
>> +     return (nerrs == 0 ? 0 : 1);
>> +}
>>
>
>
> --
> Shuah Khan
> Sr. Linux Kernel Developer
> Open Source Innovation Group
> Samsung Research America (Silicon Valley)
> shuahkh@....samsung.com | (970) 217-8978



-- 
Andy Lutomirski
AMA Capital Management, LLC
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ