Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests/x86: Add check_initial_reg_state()

This checks that ELF binaries are started with an appropriately
blank register state.

( There's currently a nasty special case in the entry asm to
arrange for this. I'm planning on removing the special case,
and this will help make sure I don't break it. )

Signed-off-by: Andy Lutomirski <luto@kernel.org>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/ef54f8d066b30a3eb36bbf26300eebb242185700.1454022279.git.luto@kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>

authored by

Andy Lutomirski and committed by
Ingo Molnar
e21d50f3 c31b3425

+117 -1
+8 -1
tools/testing/selftests/x86/Makefile
··· 4 4 5 5 .PHONY: all all_32 all_64 warn_32bit_failure clean 6 6 7 - TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs syscall_nt ptrace_syscall 7 + TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs syscall_nt ptrace_syscall \ 8 + check_initial_reg_state 8 9 TARGETS_C_32BIT_ONLY := entry_from_vm86 syscall_arg_fault sigreturn test_syscall_vdso unwind_vdso \ 9 10 test_FCMOV test_FCOMI test_FISTTP \ 10 11 ldt_gdt \ ··· 67 66 sysret_ss_attrs_64: thunks.S 68 67 ptrace_syscall_32: raw_syscall_helper_32.S 69 68 test_syscall_vdso_32: thunks_32.S 69 + 70 + # check_initial_reg_state is special: it needs a custom entry, and it 71 + # needs to be static so that its interpreter doesn't destroy its initial 72 + # state. 73 + check_initial_reg_state_32: CFLAGS += -Wl,-ereal_start -static 74 + check_initial_reg_state_64: CFLAGS += -Wl,-ereal_start -static
+109
tools/testing/selftests/x86/check_initial_reg_state.c
··· 1 + /* 2 + * check_initial_reg_state.c - check that execve sets the correct state 3 + * Copyright (c) 2014-2016 Andrew Lutomirski 4 + * 5 + * This program is free software; you can redistribute it and/or modify 6 + * it under the terms and conditions of the GNU General Public License, 7 + * version 2, as published by the Free Software Foundation. 8 + * 9 + * This program is distributed in the hope it will be useful, but 10 + * WITHOUT ANY WARRANTY; without even the implied warranty of 11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 + * General Public License for more details. 13 + */ 14 + 15 + #define _GNU_SOURCE 16 + 17 + #include <stdio.h> 18 + 19 + unsigned long ax, bx, cx, dx, si, di, bp, sp, flags; 20 + unsigned long r8, r9, r10, r11, r12, r13, r14, r15; 21 + 22 + asm ( 23 + ".pushsection .text\n\t" 24 + ".type real_start, @function\n\t" 25 + ".global real_start\n\t" 26 + "real_start:\n\t" 27 + #ifdef __x86_64__ 28 + "mov %rax, ax\n\t" 29 + "mov %rbx, bx\n\t" 30 + "mov %rcx, cx\n\t" 31 + "mov %rdx, dx\n\t" 32 + "mov %rsi, si\n\t" 33 + "mov %rdi, di\n\t" 34 + "mov %rbp, bp\n\t" 35 + "mov %rsp, sp\n\t" 36 + "mov %r8, r8\n\t" 37 + "mov %r9, r9\n\t" 38 + "mov %r10, r10\n\t" 39 + "mov %r11, r11\n\t" 40 + "mov %r12, r12\n\t" 41 + "mov %r13, r13\n\t" 42 + "mov %r14, r14\n\t" 43 + "mov %r15, r15\n\t" 44 + "pushfq\n\t" 45 + "popq flags\n\t" 46 + #else 47 + "mov %eax, ax\n\t" 48 + "mov %ebx, bx\n\t" 49 + "mov %ecx, cx\n\t" 50 + "mov %edx, dx\n\t" 51 + "mov %esi, si\n\t" 52 + "mov %edi, di\n\t" 53 + "mov %ebp, bp\n\t" 54 + "mov %esp, sp\n\t" 55 + "pushfl\n\t" 56 + "popl flags\n\t" 57 + #endif 58 + "jmp _start\n\t" 59 + ".size real_start, . - real_start\n\t" 60 + ".popsection"); 61 + 62 + int main() 63 + { 64 + int nerrs = 0; 65 + 66 + if (sp == 0) { 67 + printf("[FAIL]\tTest was built incorrectly\n"); 68 + return 1; 69 + } 70 + 71 + if (ax || bx || cx || dx || si || di || bp 72 + #ifdef __x86_64__ 73 + || r8 || r9 || r10 || r11 || r12 || r13 || r14 || r15 74 + #endif 75 + ) { 76 + printf("[FAIL]\tAll GPRs except SP should be 0\n"); 77 + #define SHOW(x) printf("\t" #x " = 0x%lx\n", x); 78 + SHOW(ax); 79 + SHOW(bx); 80 + SHOW(cx); 81 + SHOW(dx); 82 + SHOW(si); 83 + SHOW(di); 84 + SHOW(bp); 85 + SHOW(sp); 86 + #ifdef __x86_64__ 87 + SHOW(r8); 88 + SHOW(r9); 89 + SHOW(r10); 90 + SHOW(r11); 91 + SHOW(r12); 92 + SHOW(r13); 93 + SHOW(r14); 94 + SHOW(r15); 95 + #endif 96 + nerrs++; 97 + } else { 98 + printf("[OK]\tAll GPRs except SP are 0\n"); 99 + } 100 + 101 + if (flags != 0x202) { 102 + printf("[FAIL]\tFLAGS is 0x%lx, but it should be 0x202\n", flags); 103 + nerrs++; 104 + } else { 105 + printf("[OK]\tFLAGS is 0x202\n"); 106 + } 107 + 108 + return nerrs ? 1 : 0; 109 + }