]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
dtrace: accomodate changes in the 4.1 kernels
authorKris Van Hees <kris.van.hees@oracle.com>
Wed, 1 Jul 2015 09:31:30 +0000 (05:31 -0400)
committerNick Alcock <nick.alcock@oracle.com>
Tue, 21 Jul 2015 14:30:13 +0000 (15:30 +0100)
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 <kris.van.hees@oracle.com>
Acked-by: Nick Alcock <nick.alcock@oracle.com>
arch/x86/include/asm/dtrace_syscall.h
arch/x86/kernel/dtrace_syscall.c
arch/x86/kernel/dtrace_syscall_stubs.S

index 1a8fe47126063fc2e6d64a60bbcb649447fe4538..fd00689229f5dd0af8e46ebac1ae5084d8de7275 100644 (file)
@@ -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)
index a31fe68c9c4e0723f0b3026bebd531f60e84de05..f9091383285fdfa63af28f593c16a96750cd88d3 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/dtrace_syscall.h>
 #include <linux/fs.h>
 #include <linux/module.h>
+#include <linux/namei.h>
 #include <linux/sched.h>
 #include <asm/insn.h>
 #include <asm/stacktrace.h>
@@ -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 <asm/dtrace_syscall.h>
                        },
                        {
 #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 = &current->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);
index 285ebb5671880bbe3d05e3e99ae29f9bdc7f5a5d..a07f25b926f29c3cb0a6341fc565eec56180d936 100644 (file)
        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
  * 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
 
 /*
  * 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
        .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)