summaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/entry_64.S
diff options
context:
space:
mode:
authorMichael Ellerman <mpe@ellerman.id.au>2015-07-23 20:21:02 +1000
committerMichael Ellerman <mpe@ellerman.id.au>2015-07-29 11:56:11 +1000
commitd38374142b2560f233961ed3756416c68af6c6cb (patch)
tree404b608eef9a89f2b91c4152e6499a38fff449f1 /arch/powerpc/kernel/entry_64.S
parentc3525940cca53cf3568fefd35d169fea4f107f0a (diff)
downloadtalos-op-linux-d38374142b2560f233961ed3756416c68af6c6cb.tar.gz
talos-op-linux-d38374142b2560f233961ed3756416c68af6c6cb.zip
powerpc/kernel: Change the do_syscall_trace_enter() API
The API for calling do_syscall_trace_enter() is currently sensible enough, it just returns the (modified) syscall number. However once we enable seccomp filter it will get more complicated. When seccomp filter runs, the seccomp kernel code (via SECCOMP_RET_ERRNO), or a ptracer (via SECCOMP_RET_TRACE), may reject the syscall and *may* or may *not* set a return value in r3. That means the assembler that calls do_syscall_trace_enter() can not blindly return ENOSYS, it needs to only return ENOSYS if a return value has not already been set. There is no way to implement that logic with the current API. So change the do_syscall_trace_enter() API to make it deal with the return code juggling, and the assembler can then just return whatever return code it is given. Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Reviewed-by: Kees Cook <keescook@chromium.org>
Diffstat (limited to 'arch/powerpc/kernel/entry_64.S')
-rw-r--r--arch/powerpc/kernel/entry_64.S23
1 files changed, 17 insertions, 6 deletions
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index ee15d3c62e26..a94f155db78e 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -151,8 +151,7 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR)
CURRENT_THREAD_INFO(r11, r1)
ld r10,TI_FLAGS(r11)
andi. r11,r10,_TIF_SYSCALL_DOTRACE
- bne syscall_dotrace
-.Lsyscall_dotrace_cont:
+ bne syscall_dotrace /* does not return */
cmpldi 0,r0,NR_syscalls
bge- syscall_enosys
@@ -246,22 +245,34 @@ syscall_dotrace:
bl save_nvgprs
addi r3,r1,STACK_FRAME_OVERHEAD
bl do_syscall_trace_enter
+
/*
- * Restore argument registers possibly just changed.
- * We use the return value of do_syscall_trace_enter
- * for the call number to look up in the table (r0).
+ * We use the return value of do_syscall_trace_enter() as the syscall
+ * number. If the syscall was rejected for any reason do_syscall_trace_enter()
+ * returns an invalid syscall number and the test below against
+ * NR_syscalls will fail.
*/
mr r0,r3
+
+ /* Restore argument registers just clobbered and/or possibly changed. */
ld r3,GPR3(r1)
ld r4,GPR4(r1)
ld r5,GPR5(r1)
ld r6,GPR6(r1)
ld r7,GPR7(r1)
ld r8,GPR8(r1)
+
+ /* Repopulate r9 and r10 for the system_call path */
addi r9,r1,STACK_FRAME_OVERHEAD
CURRENT_THREAD_INFO(r10, r1)
ld r10,TI_FLAGS(r10)
- b .Lsyscall_dotrace_cont
+
+ cmpldi r0,NR_syscalls
+ blt+ system_call
+
+ /* Return code is already in r3 thanks to do_syscall_trace_enter() */
+ b .Lsyscall_exit
+
syscall_enosys:
li r3,-ENOSYS
OpenPOWER on IntegriCloud