diff options
author | Roland McGrath <roland@redhat.com> | 2009-02-07 03:15:18 +0100 |
---|---|---|
committer | Roland McGrath <roland@redhat.com> | 2009-02-07 03:22:29 +0100 |
commit | c09249f8d1b84344eca882547afdbffee8c09d14 (patch) | |
tree | 9c652c6aaec01f25f15d451b0f0e8009a8a8d530 /arch/x86/ia32 | |
parent | Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiw... (diff) | |
download | linux-c09249f8d1b84344eca882547afdbffee8c09d14.tar.xz linux-c09249f8d1b84344eca882547afdbffee8c09d14.zip |
x86-64: fix int $0x80 -ENOSYS return
One of my past fixes to this code introduced a different new bug.
When using 32-bit "int $0x80" entry for a bogus syscall number,
the return value is not correctly set to -ENOSYS. This only happens
when neither syscall-audit nor syscall tracing is enabled (i.e., never
seen if auditd ever started). Test program:
/* gcc -o int80-badsys -m32 -g int80-badsys.c
Run on x86-64 kernel.
Note to reproduce the bug you need auditd never to have started. */
#include <errno.h>
#include <stdio.h>
int
main (void)
{
long res;
asm ("int $0x80" : "=a" (res) : "0" (99999));
printf ("bad syscall returns %ld\n", res);
return res != -ENOSYS;
}
The fix makes the int $0x80 path match the sysenter and syscall paths.
Reported-by: Dmitry V. Levin <ldv@altlinux.org>
Signed-off-by: Roland McGrath <roland@redhat.com>
Diffstat (limited to 'arch/x86/ia32')
-rw-r--r-- | arch/x86/ia32/ia32entry.S | 8 |
1 files changed, 5 insertions, 3 deletions
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S index 256b00b61892..5a0d76dc56a4 100644 --- a/arch/x86/ia32/ia32entry.S +++ b/arch/x86/ia32/ia32entry.S @@ -418,9 +418,9 @@ ENTRY(ia32_syscall) orl $TS_COMPAT,TI_status(%r10) testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10) jnz ia32_tracesys -ia32_do_syscall: cmpl $(IA32_NR_syscalls-1),%eax - ja int_ret_from_sys_call /* ia32_tracesys has set RAX(%rsp) */ + ja ia32_badsys +ia32_do_call: IA32_ARG_FIXUP call *ia32_sys_call_table(,%rax,8) # xxx: rip relative ia32_sysret: @@ -435,7 +435,9 @@ ia32_tracesys: call syscall_trace_enter LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */ RESTORE_REST - jmp ia32_do_syscall + cmpl $(IA32_NR_syscalls-1),%eax + ja int_ret_from_sys_call /* ia32_tracesys has set RAX(%rsp) */ + jmp ia32_do_call END(ia32_syscall) ia32_badsys: |