* [PATCHv3] x86/selftests: add clobbers for int80 on x86_64
@ 2017-02-13 10:13 Dmitry Safonov
2017-02-13 19:06 ` Andy Lutomirski
2017-03-01 9:47 ` [tip:x86/urgent] x86/selftests: Add " tip-bot for Dmitry Safonov
0 siblings, 2 replies; 6+ messages in thread
From: Dmitry Safonov @ 2017-02-13 10:13 UTC (permalink / raw)
To: linux-kernel
Cc: 0x7f454c46, Dmitry Safonov, Shuah Khan, Thomas Gleixner,
Ingo Molnar, H. Peter Anvin, Andy Lutomirski, Borislav Petkov,
x86, linux-kselftest
Kernel erases R8..R11 registers prior returning to userspace
from int80: https://lkml.org/lkml/2009/10/1/164
GCC can reuse this 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 notted by Andy - removed unneeded clobber
for flags in int 0x80 inline asm.
Cc: Shuah Khan <shuah@kernel.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@suse.de>
Cc: x86@kernel.org
Cc: linux-kselftest@vger.kernel.org
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
---
v3: Remove not needed clobber for "flags" (Andy)
v2: Don't touch iopl test: it doesn't do int 0x80
tools/testing/selftests/x86/fsgsbase.c | 2 +-
tools/testing/selftests/x86/ldt_gdt.c | 16 +++++++++++-----
tools/testing/selftests/x86/ptrace_syscall.c | 3 ++-
tools/testing/selftests/x86/single_step_syscall.c | 5 ++++-
4 files changed, 18 insertions(+), 8 deletions(-)
diff --git a/tools/testing/selftests/x86/fsgsbase.c b/tools/testing/selftests/x86/fsgsbase.c
index 5b2b4b3c634c..b4967d875236 100644
--- a/tools/testing/selftests/x86/fsgsbase.c
+++ b/tools/testing/selftests/x86/fsgsbase.c
@@ -245,7 +245,7 @@ void do_unexpected_base(void)
long ret;
asm volatile ("int $0x80"
: "=a" (ret) : "a" (243), "b" (low_desc)
- : "flags");
+ : "r8", "r9", "r10", "r11");
memcpy(&desc, low_desc, sizeof(desc));
munmap(low_desc, sizeof(desc));
diff --git a/tools/testing/selftests/x86/ldt_gdt.c b/tools/testing/selftests/x86/ldt_gdt.c
index 4af47079cf04..f6121612e769 100644
--- a/tools/testing/selftests/x86/ldt_gdt.c
+++ b/tools/testing/selftests/x86/ldt_gdt.c
@@ -45,6 +45,12 @@
#define AR_DB (1 << 22)
#define AR_G (1 << 23)
+#ifdef __x86_64__
+# define INT80_CLOBBERS "r8", "r9", "r10", "r11"
+#else
+# define INT80_CLOBBERS
+#endif
+
static int nerrs;
/* Points to an array of 1024 ints, each holding its own index. */
@@ -588,7 +594,7 @@ static int invoke_set_thread_area(void)
asm volatile ("int $0x80"
: "=a" (ret), "+m" (low_user_desc) :
"a" (243), "b" (low_user_desc)
- : "flags");
+ : INT80_CLOBBERS);
return ret;
}
@@ -657,7 +663,7 @@ static void test_gdt_invalidation(void)
"+a" (eax)
: "m" (low_user_desc_clear),
[arg1] "r" ((unsigned int)(unsigned long)low_user_desc_clear)
- : "flags");
+ : INT80_CLOBBERS);
if (sel != 0) {
result = "FAIL";
@@ -688,7 +694,7 @@ static void test_gdt_invalidation(void)
"+a" (eax)
: "m" (low_user_desc_clear),
[arg1] "r" ((unsigned int)(unsigned long)low_user_desc_clear)
- : "flags");
+ : INT80_CLOBBERS);
if (sel != 0) {
result = "FAIL";
@@ -721,7 +727,7 @@ static void test_gdt_invalidation(void)
"+a" (eax)
: "m" (low_user_desc_clear),
[arg1] "r" ((unsigned int)(unsigned long)low_user_desc_clear)
- : "flags");
+ : INT80_CLOBBERS);
#ifdef __x86_64__
syscall(SYS_arch_prctl, ARCH_GET_FS, &new_base);
@@ -774,7 +780,7 @@ static void test_gdt_invalidation(void)
"+a" (eax)
: "m" (low_user_desc_clear),
[arg1] "r" ((unsigned int)(unsigned long)low_user_desc_clear)
- : "flags");
+ : INT80_CLOBBERS);
#ifdef __x86_64__
syscall(SYS_arch_prctl, ARCH_GET_GS, &new_base);
diff --git a/tools/testing/selftests/x86/ptrace_syscall.c b/tools/testing/selftests/x86/ptrace_syscall.c
index b037ce9cf116..eaea92439708 100644
--- a/tools/testing/selftests/x86/ptrace_syscall.c
+++ b/tools/testing/selftests/x86/ptrace_syscall.c
@@ -58,7 +58,8 @@ static void do_full_int80(struct syscall_args32 *args)
asm volatile ("int $0x80"
: "+a" (args->nr),
"+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;
#else
sys32_helper(args, int80_and_ret);
diff --git a/tools/testing/selftests/x86/single_step_syscall.c b/tools/testing/selftests/x86/single_step_syscall.c
index 50c26358e8b7..a48da95c18fd 100644
--- a/tools/testing/selftests/x86/single_step_syscall.c
+++ b/tools/testing/selftests/x86/single_step_syscall.c
@@ -56,9 +56,11 @@ static volatile sig_atomic_t sig_traps;
#ifdef __x86_64__
# define REG_IP REG_RIP
# define WIDTH "q"
+# define INT80_CLOBBERS "r8", "r9", "r10", "r11"
#else
# define REG_IP REG_EIP
# define WIDTH "l"
+# define INT80_CLOBBERS
#endif
static unsigned long get_eflags(void)
@@ -140,7 +142,8 @@ int main()
printf("[RUN]\tSet TF and check int80\n");
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();
/*
--
2.11.1
^ permalink raw reply related [flat|nested] 6+ messages in thread* Re: [PATCHv3] x86/selftests: add clobbers for int80 on x86_64
2017-02-13 10:13 [PATCHv3] x86/selftests: add clobbers for int80 on x86_64 Dmitry Safonov
@ 2017-02-13 19:06 ` Andy Lutomirski
2017-02-13 19:30 ` Ingo Molnar
2017-02-13 22:18 ` hpa
2017-03-01 9:47 ` [tip:x86/urgent] x86/selftests: Add " tip-bot for Dmitry Safonov
1 sibling, 2 replies; 6+ messages in thread
From: Andy Lutomirski @ 2017-02-13 19:06 UTC (permalink / raw)
To: Dmitry Safonov
Cc: linux-kernel@vger.kernel.org, Dmitry Safonov, Shuah Khan,
Thomas Gleixner, Ingo Molnar, H. Peter Anvin, Andy Lutomirski,
Borislav Petkov, X86 ML, open list:KERNEL SELFTEST FRAMEWORK
On Mon, Feb 13, 2017 at 2:13 AM, Dmitry Safonov <dsafonov@virtuozzo.com> wrote:
> Kernel erases R8..R11 registers prior returning to userspace
> from int80: https://lkml.org/lkml/2009/10/1/164
>
> GCC can reuse this 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 notted by Andy - removed unneeded clobber
> for flags in int 0x80 inline asm.
Acked-by: Andy Lutomirski <luto@kernel.org>
Although these days we could preserve these regs in the kernel at the
cost of (I think) 4 bytes of text and zero runtime overhead.
--Andy
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCHv3] x86/selftests: add clobbers for int80 on x86_64
2017-02-13 19:06 ` Andy Lutomirski
@ 2017-02-13 19:30 ` Ingo Molnar
2017-02-13 22:18 ` hpa
1 sibling, 0 replies; 6+ messages in thread
From: Ingo Molnar @ 2017-02-13 19:30 UTC (permalink / raw)
To: Andy Lutomirski
Cc: Dmitry Safonov, linux-kernel@vger.kernel.org, Dmitry Safonov,
Shuah Khan, Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
Andy Lutomirski, Borislav Petkov, X86 ML,
open list:KERNEL SELFTEST FRAMEWORK
* Andy Lutomirski <luto@amacapital.net> wrote:
> On Mon, Feb 13, 2017 at 2:13 AM, Dmitry Safonov <dsafonov@virtuozzo.com> wrote:
> > Kernel erases R8..R11 registers prior returning to userspace
> > from int80: https://lkml.org/lkml/2009/10/1/164
> >
> > GCC can reuse this 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 notted by Andy - removed unneeded clobber
> > for flags in int 0x80 inline asm.
>
> Acked-by: Andy Lutomirski <luto@kernel.org>
>
> Although these days we could preserve these regs in the kernel at the cost of (I
> think) 4 bytes of text and zero runtime overhead.
I think we should try that...
Thanks,
Ingo
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCHv3] x86/selftests: add clobbers for int80 on x86_64
2017-02-13 19:06 ` Andy Lutomirski
2017-02-13 19:30 ` Ingo Molnar
@ 2017-02-13 22:18 ` hpa
2017-02-17 17:03 ` Andy Lutomirski
1 sibling, 1 reply; 6+ messages in thread
From: hpa @ 2017-02-13 22:18 UTC (permalink / raw)
To: Andy Lutomirski, Dmitry Safonov
Cc: linux-kernel@vger.kernel.org, Dmitry Safonov, Shuah Khan,
Thomas Gleixner, Ingo Molnar, Andy Lutomirski, Borislav Petkov,
X86 ML, open list:KERNEL SELFTEST FRAMEWORK
On February 13, 2017 11:06:04 AM PST, Andy Lutomirski <luto@amacapital.net> wrote:
>On Mon, Feb 13, 2017 at 2:13 AM, Dmitry Safonov
><dsafonov@virtuozzo.com> wrote:
>> Kernel erases R8..R11 registers prior returning to userspace
>> from int80: https://lkml.org/lkml/2009/10/1/164
>>
>> GCC can reuse this 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 notted by Andy - removed unneeded clobber
>> for flags in int 0x80 inline asm.
>
>Acked-by: Andy Lutomirski <luto@kernel.org>
>
>Although these days we could preserve these regs in the kernel at the
>cost of (I think) 4 bytes of text and zero runtime overhead.
>
>--Andy
If we can do so that cheaply I think we should.
--
Sent from my Android device with K-9 Mail. Please excuse my brevity.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCHv3] x86/selftests: add clobbers for int80 on x86_64
2017-02-13 22:18 ` hpa
@ 2017-02-17 17:03 ` Andy Lutomirski
0 siblings, 0 replies; 6+ messages in thread
From: Andy Lutomirski @ 2017-02-17 17:03 UTC (permalink / raw)
To: H. Peter Anvin
Cc: Dmitry Safonov, linux-kernel@vger.kernel.org, Dmitry Safonov,
Shuah Khan, Thomas Gleixner, Ingo Molnar, Andy Lutomirski,
Borislav Petkov, X86 ML, open list:KERNEL SELFTEST FRAMEWORK
On Mon, Feb 13, 2017 at 2:18 PM, <hpa@zytor.com> wrote:
> On February 13, 2017 11:06:04 AM PST, Andy Lutomirski <luto@amacapital.net> wrote:
>>On Mon, Feb 13, 2017 at 2:13 AM, Dmitry Safonov
>><dsafonov@virtuozzo.com> wrote:
>>> Kernel erases R8..R11 registers prior returning to userspace
>>> from int80: https://lkml.org/lkml/2009/10/1/164
>>>
>>> GCC can reuse this 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 notted by Andy - removed unneeded clobber
>>> for flags in int 0x80 inline asm.
>>
>>Acked-by: Andy Lutomirski <luto@kernel.org>
>>
>>Although these days we could preserve these regs in the kernel at the
>>cost of (I think) 4 bytes of text and zero runtime overhead.
>>
>>--Andy
>
> If we can do so that cheaply I think we should.
Sure, but we should still apply Dmitry's patches first.
^ permalink raw reply [flat|nested] 6+ messages in thread
* [tip:x86/urgent] x86/selftests: Add clobbers for int80 on x86_64
2017-02-13 10:13 [PATCHv3] x86/selftests: add clobbers for int80 on x86_64 Dmitry Safonov
2017-02-13 19:06 ` Andy Lutomirski
@ 2017-03-01 9:47 ` tip-bot for Dmitry Safonov
1 sibling, 0 replies; 6+ messages in thread
From: tip-bot for Dmitry Safonov @ 2017-03-01 9:47 UTC (permalink / raw)
To: linux-tip-commits
Cc: hpa, torvalds, dsafonov, luto, brgerst, jpoimboe, shuah, bp,
linux-kernel, peterz, dvlasenk, bp, tglx, mingo
Commit-ID: 2a4d0c627f5374f365a873dea4e10ae0bb437680
Gitweb: http://git.kernel.org/tip/2a4d0c627f5374f365a873dea4e10ae0bb437680
Author: Dmitry Safonov <dsafonov@virtuozzo.com>
AuthorDate: Mon, 13 Feb 2017 13:13:36 +0300
Committer: Ingo Molnar <mingo@kernel.org>
CommitDate: Wed, 1 Mar 2017 10:24:56 +0100
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: Dmitry Safonov <dsafonov@virtuozzo.com>
Acked-by: Andy 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.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
tools/testing/selftests/x86/fsgsbase.c | 2 +-
tools/testing/selftests/x86/ldt_gdt.c | 16 +++++++++++-----
tools/testing/selftests/x86/ptrace_syscall.c | 3 ++-
tools/testing/selftests/x86/single_step_syscall.c | 5 ++++-
4 files changed, 18 insertions(+), 8 deletions(-)
diff --git a/tools/testing/selftests/x86/fsgsbase.c b/tools/testing/selftests/x86/fsgsbase.c
index 5b2b4b3..b4967d8 100644
--- a/tools/testing/selftests/x86/fsgsbase.c
+++ b/tools/testing/selftests/x86/fsgsbase.c
@@ -245,7 +245,7 @@ void do_unexpected_base(void)
long ret;
asm volatile ("int $0x80"
: "=a" (ret) : "a" (243), "b" (low_desc)
- : "flags");
+ : "r8", "r9", "r10", "r11");
memcpy(&desc, low_desc, sizeof(desc));
munmap(low_desc, sizeof(desc));
diff --git a/tools/testing/selftests/x86/ldt_gdt.c b/tools/testing/selftests/x86/ldt_gdt.c
index 4af4707..f612161 100644
--- a/tools/testing/selftests/x86/ldt_gdt.c
+++ b/tools/testing/selftests/x86/ldt_gdt.c
@@ -45,6 +45,12 @@
#define AR_DB (1 << 22)
#define AR_G (1 << 23)
+#ifdef __x86_64__
+# define INT80_CLOBBERS "r8", "r9", "r10", "r11"
+#else
+# define INT80_CLOBBERS
+#endif
+
static int nerrs;
/* Points to an array of 1024 ints, each holding its own index. */
@@ -588,7 +594,7 @@ static int invoke_set_thread_area(void)
asm volatile ("int $0x80"
: "=a" (ret), "+m" (low_user_desc) :
"a" (243), "b" (low_user_desc)
- : "flags");
+ : INT80_CLOBBERS);
return ret;
}
@@ -657,7 +663,7 @@ static void test_gdt_invalidation(void)
"+a" (eax)
: "m" (low_user_desc_clear),
[arg1] "r" ((unsigned int)(unsigned long)low_user_desc_clear)
- : "flags");
+ : INT80_CLOBBERS);
if (sel != 0) {
result = "FAIL";
@@ -688,7 +694,7 @@ static void test_gdt_invalidation(void)
"+a" (eax)
: "m" (low_user_desc_clear),
[arg1] "r" ((unsigned int)(unsigned long)low_user_desc_clear)
- : "flags");
+ : INT80_CLOBBERS);
if (sel != 0) {
result = "FAIL";
@@ -721,7 +727,7 @@ static void test_gdt_invalidation(void)
"+a" (eax)
: "m" (low_user_desc_clear),
[arg1] "r" ((unsigned int)(unsigned long)low_user_desc_clear)
- : "flags");
+ : INT80_CLOBBERS);
#ifdef __x86_64__
syscall(SYS_arch_prctl, ARCH_GET_FS, &new_base);
@@ -774,7 +780,7 @@ static void test_gdt_invalidation(void)
"+a" (eax)
: "m" (low_user_desc_clear),
[arg1] "r" ((unsigned int)(unsigned long)low_user_desc_clear)
- : "flags");
+ : INT80_CLOBBERS);
#ifdef __x86_64__
syscall(SYS_arch_prctl, ARCH_GET_GS, &new_base);
diff --git a/tools/testing/selftests/x86/ptrace_syscall.c b/tools/testing/selftests/x86/ptrace_syscall.c
index b037ce9c..eaea924 100644
--- a/tools/testing/selftests/x86/ptrace_syscall.c
+++ b/tools/testing/selftests/x86/ptrace_syscall.c
@@ -58,7 +58,8 @@ static void do_full_int80(struct syscall_args32 *args)
asm volatile ("int $0x80"
: "+a" (args->nr),
"+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;
#else
sys32_helper(args, int80_and_ret);
diff --git a/tools/testing/selftests/x86/single_step_syscall.c b/tools/testing/selftests/x86/single_step_syscall.c
index 50c2635..a48da95 100644
--- a/tools/testing/selftests/x86/single_step_syscall.c
+++ b/tools/testing/selftests/x86/single_step_syscall.c
@@ -56,9 +56,11 @@ static volatile sig_atomic_t sig_traps;
#ifdef __x86_64__
# define REG_IP REG_RIP
# define WIDTH "q"
+# define INT80_CLOBBERS "r8", "r9", "r10", "r11"
#else
# define REG_IP REG_EIP
# define WIDTH "l"
+# define INT80_CLOBBERS
#endif
static unsigned long get_eflags(void)
@@ -140,7 +142,8 @@ int main()
printf("[RUN]\tSet TF and check int80\n");
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();
/*
^ permalink raw reply related [flat|nested] 6+ messages in thread
end of thread, other threads:[~2017-03-01 9:50 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-02-13 10:13 [PATCHv3] x86/selftests: add clobbers for int80 on x86_64 Dmitry Safonov
2017-02-13 19:06 ` Andy Lutomirski
2017-02-13 19:30 ` Ingo Molnar
2017-02-13 22:18 ` hpa
2017-02-17 17:03 ` Andy Lutomirski
2017-03-01 9:47 ` [tip:x86/urgent] x86/selftests: Add " tip-bot for Dmitry Safonov
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.