* [RFC PATCH 1/3] powerpc/kernel: Get pt_regs from r9 before calling do_syscall_trace_enter() @ 2015-05-15 8:29 Michael Ellerman 2015-05-15 8:29 ` [RFC PATCH 2/3] powerpc/kernel: Prepare for seccomp-filter in the 64-bit syscall path Michael Ellerman 2015-05-15 8:29 ` [RFC PATCH 3/3] powerpc: Enable seccomp-filter for 64-bit Michael Ellerman 0 siblings, 2 replies; 4+ messages in thread From: Michael Ellerman @ 2015-05-15 8:29 UTC (permalink / raw) To: linuxppc-dev; +Cc: strosake, bogdan.purcareata To call do_syscall_trace_enter() we need pt_regs in r3, but we don't need to recalculate it based on r1, it's already in r9. Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> --- arch/powerpc/kernel/entry_64.S | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index afbc20019c2e..b55c393310f3 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -236,7 +236,9 @@ syscall_error: /* Traced system call support */ syscall_dotrace: bl save_nvgprs - addi r3,r1,STACK_FRAME_OVERHEAD + + /* Get pt_regs into r3 */ + mr r3, r9 bl do_syscall_trace_enter /* * Restore argument registers possibly just changed. -- 2.1.0 ^ permalink raw reply related [flat|nested] 4+ messages in thread
* [RFC PATCH 2/3] powerpc/kernel: Prepare for seccomp-filter in the 64-bit syscall path 2015-05-15 8:29 [RFC PATCH 1/3] powerpc/kernel: Get pt_regs from r9 before calling do_syscall_trace_enter() Michael Ellerman @ 2015-05-15 8:29 ` Michael Ellerman 2015-05-20 10:47 ` Michael Neuling 2015-05-15 8:29 ` [RFC PATCH 3/3] powerpc: Enable seccomp-filter for 64-bit Michael Ellerman 1 sibling, 1 reply; 4+ messages in thread From: Michael Ellerman @ 2015-05-15 8:29 UTC (permalink / raw) To: linuxppc-dev; +Cc: strosake, bogdan.purcareata In order to support seccomp-filter we need to be able to cope with seccomp potentially setting a return value for the syscall. Currently this doesn't work, because we assume any failure from do_syscall_trace_enter() should result in ENOSYS being returned to userspace. The complication is that we don't know if seccomp has set a return value, in fact the failure may not even be caused by seccomp it may have been from ptrace. So in some cases we should return ENOSYS, and in others we should return whatever's in regs, but we don't know which at this level. The trick is to pre-fill regs->result with -ENOSYS, so that we return that unless seccomp overwrites it with something else. Note that it's negative ENOSYS, so that we still go via the syscall_error path on the way out and set CR0[SO]. On the other hand in syscall_set_return_value() we set the return value as it should be presented to userspace. That is mainly for consistency with syscall_get_error(). Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> --- arch/powerpc/include/asm/syscall.h | 13 +++++++++++++ arch/powerpc/kernel/entry_64.S | 37 +++++++++++++++++++++++++++++++------ 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/arch/powerpc/include/asm/syscall.h b/arch/powerpc/include/asm/syscall.h index ff21b7a2f0cc..3f61ef03a54a 100644 --- a/arch/powerpc/include/asm/syscall.h +++ b/arch/powerpc/include/asm/syscall.h @@ -50,6 +50,12 @@ static inline void syscall_set_return_value(struct task_struct *task, struct pt_regs *regs, int error, long val) { + /* + * We are setting the return value _as presented to userspace_. + * So we set CR0[SO] and also negate error, making it positive. + * That means we will _not_ go through the syscall_error path on the + * exit to userspace. + */ if (error) { regs->ccr |= 0x10000000L; regs->gpr[3] = -error; @@ -57,6 +63,13 @@ static inline void syscall_set_return_value(struct task_struct *task, regs->ccr &= ~0x10000000L; regs->gpr[3] = val; } + + /* + * Set regs->result to match r3. This mirrors the way a regular syscall + * exit works. It also makes the return value juggling in + * syscall_dotrace work. + */ + regs->result = regs->gpr[3]; } static inline void syscall_get_arguments(struct task_struct *task, diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index b55c393310f3..3c912d9047c4 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -143,8 +143,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 @@ -235,27 +234,53 @@ syscall_error: /* Traced system call support */ syscall_dotrace: + /* Save non-volatile GPRs so seccomp/ptrace etc. can see them */ bl save_nvgprs + /* + * Seccomp may set regs->result, but we don't know at this level, so + * preload result with ENOSYS here. That way below in the path to + * .Lsyscall_exit we can load regs->result and get either ENOSYS, or + * the value set by seccomp. + */ + li r3,-ENOSYS + std r3,RESULT(r1) + /* Get pt_regs into r3 */ mr r3, r9 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 -1 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 + + /* Check the syscall number is valid */ + cmpldi 0,r0,NR_syscalls + blt+ system_call + + /* + * Syscall number is bad, get the result, either ENOSYS from above or + * something set by seccomp. + */ + ld r3,RESULT(r1) + b .Lsyscall_exit syscall_enosys: li r3,-ENOSYS -- 2.1.0 ^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [RFC PATCH 2/3] powerpc/kernel: Prepare for seccomp-filter in the 64-bit syscall path 2015-05-15 8:29 ` [RFC PATCH 2/3] powerpc/kernel: Prepare for seccomp-filter in the 64-bit syscall path Michael Ellerman @ 2015-05-20 10:47 ` Michael Neuling 0 siblings, 0 replies; 4+ messages in thread From: Michael Neuling @ 2015-05-20 10:47 UTC (permalink / raw) To: Michael Ellerman; +Cc: linuxppc-dev, strosake, bogdan.purcareata On Fri, 2015-05-15 at 18:29 +1000, Michael Ellerman wrote: > In order to support seccomp-filter we need to be able to cope with > seccomp potentially setting a return value for the syscall. >=20 > Currently this doesn't work, because we assume any failure from > do_syscall_trace_enter() should result in ENOSYS being returned to > userspace. >=20 > The complication is that we don't know if seccomp has set a return > value, in fact the failure may not even be caused by seccomp it may have > been from ptrace. So in some cases we should return ENOSYS, and in > others we should return whatever's in regs, but we don't know which at > this level. >=20 > The trick is to pre-fill regs->result with -ENOSYS, so that we return > that unless seccomp overwrites it with something else. >=20 > Note that it's negative ENOSYS, so that we still go via the > syscall_error path on the way out and set CR0[SO]. >=20 > On the other hand in syscall_set_return_value() we set the return value > as it should be presented to userspace. That is mainly for consistency > with syscall_get_error(). >=20 > Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> > --- > arch/powerpc/include/asm/syscall.h | 13 +++++++++++++ > arch/powerpc/kernel/entry_64.S | 37 +++++++++++++++++++++++++++++++-= ----- > 2 files changed, 44 insertions(+), 6 deletions(-) >=20 > diff --git a/arch/powerpc/include/asm/syscall.h b/arch/powerpc/include/as= m/syscall.h > index ff21b7a2f0cc..3f61ef03a54a 100644 > --- a/arch/powerpc/include/asm/syscall.h > +++ b/arch/powerpc/include/asm/syscall.h > @@ -50,6 +50,12 @@ static inline void syscall_set_return_value(struct tas= k_struct *task, > struct pt_regs *regs, > int error, long val) > { > + /* > + * We are setting the return value _as presented to userspace_. > + * So we set CR0[SO] and also negate error, making it positive. > + * That means we will _not_ go through the syscall_error path on the > + * exit to userspace. > + */ > if (error) { > regs->ccr |=3D 0x10000000L; > regs->gpr[3] =3D -error; > @@ -57,6 +63,13 @@ static inline void syscall_set_return_value(struct tas= k_struct *task, > regs->ccr &=3D ~0x10000000L; > regs->gpr[3] =3D val; > } > + > + /* > + * Set regs->result to match r3. This mirrors the way a regular syscall > + * exit works. It also makes the return value juggling in > + * syscall_dotrace work. > + */ > + regs->result =3D regs->gpr[3]; > } > =20 > static inline void syscall_get_arguments(struct task_struct *task, > diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_6= 4.S > index b55c393310f3..3c912d9047c4 100644 > --- a/arch/powerpc/kernel/entry_64.S > +++ b/arch/powerpc/kernel/entry_64.S > @@ -143,8 +143,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 > =20 > @@ -235,27 +234,53 @@ syscall_error: > =09 > /* Traced system call support */ > syscall_dotrace: > + /* Save non-volatile GPRs so seccomp/ptrace etc. can see them */ > bl save_nvgprs > =20 > + /* > + * Seccomp may set regs->result, but we don't know at this level, so > + * preload result with ENOSYS here. That way below in the path to > + * .Lsyscall_exit we can load regs->result and get either ENOSYS, or > + * the value set by seccomp. > + */ > + li r3,-ENOSYS > + std r3,RESULT(r1) > + > /* Get pt_regs into r3 */ > mr r3, r9 > 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 -1 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 > + > + /* Check the syscall number is valid */ > + cmpldi 0,r0,NR_syscalls > + blt+ system_call > + > + /* > + * Syscall number is bad, get the result, either ENOSYS from above or > + * something set by seccomp. > + */ > + ld r3,RESULT(r1) > + b .Lsyscall_exit >=20 Minor nit... one thing that confused me is this last label below here "syscall_enosys". You are talking about enosys a bunch above but if you perform the syscall, you don't actually use it as you exit via the branch just above. Should we rename it to syscall_enosys_early: or something else? > syscall_enosys: > li r3,-ENOSYS ^ permalink raw reply [flat|nested] 4+ messages in thread
* [RFC PATCH 3/3] powerpc: Enable seccomp-filter for 64-bit 2015-05-15 8:29 [RFC PATCH 1/3] powerpc/kernel: Get pt_regs from r9 before calling do_syscall_trace_enter() Michael Ellerman 2015-05-15 8:29 ` [RFC PATCH 2/3] powerpc/kernel: Prepare for seccomp-filter in the 64-bit syscall path Michael Ellerman @ 2015-05-15 8:29 ` Michael Ellerman 1 sibling, 0 replies; 4+ messages in thread From: Michael Ellerman @ 2015-05-15 8:29 UTC (permalink / raw) To: linuxppc-dev; +Cc: strosake, bogdan.purcareata We now have the right pieces in place to enable seccomp-filter on 64-bit. We select HAVE_ARCH_SECCOMP_FILTER to enable the code, and we also need to switch to using secure_computing() rather than the strict variant. Enabling support on 32-bit should just be a matter of fixing the assembler in entry_32.S in a similar fashion to the 64-bit code. Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> --- arch/powerpc/Kconfig | 1 + arch/powerpc/kernel/ptrace.c | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 190cc48abc0c..a90bbd2c3f3b 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -104,6 +104,7 @@ config PPC select HAVE_EFFICIENT_UNALIGNED_ACCESS if !CPU_LITTLE_ENDIAN select HAVE_KPROBES select HAVE_ARCH_KGDB + select HAVE_ARCH_SECCOMP_FILTER if PPC64 select HAVE_KRETPROBES select HAVE_ARCH_TRACEHOOK select HAVE_MEMBLOCK diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index f21897b42057..473d555ce60c 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c @@ -1772,7 +1772,13 @@ long do_syscall_trace_enter(struct pt_regs *regs) user_exit(); +#ifdef CONFIG_PPC64 + /* Do the secure computing check first */ + if (secure_computing() == -1) + return -1L; +#else secure_computing_strict(regs->gpr[0]); +#endif if (test_thread_flag(TIF_SYSCALL_TRACE) && tracehook_report_syscall_entry(regs)) -- 2.1.0 ^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2015-05-20 10:47 UTC | newest] Thread overview: 4+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2015-05-15 8:29 [RFC PATCH 1/3] powerpc/kernel: Get pt_regs from r9 before calling do_syscall_trace_enter() Michael Ellerman 2015-05-15 8:29 ` [RFC PATCH 2/3] powerpc/kernel: Prepare for seccomp-filter in the 64-bit syscall path Michael Ellerman 2015-05-20 10:47 ` Michael Neuling 2015-05-15 8:29 ` [RFC PATCH 3/3] powerpc: Enable seccomp-filter for 64-bit Michael Ellerman
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).