From: Kris Van Hees Date: Wed, 1 Jul 2015 09:31:30 +0000 (-0400) Subject: dtrace: accomodate changes in the 4.1 kernels X-Git-Tag: v4.1.12-92~313^2~7 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=93f57aa2e742fbffdf427300531889974afac2ea;p=users%2Fjedix%2Flinux-maple.git dtrace: accomodate changes in the 4.1 kernels The handling of some system calls changed in the 4.1 kernel. - The iopl system call is no longer a special case using a stub. - The implementation of stub-based system calls changed. - New system call: execveat Signed-off-by: Kris Van Hees Acked-by: Nick Alcock --- diff --git a/arch/x86/include/asm/dtrace_syscall.h b/arch/x86/include/asm/dtrace_syscall.h index 1a8fe47126063..fd00689229f5d 100644 --- a/arch/x86/include/asm/dtrace_syscall.h +++ b/arch/x86/include/asm/dtrace_syscall.h @@ -3,6 +3,6 @@ DTRACE_SYSCALL_STUB(CLONE, clone) DTRACE_SYSCALL_STUB(FORK, fork) DTRACE_SYSCALL_STUB(VFORK, vfork) -DTRACE_SYSCALL_STUB(IOPL, iopl) DTRACE_SYSCALL_STUB(EXECVE, execve) +DTRACE_SYSCALL_STUB(EXECVEAT, execveat) DTRACE_SYSCALL_STUB(RT_SIGRETURN, rt_sigreturn) diff --git a/arch/x86/kernel/dtrace_syscall.c b/arch/x86/kernel/dtrace_syscall.c index a31fe68c9c4e0..f9091383285fd 100644 --- a/arch/x86/kernel/dtrace_syscall.c +++ b/arch/x86/kernel/dtrace_syscall.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -55,12 +56,9 @@ static systrace_info_t systrace_info = systrace_stub, systrace_syscall, { - [SCE_CLONE] dtrace_stub_clone, - [SCE_FORK] dtrace_stub_fork, - [SCE_VFORK] dtrace_stub_vfork, - [SCE_IOPL] dtrace_stub_iopl, - [SCE_EXECVE] dtrace_stub_execve, - [SCE_RT_SIGRETURN] dtrace_stub_rt_sigreturn, +#define DTRACE_SYSCALL_STUB(id, name) \ + [SCE_##id] dtrace_stub_##name, +#include }, { #define __SYSCALL_64(nr, sym, compat) [nr] { __stringify(sym), }, @@ -117,7 +115,7 @@ EXPORT_SYMBOL(dtrace_syscalls_init); long dtrace_sys_clone(unsigned long clone_flags, unsigned long newsp, int __user *parent_tidptr, int __user *child_tidptr, - int tls_val) + int tls_val) { long rc = 0; dtrace_id_t id; @@ -218,48 +216,30 @@ long dtrace_sys_execve(const char __user *name, return rc; } -long dtrace_sys_iopl(unsigned int level) +long dtrace_sys_execveat(int fd, const char __user *name, + const char __user *const __user *argv, + const char __user *const __user *envp, + int flags) { long rc = 0; dtrace_id_t id; dtrace_syscalls_t *sc; - struct pt_regs *regs = current_pt_regs(); - unsigned int old = (regs->flags >> 12) & 3; - struct thread_struct *t = ¤t->thread; - - sc = &systrace_info.sysent[__NR_iopl]; + int lookup_flags = + (flags & AT_EMPTY_PATH) ? LOOKUP_EMPTY : 0; - /* - * regs is an argument de facto since it is plucked straight out of the - * stack frame by current_pt_regs(). - */ + sc = &systrace_info.sysent[__NR_execveat]; if ((id = sc->stsy_entry) != DTRACE_IDNONE) - (*systrace_probe)(id, (uintptr_t)level, (uintptr_t)regs, - 0, 0, 0, 0); + (*systrace_probe)(id, (uintptr_t)name, (uintptr_t)argv, + (uintptr_t)envp, 0, 0, 0); /* * FIXME: Add stop functionality for DTrace. */ - if (level > 3) { - rc = -EINVAL; - goto out; - } - - /* Trying to gain more privileges? */ - if (level > old) { - if (!capable(CAP_SYS_RAWIO)) { - rc = -EPERM; - goto out; - } - } - - regs->flags = (regs->flags & ~X86_EFLAGS_IOPL) | (level << 12); - t->iopl = level << 12; - set_iopl_mask(t->iopl); + rc = do_execveat(fd, getname_flags(name, lookup_flags, NULL), argv, + envp, flags); -out: if ((id = sc->stsy_return) != DTRACE_IDNONE) (*systrace_probe)(id, (uintptr_t)rc, (uintptr_t)rc, (uintptr_t)((uint64_t)rc >> 32), 0, 0, 0); diff --git a/arch/x86/kernel/dtrace_syscall_stubs.S b/arch/x86/kernel/dtrace_syscall_stubs.S index 285ebb5671880..a07f25b926f29 100644 --- a/arch/x86/kernel/dtrace_syscall_stubs.S +++ b/arch/x86/kernel/dtrace_syscall_stubs.S @@ -57,29 +57,8 @@ movq \tmp,R11+\offset(%rsp) .endm - .macro FAKE_STACK_FRAME child_rip - /* push in order ss, rsp, eflags, cs, rip */ - xorl %eax, %eax - pushq_cfi $__KERNEL_DS /* ss */ - /*CFI_REL_OFFSET ss,0*/ - pushq_cfi %rax /* rsp */ - CFI_REL_OFFSET rsp,0 - pushq_cfi $X86_EFLAGS_IF /* eflags - interrupts on */ - /*CFI_REL_OFFSET rflags,0*/ - pushq_cfi $__KERNEL_CS /* cs */ - /*CFI_REL_OFFSET cs,0*/ - pushq_cfi \child_rip /* rip */ - CFI_REL_OFFSET rip,0 - pushq_cfi %rax /* orig rax */ - .endm - - .macro UNFAKE_STACK_FRAME - addq $8*6, %rsp - CFI_ADJUST_CFA_OFFSET -(6*8) - .endm - /* - * initial frame state for interrupts (and exceptions without error code) + * empty frame */ .macro EMPTY_FRAME start=1 offset=0 .if \start @@ -95,12 +74,12 @@ * initial frame state for interrupts (and exceptions without error code) */ .macro INTR_FRAME start=1 offset=0 - EMPTY_FRAME \start, SS+8+\offset-RIP - /*CFI_REL_OFFSET ss, SS+\offset-RIP*/ - CFI_REL_OFFSET rsp, RSP+\offset-RIP - /*CFI_REL_OFFSET rflags, EFLAGS+\offset-RIP*/ - /*CFI_REL_OFFSET cs, CS+\offset-RIP*/ - CFI_REL_OFFSET rip, RIP+\offset-RIP + EMPTY_FRAME \start, 5*8+\offset + /*CFI_REL_OFFSET ss, 4*8+\offset*/ + CFI_REL_OFFSET rsp, 3*8+\offset + /*CFI_REL_OFFSET rflags, 2*8+\offset*/ + /*CFI_REL_OFFSET cs, 1*8+\offset*/ + CFI_REL_OFFSET rip, 0*8+\offset .endm /* @@ -108,31 +87,23 @@ * with vector already pushed) */ .macro XCPT_FRAME start=1 offset=0 - INTR_FRAME \start, RIP+\offset-ORIG_RAX - /*CFI_REL_OFFSET orig_rax, ORIG_RAX-ORIG_RAX*/ - .endm - -/* - * frame that enables calling into C. - */ - .macro PARTIAL_FRAME start=1 offset=0 - XCPT_FRAME \start, ORIG_RAX+\offset-ARGOFFSET - CFI_REL_OFFSET rdi, RDI+\offset-ARGOFFSET - CFI_REL_OFFSET rsi, RSI+\offset-ARGOFFSET - CFI_REL_OFFSET rdx, RDX+\offset-ARGOFFSET - CFI_REL_OFFSET rcx, RCX+\offset-ARGOFFSET - CFI_REL_OFFSET rax, RAX+\offset-ARGOFFSET - CFI_REL_OFFSET r8, R8+\offset-ARGOFFSET - CFI_REL_OFFSET r9, R9+\offset-ARGOFFSET - CFI_REL_OFFSET r10, R10+\offset-ARGOFFSET - CFI_REL_OFFSET r11, R11+\offset-ARGOFFSET + INTR_FRAME \start, 1*8+\offset .endm /* * frame that enables passing a complete pt_regs to a C function. */ .macro DEFAULT_FRAME start=1 offset=0 - PARTIAL_FRAME \start, R11+\offset-R15 + XCPT_FRAME \start, ORIG_RAX+\offset + CFI_REL_OFFSET rdi, RDI+\offset + CFI_REL_OFFSET rsi, RSI+\offset + CFI_REL_OFFSET rdx, RDX+\offset + CFI_REL_OFFSET rcx, RCX+\offset + CFI_REL_OFFSET rax, RAX+\offset + CFI_REL_OFFSET r8, R8+\offset + CFI_REL_OFFSET r9, R9+\offset + CFI_REL_OFFSET r10, R10+\offset + CFI_REL_OFFSET r11, R11+\offset CFI_REL_OFFSET rbx, RBX+\offset CFI_REL_OFFSET rbp, RBP+\offset CFI_REL_OFFSET r12, R12+\offset @@ -144,62 +115,57 @@ .macro FORK_LIKE func ENTRY(dtrace_stub_\func) CFI_STARTPROC - popq %r11 /* save return address */ - PARTIAL_FRAME 0 - SAVE_REST - pushq %r11 /* put it back on stack */ - FIXUP_TOP_OF_STACK %r11, 8 - DEFAULT_FRAME 0 8 /* offset 8: return address */ - call dtrace_sys_\func - RESTORE_TOP_OF_STACK %r11, 8 - ret $REST_SKIP /* pop extended registers */ + DEFAULT_FRAME 0, 8 + SAVE_EXTRA_REGS 8 + jmp dtrace_sys_\func CFI_ENDPROC END(dtrace_stub_\func) .endm - .macro FIXED_FRAME label,func -ENTRY(\label) - CFI_STARTPROC - PARTIAL_FRAME 0 8 /* offset 8: return address */ - FIXUP_TOP_OF_STACK %r11, 8-ARGOFFSET - call \func - RESTORE_TOP_OF_STACK %r11, 8-ARGOFFSET - ret - CFI_ENDPROC -END(\label) - .endm - FORK_LIKE clone FORK_LIKE fork FORK_LIKE vfork - FIXED_FRAME dtrace_stub_iopl, dtrace_sys_iopl ENTRY(dtrace_stub_execve) CFI_STARTPROC - addq $8, %rsp - PARTIAL_FRAME 0 - SAVE_REST - FIXUP_TOP_OF_STACK %r11 + DEFAULT_FRAME 0, 8 call dtrace_sys_execve - movq %rax,RAX(%rsp) - RESTORE_REST - jmp int_ret_from_sys_call +return_from_execve: + testl %eax, %eax + jz 1f + /* exec failed, can use fast SYSRET code path in this case */ + ret +1: + /* must use IRET code path (pt_regs->cs may have changed) */ + addq $8, %rsp + CFI_ADJUST_CFA_OFFSET -8 + ZERO_EXTRA_REGS + movq %rax,RAX(%rsp) + jmp int_ret_from_sys_call CFI_ENDPROC END(dtrace_stub_execve) +GLOBAL(dtrace_stub_execveat) + CFI_STARTPROC + DEFAULT_FRAME 0, 8 + call dtrace_sys_execveat + jmp return_from_execve + CFI_ENDPROC +END(dtrace_stub_execveat) + /* * sigreturn is special because it needs to restore all registers on return. * This cannot be done with SYSRET, so use the IRET return path instead. */ ENTRY(dtrace_stub_rt_sigreturn) CFI_STARTPROC - addq $8, %rsp - PARTIAL_FRAME 0 - SAVE_REST - FIXUP_TOP_OF_STACK %r11 + DEFAULT_FRAME 0, 8 + SAVE_EXTRA_REGS 8 call dtrace_sys_rt_sigreturn - movq %rax,RAX(%rsp) # fixme, this could be done at the higher layer - RESTORE_REST + addq $8, %rsp + CFI_ADJUST_CFA_OFFSET -8 + RESTORE_EXTRA_REGS + movq %rax,RAX(%rsp) jmp int_ret_from_sys_call CFI_ENDPROC END(dtrace_stub_rt_sigreturn)