Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e21d50f3 authored by Andy Lutomirski's avatar Andy Lutomirski Committed by Ingo Molnar
Browse files

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: default avatarAndy 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: default avatarIngo Molnar <mingo@kernel.org>
parent c31b3425
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -4,7 +4,8 @@ include ../lib.mk

.PHONY: all all_32 all_64 warn_32bit_failure clean

TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs syscall_nt ptrace_syscall
TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs syscall_nt ptrace_syscall \
			check_initial_reg_state
TARGETS_C_32BIT_ONLY := entry_from_vm86 syscall_arg_fault sigreturn test_syscall_vdso unwind_vdso \
			test_FCMOV test_FCOMI test_FISTTP \
			ldt_gdt \
@@ -66,3 +67,9 @@ endif
sysret_ss_attrs_64: thunks.S
ptrace_syscall_32: raw_syscall_helper_32.S
test_syscall_vdso_32: thunks_32.S

# check_initial_reg_state is special: it needs a custom entry, and it
# needs to be static so that its interpreter doesn't destroy its initial
# state.
check_initial_reg_state_32: CFLAGS += -Wl,-ereal_start -static
check_initial_reg_state_64: CFLAGS += -Wl,-ereal_start -static
+109 −0
Original line number Diff line number Diff line
/*
 * check_initial_reg_state.c - check that execve sets the correct state
 * Copyright (c) 2014-2016 Andrew Lutomirski
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms and conditions of the GNU General Public License,
 * version 2, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 */

#define _GNU_SOURCE

#include <stdio.h>

unsigned long ax, bx, cx, dx, si, di, bp, sp, flags;
unsigned long r8, r9, r10, r11, r12, r13, r14, r15;

asm (
	".pushsection .text\n\t"
	".type real_start, @function\n\t"
	".global real_start\n\t"
	"real_start:\n\t"
#ifdef __x86_64__
	"mov %rax, ax\n\t"
	"mov %rbx, bx\n\t"
	"mov %rcx, cx\n\t"
	"mov %rdx, dx\n\t"
	"mov %rsi, si\n\t"
	"mov %rdi, di\n\t"
	"mov %rbp, bp\n\t"
	"mov %rsp, sp\n\t"
	"mov %r8, r8\n\t"
	"mov %r9, r9\n\t"
	"mov %r10, r10\n\t"
	"mov %r11, r11\n\t"
	"mov %r12, r12\n\t"
	"mov %r13, r13\n\t"
	"mov %r14, r14\n\t"
	"mov %r15, r15\n\t"
	"pushfq\n\t"
	"popq flags\n\t"
#else
	"mov %eax, ax\n\t"
	"mov %ebx, bx\n\t"
	"mov %ecx, cx\n\t"
	"mov %edx, dx\n\t"
	"mov %esi, si\n\t"
	"mov %edi, di\n\t"
	"mov %ebp, bp\n\t"
	"mov %esp, sp\n\t"
	"pushfl\n\t"
	"popl flags\n\t"
#endif
	"jmp _start\n\t"
	".size real_start, . - real_start\n\t"
	".popsection");

int main()
{
	int nerrs = 0;

	if (sp == 0) {
		printf("[FAIL]\tTest was built incorrectly\n");
		return 1;
	}

	if (ax || bx || cx || dx || si || di || bp
#ifdef __x86_64__
	    || r8 || r9 || r10 || r11 || r12 || r13 || r14 || r15
#endif
		) {
		printf("[FAIL]\tAll GPRs except SP should be 0\n");
#define SHOW(x) printf("\t" #x " = 0x%lx\n", x);
		SHOW(ax);
		SHOW(bx);
		SHOW(cx);
		SHOW(dx);
		SHOW(si);
		SHOW(di);
		SHOW(bp);
		SHOW(sp);
#ifdef __x86_64__
		SHOW(r8);
		SHOW(r9);
		SHOW(r10);
		SHOW(r11);
		SHOW(r12);
		SHOW(r13);
		SHOW(r14);
		SHOW(r15);
#endif
		nerrs++;
	} else {
		printf("[OK]\tAll GPRs except SP are 0\n");
	}

	if (flags != 0x202) {
		printf("[FAIL]\tFLAGS is 0x%lx, but it should be 0x202\n", flags);
		nerrs++;
	} else {
		printf("[OK]\tFLAGS is 0x202\n");
	}

	return nerrs ? 1 : 0;
}