summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHelge Deller <deller@gmx.de>2016-03-30 15:14:31 +0300
committerHelge Deller <deller@gmx.de>2016-03-31 13:28:38 +0300
commit910cd32e552ea09caa89cdbe328e468979b030dd (patch)
tree02cc8c1d9d0202d76f988ae242ccbc328a8e43cd
parent4f4acc9472e54ce702f1d85fc9e6d57767dec91f (diff)
downloadlinux-910cd32e552ea09caa89cdbe328e468979b030dd.tar.xz
parisc: Fix and enable seccomp filter support
The seccomp filter support requires careful handling of task registers. This includes reloading of the return value (%r28) and proper syscall exit if secure_computing() returned -1. Additionally we need to sign-extend the syscall number from signed 32bit to signed 64bit in do_syscall_trace_enter() since the ptrace interface only allows storing 32bit values in compat mode. Signed-off-by: Helge Deller <deller@gmx.de> Cc: stable@vger.kernel.org # v4.5
-rw-r--r--arch/parisc/Kconfig1
-rw-r--r--arch/parisc/include/asm/syscall.h13
-rw-r--r--arch/parisc/kernel/ptrace.c9
-rw-r--r--arch/parisc/kernel/syscall.S2
4 files changed, 23 insertions, 2 deletions
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index 14f655cf542e..86ed37671ef5 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -29,6 +29,7 @@ config PARISC
select TTY # Needed for pdc_cons.c
select HAVE_DEBUG_STACKOVERFLOW
select HAVE_ARCH_AUDITSYSCALL
+ select HAVE_ARCH_SECCOMP_FILTER
select ARCH_NO_COHERENT_DMA_MMAP
help
diff --git a/arch/parisc/include/asm/syscall.h b/arch/parisc/include/asm/syscall.h
index a5eba95d87fe..637ce8d6f375 100644
--- a/arch/parisc/include/asm/syscall.h
+++ b/arch/parisc/include/asm/syscall.h
@@ -39,6 +39,19 @@ static inline void syscall_get_arguments(struct task_struct *tsk,
}
}
+static inline void syscall_set_return_value(struct task_struct *task,
+ struct pt_regs *regs,
+ int error, long val)
+{
+ regs->gr[28] = error ? error : val;
+}
+
+static inline void syscall_rollback(struct task_struct *task,
+ struct pt_regs *regs)
+{
+ /* do nothing */
+}
+
static inline int syscall_get_arch(void)
{
int arch = AUDIT_ARCH_PARISC;
diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c
index ce0b2b4075c7..8fb81a391599 100644
--- a/arch/parisc/kernel/ptrace.c
+++ b/arch/parisc/kernel/ptrace.c
@@ -270,7 +270,8 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
long do_syscall_trace_enter(struct pt_regs *regs)
{
/* Do the secure computing check first. */
- secure_computing_strict(regs->gr[20]);
+ if (secure_computing() == -1)
+ return -1;
if (test_thread_flag(TIF_SYSCALL_TRACE) &&
tracehook_report_syscall_entry(regs)) {
@@ -296,7 +297,11 @@ long do_syscall_trace_enter(struct pt_regs *regs)
regs->gr[23] & 0xffffffff);
out:
- return regs->gr[20];
+ /*
+ * Sign extend the syscall number to 64bit since it may have been
+ * modified by a compat ptrace call
+ */
+ return (int) ((u32) regs->gr[20]);
}
void do_syscall_trace_exit(struct pt_regs *regs)
diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S
index fbafa0d0e2bf..c976ebfe2269 100644
--- a/arch/parisc/kernel/syscall.S
+++ b/arch/parisc/kernel/syscall.S
@@ -329,6 +329,7 @@ tracesys_next:
ldo -THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get task ptr */
LDREG TI_TASK(%r1), %r1
+ LDREG TASK_PT_GR28(%r1), %r28 /* Restore return value */
LDREG TASK_PT_GR26(%r1), %r26 /* Restore the users args */
LDREG TASK_PT_GR25(%r1), %r25
LDREG TASK_PT_GR24(%r1), %r24
@@ -342,6 +343,7 @@ tracesys_next:
stw %r21, -56(%r30) /* 6th argument */
#endif
+ cmpib,COND(=),n -1,%r20,tracesys_exit /* seccomp may have returned -1 */
comiclr,>>= __NR_Linux_syscalls, %r20, %r0
b,n .Ltracesys_nosys