Bug 79661
Summary: | syscalls with number >= NR_syscalls not returning an error | ||
---|---|---|---|
Product: | Platform Specific/Hardware | Reporter: | Mark Davies (junk) |
Component: | i386 | Assignee: | platform_i386 |
Status: | RESOLVED PATCH_ALREADY_AVAILABLE | ||
Severity: | normal | CC: | cijewoj, emadahmed1995, faquwas, gmouhroky1, jovys, towolu |
Priority: | P1 | ||
Hardware: | i386 | ||
OS: | Linux | ||
Kernel Version: | 3.4.96, 3.10.46, 3.15.3 | Subsystem: | |
Regression: | No | Bisected commit-id: | |
Attachments: |
Kernel config file used for 3.4.96
cpuinfo sysenter_badsys.fix |
Description
Mark Davies
2014-07-08 13:35:13 UTC
Created attachment 143821 [details]
cpuinfo
Created attachment 144061 [details] sysenter_badsys.fix I think I have found the problem that the addition of sysenter_badsys introduced in https://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git/commit/?id=d3007333170435135f0620fb52386aad3fb2a14f The code flow when the syscall number is >= NR_syscalls now is as follows - top to bottom assuming no jump to sysexit_audit. sysenter_do_call: cmpl $(NR_syscalls), %eax jae sysenter_badsys sysenter_badsys: movl $-ENOSYS,PT_EAX(%esp) jmp sysenter_after_call sysenter_after_call: LOCKDEP_SYS_EXIT DISABLE_INTERRUPTS(CLBR_ANY) TRACE_IRQS_OFF movl TI_flags(%ebp), %ecx testl $_TIF_ALLWORK_MASK, %ecx jne sysexit_audit sysenter_exit: /* if something modifies registers it must also disable sysexit */ movl PT_EIP(%esp), %edx movl PT_OLDESP(%esp), %ecx xorl %ebp,%ebp TRACE_IRQS_ON 1: mov PT_FS(%esp), %fs PTGS_TO_GS ENABLE_INTERRUPTS_SYSEXIT eax contains the syscall number at start and is never changed. Thus the return value from the syscall is the original syscall number and no error is detected in userspace. Modifying sysenter_badsys to set eax to the error solves the problem, i.e. sysenter_badsys becomes sysenter_badsys: movl $-ENOSYS,%eax movl %eax,PT_EAX(%esp) jmp sysenter_after_call With the previous syscall_badsys path and when straceing the calls go through syscall_exit I believe. I think that path must be setting eax from PT_EAX(%esp) perhaps in restore_all before returning to userspace. I can't really follow what is code is doing (or suppose to be doing) along that path. Tested above change (sysenter_badsys.fix attachment) as before I get. $ uname -a Linux amd 3.4.96+ #26 SMP Tue Jul 22 17:32:57 BST 2014 i686 AMD Athlon(tm) 64 X2 Dual Core Processor 4400+ AuthenticAMD GNU/Linux $ ./a.out syscall(350) = -1 (Function not implemented) syscall(999) = -1 (Function not implemented) $ strace -o /dev/null ./a.out syscall(350) = -1 (Function not implemented) syscall(999) = -1 (Function not implemented) $ perl -e 'print syscall(349), " $!\n";' -1 Function not implemented $ strace -o /dev/null perl -e 'print syscall(349), " $!\n";' -1 Function not implemented Seem that someone else spotted the problem and has it covered. See https://lkml.org/lkml/2014/7/20/222 |