These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / arch / x86 / kernel / ptrace.c
index a7bc794..558f50e 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/ptrace.h>
-#include <linux/regset.h>
 #include <linux/tracehook.h>
 #include <linux/user.h>
 #include <linux/elf.h>
@@ -28,8 +27,9 @@
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/processor.h>
-#include <asm/i387.h>
-#include <asm/fpu-internal.h>
+#include <asm/fpu/internal.h>
+#include <asm/fpu/signal.h>
+#include <asm/fpu/regset.h>
 #include <asm/debugreg.h>
 #include <asm/ldt.h>
 #include <asm/desc.h>
 #include <asm/proto.h>
 #include <asm/hw_breakpoint.h>
 #include <asm/traps.h>
+#include <asm/syscall.h>
 
 #include "tls.h"
 
-#define CREATE_TRACE_POINTS
-#include <trace/events/syscalls.h>
-
 enum x86_regset {
        REGSET_GENERAL,
        REGSET_FP,
@@ -1123,6 +1121,73 @@ static int genregs32_set(struct task_struct *target,
        return ret;
 }
 
+static long ia32_arch_ptrace(struct task_struct *child, compat_long_t request,
+                            compat_ulong_t caddr, compat_ulong_t cdata)
+{
+       unsigned long addr = caddr;
+       unsigned long data = cdata;
+       void __user *datap = compat_ptr(data);
+       int ret;
+       __u32 val;
+
+       switch (request) {
+       case PTRACE_PEEKUSR:
+               ret = getreg32(child, addr, &val);
+               if (ret == 0)
+                       ret = put_user(val, (__u32 __user *)datap);
+               break;
+
+       case PTRACE_POKEUSR:
+               ret = putreg32(child, addr, data);
+               break;
+
+       case PTRACE_GETREGS:    /* Get all gp regs from the child. */
+               return copy_regset_to_user(child, &user_x86_32_view,
+                                          REGSET_GENERAL,
+                                          0, sizeof(struct user_regs_struct32),
+                                          datap);
+
+       case PTRACE_SETREGS:    /* Set all gp regs in the child. */
+               return copy_regset_from_user(child, &user_x86_32_view,
+                                            REGSET_GENERAL, 0,
+                                            sizeof(struct user_regs_struct32),
+                                            datap);
+
+       case PTRACE_GETFPREGS:  /* Get the child FPU state. */
+               return copy_regset_to_user(child, &user_x86_32_view,
+                                          REGSET_FP, 0,
+                                          sizeof(struct user_i387_ia32_struct),
+                                          datap);
+
+       case PTRACE_SETFPREGS:  /* Set the child FPU state. */
+               return copy_regset_from_user(
+                       child, &user_x86_32_view, REGSET_FP,
+                       0, sizeof(struct user_i387_ia32_struct), datap);
+
+       case PTRACE_GETFPXREGS: /* Get the child extended FPU state. */
+               return copy_regset_to_user(child, &user_x86_32_view,
+                                          REGSET_XFP, 0,
+                                          sizeof(struct user32_fxsr_struct),
+                                          datap);
+
+       case PTRACE_SETFPXREGS: /* Set the child extended FPU state. */
+               return copy_regset_from_user(child, &user_x86_32_view,
+                                            REGSET_XFP, 0,
+                                            sizeof(struct user32_fxsr_struct),
+                                            datap);
+
+       case PTRACE_GET_THREAD_AREA:
+       case PTRACE_SET_THREAD_AREA:
+               return arch_ptrace(child, request, addr, data);
+
+       default:
+               return compat_ptrace_request(child, request, addr, data);
+       }
+
+       return ret;
+}
+#endif /* CONFIG_IA32_EMULATION */
+
 #ifdef CONFIG_X86_X32_ABI
 static long x32_arch_ptrace(struct task_struct *child,
                            compat_long_t request, compat_ulong_t caddr,
@@ -1211,78 +1276,21 @@ static long x32_arch_ptrace(struct task_struct *child,
 }
 #endif
 
+#ifdef CONFIG_COMPAT
 long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
                        compat_ulong_t caddr, compat_ulong_t cdata)
 {
-       unsigned long addr = caddr;
-       unsigned long data = cdata;
-       void __user *datap = compat_ptr(data);
-       int ret;
-       __u32 val;
-
 #ifdef CONFIG_X86_X32_ABI
        if (!is_ia32_task())
                return x32_arch_ptrace(child, request, caddr, cdata);
 #endif
-
-       switch (request) {
-       case PTRACE_PEEKUSR:
-               ret = getreg32(child, addr, &val);
-               if (ret == 0)
-                       ret = put_user(val, (__u32 __user *)datap);
-               break;
-
-       case PTRACE_POKEUSR:
-               ret = putreg32(child, addr, data);
-               break;
-
-       case PTRACE_GETREGS:    /* Get all gp regs from the child. */
-               return copy_regset_to_user(child, &user_x86_32_view,
-                                          REGSET_GENERAL,
-                                          0, sizeof(struct user_regs_struct32),
-                                          datap);
-
-       case PTRACE_SETREGS:    /* Set all gp regs in the child. */
-               return copy_regset_from_user(child, &user_x86_32_view,
-                                            REGSET_GENERAL, 0,
-                                            sizeof(struct user_regs_struct32),
-                                            datap);
-
-       case PTRACE_GETFPREGS:  /* Get the child FPU state. */
-               return copy_regset_to_user(child, &user_x86_32_view,
-                                          REGSET_FP, 0,
-                                          sizeof(struct user_i387_ia32_struct),
-                                          datap);
-
-       case PTRACE_SETFPREGS:  /* Set the child FPU state. */
-               return copy_regset_from_user(
-                       child, &user_x86_32_view, REGSET_FP,
-                       0, sizeof(struct user_i387_ia32_struct), datap);
-
-       case PTRACE_GETFPXREGS: /* Get the child extended FPU state. */
-               return copy_regset_to_user(child, &user_x86_32_view,
-                                          REGSET_XFP, 0,
-                                          sizeof(struct user32_fxsr_struct),
-                                          datap);
-
-       case PTRACE_SETFPXREGS: /* Set the child extended FPU state. */
-               return copy_regset_from_user(child, &user_x86_32_view,
-                                            REGSET_XFP, 0,
-                                            sizeof(struct user32_fxsr_struct),
-                                            datap);
-
-       case PTRACE_GET_THREAD_AREA:
-       case PTRACE_SET_THREAD_AREA:
-               return arch_ptrace(child, request, addr, data);
-
-       default:
-               return compat_ptrace_request(child, request, addr, data);
-       }
-
-       return ret;
+#ifdef CONFIG_IA32_EMULATION
+       return ia32_arch_ptrace(child, request, caddr, cdata);
+#else
+       return 0;
+#endif
 }
-
-#endif /* CONFIG_IA32_EMULATION */
+#endif /* CONFIG_COMPAT */
 
 #ifdef CONFIG_X86_64
 
@@ -1297,7 +1305,7 @@ static struct user_regset x86_64_regsets[] __read_mostly = {
                .core_note_type = NT_PRFPREG,
                .n = sizeof(struct user_i387_struct) / sizeof(long),
                .size = sizeof(long), .align = sizeof(long),
-               .active = xfpregs_active, .get = xfpregs_get, .set = xfpregs_set
+               .active = regset_xregset_fpregs_active, .get = xfpregs_get, .set = xfpregs_set
        },
        [REGSET_XSTATE] = {
                .core_note_type = NT_X86_XSTATE,
@@ -1338,13 +1346,13 @@ static struct user_regset x86_32_regsets[] __read_mostly = {
                .core_note_type = NT_PRFPREG,
                .n = sizeof(struct user_i387_ia32_struct) / sizeof(u32),
                .size = sizeof(u32), .align = sizeof(u32),
-               .active = fpregs_active, .get = fpregs_get, .set = fpregs_set
+               .active = regset_fpregs_active, .get = fpregs_get, .set = fpregs_set
        },
        [REGSET_XFP] = {
                .core_note_type = NT_PRXFPREG,
                .n = sizeof(struct user32_fxsr_struct) / sizeof(u32),
                .size = sizeof(u32), .align = sizeof(u32),
-               .active = xfpregs_active, .get = xfpregs_get, .set = xfpregs_set
+               .active = regset_xregset_fpregs_active, .get = xfpregs_get, .set = xfpregs_set
        },
        [REGSET_XSTATE] = {
                .core_note_type = NT_X86_XSTATE,
@@ -1434,201 +1442,3 @@ void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs,
        /* Send us the fake SIGTRAP */
        force_sig_info(SIGTRAP, &info, tsk);
 }
-
-static void do_audit_syscall_entry(struct pt_regs *regs, u32 arch)
-{
-#ifdef CONFIG_X86_64
-       if (arch == AUDIT_ARCH_X86_64) {
-               audit_syscall_entry(regs->orig_ax, regs->di,
-                                   regs->si, regs->dx, regs->r10);
-       } else
-#endif
-       {
-               audit_syscall_entry(regs->orig_ax, regs->bx,
-                                   regs->cx, regs->dx, regs->si);
-       }
-}
-
-/*
- * We can return 0 to resume the syscall or anything else to go to phase
- * 2.  If we resume the syscall, we need to put something appropriate in
- * regs->orig_ax.
- *
- * NB: We don't have full pt_regs here, but regs->orig_ax and regs->ax
- * are fully functional.
- *
- * For phase 2's benefit, our return value is:
- * 0:                  resume the syscall
- * 1:                  go to phase 2; no seccomp phase 2 needed
- * anything else:      go to phase 2; pass return value to seccomp
- */
-unsigned long syscall_trace_enter_phase1(struct pt_regs *regs, u32 arch)
-{
-       unsigned long ret = 0;
-       u32 work;
-
-       BUG_ON(regs != task_pt_regs(current));
-
-       work = ACCESS_ONCE(current_thread_info()->flags) &
-               _TIF_WORK_SYSCALL_ENTRY;
-
-       /*
-        * If TIF_NOHZ is set, we are required to call user_exit() before
-        * doing anything that could touch RCU.
-        */
-       if (work & _TIF_NOHZ) {
-               user_exit();
-               work &= ~_TIF_NOHZ;
-       }
-
-#ifdef CONFIG_SECCOMP
-       /*
-        * Do seccomp first -- it should minimize exposure of other
-        * code, and keeping seccomp fast is probably more valuable
-        * than the rest of this.
-        */
-       if (work & _TIF_SECCOMP) {
-               struct seccomp_data sd;
-
-               sd.arch = arch;
-               sd.nr = regs->orig_ax;
-               sd.instruction_pointer = regs->ip;
-#ifdef CONFIG_X86_64
-               if (arch == AUDIT_ARCH_X86_64) {
-                       sd.args[0] = regs->di;
-                       sd.args[1] = regs->si;
-                       sd.args[2] = regs->dx;
-                       sd.args[3] = regs->r10;
-                       sd.args[4] = regs->r8;
-                       sd.args[5] = regs->r9;
-               } else
-#endif
-               {
-                       sd.args[0] = regs->bx;
-                       sd.args[1] = regs->cx;
-                       sd.args[2] = regs->dx;
-                       sd.args[3] = regs->si;
-                       sd.args[4] = regs->di;
-                       sd.args[5] = regs->bp;
-               }
-
-               BUILD_BUG_ON(SECCOMP_PHASE1_OK != 0);
-               BUILD_BUG_ON(SECCOMP_PHASE1_SKIP != 1);
-
-               ret = seccomp_phase1(&sd);
-               if (ret == SECCOMP_PHASE1_SKIP) {
-                       regs->orig_ax = -1;
-                       ret = 0;
-               } else if (ret != SECCOMP_PHASE1_OK) {
-                       return ret;  /* Go directly to phase 2 */
-               }
-
-               work &= ~_TIF_SECCOMP;
-       }
-#endif
-
-       /* Do our best to finish without phase 2. */
-       if (work == 0)
-               return ret;  /* seccomp and/or nohz only (ret == 0 here) */
-
-#ifdef CONFIG_AUDITSYSCALL
-       if (work == _TIF_SYSCALL_AUDIT) {
-               /*
-                * If there is no more work to be done except auditing,
-                * then audit in phase 1.  Phase 2 always audits, so, if
-                * we audit here, then we can't go on to phase 2.
-                */
-               do_audit_syscall_entry(regs, arch);
-               return 0;
-       }
-#endif
-
-       return 1;  /* Something is enabled that we can't handle in phase 1 */
-}
-
-/* Returns the syscall nr to run (which should match regs->orig_ax). */
-long syscall_trace_enter_phase2(struct pt_regs *regs, u32 arch,
-                               unsigned long phase1_result)
-{
-       long ret = 0;
-       u32 work = ACCESS_ONCE(current_thread_info()->flags) &
-               _TIF_WORK_SYSCALL_ENTRY;
-
-       BUG_ON(regs != task_pt_regs(current));
-
-       /*
-        * If we stepped into a sysenter/syscall insn, it trapped in
-        * kernel mode; do_debug() cleared TF and set TIF_SINGLESTEP.
-        * If user-mode had set TF itself, then it's still clear from
-        * do_debug() and we need to set it again to restore the user
-        * state.  If we entered on the slow path, TF was already set.
-        */
-       if (work & _TIF_SINGLESTEP)
-               regs->flags |= X86_EFLAGS_TF;
-
-#ifdef CONFIG_SECCOMP
-       /*
-        * Call seccomp_phase2 before running the other hooks so that
-        * they can see any changes made by a seccomp tracer.
-        */
-       if (phase1_result > 1 && seccomp_phase2(phase1_result)) {
-               /* seccomp failures shouldn't expose any additional code. */
-               return -1;
-       }
-#endif
-
-       if (unlikely(work & _TIF_SYSCALL_EMU))
-               ret = -1L;
-
-       if ((ret || test_thread_flag(TIF_SYSCALL_TRACE)) &&
-           tracehook_report_syscall_entry(regs))
-               ret = -1L;
-
-       if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
-               trace_sys_enter(regs, regs->orig_ax);
-
-       do_audit_syscall_entry(regs, arch);
-
-       return ret ?: regs->orig_ax;
-}
-
-long syscall_trace_enter(struct pt_regs *regs)
-{
-       u32 arch = is_ia32_task() ? AUDIT_ARCH_I386 : AUDIT_ARCH_X86_64;
-       unsigned long phase1_result = syscall_trace_enter_phase1(regs, arch);
-
-       if (phase1_result == 0)
-               return regs->orig_ax;
-       else
-               return syscall_trace_enter_phase2(regs, arch, phase1_result);
-}
-
-void syscall_trace_leave(struct pt_regs *regs)
-{
-       bool step;
-
-       /*
-        * We may come here right after calling schedule_user()
-        * or do_notify_resume(), in which case we can be in RCU
-        * user mode.
-        */
-       user_exit();
-
-       audit_syscall_exit(regs);
-
-       if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
-               trace_sys_exit(regs, regs->ax);
-
-       /*
-        * If TIF_SYSCALL_EMU is set, we only get here because of
-        * TIF_SINGLESTEP (i.e. this is PTRACE_SYSEMU_SINGLESTEP).
-        * We already reported this syscall instruction in
-        * syscall_trace_enter().
-        */
-       step = unlikely(test_thread_flag(TIF_SINGLESTEP)) &&
-                       !test_thread_flag(TIF_SYSCALL_EMU);
-       if (step || test_thread_flag(TIF_SYSCALL_TRACE))
-               tracehook_report_syscall_exit(regs, step);
-
-       user_enter();
-}