提交 2a4d0c62 编写于 作者: D Dmitry Safonov 提交者: Ingo Molnar

x86/selftests: Add clobbers for int80 on x86_64

Kernel erases R8..R11 registers prior returning to userspace
from int80:

  https://lkml.org/lkml/2009/10/1/164

GCC can reuse these registers and doesn't expect them to change
during syscall invocation. I met this kind of bug in CRIU once
GCC 6.1 and CLANG stored local variables in those registers
and the kernel zerofied them during syscall:

  https://github.com/xemul/criu/commit/990d33f1a1cdd17bca6c2eb059ab3be2564f7fa2

By that reason I suggest to add those registers to clobbers
in selftests.  Also, as noted by Andy - removed unneeded clobber
for flags in INT $0x80 inline asm.
Signed-off-by: NDmitry Safonov <dsafonov@virtuozzo.com>
Acked-by: NAndy Lutomirski <luto@kernel.org>
Cc: 0x7f454c46@gmail.com
Cc: Borislav Petkov <bp@alien8.de>
Cc: Borislav Petkov <bp@suse.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-kselftest@vger.kernel.org
Link: http://lkml.kernel.org/r/20170213101336.20486-1-dsafonov@virtuozzo.comSigned-off-by: NIngo Molnar <mingo@kernel.org>
上级 11277aab
...@@ -245,7 +245,7 @@ void do_unexpected_base(void) ...@@ -245,7 +245,7 @@ void do_unexpected_base(void)
long ret; long ret;
asm volatile ("int $0x80" asm volatile ("int $0x80"
: "=a" (ret) : "a" (243), "b" (low_desc) : "=a" (ret) : "a" (243), "b" (low_desc)
: "flags"); : "r8", "r9", "r10", "r11");
memcpy(&desc, low_desc, sizeof(desc)); memcpy(&desc, low_desc, sizeof(desc));
munmap(low_desc, sizeof(desc)); munmap(low_desc, sizeof(desc));
......
...@@ -45,6 +45,12 @@ ...@@ -45,6 +45,12 @@
#define AR_DB (1 << 22) #define AR_DB (1 << 22)
#define AR_G (1 << 23) #define AR_G (1 << 23)
#ifdef __x86_64__
# define INT80_CLOBBERS "r8", "r9", "r10", "r11"
#else
# define INT80_CLOBBERS
#endif
static int nerrs; static int nerrs;
/* Points to an array of 1024 ints, each holding its own index. */ /* Points to an array of 1024 ints, each holding its own index. */
...@@ -588,7 +594,7 @@ static int invoke_set_thread_area(void) ...@@ -588,7 +594,7 @@ static int invoke_set_thread_area(void)
asm volatile ("int $0x80" asm volatile ("int $0x80"
: "=a" (ret), "+m" (low_user_desc) : : "=a" (ret), "+m" (low_user_desc) :
"a" (243), "b" (low_user_desc) "a" (243), "b" (low_user_desc)
: "flags"); : INT80_CLOBBERS);
return ret; return ret;
} }
...@@ -657,7 +663,7 @@ static void test_gdt_invalidation(void) ...@@ -657,7 +663,7 @@ static void test_gdt_invalidation(void)
"+a" (eax) "+a" (eax)
: "m" (low_user_desc_clear), : "m" (low_user_desc_clear),
[arg1] "r" ((unsigned int)(unsigned long)low_user_desc_clear) [arg1] "r" ((unsigned int)(unsigned long)low_user_desc_clear)
: "flags"); : INT80_CLOBBERS);
if (sel != 0) { if (sel != 0) {
result = "FAIL"; result = "FAIL";
...@@ -688,7 +694,7 @@ static void test_gdt_invalidation(void) ...@@ -688,7 +694,7 @@ static void test_gdt_invalidation(void)
"+a" (eax) "+a" (eax)
: "m" (low_user_desc_clear), : "m" (low_user_desc_clear),
[arg1] "r" ((unsigned int)(unsigned long)low_user_desc_clear) [arg1] "r" ((unsigned int)(unsigned long)low_user_desc_clear)
: "flags"); : INT80_CLOBBERS);
if (sel != 0) { if (sel != 0) {
result = "FAIL"; result = "FAIL";
...@@ -721,7 +727,7 @@ static void test_gdt_invalidation(void) ...@@ -721,7 +727,7 @@ static void test_gdt_invalidation(void)
"+a" (eax) "+a" (eax)
: "m" (low_user_desc_clear), : "m" (low_user_desc_clear),
[arg1] "r" ((unsigned int)(unsigned long)low_user_desc_clear) [arg1] "r" ((unsigned int)(unsigned long)low_user_desc_clear)
: "flags"); : INT80_CLOBBERS);
#ifdef __x86_64__ #ifdef __x86_64__
syscall(SYS_arch_prctl, ARCH_GET_FS, &new_base); syscall(SYS_arch_prctl, ARCH_GET_FS, &new_base);
...@@ -774,7 +780,7 @@ static void test_gdt_invalidation(void) ...@@ -774,7 +780,7 @@ static void test_gdt_invalidation(void)
"+a" (eax) "+a" (eax)
: "m" (low_user_desc_clear), : "m" (low_user_desc_clear),
[arg1] "r" ((unsigned int)(unsigned long)low_user_desc_clear) [arg1] "r" ((unsigned int)(unsigned long)low_user_desc_clear)
: "flags"); : INT80_CLOBBERS);
#ifdef __x86_64__ #ifdef __x86_64__
syscall(SYS_arch_prctl, ARCH_GET_GS, &new_base); syscall(SYS_arch_prctl, ARCH_GET_GS, &new_base);
......
...@@ -58,7 +58,8 @@ static void do_full_int80(struct syscall_args32 *args) ...@@ -58,7 +58,8 @@ static void do_full_int80(struct syscall_args32 *args)
asm volatile ("int $0x80" asm volatile ("int $0x80"
: "+a" (args->nr), : "+a" (args->nr),
"+b" (args->arg0), "+c" (args->arg1), "+d" (args->arg2), "+b" (args->arg0), "+c" (args->arg1), "+d" (args->arg2),
"+S" (args->arg3), "+D" (args->arg4), "+r" (bp)); "+S" (args->arg3), "+D" (args->arg4), "+r" (bp)
: : "r8", "r9", "r10", "r11");
args->arg5 = bp; args->arg5 = bp;
#else #else
sys32_helper(args, int80_and_ret); sys32_helper(args, int80_and_ret);
......
...@@ -56,9 +56,11 @@ static volatile sig_atomic_t sig_traps; ...@@ -56,9 +56,11 @@ static volatile sig_atomic_t sig_traps;
#ifdef __x86_64__ #ifdef __x86_64__
# define REG_IP REG_RIP # define REG_IP REG_RIP
# define WIDTH "q" # define WIDTH "q"
# define INT80_CLOBBERS "r8", "r9", "r10", "r11"
#else #else
# define REG_IP REG_EIP # define REG_IP REG_EIP
# define WIDTH "l" # define WIDTH "l"
# define INT80_CLOBBERS
#endif #endif
static unsigned long get_eflags(void) static unsigned long get_eflags(void)
...@@ -140,7 +142,8 @@ int main() ...@@ -140,7 +142,8 @@ int main()
printf("[RUN]\tSet TF and check int80\n"); printf("[RUN]\tSet TF and check int80\n");
set_eflags(get_eflags() | X86_EFLAGS_TF); set_eflags(get_eflags() | X86_EFLAGS_TF);
asm volatile ("int $0x80" : "=a" (tmp) : "a" (SYS_getpid)); asm volatile ("int $0x80" : "=a" (tmp) : "a" (SYS_getpid)
: INT80_CLOBBERS);
check_result(); check_result();
/* /*
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册