x86-64: fix int $0x80 -ENOSYS return
authorRoland McGrath <roland@redhat.com>
Sat, 7 Feb 2009 02:15:18 +0000 (18:15 -0800)
committerRoland McGrath <roland@redhat.com>
Sat, 7 Feb 2009 02:22:29 +0000 (18:22 -0800)
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>
arch/x86/ia32/ia32entry.S

index 256b00b61892b2e3049ef8ff65a672df701efc77..5a0d76dc56a46431690702be8f745d6813db4cfc 100644 (file)
@@ -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: