]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
powerpc: Hard wire PT_SOFTE value to 1 in ptrace & signals
authorMadhavan Srinivasan <maddy@linux.vnet.ibm.com>
Sun, 20 Aug 2017 17:58:24 +0000 (23:28 +0530)
committerMichael Ellerman <mpe@ellerman.id.au>
Fri, 19 Jan 2018 11:36:54 +0000 (22:36 +1100)
We have always had softe in pt_regs, and accessible via PT_SOFTE, even
though it is not userspace state.

The value userspace sees should always be 1, because we should never
be in userspace with interrupts soft disabled.

In a subsequent patch we will be changing the semantics of the kernel
softe value, so hard wire the value to 1 to retain the existing
semantics. As far as we know nothing ever looks at it, but better safe
than sorry.

Signed-off-by: Madhavan Srinivasan <maddy@linux.vnet.ibm.com>
[mpe: Split out of larger patch, write change log]
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
arch/powerpc/kernel/ptrace.c
arch/powerpc/kernel/signal_32.c
arch/powerpc/kernel/signal_64.c

index f52ad5bb710960906b8ae61400688845e2811dd5..bd2c49475473d0438d487f69cda7ce6cd1fcf6e3 100644 (file)
@@ -283,6 +283,18 @@ int ptrace_get_reg(struct task_struct *task, int regno, unsigned long *data)
        if (regno == PT_DSCR)
                return get_user_dscr(task, data);
 
+#ifdef CONFIG_PPC64
+       /*
+        * softe copies paca->soft_enabled variable state. Since soft_enabled is
+        * no more used as a flag, lets force usr to alway see the softe value as 1
+        * which means interrupts are not soft disabled.
+        */
+       if (regno == PT_SOFTE) {
+               *data = 1;
+               return  0;
+       }
+#endif
+
        if (regno < (sizeof(struct pt_regs) / sizeof(unsigned long))) {
                *data = ((unsigned long *)task->thread.regs)[regno];
                return 0;
index 9ffd73296f649490cc5c31c3b14b789244a5b337..a30c6562ed668ffe0a068920d11e6edf07365947 100644 (file)
@@ -111,12 +111,20 @@ static inline int save_general_regs(struct pt_regs *regs,
 {
        elf_greg_t64 *gregs = (elf_greg_t64 *)regs;
        int i;
+       /* Force usr to alway see softe as 1 (interrupts enabled) */
+       elf_greg_t64 softe = 0x1;
 
        WARN_ON(!FULL_REGS(regs));
 
        for (i = 0; i <= PT_RESULT; i ++) {
                if (i == 14 && !FULL_REGS(regs))
                        i = 32;
+               if ( i == PT_SOFTE) {
+                       if(__put_user((unsigned int)softe, &frame->mc_gregs[i]))
+                               return -EFAULT;
+                       else
+                               continue;
+               }
                if (__put_user((unsigned int)gregs[i], &frame->mc_gregs[i]))
                        return -EFAULT;
        }
index 4b9ca3570344c17ba8fa5fa218fe132f01a3f446..2705fba544ad9b828661349a4ed0a4edb08bdded 100644 (file)
@@ -110,6 +110,8 @@ static long setup_sigcontext(struct sigcontext __user *sc,
        struct pt_regs *regs = tsk->thread.regs;
        unsigned long msr = regs->msr;
        long err = 0;
+       /* Force usr to alway see softe as 1 (interrupts enabled) */
+       unsigned long softe = 0x1;
 
        BUG_ON(tsk != current);
 
@@ -169,6 +171,7 @@ static long setup_sigcontext(struct sigcontext __user *sc,
        WARN_ON(!FULL_REGS(regs));
        err |= __copy_to_user(&sc->gp_regs, regs, GP_REGS_SIZE);
        err |= __put_user(msr, &sc->gp_regs[PT_MSR]);
+       err |= __put_user(softe, &sc->gp_regs[PT_SOFTE]);
        err |= __put_user(signr, &sc->signal);
        err |= __put_user(handler, &sc->handler);
        if (set != NULL)