* [RFC] ARM support for syscall tracing
@ 2011-11-29 16:28 Steven Walter
2011-11-29 16:28 ` [PATCH 1/3] ARM: add support for the generic syscall.h interface Steven Walter
` (2 more replies)
0 siblings, 3 replies; 11+ messages in thread
From: Steven Walter @ 2011-11-29 16:28 UTC (permalink / raw)
To: linux-arm-kernel
I recently noticed that "perf test" fails tests #2 - #4 on ARM. In
investigating that failure, I noticed that those tests rely on
FTRACE_SYSCALLS, which was not available on ARM.
It didn't look like too much work to enable HAVE_SYSCALL_TRACEPOINTS, so
that's what I did in the patches that follow. This is a
request-for-comment because I don't entirely understand some of the
changes I made, so it's quite likely that some parts are either
out-and-out wrong, or at least can be done a better way.
That said, the tests in "perf test" pass except for #1 (kallsyms), and
strace still seems to report sensible values for system calls.
Comments?
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 1/3] ARM: add support for the generic syscall.h interface
2011-11-29 16:28 [RFC] ARM support for syscall tracing Steven Walter
@ 2011-11-29 16:28 ` Steven Walter
2011-11-29 16:28 ` [PATCH 2/3] ARM: add TRACEHOOK support Steven Walter
2011-11-29 16:28 ` [PATCH 3/3] ARM: support syscall tracing Steven Walter
2 siblings, 0 replies; 11+ messages in thread
From: Steven Walter @ 2011-11-29 16:28 UTC (permalink / raw)
To: linux-arm-kernel
Supplying the asm-generic/syscall.h interface is a pre-requisite for
HAVE_ARCH_TRACEHOOK
Signed-off-by: Steven Walter <stevenrwalter@gmail.com>
---
arch/arm/include/asm/syscall.h | 78 ++++++++++++++++++++++++++++++++++++++++
1 files changed, 78 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/include/asm/syscall.h
diff --git a/arch/arm/include/asm/syscall.h b/arch/arm/include/asm/syscall.h
new file mode 100644
index 0000000..f104339
--- /dev/null
+++ b/arch/arm/include/asm/syscall.h
@@ -0,0 +1,78 @@
+/*
+ * Access to user system call parameters and results
+ *
+ * See asm-generic/syscall.h for descriptions of what we must do here.
+ */
+
+#ifndef _ASM_ARM_SYSCALL_H
+#define _ASM_ARM_SYSCALL_H
+
+#include <linux/err.h>
+
+extern const unsigned long sys_call_table[];
+
+static inline int syscall_get_nr(struct task_struct *task,
+ struct pt_regs *regs)
+{
+ return task_thread_info(task)->syscall;
+}
+
+static inline void syscall_rollback(struct task_struct *task,
+ struct pt_regs *regs)
+{
+ regs->ARM_r0 = regs->ARM_ORIG_r0;
+}
+
+static inline long syscall_get_error(struct task_struct *task,
+ struct pt_regs *regs)
+{
+ unsigned long error = regs->ARM_r0;
+ return IS_ERR_VALUE(error) ? error : 0;
+}
+
+static inline long syscall_get_return_value(struct task_struct *task,
+ struct pt_regs *regs)
+{
+ return regs->ARM_r0;
+}
+
+static inline void syscall_set_return_value(struct task_struct *task,
+ struct pt_regs *regs,
+ int error, long val)
+{
+ regs->ARM_r0 = (long) error ?: val;
+}
+
+static inline void syscall_get_arguments(struct task_struct *task,
+ struct pt_regs *regs,
+ unsigned int i, unsigned int n,
+ unsigned long *args)
+{
+ BUG_ON(i + n > 6);
+ if (i == 0) {
+ args[0] = regs->ARM_ORIG_r0;
+ args++;
+ i++;
+ n--;
+ }
+
+ memcpy(args, ®s->ARM_r1 + (i - 1), n * sizeof(args[0]));
+}
+
+static inline void syscall_set_arguments(struct task_struct *task,
+ struct pt_regs *regs,
+ unsigned int i, unsigned int n,
+ const unsigned long *args)
+{
+ BUG_ON(i + n > 6);
+ if (i == 0) {
+ regs->ARM_ORIG_r0 = args[0];
+ args++;
+ i++;
+ n--;
+ }
+
+ memcpy(®s->ARM_r1 + (i - 1), args, n * sizeof(args[0]));
+}
+
+#endif /* _ASM_ARM_SYSCALL_H */
--
1.7.5.4.2.g81f75
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 2/3] ARM: add TRACEHOOK support
2011-11-29 16:28 [RFC] ARM support for syscall tracing Steven Walter
2011-11-29 16:28 ` [PATCH 1/3] ARM: add support for the generic syscall.h interface Steven Walter
@ 2011-11-29 16:28 ` Steven Walter
2011-11-29 17:04 ` Will Deacon
2011-11-29 16:28 ` [PATCH 3/3] ARM: support syscall tracing Steven Walter
2 siblings, 1 reply; 11+ messages in thread
From: Steven Walter @ 2011-11-29 16:28 UTC (permalink / raw)
To: linux-arm-kernel
Add calls to tracehook_report_syscall_{entry,exit} and tracehook_signal_handler
Signed-off-by: Steven Walter <stevenrwalter@gmail.com>
---
arch/arm/Kconfig | 1 +
arch/arm/include/asm/ptrace.h | 5 +++++
arch/arm/kernel/ptrace.c | 21 +++++++--------------
arch/arm/kernel/signal.c | 2 ++
4 files changed, 15 insertions(+), 14 deletions(-)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index b65b910..0a93d76 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -10,6 +10,7 @@ config ARM
select GENERIC_ATOMIC64 if (CPU_V6 || !CPU_32v6K || !AEABI)
select HAVE_OPROFILE if (HAVE_PERF_EVENTS)
select HAVE_ARCH_KGDB
+ select HAVE_ARCH_TRACEHOOK
select HAVE_KPROBES if (!XIP_KERNEL && !THUMB2_KERNEL)
select HAVE_KRETPROBES if (HAVE_KPROBES)
select HAVE_FUNCTION_TRACER if (!XIP_KERNEL)
diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h
index 312d108..98ea76d 100644
--- a/arch/arm/include/asm/ptrace.h
+++ b/arch/arm/include/asm/ptrace.h
@@ -235,6 +235,11 @@ static inline unsigned long kernel_stack_pointer(struct pt_regs *regs)
return regs->ARM_sp;
}
+static inline unsigned long user_stack_pointer(struct pt_regs *regs)
+{
+ return regs->ARM_sp;
+}
+
#endif /* __KERNEL__ */
#endif /* __ASSEMBLY__ */
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index 9726006..1411848 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -22,6 +22,7 @@
#include <linux/perf_event.h>
#include <linux/hw_breakpoint.h>
#include <linux/regset.h>
+#include <linux/tracehook.h>
#include <asm/pgtable.h>
#include <asm/system.h>
@@ -928,8 +929,6 @@ asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno)
if (!test_thread_flag(TIF_SYSCALL_TRACE))
return scno;
- if (!(current->ptrace & PT_PTRACED))
- return scno;
/*
* Save IP. IP is used to denote syscall entry/exit:
@@ -940,19 +939,13 @@ asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno)
current_thread_info()->syscall = scno;
- /* the 0x80 provides a way for the tracing parent to distinguish
- between a syscall stop and SIGTRAP delivery */
- ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
- ? 0x80 : 0));
- /*
- * this isn't the same as continuing with a signal, but it will do
- * for normal use. strace only continues with a signal if the
- * stopping signal is not SIGTRAP. -brl
- */
- if (current->exit_code) {
- send_sig(current->exit_code, current, 1);
- current->exit_code = 0;
+ if (why == 0) {
+ if (tracehook_report_syscall_entry(regs))
+ current_thread_info()->syscall = -1;
+ } else {
+ tracehook_report_syscall_exit(regs, 0);
}
+
regs->ARM_ip = ip;
return current_thread_info()->syscall;
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index 0340224..26c26f5 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -645,6 +645,8 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
recalc_sigpending();
spin_unlock_irq(&tsk->sighand->siglock);
+ tracehook_signal_handler(sig, info, ka, regs, 0);
+
return 0;
}
--
1.7.5.4.2.g81f75
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 3/3] ARM: support syscall tracing
2011-11-29 16:28 [RFC] ARM support for syscall tracing Steven Walter
2011-11-29 16:28 ` [PATCH 1/3] ARM: add support for the generic syscall.h interface Steven Walter
2011-11-29 16:28 ` [PATCH 2/3] ARM: add TRACEHOOK support Steven Walter
@ 2011-11-29 16:28 ` Steven Walter
2011-11-29 17:24 ` Will Deacon
2011-11-29 17:46 ` Russell King - ARM Linux
2 siblings, 2 replies; 11+ messages in thread
From: Steven Walter @ 2011-11-29 16:28 UTC (permalink / raw)
To: linux-arm-kernel
As specified by ftrace-design.txt, TIF_SYSCALL_TRACEPOINT was added, as
well as NR_syscalls in asm/unistd.h. Additionally, __sys_trace was
modified to call trace_sys_enter and trace_sys_exit when appropriate.
There was previously an assembler variable named NR_syscalls in
entry-common.S. This was renamed NR_syscalls_asm so as not to collide
with NR_syscalls from asm/unistd.h.
Tests #2 - #4 of "perf test" now complete successfully.
Signed-off-by: Steven Walter <stevenrwalter@gmail.com>
---
arch/arm/Kconfig | 1 +
arch/arm/include/asm/thread_info.h | 2 ++
arch/arm/include/asm/unistd.h | 2 ++
arch/arm/kernel/entry-common.S | 14 ++++++++------
arch/arm/kernel/ptrace.c | 24 ++++++++++++++++++------
5 files changed, 31 insertions(+), 12 deletions(-)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 0a93d76..7f0c53b 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -11,6 +11,7 @@ config ARM
select HAVE_OPROFILE if (HAVE_PERF_EVENTS)
select HAVE_ARCH_KGDB
select HAVE_ARCH_TRACEHOOK
+ select HAVE_SYSCALL_TRACEPOINTS
select HAVE_KPROBES if (!XIP_KERNEL && !THUMB2_KERNEL)
select HAVE_KRETPROBES if (HAVE_KPROBES)
select HAVE_FUNCTION_TRACER if (!XIP_KERNEL)
diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h
index 7b5cc8d..17a84b6 100644
--- a/arch/arm/include/asm/thread_info.h
+++ b/arch/arm/include/asm/thread_info.h
@@ -145,6 +145,7 @@ extern void vfp_flush_hwstate(struct thread_info *);
#define TIF_FREEZE 19
#define TIF_RESTORE_SIGMASK 20
#define TIF_SECCOMP 21
+#define TIF_SYSCALL_TRACEPOINT 22
#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
@@ -155,6 +156,7 @@ extern void vfp_flush_hwstate(struct thread_info *);
#define _TIF_FREEZE (1 << TIF_FREEZE)
#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK)
#define _TIF_SECCOMP (1 << TIF_SECCOMP)
+#define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT)
/*
* Change these and you break ASM code in entry-common.S
diff --git a/arch/arm/include/asm/unistd.h b/arch/arm/include/asm/unistd.h
index 2c04ed5..1f23923 100644
--- a/arch/arm/include/asm/unistd.h
+++ b/arch/arm/include/asm/unistd.h
@@ -403,6 +403,8 @@
#define __NR_sendmmsg (__NR_SYSCALL_BASE+374)
#define __NR_setns (__NR_SYSCALL_BASE+375)
+#define NR_syscalls (__NR_setns+1)
+
/*
* The following SWIs are ARM private.
*/
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index b2a27b6..314280d 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -88,6 +88,7 @@ ENTRY(ret_from_fork)
ldr r1, [tsk, #TI_FLAGS] @ check for syscall tracing
mov why, #1
tst r1, #_TIF_SYSCALL_TRACE @ are we tracing syscalls?
+ tsteq r1, #_TIF_SYSCALL_TRACEPOINT
beq ret_slow_syscall
mov r1, sp
mov r0, #1 @ trace exit [IP = 1]
@@ -95,8 +96,8 @@ ENTRY(ret_from_fork)
b ret_slow_syscall
ENDPROC(ret_from_fork)
- .equ NR_syscalls,0
-#define CALL(x) .equ NR_syscalls,NR_syscalls+1
+ .equ NR_syscalls_asm,0
+#define CALL(x) .equ NR_syscalls_asm,NR_syscalls_asm+1
#include "calls.S"
#undef CALL
#define CALL(x) .long x
@@ -443,10 +444,11 @@ ENTRY(vector_swi)
1:
#endif
- tst r10, #_TIF_SYSCALL_TRACE @ are we tracing syscalls?
+ tst r10, #_TIF_SYSCALL_TRACE @ are we tracing syscalls?
+ tsteq r10, #_TIF_SYSCALL_TRACEPOINT
bne __sys_trace
- cmp scno, #NR_syscalls @ check upper syscall limit
+ cmp scno, #NR_syscalls_asm @ check upper syscall limit
adr lr, BSYM(ret_fast_syscall) @ return address
ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine
@@ -471,7 +473,7 @@ __sys_trace:
adr lr, BSYM(__sys_trace_return) @ return address
mov scno, r0 @ syscall number (possibly new)
add r1, sp, #S_R0 + S_OFF @ pointer to regs
- cmp scno, #NR_syscalls @ check upper syscall limit
+ cmp scno, #NR_syscalls_asm @ check upper syscall limit
ldmccia r1, {r0 - r3} @ have to reload r0 - r3
ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine
b 2b
@@ -517,7 +519,7 @@ ENTRY(sys_call_table)
sys_syscall:
bic scno, r0, #__NR_OABI_SYSCALL_BASE
cmp scno, #__NR_syscall - __NR_SYSCALL_BASE
- cmpne scno, #NR_syscalls @ check range
+ cmpne scno, #NR_syscalls_asm @ check range
stmloia sp, {r5, r6} @ shuffle args
movlo r0, r1
movlo r1, r2
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index 1411848..0e2699a 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -28,6 +28,9 @@
#include <asm/system.h>
#include <asm/traps.h>
+#define CREATE_TRACE_POINTS
+#include <trace/events/syscalls.h>
+
#define REG_PC 15
#define REG_PSR 16
/*
@@ -927,7 +930,7 @@ asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno)
{
unsigned long ip;
- if (!test_thread_flag(TIF_SYSCALL_TRACE))
+ if (!test_thread_flag(TIF_SYSCALL_TRACE) && !test_thread_flag(TIF_SYSCALL_TRACEPOINT))
return scno;
/*
@@ -939,11 +942,20 @@ asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno)
current_thread_info()->syscall = scno;
- if (why == 0) {
- if (tracehook_report_syscall_entry(regs))
- current_thread_info()->syscall = -1;
- } else {
- tracehook_report_syscall_exit(regs, 0);
+ if (test_thread_flag(TIF_SYSCALL_TRACE)) {
+ if (why == 0) {
+ if (tracehook_report_syscall_entry(regs))
+ current_thread_info()->syscall = -1;
+ } else {
+ tracehook_report_syscall_exit(regs, 0);
+ }
+ }
+
+ if (test_thread_flag(TIF_SYSCALL_TRACEPOINT)) {
+ if (why == 0)
+ trace_sys_enter(regs, scno);
+ else
+ trace_sys_exit(regs, scno);
}
regs->ARM_ip = ip;
--
1.7.5.4.2.g81f75
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 2/3] ARM: add TRACEHOOK support
2011-11-29 16:28 ` [PATCH 2/3] ARM: add TRACEHOOK support Steven Walter
@ 2011-11-29 17:04 ` Will Deacon
2011-11-29 17:51 ` Steven Walter
0 siblings, 1 reply; 11+ messages in thread
From: Will Deacon @ 2011-11-29 17:04 UTC (permalink / raw)
To: linux-arm-kernel
Hi Steven,
On Tue, Nov 29, 2011 at 04:28:14PM +0000, Steven Walter wrote:
> diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
> index 9726006..1411848 100644
> --- a/arch/arm/kernel/ptrace.c
> +++ b/arch/arm/kernel/ptrace.c
> @@ -22,6 +22,7 @@
> #include <linux/perf_event.h>
> #include <linux/hw_breakpoint.h>
> #include <linux/regset.h>
> +#include <linux/tracehook.h>
>
> #include <asm/pgtable.h>
> #include <asm/system.h>
> @@ -928,8 +929,6 @@ asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno)
>
> if (!test_thread_flag(TIF_SYSCALL_TRACE))
> return scno;
> - if (!(current->ptrace & PT_PTRACED))
> - return scno;
This means that we can potentially corrupt current_thread_info()->syscall
for tasks that aren't being traced. I don't think that matters as it's only
used by ptrace, but worth bearing in mind.
> /*
> * Save IP. IP is used to denote syscall entry/exit:
> @@ -940,19 +939,13 @@ asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno)
>
> current_thread_info()->syscall = scno;
>
> - /* the 0x80 provides a way for the tracing parent to distinguish
> - between a syscall stop and SIGTRAP delivery */
> - ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
> - ? 0x80 : 0));
> - /*
> - * this isn't the same as continuing with a signal, but it will do
> - * for normal use. strace only continues with a signal if the
> - * stopping signal is not SIGTRAP. -brl
> - */
> - if (current->exit_code) {
> - send_sig(current->exit_code, current, 1);
> - current->exit_code = 0;
> + if (why == 0) {
> + if (tracehook_report_syscall_entry(regs))
> + current_thread_info()->syscall = -1;
Why do you set syscall to -1 here? It looks like
tracehook_report_syscall_entry always returns 0, but even so, I'm not sure
what this -1 represents. You could also rewrite this a bit more neatly:
if (why)
tracehook_report_syscall_exit(...);
else
tracehook_report_syscall_entry(...);
> + } else {
> + tracehook_report_syscall_exit(regs, 0);
> }
> +
> regs->ARM_ip = ip;
>
> return current_thread_info()->syscall;
> diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
> index 0340224..26c26f5 100644
> --- a/arch/arm/kernel/signal.c
> +++ b/arch/arm/kernel/signal.c
> @@ -645,6 +645,8 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
> recalc_sigpending();
> spin_unlock_irq(&tsk->sighand->siglock);
>
> + tracehook_signal_handler(sig, info, ka, regs, 0);
> +
This doesn't appear to do anything but I guess that's where it should live.
Will
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 3/3] ARM: support syscall tracing
2011-11-29 16:28 ` [PATCH 3/3] ARM: support syscall tracing Steven Walter
@ 2011-11-29 17:24 ` Will Deacon
2011-11-29 18:02 ` Steven Walter
2011-11-29 17:46 ` Russell King - ARM Linux
1 sibling, 1 reply; 11+ messages in thread
From: Will Deacon @ 2011-11-29 17:24 UTC (permalink / raw)
To: linux-arm-kernel
On Tue, Nov 29, 2011 at 04:28:15PM +0000, Steven Walter wrote:
> diff --git a/arch/arm/include/asm/unistd.h b/arch/arm/include/asm/unistd.h
> index 2c04ed5..1f23923 100644
> --- a/arch/arm/include/asm/unistd.h
> +++ b/arch/arm/include/asm/unistd.h
> @@ -403,6 +403,8 @@
> #define __NR_sendmmsg (__NR_SYSCALL_BASE+374)
> #define __NR_setns (__NR_SYSCALL_BASE+375)
>
> +#define NR_syscalls (__NR_setns+1)
[...]
> - .equ NR_syscalls,0
> -#define CALL(x) .equ NR_syscalls,NR_syscalls+1
> + .equ NR_syscalls_asm,0
> +#define CALL(x) .equ NR_syscalls_asm,NR_syscalls_asm+1
If we need to have two definitions of NR_syscalls, then it's probably best
to define one in terms of the other to ensure they are consistent.
Unfortunately, it looks like we calculate NR_syscalls recursively from the
syscall table. Perhaps you'd be better off with just the #define and have a
sanity check on the table size using that.
> - tst r10, #_TIF_SYSCALL_TRACE @ are we tracing syscalls?
> + tst r10, #_TIF_SYSCALL_TRACE @ are we tracing syscalls?
> + tsteq r10, #_TIF_SYSCALL_TRACEPOINT
> bne __sys_trace
Maybe you could macroise this pattern.
> diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
> index 1411848..0e2699a 100644
> --- a/arch/arm/kernel/ptrace.c
> +++ b/arch/arm/kernel/ptrace.c
> @@ -28,6 +28,9 @@
> #include <asm/system.h>
> #include <asm/traps.h>
>
> +#define CREATE_TRACE_POINTS
> +#include <trace/events/syscalls.h>
[...]
> @@ -939,11 +942,20 @@ asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno)
>
> current_thread_info()->syscall = scno;
>
> - if (why == 0) {
> - if (tracehook_report_syscall_entry(regs))
> - current_thread_info()->syscall = -1;
> - } else {
> - tracehook_report_syscall_exit(regs, 0);
Wait - didn't you just add this code?
Will
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 3/3] ARM: support syscall tracing
2011-11-29 16:28 ` [PATCH 3/3] ARM: support syscall tracing Steven Walter
2011-11-29 17:24 ` Will Deacon
@ 2011-11-29 17:46 ` Russell King - ARM Linux
2011-11-29 18:12 ` Steven Walter
1 sibling, 1 reply; 11+ messages in thread
From: Russell King - ARM Linux @ 2011-11-29 17:46 UTC (permalink / raw)
To: linux-arm-kernel
On Tue, Nov 29, 2011 at 11:28:15AM -0500, Steven Walter wrote:
> diff --git a/arch/arm/include/asm/unistd.h b/arch/arm/include/asm/unistd.h
> index 2c04ed5..1f23923 100644
> --- a/arch/arm/include/asm/unistd.h
> +++ b/arch/arm/include/asm/unistd.h
> @@ -403,6 +403,8 @@
> #define __NR_sendmmsg (__NR_SYSCALL_BASE+374)
> #define __NR_setns (__NR_SYSCALL_BASE+375)
>
> +#define NR_syscalls (__NR_setns+1)
NAK. This is a recipe for it being forgotten to be updated, and for it
to become unsynchronized with what is the _real_ number of syscalls,
which is what is in the assembly code.
You're also exporting it to userspace. It has no business being in
userspace.
Lastly, it's wrong. __NR_SYSCALL_BASE may be 0 or 0x90000 depending on
the ABI selected. If it's 0x90000, will tracepoint stuff work or will it
explode because of a stupidly large table somewhere?
kernel/trace/trace_syscalls.c: for (i = 0; i < NR_syscalls; i++) {
and
kernel/trace/trace_syscalls.c:static DECLARE_BITMAP(enabled_perf_enter_syscalls, NR_syscalls);
kernel/trace/trace_syscalls.c:static DECLARE_BITMAP(enabled_perf_exit_syscalls,NR_syscalls);
all point@this being very wrong.
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 2/3] ARM: add TRACEHOOK support
2011-11-29 17:04 ` Will Deacon
@ 2011-11-29 17:51 ` Steven Walter
0 siblings, 0 replies; 11+ messages in thread
From: Steven Walter @ 2011-11-29 17:51 UTC (permalink / raw)
To: linux-arm-kernel
On Tue, Nov 29, 2011 at 12:04 PM, Will Deacon <will.deacon@arm.com> wrote:
> Hi Steven,
>
> On Tue, Nov 29, 2011 at 04:28:14PM +0000, Steven Walter wrote:
>> diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
>> index 9726006..1411848 100644
>> --- a/arch/arm/kernel/ptrace.c
>> +++ b/arch/arm/kernel/ptrace.c
>> @@ -22,6 +22,7 @@
>> ?#include <linux/perf_event.h>
>> ?#include <linux/hw_breakpoint.h>
>> ?#include <linux/regset.h>
>> +#include <linux/tracehook.h>
>>
>> ?#include <asm/pgtable.h>
>> ?#include <asm/system.h>
>> @@ -928,8 +929,6 @@ asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno)
>>
>> ? ? ? if (!test_thread_flag(TIF_SYSCALL_TRACE))
>> ? ? ? ? ? ? ? return scno;
>> - ? ? if (!(current->ptrace & PT_PTRACED))
>> - ? ? ? ? ? ? return scno;
>
> This means that we can potentially corrupt current_thread_info()->syscall
> for tasks that aren't being traced. I don't think that matters as it's only
> used by ptrace, but worth bearing in mind.
Is it valid for a process to have TIF_SYSCALL_TRACE set but not
PT_PTRACED? Given that they were checking both before, one might
assume so, but I don't really know what that would mean.
>> ? ? ? /*
>> ? ? ? ?* Save IP. ?IP is used to denote syscall entry/exit:
>> @@ -940,19 +939,13 @@ asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno)
>>
>> ? ? ? current_thread_info()->syscall = scno;
>>
>> - ? ? /* the 0x80 provides a way for the tracing parent to distinguish
>> - ? ? ? ?between a syscall stop and SIGTRAP delivery */
>> - ? ? ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
>> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? 0x80 : 0));
>> - ? ? /*
>> - ? ? ?* this isn't the same as continuing with a signal, but it will do
>> - ? ? ?* for normal use. ?strace only continues with a signal if the
>> - ? ? ?* stopping signal is not SIGTRAP. ?-brl
>> - ? ? ?*/
>> - ? ? if (current->exit_code) {
>> - ? ? ? ? ? ? send_sig(current->exit_code, current, 1);
>> - ? ? ? ? ? ? current->exit_code = 0;
>> + ? ? if (why == 0) {
>> + ? ? ? ? ? ? if (tracehook_report_syscall_entry(regs))
>> + ? ? ? ? ? ? ? ? ? ? current_thread_info()->syscall = -1;
>
> Why do you set syscall to -1 here? It looks like
> tracehook_report_syscall_entry always returns 0, but even so, I'm not sure
> what this -1 represents. You could also rewrite this a bit more neatly:
tracehook_report_syscall_entry is marked __must_check, and the comment
says that if it returns non-zero the arch could should abort the
system call. x86 just returns -1 from its trace function in that
case, so I took the same approach. In particular, if we treat -1 as
the system call number, the system call should fail with ENOSYS, which
include/linux/tracehook.h says is acceptable.
> if (why)
> ? ? ? ?tracehook_report_syscall_exit(...);
> else
> ? ? ? ?tracehook_report_syscall_entry(...);
Agreed, will fix
>> + ? ? } else {
>> + ? ? ? ? ? ? tracehook_report_syscall_exit(regs, 0);
>> ? ? ? }
>> +
>> ? ? ? regs->ARM_ip = ip;
>>
>> ? ? ? return current_thread_info()->syscall;
>> diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
>> index 0340224..26c26f5 100644
>> --- a/arch/arm/kernel/signal.c
>> +++ b/arch/arm/kernel/signal.c
>> @@ -645,6 +645,8 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
>> ? ? ? recalc_sigpending();
>> ? ? ? spin_unlock_irq(&tsk->sighand->siglock);
>>
>> + ? ? tracehook_signal_handler(sig, info, ka, regs, 0);
>> +
>
> This doesn't appear to do anything but I guess that's where it should live.
Right, I just added it because arch/Kconfig said to :-)
--
-Steven Walter <stevenrwalter@gmail.com>
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 3/3] ARM: support syscall tracing
2011-11-29 17:24 ` Will Deacon
@ 2011-11-29 18:02 ` Steven Walter
0 siblings, 0 replies; 11+ messages in thread
From: Steven Walter @ 2011-11-29 18:02 UTC (permalink / raw)
To: linux-arm-kernel
(Oops, dropped l-a-k from CC: )
On Tue, Nov 29, 2011 at 12:24 PM, Will Deacon <will.deacon@arm.com> wrote:
> On Tue, Nov 29, 2011 at 04:28:15PM +0000, Steven Walter wrote:
>> diff --git a/arch/arm/include/asm/unistd.h b/arch/arm/include/asm/unistd.h
>> index 2c04ed5..1f23923 100644
>> --- a/arch/arm/include/asm/unistd.h
>> +++ b/arch/arm/include/asm/unistd.h
>> @@ -403,6 +403,8 @@
>> #define __NR_sendmmsg (__NR_SYSCALL_BASE+374)
>> #define __NR_setns (__NR_SYSCALL_BASE+375)
>>
>> +#define NR_syscalls (__NR_setns+1)
>
> [...]
>
>> - .equ NR_syscalls,0
>> -#define CALL(x) .equ NR_syscalls,NR_syscalls+1
>> + .equ NR_syscalls_asm,0
>> +#define CALL(x) .equ NR_syscalls_asm,NR_syscalls_asm+1
>
> If we need to have two definitions of NR_syscalls, then it's probably best
> to define one in terms of the other to ensure they are consistent.
> Unfortunately, it looks like we calculate NR_syscalls recursively from the
> syscall table. Perhaps you'd be better off with just the #define and have a
> sanity check on the table size using that.
Yeah I'll have to do something about this. Russell also raised
concern about it.
>> - tst r10, #_TIF_SYSCALL_TRACE @ are we tracing syscalls?
>> + tst r10, #_TIF_SYSCALL_TRACE @ are we tracing syscalls?
>> + tsteq r10, #_TIF_SYSCALL_TRACEPOINT
>> bne __sys_trace
>
> Maybe you could macroise this pattern.
Good idea.
>> diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
>> index 1411848..0e2699a 100644
>> --- a/arch/arm/kernel/ptrace.c
>> +++ b/arch/arm/kernel/ptrace.c
>> @@ -28,6 +28,9 @@
>> #include <asm/system.h>
>> #include <asm/traps.h>
>>
>> +#define CREATE_TRACE_POINTS
>> +#include <trace/events/syscalls.h>
>
> [...]
>
>> @@ -939,11 +942,20 @@ asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno)
>>
>> current_thread_info()->syscall = scno;
>>
>> - if (why == 0) {
>> - if (tracehook_report_syscall_entry(regs))
>> - current_thread_info()->syscall = -1;
>> - } else {
>> - tracehook_report_syscall_exit(regs, 0);
>
> Wait - didn't you just add this code?
Indeed. It's not going away, just getting indented. Previously we
couldn't get to that line unless TIF_SYSCALL_TRACE. Now, all we know
is TIF_SYSCALL_TRACE || TIF_SYSCALL_TRACEPOINT, so I have to check
which.
--
-Steven Walter <stevenrwalter@gmail.com>
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 3/3] ARM: support syscall tracing
2011-11-29 17:46 ` Russell King - ARM Linux
@ 2011-11-29 18:12 ` Steven Walter
2011-11-29 21:55 ` Russell King - ARM Linux
0 siblings, 1 reply; 11+ messages in thread
From: Steven Walter @ 2011-11-29 18:12 UTC (permalink / raw)
To: linux-arm-kernel
Thanks for your comments, responses below
On Tue, Nov 29, 2011 at 12:46 PM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Tue, Nov 29, 2011 at 11:28:15AM -0500, Steven Walter wrote:
>> diff --git a/arch/arm/include/asm/unistd.h b/arch/arm/include/asm/unistd.h
>> index 2c04ed5..1f23923 100644
>> --- a/arch/arm/include/asm/unistd.h
>> +++ b/arch/arm/include/asm/unistd.h
>> @@ -403,6 +403,8 @@
>> ?#define __NR_sendmmsg ? ? ? ? ? ? ? ? ? ? ? ?(__NR_SYSCALL_BASE+374)
>> ?#define __NR_setns ? ? ? ? ? ? ? ? ? (__NR_SYSCALL_BASE+375)
>>
>> +#define NR_syscalls (__NR_setns+1)
>
> NAK. ?This is a recipe for it being forgotten to be updated, and for it
> to become unsynchronized with what is the _real_ number of syscalls,
> which is what is in the assembly code.
Yes, I like how the assembler counts the number of syscalls for you.
However, every other architecture uses either a bare number or
__NR_last_syscall+1 for defining NR_syscalls.
> You're also exporting it to userspace. ?It has no business being in
> userspace.
That was unintentional, I'll fix.
> Lastly, it's wrong. ?__NR_SYSCALL_BASE may be 0 or 0x90000 depending on
> the ABI selected. ?If it's 0x90000, will tracepoint stuff work or will it
> explode because of a stupidly large table somewhere?
Right you are. Didn't consider that. Does that mean that
syscall_get_nr() should return the offset from __NR_SYSCALL_BASE, so
that it will be strictly less than NR_syscalls?
> kernel/trace/trace_syscalls.c: ? ? ?for (i = 0; i < NR_syscalls; i++) {
>
> and
>
> kernel/trace/trace_syscalls.c:static DECLARE_BITMAP(enabled_perf_enter_syscalls, NR_syscalls);
> kernel/trace/trace_syscalls.c:static DECLARE_BITMAP(enabled_perf_exit_syscalls,NR_syscalls);
>
> all point at this being very wrong.
Initially I was going to assign the assembler version of NR_syscalls
to a symbol which could be referenced from C. However, putting the C
declaration for the variable in unistd.h made the assembler unhappy.
Is it kosher to have C stuff in unistd.h? Since there was no prior
example of it, I assumed not. However, perhaps I could just hide it
from the assembler with some kind of #ifdef?
Thanks again
--
-Steven Walter <stevenrwalter@gmail.com>
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 3/3] ARM: support syscall tracing
2011-11-29 18:12 ` Steven Walter
@ 2011-11-29 21:55 ` Russell King - ARM Linux
0 siblings, 0 replies; 11+ messages in thread
From: Russell King - ARM Linux @ 2011-11-29 21:55 UTC (permalink / raw)
To: linux-arm-kernel
On Tue, Nov 29, 2011 at 01:12:50PM -0500, Steven Walter wrote:
> Yes, I like how the assembler counts the number of syscalls for you.
> However, every other architecture uses either a bare number or
> __NR_last_syscall+1 for defining NR_syscalls.
>
> > You're also exporting it to userspace. ?It has no business being in
> > userspace.
>
> That was unintentional, I'll fix.
>
> > Lastly, it's wrong. ?__NR_SYSCALL_BASE may be 0 or 0x90000 depending on
> > the ABI selected. ?If it's 0x90000, will tracepoint stuff work or will it
> > explode because of a stupidly large table somewhere?
>
> Right you are. Didn't consider that. Does that mean that
> syscall_get_nr() should return the offset from __NR_SYSCALL_BASE, so
> that it will be strictly less than NR_syscalls?
strace sees the 0x90000 offset today, so tracehook is going to be
compatible with our existing APIs, tracehook needs to keep seeing
that offset.
However, I suspect that's incompatible with tracehook as it stands
today - especially when we might be running a kernel with OABI compat
support enabled (which means you'll get 0x90000+ syscalls for OABI and
0+ syscalls for EABI.)
> > kernel/trace/trace_syscalls.c: ? ? ?for (i = 0; i < NR_syscalls; i++) {
> >
> > and
> >
> > kernel/trace/trace_syscalls.c:static DECLARE_BITMAP(enabled_perf_enter_syscalls, NR_syscalls);
> > kernel/trace/trace_syscalls.c:static DECLARE_BITMAP(enabled_perf_exit_syscalls,NR_syscalls);
> >
> > all point at this being very wrong.
>
> Initially I was going to assign the assembler version of NR_syscalls
> to a symbol which could be referenced from C. However, putting the C
> declaration for the variable in unistd.h made the assembler unhappy.
> Is it kosher to have C stuff in unistd.h? Since there was no prior
> example of it, I assumed not. However, perhaps I could just hide it
> from the assembler with some kind of #ifdef?
#ifndef __ASSEMBLY__
but, as I say, the number of syscalls which the kernel implements is
defined by the size of the table in calls.S, not by the list in
unistd.h. We may allocate a number and put it in unistd.h to reserve
it before we have a final implementation.
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2011-11-29 21:55 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-11-29 16:28 [RFC] ARM support for syscall tracing Steven Walter
2011-11-29 16:28 ` [PATCH 1/3] ARM: add support for the generic syscall.h interface Steven Walter
2011-11-29 16:28 ` [PATCH 2/3] ARM: add TRACEHOOK support Steven Walter
2011-11-29 17:04 ` Will Deacon
2011-11-29 17:51 ` Steven Walter
2011-11-29 16:28 ` [PATCH 3/3] ARM: support syscall tracing Steven Walter
2011-11-29 17:24 ` Will Deacon
2011-11-29 18:02 ` Steven Walter
2011-11-29 17:46 ` Russell King - ARM Linux
2011-11-29 18:12 ` Steven Walter
2011-11-29 21:55 ` Russell King - ARM Linux
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).