* [PATCH] utrace: remove indirections
@ 2007-04-18 18:03 Christoph Hellwig
2007-04-30 4:02 ` Roland McGrath
0 siblings, 1 reply; 2+ messages in thread
From: Christoph Hellwig @ 2007-04-18 18:03 UTC (permalink / raw)
To: akpm, roland, linux-kernel
Currently generic code calls into tracehook_* which then alls into
utrace_* to do the actual work. With utrace as the new singing dancing
framework there's little point in that, and readability would be greatly
improved by getting rid of this. The few places where tracehook_*
was more than a one-liner and used in multiple places in arch code
I renamed the call to utrace_*.
Also kill the CONFIG_UTRACE config option, there's very little reason
in not having a core debugging mechanisms, and this allows to get rid
of another layer of wrapping again.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Index: linux-2.6/arch/arm/kernel/ptrace.c
===================================================================
--- linux-2.6.orig/arch/arm/kernel/ptrace.c 2007-04-13 15:05:11.000000000 +0200
+++ linux-2.6/arch/arm/kernel/ptrace.c 2007-04-13 15:37:11.000000000 +0200
@@ -820,7 +820,7 @@ asmlinkage int syscall_trace(int why, st
ip = regs->ARM_ip;
regs->ARM_ip = why;
- tracehook_report_syscall(regs, why);
+ utrace_report_syscall(regs, why);
regs->ARM_ip = ip;
}
Index: linux-2.6/arch/arm26/kernel/ptrace.c
===================================================================
--- linux-2.6.orig/arch/arm26/kernel/ptrace.c 2007-04-13 15:05:11.000000000 +0200
+++ linux-2.6/arch/arm26/kernel/ptrace.c 2007-04-13 15:37:08.000000000 +0200
@@ -661,7 +661,7 @@ asmlinkage void syscall_trace(int why, s
ip = regs->ARM_ip;
regs->ARM_ip = why;
- tracehook_report_syscall(regs, why);
+ utrace_report_syscall(regs, why);
regs->ARM_ip = ip;
}
Index: linux-2.6/arch/frv/kernel/ptrace.c
===================================================================
--- linux-2.6.orig/arch/frv/kernel/ptrace.c 2007-04-13 15:05:11.000000000 +0200
+++ linux-2.6/arch/frv/kernel/ptrace.c 2007-04-13 15:37:18.000000000 +0200
@@ -706,5 +706,5 @@ asmlinkage void do_syscall_trace(int lea
else
__frame->__status |= REG__STATUS_SYSC_ENTRY;
- tracehook_report_syscall(regs, leaving);
+ utrace_report_syscall(regs, leaving);
}
Index: linux-2.6/arch/i386/kernel/ptrace.c
===================================================================
--- linux-2.6.orig/arch/i386/kernel/ptrace.c 2007-04-13 15:05:11.000000000 +0200
+++ linux-2.6/arch/i386/kernel/ptrace.c 2007-04-13 15:58:53.000000000 +0200
@@ -804,11 +804,10 @@ void do_syscall_trace(struct pt_regs *re
audit_syscall_exit(AUDITSC_RESULT(regs->eax), regs->eax);
if (test_thread_flag(TIF_SYSCALL_TRACE))
- tracehook_report_syscall(regs, entryexit);
+ utrace_report_syscall(regs, entryexit);
if (test_thread_flag(TIF_SINGLESTEP) && entryexit) {
send_sigtrap(current, regs, 0); /* XXX */
- tracehook_report_syscall_step(regs);
}
if (unlikely(current->audit_context) && !entryexit)
Index: linux-2.6/arch/i386/kernel/signal.c
===================================================================
--- linux-2.6.orig/arch/i386/kernel/signal.c 2007-04-13 15:35:36.000000000 +0200
+++ linux-2.6/arch/i386/kernel/signal.c 2007-04-13 15:35:46.000000000 +0200
@@ -543,7 +543,7 @@ handle_signal(unsigned long sig, siginfo
* handler too.
*/
regs->eflags &= ~TF_MASK;
- tracehook_report_handle_signal(sig, ka, oldset, regs);
+ utrace_report_handle_signal(sig, ka, oldset, regs);
}
return ret;
Index: linux-2.6/arch/ia64/ia32/sys_ia32.c
===================================================================
--- linux-2.6.orig/arch/ia64/ia32/sys_ia32.c 2007-04-13 15:15:29.000000000 +0200
+++ linux-2.6/arch/ia64/ia32/sys_ia32.c 2007-04-13 15:58:53.000000000 +0200
@@ -1869,7 +1869,6 @@ sys32_ptrace (int request, pid_t pid, un
}
#endif
-#ifdef CONFIG_UTRACE
typedef struct utrace_get {
void *kbuf;
void __user *ubuf;
@@ -2339,7 +2338,6 @@ const struct utrace_regset_view utrace_i
.regsets = ia32_regsets, .n = ARRAY_SIZE(ia32_regsets)
};
EXPORT_SYMBOL_GPL(utrace_ia32_view);
-#endif
#ifdef CONFIG_PTRACE
/*
Index: linux-2.6/arch/ia64/kernel/ptrace.c
===================================================================
--- linux-2.6.orig/arch/ia64/kernel/ptrace.c 2007-04-13 15:05:11.000000000 +0200
+++ linux-2.6/arch/ia64/kernel/ptrace.c 2007-04-13 15:58:53.000000000 +0200
@@ -726,7 +726,7 @@ syscall_trace_enter (long arg0, long arg
struct pt_regs regs)
{
if (test_thread_flag(TIF_SYSCALL_TRACE))
- tracehook_report_syscall(®s, 0);
+ utrace_report_syscall(®s, 0);
if (unlikely(current->audit_context)) {
long syscall;
@@ -762,17 +762,14 @@ syscall_trace_leave (long arg0, long arg
}
if (test_thread_flag(TIF_SYSCALL_TRACE))
- tracehook_report_syscall(®s, 1);
+ utrace_report_syscall(®s, 1);
if (test_thread_flag(TIF_SINGLESTEP)) {
force_sig(SIGTRAP, current); /* XXX */
- tracehook_report_syscall_step(®s);
}
}
-#ifdef CONFIG_UTRACE
-
/* Utrace implementation starts here */
typedef struct utrace_get {
@@ -1552,9 +1549,6 @@ const struct utrace_regset_view utrace_i
};
EXPORT_SYMBOL_GPL(utrace_ia64_native);
-#endif /* CONFIG_UTRACE */
-
-
#ifdef CONFIG_PTRACE
#define WORD(member, num) \
Index: linux-2.6/arch/ia64/kernel/signal.c
===================================================================
--- linux-2.6.orig/arch/ia64/kernel/signal.c 2007-04-13 15:35:36.000000000 +0200
+++ linux-2.6/arch/ia64/kernel/signal.c 2007-04-13 15:35:58.000000000 +0200
@@ -472,7 +472,7 @@ handle_signal (unsigned long sig, struct
recalc_sigpending();
spin_unlock_irq(¤t->sighand->siglock);
- tracehook_report_handle_signal(sig, ka, oldset, &scr->pt);
+ utrace_report_handle_signal(sig, ka, oldset, &scr->pt);
return 1;
}
Index: linux-2.6/arch/mips/kernel/ptrace.c
===================================================================
--- linux-2.6.orig/arch/mips/kernel/ptrace.c 2007-04-13 15:05:11.000000000 +0200
+++ linux-2.6/arch/mips/kernel/ptrace.c 2007-04-13 15:37:59.000000000 +0200
@@ -488,7 +488,7 @@ asmlinkage void do_syscall_trace(struct
regs->regs[2]);
if (test_thread_flag(TIF_SYSCALL_TRACE))
- tracehook_report_syscall(regs, entryexit);
+ utrace_report_syscall(regs, entryexit);
if (unlikely(current->audit_context) && !entryexit)
audit_syscall_entry(audit_arch(), regs->regs[2],
Index: linux-2.6/arch/powerpc/kernel/ptrace.c
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/ptrace.c 2007-04-13 15:05:11.000000000 +0200
+++ linux-2.6/arch/powerpc/kernel/ptrace.c 2007-04-13 15:58:53.000000000 +0200
@@ -710,7 +710,7 @@ void do_syscall_trace_enter(struct pt_re
secure_computing(regs->gpr[0]);
if (test_thread_flag(TIF_SYSCALL_TRACE))
- tracehook_report_syscall(regs, 0);
+ utrace_report_syscall(regs, 0);
if (unlikely(current->audit_context)) {
#ifdef CONFIG_PPC64
@@ -737,10 +737,9 @@ void do_syscall_trace_leave(struct pt_re
regs->result);
if (test_thread_flag(TIF_SYSCALL_TRACE))
- tracehook_report_syscall(regs, 1);
+ utrace_report_syscall(regs, 1);
if (test_thread_flag(TIF_SINGLESTEP)) {
force_sig(SIGTRAP, current); /* XXX */
- tracehook_report_syscall_step(regs);
}
}
Index: linux-2.6/arch/powerpc/kernel/signal_32.c
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/signal_32.c 2007-04-13 15:35:36.000000000 +0200
+++ linux-2.6/arch/powerpc/kernel/signal_32.c 2007-04-13 15:35:55.000000000 +0200
@@ -1280,7 +1280,7 @@ no_signal:
if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
- tracehook_report_handle_signal(signr, &ka, oldset, regs);
+ utrace_report_handle_signal(signr, &ka, oldset, regs);
}
return ret;
Index: linux-2.6/arch/powerpc/kernel/signal_64.c
===================================================================
--- linux-2.6.orig/arch/powerpc/kernel/signal_64.c 2007-04-13 15:35:36.000000000 +0200
+++ linux-2.6/arch/powerpc/kernel/signal_64.c 2007-04-13 15:36:05.000000000 +0200
@@ -461,7 +461,7 @@ static int handle_signal(unsigned long s
recalc_sigpending();
spin_unlock_irq(¤t->sighand->siglock);
- tracehook_report_handle_signal(sig, ka, oldset, regs);
+ utrace_report_handle_signal(sig, ka, oldset, regs);
}
return ret;
Index: linux-2.6/arch/s390/kernel/compat_signal.c
===================================================================
--- linux-2.6.orig/arch/s390/kernel/compat_signal.c 2007-04-13 15:35:36.000000000 +0200
+++ linux-2.6/arch/s390/kernel/compat_signal.c 2007-04-13 15:36:08.000000000 +0200
@@ -581,7 +581,7 @@ handle_signal32(unsigned long sig, struc
recalc_sigpending();
spin_unlock_irq(¤t->sighand->siglock);
- tracehook_report_handle_signal(sig, ka, oldset, regs);
+ utrace_report_handle_signal(sig, ka, oldset, regs);
}
return ret;
Index: linux-2.6/arch/s390/kernel/ptrace.c
===================================================================
--- linux-2.6.orig/arch/s390/kernel/ptrace.c 2007-04-13 15:05:11.000000000 +0200
+++ linux-2.6/arch/s390/kernel/ptrace.c 2007-04-13 15:58:53.000000000 +0200
@@ -726,7 +726,7 @@ syscall_trace(struct pt_regs *regs, int
audit_syscall_exit(AUDITSC_RESULT(regs->gprs[2]), regs->gprs[2]);
if (test_thread_flag(TIF_SYSCALL_TRACE)) {
- tracehook_report_syscall(regs, entryexit);
+ utrace_report_syscall(regs, entryexit);
/*
* If the debugger has set an invalid system call number,
Index: linux-2.6/arch/s390/kernel/signal.c
===================================================================
--- linux-2.6.orig/arch/s390/kernel/signal.c 2007-04-13 15:35:37.000000000 +0200
+++ linux-2.6/arch/s390/kernel/signal.c 2007-04-13 15:36:10.000000000 +0200
@@ -397,7 +397,7 @@ handle_signal(unsigned long sig, struct
recalc_sigpending();
spin_unlock_irq(¤t->sighand->siglock);
- tracehook_report_handle_signal(sig, ka, oldset, regs);
+ utrace_report_handle_signal(sig, ka, oldset, regs);
}
return ret;
Index: linux-2.6/arch/s390/kernel/traps.c
===================================================================
--- linux-2.6.orig/arch/s390/kernel/traps.c 2007-04-13 15:22:41.000000000 +0200
+++ linux-2.6/arch/s390/kernel/traps.c 2007-04-13 15:23:30.000000000 +0200
@@ -360,7 +360,7 @@ void __kprobes do_single_step(struct pt_
SIGTRAP) == NOTIFY_STOP){
return;
}
- if (tracehook_consider_fatal_signal(current, SIGTRAP))
+ if (utrace_consider_fatal_signal(current, SIGTRAP))
force_sig(SIGTRAP, current);
}
@@ -461,7 +461,7 @@ static void illegal_op(struct pt_regs *
if (get_user(*((__u16 *) opcode), (__u16 __user *) location))
return;
if (*((__u16 *) opcode) == S390_BREAKPOINT_U16) {
- if (tracehook_consider_fatal_signal(current, SIGTRAP))
+ if (utrace_consider_fatal_signal(current, SIGTRAP))
force_sig(SIGTRAP, current);
else
signal = SIGILL;
Index: linux-2.6/arch/sparc64/kernel/ptrace.c
===================================================================
--- linux-2.6.orig/arch/sparc64/kernel/ptrace.c 2007-04-13 15:05:12.000000000 +0200
+++ linux-2.6/arch/sparc64/kernel/ptrace.c 2007-04-13 15:58:53.000000000 +0200
@@ -789,7 +789,7 @@ asmlinkage void syscall_trace(struct pt_
}
if (test_thread_flag(TIF_SYSCALL_TRACE))
- tracehook_report_syscall(regs, syscall_exit_p);
+ utrace_report_syscall(regs, syscall_exit_p);
if (unlikely(current->audit_context) && !syscall_exit_p)
audit_syscall_entry((test_thread_flag(TIF_32BIT) ?
Index: linux-2.6/arch/sparc64/kernel/signal.c
===================================================================
--- linux-2.6.orig/arch/sparc64/kernel/signal.c 2007-04-13 15:35:37.000000000 +0200
+++ linux-2.6/arch/sparc64/kernel/signal.c 2007-04-13 15:36:12.000000000 +0200
@@ -492,7 +492,7 @@ static inline void handle_signal(unsigne
sigaddset(¤t->blocked,signr);
recalc_sigpending();
spin_unlock_irq(¤t->sighand->siglock);
- tracehook_report_handle_signal(signr, ka, oldset, regs);
+ utrace_report_handle_signal(signr, ka, oldset, regs);
}
static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
Index: linux-2.6/arch/sparc64/kernel/signal32.c
===================================================================
--- linux-2.6.orig/arch/sparc64/kernel/signal32.c 2007-04-13 15:35:37.000000000 +0200
+++ linux-2.6/arch/sparc64/kernel/signal32.c 2007-04-13 15:36:22.000000000 +0200
@@ -1238,7 +1238,7 @@ static inline void handle_signal32(unsig
sigaddset(¤t->blocked,signr);
recalc_sigpending();
spin_unlock_irq(¤t->sighand->siglock);
- tracehook_report_handle_signal(signr, ka, oldset, regs);
+ utrace_report_handle_signal(signr, ka, oldset, regs);
}
static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs,
Index: linux-2.6/arch/um/kernel/ptrace.c
===================================================================
--- linux-2.6.orig/arch/um/kernel/ptrace.c 2007-04-13 15:05:12.000000000 +0200
+++ linux-2.6/arch/um/kernel/ptrace.c 2007-04-13 15:38:20.000000000 +0200
@@ -52,12 +52,10 @@ void do_syscall_trace(struct pt_regs *re
UPT_SYSCALL_RET(®s->regs));
if (test_thread_flag(TIF_SYSCALL_TRACE))
- tracehook_report_syscall(regs, entryexit);
+ utrace_report_syscall(regs, entryexit);
- if (test_thread_flag(TIF_SINGLESTEP) && entryexit) {
+ if (test_thread_flag(TIF_SINGLESTEP) && entryexit)
send_sigtrap(current, regs, 0); /* XXX */
- tracehook_report_syscall_step(regs);
- }
if (unlikely(current->audit_context) && !entryexit)
audit_syscall_entry(HOST_AUDIT_ARCH,
Index: linux-2.6/arch/um/kernel/signal.c
===================================================================
--- linux-2.6.orig/arch/um/kernel/signal.c 2007-04-13 15:35:37.000000000 +0200
+++ linux-2.6/arch/um/kernel/signal.c 2007-04-13 15:36:24.000000000 +0200
@@ -95,7 +95,7 @@ static int handle_signal(struct pt_regs
recalc_sigpending();
spin_unlock_irq(¤t->sighand->siglock);
- tracehook_report_handle_signal(signr, ka, oldset, regs);
+ utrace_report_handle_signal(signr, ka, oldset, regs);
}
return err;
Index: linux-2.6/arch/x86_64/kernel/ptrace.c
===================================================================
--- linux-2.6.orig/arch/x86_64/kernel/ptrace.c 2007-04-13 15:05:12.000000000 +0200
+++ linux-2.6/arch/x86_64/kernel/ptrace.c 2007-04-13 15:58:53.000000000 +0200
@@ -758,7 +758,7 @@ asmlinkage void syscall_trace_enter(stru
secure_computing(regs->orig_rax);
if (test_thread_flag(TIF_SYSCALL_TRACE))
- tracehook_report_syscall(regs, 0);
+ utrace_report_syscall(regs, 0);
if (unlikely(current->audit_context)) {
if (test_thread_flag(TIF_IA32)) {
@@ -781,10 +781,8 @@ asmlinkage void syscall_trace_leave(stru
audit_syscall_exit(AUDITSC_RESULT(regs->rax), regs->rax);
if (test_thread_flag(TIF_SYSCALL_TRACE))
- tracehook_report_syscall(regs, 1);
+ utrace_report_syscall(regs, 1);
- if (test_thread_flag(TIF_SINGLESTEP)) {
+ if (test_thread_flag(TIF_SINGLESTEP))
force_sig(SIGTRAP, current); /* XXX */
- tracehook_report_syscall_step(regs);
- }
}
Index: linux-2.6/arch/x86_64/kernel/signal.c
===================================================================
--- linux-2.6.orig/arch/x86_64/kernel/signal.c 2007-04-13 15:35:37.000000000 +0200
+++ linux-2.6/arch/x86_64/kernel/signal.c 2007-04-13 15:36:26.000000000 +0200
@@ -380,7 +380,7 @@ handle_signal(unsigned long sig, siginfo
* handler too.
*/
regs->eflags &= ~TF_MASK;
- tracehook_report_handle_signal(sig, ka, oldset, regs);
+ utrace_report_handle_signal(sig, ka, oldset, regs);
}
return ret;
Index: linux-2.6/arch/x86_64/mm/fault.c
===================================================================
--- linux-2.6.orig/arch/x86_64/mm/fault.c 2007-04-13 15:22:41.000000000 +0200
+++ linux-2.6/arch/x86_64/mm/fault.c 2007-04-13 15:23:37.000000000 +0200
@@ -225,7 +225,7 @@ int unhandled_signal(struct task_struct
{
if (is_init(tsk))
return 1;
- if (tracehook_consider_fatal_signal(tsk, sig))
+ if (utrace_consider_fatal_signal(tsk, sig))
return 0;
return (tsk->sighand->action[sig-1].sa.sa_handler == SIG_IGN) ||
(tsk->sighand->action[sig-1].sa.sa_handler == SIG_DFL);
Index: linux-2.6/fs/exec.c
===================================================================
--- linux-2.6.orig/fs/exec.c 2007-04-13 14:59:56.000000000 +0200
+++ linux-2.6/fs/exec.c 2007-04-13 15:14:47.000000000 +0200
@@ -953,7 +953,11 @@ EXPORT_SYMBOL(prepare_binprm);
static int unsafe_exec(struct task_struct *p)
{
- int unsafe = tracehook_unsafe_exec(p);
+ int unsafe = 0;
+
+ if (p->utrace_flags)
+ unsafe = utrace_unsafe_exec(p);
+
if (atomic_read(&p->fs->count) > 1 ||
atomic_read(&p->files->count) > 1 ||
atomic_read(&p->sighand->count) > 1)
@@ -1078,7 +1082,8 @@ int search_binary_handler(struct linux_b
bprm->file = NULL;
current->did_exec = 1;
proc_exec_connector(current);
- tracehook_report_exec(bprm, regs);
+ if (current->utrace_flags & UTRACE_EVENT(EXEC))
+ utrace_report_exec(bprm, regs);
return retval;
}
read_lock(&binfmt_lock);
Index: linux-2.6/fs/proc/array.c
===================================================================
--- linux-2.6.orig/fs/proc/array.c 2007-04-13 15:24:17.000000000 +0200
+++ linux-2.6/fs/proc/array.c 2007-04-13 15:25:05.000000000 +0200
@@ -166,7 +166,7 @@ static inline char * task_state(struct t
struct fdtable *fdt = NULL;
rcu_read_lock();
- tracer = tracehook_tracer_task(p);
+ tracer = p->utrace_flags ? utrace_tracer_task(p) : NULL;
tracer_pid = tracer == NULL ? 0 : tracer->pid;
buffer += sprintf(buffer,
Index: linux-2.6/fs/proc/base.c
===================================================================
--- linux-2.6.orig/fs/proc/base.c 2007-04-13 15:26:32.000000000 +0200
+++ linux-2.6/fs/proc/base.c 2007-04-13 15:30:44.000000000 +0200
@@ -539,6 +539,20 @@ static const struct file_operations proc
.read = proc_info_read,
};
+/*
+ * Return nonzero if the current task should be allowed to use
+ * access_process_vm on the given task.
+ */
+static int allow_access_process_vm(struct task_struct *tsk)
+{
+ if (tsk == current)
+ return 1;
+ if (tsk->utrace_flags)
+ return utrace_allow_access_process_vm(tsk);
+ return 0;
+}
+
+
static int mem_open(struct inode* inode, struct file* file)
{
file->private_data = (void*)((long)current->self_exec_id);
@@ -557,8 +571,7 @@ static ssize_t mem_read(struct file * fi
if (!task)
goto out_no_task;
- if (!tracehook_allow_access_process_vm(task)
- || !ptrace_may_attach(task))
+ if (!allow_access_process_vm(task) || !ptrace_may_attach(task))
goto out;
ret = -ENOMEM;
@@ -584,8 +597,8 @@ static ssize_t mem_read(struct file * fi
this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count;
retval = access_process_vm(task, src, page, this_len, 0);
- if (!retval || !tracehook_allow_access_process_vm(task)
- || !ptrace_may_attach(task)) {
+ if (!retval || !allow_access_process_vm(task) ||
+ !ptrace_may_attach(task)) {
if (!ret)
ret = -EIO;
break;
@@ -629,8 +642,7 @@ static ssize_t mem_write(struct file * f
if (!task)
goto out_no_task;
- if (!tracehook_allow_access_process_vm(task)
- || !ptrace_may_attach(task))
+ if (!allow_access_process_vm(task) || !ptrace_may_attach(task))
goto out;
copied = -ENOMEM;
Index: linux-2.6/include/linux/sched.h
===================================================================
--- linux-2.6.orig/include/linux/sched.h 2007-04-13 15:16:21.000000000 +0200
+++ linux-2.6/include/linux/sched.h 2007-04-13 15:16:25.000000000 +0200
@@ -941,10 +941,8 @@ struct task_struct {
struct audit_context *audit_context;
seccomp_t seccomp;
-#ifdef CONFIG_UTRACE
struct utrace *utrace;
unsigned long utrace_flags;
-#endif
/* Thread group tracking */
u32 parent_exec_id;
Index: linux-2.6/include/linux/tracehook.h
===================================================================
--- linux-2.6.orig/include/linux/tracehook.h 2007-04-13 14:45:28.000000000 +0200
+++ linux-2.6/include/linux/tracehook.h 2007-04-13 15:39:32.000000000 +0200
@@ -69,12 +69,12 @@ struct pt_regs;
* should be one that can be evaluated in modules, i.e. uses exported symbols.
*
* Control system call tracing. When enabled a syscall entry or exit
- * produces a call to tracehook_report_syscall, below.
+ * produces a call to utrace_report_syscall, below.
*
* void tracehook_enable_syscall_trace(struct task_struct *tsk);
* void tracehook_disable_syscall_trace(struct task_struct *tsk);
*
- * When stopped in tracehook_report_syscall for syscall entry,
+ * When stopped in utrace_report_syscall for syscall entry,
* abort the syscall so no kernel function is called.
* If the register state was not otherwise updated before,
* this produces an -ENOSYS error return as for an invalid syscall number.
@@ -299,355 +299,5 @@ utrace_regset_copyin_ignore(unsigned int
return 0;
}
-/**/
-
-
-/***
- ***
- *** Following are entry points from core code, where the user debugging
- *** support can affect the normal behavior. The locking situation is
- *** described for each call.
- ***
- ***/
-
-
-/*
- * Called in copy_process when setting up the copied task_struct,
- * with tasklist_lock held for writing.
- */
-static inline void tracehook_init_task(struct task_struct *child)
-{
- utrace_init_task(child);
-}
-
-/*
- * Called from release_task, no locks held.
- * After this, there should be no tracing entanglements.
- */
-static inline void tracehook_release_task(struct task_struct *p)
-{
- smp_mb();
- if (tsk_utrace_struct(p) != NULL)
- utrace_release_task(p);
-}
-
-/*
- * Return nonzero to trigger a BUG_ON crash in release_task.
- * This should verify that there is no tracing-related state
- * still affecting the task_struct about to be released.
- * Called with tasklist_lock held for writing.
- */
-static inline int tracehook_check_released(struct task_struct *p)
-{
- return unlikely(tsk_utrace_struct(p) != NULL);
-}
-
-/*
- * do_notify_parent_cldstop calls this when it's about to generate a SIGCHLD
- * for a job control stop. Return nonzero to prevent that signal generation.
- * Called with tasklist_lock held for reading, sometimes with irqs disabled.
- */
-static inline int tracehook_notify_cldstop(struct task_struct *tsk,
- const siginfo_t *info)
-{
- return (tsk_utrace_flags(tsk) & UTRACE_ACTION_NOREAP);
-}
-
-/*
- * exit_notify calls this with tasklist_lock held for writing.
- * Return nonzero to prevent any normal SIGCHLD generation for this
- * thread's death (i.e. when it is not ignored and its thread group is
- * empty). This call must set *noreap to 0, or to 1 to force this thread
- * to become a zombie when it would normally reap itself.
- * The *death_cookie is passed to tracehook_report_death (below).
- */
-static inline int tracehook_notify_death(struct task_struct *tsk,
- int *noreap, void **death_cookie)
-{
- *death_cookie = tsk_utrace_struct(tsk);
- if (tsk_utrace_flags(tsk) & UTRACE_ACTION_NOREAP) {
- *noreap = 1;
- return 1;
- }
- *noreap = 0;
- return 0;
-}
-
-/*
- * Return zero iff tracing doesn't care to examine this fatal signal,
- * so it can short-circuit normal delivery directly to a group exit.
- * Called with tsk->sighand->siglock held.
- */
-static inline int tracehook_consider_fatal_signal(struct task_struct *tsk,
- int sig)
-{
- return (tsk_utrace_flags(tsk) & (UTRACE_EVENT(SIGNAL_TERM)
- | UTRACE_EVENT(SIGNAL_CORE)));
-}
-
-/*
- * Return zero iff tracing doesn't care to examine this ignored signal,
- * so it can short-circuit normal delivery and never even get queued.
- * Either the handler is SIG_DFL and sig's default is ignore, or it's SIG_IGN.
- * Called with tsk->sighand->siglock held.
- */
-static inline int tracehook_consider_ignored_signal(struct task_struct *tsk,
- int sig,
- void __user *handler)
-{
- return (tsk_utrace_flags(tsk) & UTRACE_EVENT(SIGNAL_IGN));
-}
-
-
-/*
- * Called with the siglock held when computing tsk's signal_pending flag.
- * Return nonzero to force the signal_pending flag on, so that
- * tracehook_induce_signal will be called before the next return to user mode.
- */
-static inline int tracehook_induce_sigpending(struct task_struct *tsk)
-{
- return unlikely(tsk_utrace_flags(tsk) & UTRACE_ACTION_QUIESCE);
-}
-
-/*
- * Called with the siglock held before dequeuing pending signals.
- * Return zero to check for a real pending signal normally.
- * Return -1 after releasing the siglock to repeat the check.
- * Return a signal number to induce an artifical signal delivery,
- * setting *info and *return_ka to specify its details and behavior.
- */
-static inline int tracehook_get_signal(struct task_struct *tsk,
- struct pt_regs *regs,
- siginfo_t *info,
- struct k_sigaction *return_ka)
-{
- if (unlikely(tsk_utrace_flags(tsk)))
- return utrace_get_signal(tsk, regs, info, return_ka);
- return 0;
-}
-
-/*
- * Called with no locks held when about to stop for job control;
- * we are already in TASK_STOPPED state, about to call schedule.
- * Return zero if the normal SIGCHLD should be generated, which
- * will happen if last_one is true meaning this is the last thread
- * in the thread group to stop.
- */
-static inline int tracehook_finish_stop(int last_one)
-{
- if (tsk_utrace_flags(current) & UTRACE_EVENT(JCTL))
- return utrace_report_jctl(CLD_STOPPED);
- return 0;
-}
-
-
-/*
- * Return nonzero if the child's parent (current) should be prevented
- * from seeing its child in TASK_STOPPED state when it waits with WSTOPPED.
- * Called with tasklist_lock held for reading.
- */
-static inline int tracehook_inhibit_wait_stopped(struct task_struct *child)
-{
- return (tsk_utrace_flags(child) & UTRACE_ACTION_NOREAP);
-}
-
-/*
- * Return nonzero if the child's parent (current) should be prevented
- * from seeing its child in TASK_ZOMBIE state when it waits with WEXITED.
- * Called with tasklist_lock held for reading.
- */
-static inline int tracehook_inhibit_wait_zombie(struct task_struct *child)
-{
- return (tsk_utrace_flags(child) & UTRACE_ACTION_NOREAP);
-}
-
-/*
- * Return nonzero if the child's parent (current) should be prevented
- * from seeing its child resuming after job stop when it waits with WCONTINUED.
- * Called with tasklist_lock held for reading.
- */
-static inline int tracehook_inhibit_wait_continued(struct task_struct *child)
-{
- return (tsk_utrace_flags(child) & UTRACE_ACTION_NOREAP);
-}
-
-
-/*
- * Return LSM_UNSAFE_* bits applied to an exec because of tracing.
- * Called with task_lock(tsk) held.
- */
-static inline int tracehook_unsafe_exec(struct task_struct *tsk)
-{
- if (tsk_utrace_flags(tsk))
- return utrace_unsafe_exec(tsk);
- return 0;
-}
-
-/*
- * Return the task_struct for the task using ptrace on this one, or NULL.
- * Must be called with rcu_read_lock held to keep the returned struct alive.
- *
- * At exec time, this may be called with task_lock(p) still held from when
- * tracehook_unsafe_exec was just called.
- *
- * The value is also used to display after "TracerPid:" in /proc/PID/status,
- * where it is called with only rcu_read_lock held.
- */
-static inline struct task_struct *tracehook_tracer_task(struct task_struct *p)
-{
- if (tsk_utrace_flags(p))
- return utrace_tracer_task(p);
- return NULL;
-}
-
-/*
- * Return nonzero if the current task should be allowed to use
- * access_process_vm on the given task.
- */
-static inline int tracehook_allow_access_process_vm(struct task_struct *tsk)
-{
- if (tsk == current)
- return 1;
- if (tsk_utrace_flags(tsk))
- return utrace_allow_access_process_vm(tsk);
- return 0;
-}
-
-
-/***
- ***
- *** Following decelarations are hook stubs where core code reports
- *** events. These are called without locks, from the thread having the
- *** event. In all tracehook_report_* calls, no locks are held and the thread
- *** is in a state close to returning to user mode with little baggage to
- *** unwind, except as noted below for tracehook_report_clone. It is generally
- *** OK to block in these places if you want the user thread to be suspended.
- ***
- ***/
-
-/*
- * Thread has just become a zombie (exit_state==TASK_ZOMBIE) or is about to
- * self-reap (exit_state==EXIT_DEAD). If normal reaping is not inhibited,
- * tsk->exit_state might be changing in parallel. The death_cookie was
- * passed back by tracehook_notify_death (above).
- */
-static inline void tracehook_report_death(struct task_struct *tsk,
- int exit_state, void *death_cookie)
-{
- smp_mb();
- if (tsk_utrace_flags(tsk) & (UTRACE_EVENT(DEATH)
- | UTRACE_ACTION_QUIESCE))
- utrace_report_death(tsk, death_cookie);
-}
-
-/*
- * This is called when tracehook_inhibit_wait_zombie(p) returned true
- * and a previously delayed group_leader is now eligible for reaping.
- * It's called from release_task, with no locks held, and p is not current.
- */
-static inline void tracehook_report_delayed_group_leader(struct task_struct *p)
-{
- utrace_report_delayed_group_leader(p);
-}
-
-/*
- * exec completed, we are shortly going to return to user mode.
- * The freshly initialized register state can be seen and changed here.
- */
-static inline void tracehook_report_exec(struct linux_binprm *bprm,
- struct pt_regs *regs)
-{
- if (tsk_utrace_flags(current) & UTRACE_EVENT(EXEC))
- utrace_report_exec(bprm, regs);
-}
-
-/*
- * Called from do_exit, we are about to exit. The code returned to the
- * parent for wait can be changed here.
- */
-static inline void tracehook_report_exit(long *exit_code)
-{
- if (tsk_utrace_flags(current) & UTRACE_EVENT(EXIT))
- utrace_report_exit(exit_code);
-}
-
-/*
- * Called after a child is set up, but before it has been started or
- * been given its CLONE_STOPPED initial stop. (See also tracehook_init_task.)
- * This is not a good place to block, because the child has not started yet.
- * Suspend the child here if desired, and block in clone_complete (below).
- * This must prevent the child from self-reaping if clone_complete uses
- * the task_struct pointer; otherwise it might have died and been released
- * by the time tracehook_report_clone_complete is called.
- */
-static inline void tracehook_report_clone(unsigned long clone_flags,
- struct task_struct *child)
-{
- if (tsk_utrace_flags(current) & UTRACE_EVENT(CLONE))
- utrace_report_clone(clone_flags, child);
-}
-
-/*
- * Called after the child has started running, shortly after
- * tracehook_report_clone. This is just before the clone/fork syscall returns,
- * or blocks for vfork child completion if (clone_flags & CLONE_VFORK).
- * The child pointer may be invalid if a self-reaping child died and
- * tracehook_report_clone took no action to prevent it from self-reaping.
- */
-static inline void tracehook_report_clone_complete(unsigned long clone_flags,
- pid_t pid,
- struct task_struct *child)
-{
- if (tsk_utrace_flags(current) & UTRACE_ACTION_QUIESCE)
- utrace_quiescent(current, NULL);
-}
-
-/*
- * Called after a CLONE_VFORK parent has waited for the child to complete.
- * The clone/vfork system call will return immediately after this.
- * The child pointer may be invalid if a self-reaping child died and
- * tracehook_report_clone took no action to prevent it from self-reaping.
- */
-static inline void tracehook_report_vfork_done(struct task_struct *child,
- pid_t child_pid)
-{
- if (tsk_utrace_flags(current) & UTRACE_EVENT(VFORK_DONE))
- utrace_report_vfork_done(child_pid);
-}
-
-/*
- * Called for system call entry or exit.
- */
-static inline void tracehook_report_syscall(struct pt_regs *regs, int is_exit)
-{
- if (tsk_utrace_flags(current) & (is_exit ? UTRACE_EVENT(SYSCALL_EXIT)
- : UTRACE_EVENT(SYSCALL_ENTRY)))
- utrace_report_syscall(regs, is_exit);
-}
-
-/*
- * Called after system call exit if single/block-stepped into the syscall.
- */
-static inline void tracehook_report_syscall_step(struct pt_regs *regs)
-{
-}
-
-/*
- * Called when a signal handler has been set up.
- * Register and stack state reflects the user handler about to run.
- * Signal mask changes have already been made.
- */
-static inline void tracehook_report_handle_signal(int sig,
- const struct k_sigaction *ka,
- const sigset_t *oldset,
- struct pt_regs *regs)
-{
- struct task_struct *tsk = current;
- if ((tsk_utrace_flags(tsk) & UTRACE_EVENT_SIGNAL_ALL)
- && (tsk_utrace_flags(tsk) & (UTRACE_ACTION_SINGLESTEP
- | UTRACE_ACTION_BLOCKSTEP)))
- utrace_signal_handler_singlestep(tsk, regs);
-}
-
#endif /* <linux/tracehook.h> */
Index: linux-2.6/include/linux/utrace.h
===================================================================
--- linux-2.6.orig/include/linux/utrace.h 2007-04-13 14:35:01.000000000 +0200
+++ linux-2.6/include/linux/utrace.h 2007-04-13 15:47:43.000000000 +0200
@@ -178,7 +178,6 @@ enum utrace_events {
#define UTRACE_ATTACH_MATCH_MASK 0x000f
-#ifdef CONFIG_UTRACE
/*
* Per-engine per-thread structure.
*
@@ -470,9 +469,6 @@ const struct utrace_regset *utrace_regse
int which);
-/*
- * Hooks in <linux/tracehook.h> call these entry points to the utrace dispatch.
- */
int utrace_quiescent(struct task_struct *, struct utrace_signal *);
void utrace_release_task(struct task_struct *);
int utrace_get_signal(struct task_struct *, struct pt_regs *,
@@ -484,120 +480,47 @@ void utrace_report_death(struct task_str
void utrace_report_delayed_group_leader(struct task_struct *);
int utrace_report_jctl(int type);
void utrace_report_exec(struct linux_binprm *bprm, struct pt_regs *regs);
-void utrace_report_syscall(struct pt_regs *regs, int is_exit);
+void __utrace_report_syscall(struct pt_regs *regs, int is_exit);
struct task_struct *utrace_tracer_task(struct task_struct *);
int utrace_allow_access_process_vm(struct task_struct *);
int utrace_unsafe_exec(struct task_struct *);
void utrace_signal_handler_singlestep(struct task_struct *, struct pt_regs *);
/*
- * <linux/tracehook.h> uses these accessors to avoid #ifdef CONFIG_UTRACE.
+ * Return zero iff tracing doesn't care to examine this fatal signal,
+ * so it can short-circuit normal delivery directly to a group exit.
+ * Called with tsk->sighand->siglock held.
*/
-static inline unsigned long tsk_utrace_flags(struct task_struct *tsk)
-{
- return tsk->utrace_flags;
-}
-static inline struct utrace *tsk_utrace_struct(struct task_struct *tsk)
-{
- return tsk->utrace;
-}
-static inline void utrace_init_task(struct task_struct *child)
-{
- child->utrace_flags = 0;
- child->utrace = NULL;
-}
-
-#else /* !CONFIG_UTRACE */
-
-static unsigned long tsk_utrace_flags(struct task_struct *tsk)
-{
- return 0;
-}
-static struct utrace *tsk_utrace_struct(struct task_struct *tsk)
-{
- return NULL;
-}
-static inline void utrace_init_task(struct task_struct *child)
+static inline int utrace_consider_fatal_signal(struct task_struct *tsk,
+ int sig)
{
+ return (tsk->utrace_flags &
+ (UTRACE_EVENT(SIGNAL_TERM) | UTRACE_EVENT(SIGNAL_CORE)));
}
/*
- * The calls to these should all be in if (0) and optimized out entirely.
- * We have stubs here only so tracehook.h doesn't need to #ifdef them
- * to avoid external references in case of unoptimized compilation.
+ * Called for system call entry or exit.
*/
-static inline int utrace_quiescent(struct task_struct *tsk, void *ignored)
-{
- BUG();
- return 0;
-}
-static inline void utrace_release_task(struct task_struct *tsk)
-{
- BUG();
-}
-static inline int utrace_get_signal(struct task_struct *tsk,
- struct pt_regs *regs,
- siginfo_t *info, struct k_sigaction *ka)
-{
- BUG();
- return 0;
-}
-static inline void utrace_report_clone(unsigned long clone_flags,
- struct task_struct *child)
-{
- BUG();
-}
-static inline void utrace_report_vfork_done(pid_t child_pid)
-{
- BUG();
-}
-static inline void utrace_report_exit(long *exit_code)
-{
- BUG();
-}
-static inline void utrace_report_death(struct task_struct *tsk, void *ignored)
-{
- BUG();
-}
-static inline void utrace_report_delayed_group_leader(struct task_struct *tsk)
-{
- BUG();
-}
-static inline int utrace_report_jctl(int type)
-{
- BUG();
- return 0;
-}
-static inline void utrace_report_exec(struct linux_binprm *bprm,
- struct pt_regs *regs)
-{
- BUG();
-}
static inline void utrace_report_syscall(struct pt_regs *regs, int is_exit)
{
- BUG();
-}
-static inline struct task_struct *utrace_tracer_task(struct task_struct *tsk)
-{
- BUG();
- return NULL;
-}
-static inline int utrace_allow_access_process_vm(struct task_struct *tsk)
-{
- BUG();
- return 0;
-}
-static inline int utrace_unsafe_exec(struct task_struct *tsk)
-{
- BUG();
- return 0;
-}
-static inline void utrace_signal_handler_singlestep(struct task_struct *tsk,
- struct pt_regs *regs)
-{
- BUG();
+ if (current->utrace_flags &
+ (is_exit ? UTRACE_EVENT(SYSCALL_EXIT) : UTRACE_EVENT(SYSCALL_ENTRY)))
+ __utrace_report_syscall(regs, is_exit);
}
-#endif /* CONFIG_UTRACE */
+/*
+ * Called when a signal handler has been set up.
+ * Register and stack state reflects the user handler about to run.
+ * Signal mask changes have already been made.
+ */
+static inline void utrace_report_handle_signal(int sig,
+ const struct k_sigaction *ka,
+ const sigset_t *oldset,
+ struct pt_regs *regs)
+{
+ if (current->utrace_flags & (UTRACE_EVENT_SIGNAL_ALL |
+ UTRACE_ACTION_SINGLESTEP | UTRACE_ACTION_BLOCKSTEP))
+ utrace_signal_handler_singlestep(current, regs);
+}
#endif /* linux/utrace.h */
Index: linux-2.6/kernel/Makefile
===================================================================
--- linux-2.6.orig/kernel/Makefile 2007-04-13 15:16:02.000000000 +0200
+++ linux-2.6/kernel/Makefile 2007-04-13 15:16:10.000000000 +0200
@@ -8,7 +8,7 @@ obj-y = sched.o fork.o exec_domain.o
signal.o sys.o kmod.o workqueue.o pid.o \
rcupdate.o extable.o params.o posix-timers.o \
kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \
- hrtimer.o rwsem.o latency.o nsproxy.o srcu.o
+ hrtimer.o rwsem.o latency.o nsproxy.o srcu.o utrace.o
obj-$(CONFIG_STACKTRACE) += stacktrace.o
obj-y += time/
@@ -51,7 +51,6 @@ obj-$(CONFIG_SYSCTL) += utsname_sysctl.o
obj-$(CONFIG_UTS_NS) += utsname.o
obj-$(CONFIG_TASK_DELAY_ACCT) += delayacct.o
obj-$(CONFIG_TASKSTATS) += taskstats.o tsacct.o
-obj-$(CONFIG_UTRACE) += utrace.o
obj-$(CONFIG_PTRACE) += ptrace.o
ifneq ($(CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER),y)
Index: linux-2.6/kernel/exit.c
===================================================================
--- linux-2.6.orig/kernel/exit.c 2007-04-13 14:46:55.000000000 +0200
+++ linux-2.6/kernel/exit.c 2007-04-13 15:48:03.000000000 +0200
@@ -145,10 +145,12 @@ void release_task(struct task_struct * p
int zap_leader;
int inhibited_leader;
repeat:
- tracehook_release_task(p);
+ smp_mb();
+ if (p->utrace)
+ utrace_release_task(p);
atomic_dec(&p->user->processes);
write_lock_irq(&tasklist_lock);
- BUG_ON(tracehook_check_released(p));
+ BUG_ON(p->utrace);
__exit_signal(p);
/*
@@ -161,7 +163,7 @@ repeat:
leader = p->group_leader;
if (leader != p && thread_group_empty(leader) && leader->exit_state == EXIT_ZOMBIE) {
BUG_ON(leader->exit_signal == -1);
- if (tracehook_inhibit_wait_zombie(leader))
+ if (leader->utrace_flags & UTRACE_ACTION_NOREAP)
inhibited_leader = 1;
else
do_notify_parent(leader, leader->exit_signal);
@@ -191,7 +193,7 @@ repeat:
* to be notified it would normally be reapable now.
*/
if (unlikely(inhibited_leader))
- tracehook_report_delayed_group_leader(leader);
+ utrace_report_delayed_group_leader(leader);
}
/*
@@ -627,7 +629,7 @@ reparent_thread(struct task_struct *p, s
/* If we'd notified the old parent about this child's death,
* also notify the new parent.
*/
- if (!tracehook_inhibit_wait_zombie(p) &&
+ if (!(p->utrace_flags & UTRACE_ACTION_NOREAP) &&
p->exit_state == EXIT_ZOMBIE &&
p->exit_signal != -1 && thread_group_empty(p))
do_notify_parent(p, p->exit_signal);
@@ -687,8 +689,7 @@ static void exit_notify(struct task_stru
int state;
struct task_struct *t;
struct pid *pgrp;
- int noreap;
- void *cookie;
+ struct utrace *cookie;
if (signal_pending(tsk) && !(tsk->signal->flags & SIGNAL_GROUP_EXIT)
&& !thread_group_empty(tsk)) {
@@ -770,18 +771,19 @@ static void exit_notify(struct task_stru
&& !capable(CAP_KILL))
tsk->exit_signal = SIGCHLD;
- if (!tracehook_notify_death(tsk, &noreap, &cookie)
- && tsk->exit_signal != -1 && thread_group_empty(tsk))
- do_notify_parent(tsk, tsk->exit_signal);
-
state = EXIT_ZOMBIE;
- if (tsk->exit_signal == -1 && !noreap)
- state = EXIT_DEAD;
+ cookie = tsk->utrace;
+ if (!(tsk->utrace_flags & UTRACE_ACTION_NOREAP)) {
+ if (tsk->exit_signal == -1)
+ state = EXIT_DEAD;
+ else if (thread_group_empty(tsk))
+ do_notify_parent(tsk, tsk->exit_signal);
+ }
tsk->exit_state = state;
write_unlock_irq(&tasklist_lock);
-
- tracehook_report_death(tsk, state, cookie);
+ if (tsk->utrace_flags & (UTRACE_EVENT(DEATH) | UTRACE_ACTION_QUIESCE))
+ utrace_report_death(tsk, cookie);
/* If the process is dead, release it - nobody will wait for it */
if (state == EXIT_DEAD)
@@ -808,8 +810,8 @@ fastcall NORET_TYPE void do_exit(long co
panic("Attempted to kill init!");
}
-
- tracehook_report_exit(&code);
+ if (current->utrace_flags & UTRACE_EVENT(EXIT))
+ utrace_report_exit(&code);
/*
* We're taking recursive faults here in do_exit. Safest is to just
@@ -1374,7 +1376,7 @@ repeat:
flag = 1;
if (!(options & WUNTRACED))
continue;
- if (tracehook_inhibit_wait_stopped(p))
+ if (p->utrace_flags & UTRACE_ACTION_NOREAP)
continue;
retval = wait_task_stopped(p, ret == 2,
(options & WNOWAIT),
@@ -1399,7 +1401,8 @@ repeat:
goto check_continued;
if (!likely(options & WEXITED))
continue;
- if (tracehook_inhibit_wait_zombie(p)) {
+ if (p->utrace_flags &
+ UTRACE_ACTION_NOREAP) {
flag = 1;
continue;
}
@@ -1419,7 +1422,7 @@ check_continued:
flag = 1;
if (!unlikely(options & WCONTINUED))
continue;
- if (tracehook_inhibit_wait_continued(p))
+ if (p->utrace_flags & UTRACE_ACTION_NOREAP)
continue;
retval = wait_task_continued(
p, (options & WNOWAIT),
Index: linux-2.6/kernel/fork.c
===================================================================
--- linux-2.6.orig/kernel/fork.c 2007-04-13 14:45:28.000000000 +0200
+++ linux-2.6/kernel/fork.c 2007-04-13 15:17:59.000000000 +0200
@@ -1241,7 +1241,8 @@ static struct task_struct *copy_process(
if (likely(p->pid)) {
add_parent(p);
- tracehook_init_task(p);
+ p->utrace_flags = 0;
+ p->utrace = NULL;
if (thread_group_leader(p)) {
p->signal->tty = current->signal->tty;
@@ -1362,8 +1363,9 @@ long do_fork(unsigned long clone_flags,
init_completion(&vfork);
}
- if (likely(is_user))
- tracehook_report_clone(clone_flags, p);
+ if (likely(is_user) &&
+ (current->utrace_flags & UTRACE_EVENT(CLONE)))
+ utrace_report_clone(clone_flags, p);
p->flags &= ~PF_STARTING;
@@ -1378,13 +1380,15 @@ long do_fork(unsigned long clone_flags,
else
wake_up_new_task(p, clone_flags);
- if (likely(is_user))
- tracehook_report_clone_complete(clone_flags, nr, p);
+ if (likely(is_user) &&
+ (current->utrace_flags & UTRACE_ACTION_QUIESCE))
+ utrace_quiescent(current, NULL);
if (clone_flags & CLONE_VFORK) {
wait_for_completion(&vfork);
- if (likely(is_user))
- tracehook_report_vfork_done(p, nr);
+ if (likely(is_user) &&
+ (current->utrace_flags & UTRACE_EVENT(VFORK_DONE)))
+ utrace_report_vfork_done(nr);
}
} else {
free_pid(pid);
Index: linux-2.6/kernel/signal.c
===================================================================
--- linux-2.6.orig/kernel/signal.c 2007-04-13 14:52:52.000000000 +0200
+++ linux-2.6/kernel/signal.c 2007-04-13 15:23:22.000000000 +0200
@@ -178,7 +178,7 @@ static int sig_ignored(struct task_struc
return 0;
/* It's ignored, we can short-circuit unless a debugger wants it. */
- return !tracehook_consider_ignored_signal(t, sig, handler);
+ return !(t->utrace_flags & UTRACE_EVENT(SIGNAL_IGN));
}
/*
@@ -219,7 +219,7 @@ fastcall void recalc_sigpending_tsk(stru
(freezing(t)) ||
PENDING(&t->pending, &t->blocked) ||
PENDING(&t->signal->shared_pending, &t->blocked) ||
- tracehook_induce_sigpending(t))
+ unlikely(t->utrace_flags & UTRACE_ACTION_QUIESCE))
set_tsk_thread_flag(t, TIF_SIGPENDING);
else
clear_tsk_thread_flag(t, TIF_SIGPENDING);
@@ -927,7 +927,7 @@ __group_complete_signal(int sig, struct
*/
if (sig_fatal(p, sig) && !(p->signal->flags & SIGNAL_GROUP_EXIT) &&
!sigismember(&t->real_blocked, sig) &&
- (sig == SIGKILL || !tracehook_consider_fatal_signal(t, sig))) {
+ (sig == SIGKILL || !utrace_consider_fatal_signal(t, sig))) {
/*
* This signal will be fatal to the whole group.
*/
@@ -1570,7 +1570,7 @@ void do_notify_parent_cldstop(struct tas
/*
* Tracing can decide that we should not do the normal notification.
*/
- if (tracehook_notify_cldstop(tsk, &info))
+ if (tsk->utrace_flags & UTRACE_ACTION_NOREAP)
return;
tsk = tsk->group_leader;
@@ -1591,12 +1591,12 @@ void do_notify_parent_cldstop(struct tas
static void
finish_stop(int stop_count)
{
- /*
- * If there are no other threads in the group, or if there is
- * a group stop in progress and we are the last to stop,
- * report to the parent. When ptraced, every thread reports itself.
- */
- if (!tracehook_finish_stop(stop_count <= 0) && stop_count <= 0) {
+ int skip_notify = 0;
+
+ if (current->utrace_flags & UTRACE_EVENT(JCTL))
+ skip_notify = utrace_report_jctl(CLD_STOPPED);
+
+ if (!skip_notify && stop_count <= 0) {
read_lock(&tasklist_lock);
do_notify_parent_cldstop(current, CLD_STOPPED);
read_unlock(&tasklist_lock);
@@ -1728,7 +1728,11 @@ relock:
* The return value in signr determines the default action,
* but info->si_signo is the signal number we will report.
*/
- signr = tracehook_get_signal(current, regs, info, return_ka);
+ if (unlikely(current->utrace_flags))
+ signr = utrace_get_signal(current, regs,
+ info, return_ka);
+ else
+ signr = 0;
if (unlikely(signr < 0))
goto relock;
if (unlikely(signr != 0))
Index: linux-2.6/kernel/utrace.c
===================================================================
--- linux-2.6.orig/kernel/utrace.c 2007-04-13 14:35:01.000000000 +0200
+++ linux-2.6/kernel/utrace.c 2007-04-13 15:58:53.000000000 +0200
@@ -1464,7 +1464,7 @@ utrace_report_exec(struct linux_binprm *
* Called iff UTRACE_EVENT(SYSCALL_{ENTRY,EXIT}) flag is set.
*/
void
-utrace_report_syscall(struct pt_regs *regs, int is_exit)
+__utrace_report_syscall(struct pt_regs *regs, int is_exit)
{
struct task_struct *tsk = current;
struct utrace *utrace = tsk->utrace;
Index: linux-2.6/security/selinux/hooks.c
===================================================================
--- linux-2.6.orig/security/selinux/hooks.c 2007-04-13 15:24:17.000000000 +0200
+++ linux-2.6/security/selinux/hooks.c 2007-04-13 15:25:47.000000000 +0200
@@ -1849,7 +1849,8 @@ static void selinux_bprm_apply_creds(str
struct task_struct *t;
rcu_read_lock();
- t = tracehook_tracer_task(current);
+ t = current->utrace_flags ?
+ utrace_tracer_task(current) : NULL;
if (unlikely(t == NULL))
rcu_read_unlock();
else {
@@ -4602,7 +4603,7 @@ static int selinux_setprocattr(struct ta
Otherwise, leave SID unchanged and fail. */
task_lock(p);
rcu_read_lock();
- tracer = tracehook_tracer_task(p);
+ tracer = p->utrace_flags ? utrace_tracer_task(p) : NULL;
if (tracer != NULL) {
struct task_security_struct *ptsec = tracer->security;
u32 ptsid = ptsec->sid;
Index: linux-2.6/init/Kconfig
===================================================================
--- linux-2.6.orig/init/Kconfig 2007-04-13 15:40:38.000000000 +0200
+++ linux-2.6/init/Kconfig 2007-04-13 15:40:56.000000000 +0200
@@ -597,24 +597,10 @@ endmenu
menu "Process debugging support"
-config UTRACE
- bool "Infrastructure for tracing and debugging user processes"
- default y
- help
- Enable the utrace process tracing interface.
- This is an internal kernel interface to track events in user
- threads, extract and change user thread state. This interface
- is exported to kernel modules, and is also used to implement ptrace.
- If you disable this, no facilities for debugging user processes
- will be available, nor the facilities used by UML and other
- applications. Unless you are making a specially stripped-down
- kernel and are very sure you don't need these facilitiies,
- say Y.
-
config PTRACE
bool "Legacy ptrace system call interface"
default y
- depends on UTRACE && PROC_FS
+ depends on PROC_FS
help
Enable the ptrace system call.
This is traditionally used by debuggers like GDB,
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH] utrace: remove indirections
2007-04-18 18:03 [PATCH] utrace: remove indirections Christoph Hellwig
@ 2007-04-30 4:02 ` Roland McGrath
0 siblings, 0 replies; 2+ messages in thread
From: Roland McGrath @ 2007-04-30 4:02 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: Andrew Morton, linux-kernel
I am not in favor of this change.
Previously you said:
> This shows very nicely why the tracehooks vs utrace abstraction
> is utter madness. Every tracehook 'abstraction' just conatains
> an ifdef block. Just kill CONFIG_UTRACE as there is no point
> in making this functionality conditional an opencode the
> utrace functionality at the callers (or add a utrace_ helper
> for the few cases where it makes sense)
Since then I have gotten rid of the #ifdef's there so it is easier on the
eyes. But that is not the crux of the issue.
> Currently generic code calls into tracehook_* which then alls into
> utrace_* to do the actual work. With utrace as the new singing dancing
> framework there's little point in that, and readability would be greatly
> improved by getting rid of this. The few places where tracehook_*
> was more than a one-liner and used in multiple places in arch code
> I renamed the call to utrace_*.
I've never meant to claim that tracehook is, or should be, an abstraction
layer in the sense of multiplexing across different implementations
simultaneously. It's always been intended to compile away completely.
The purpose of the tracehook layer is to be "abstract" in the sense that
it is all that any other kernel code should need to know about the
tracing infrastructure. I believe it helps readability, not of
tracehook.h, but of the rest of the kernel, and maintainability too.
The first phase of my work, and an arduous one, was to untangle and
document all the interwinings of the old ptrace implementation with core
code and the implicit assumptions between them. utrace-tracehook.patch
is the product of this work. Noone should ever have to deal with that
again. Now, when someone is modifying kernel code and stumbles across a
tracehook_* call, there is a single obvious place to go looking for what
that's about. Each call's documentation in tracehook.h gives explicit
details about the expectations of the call, including locking conditions
and so forth. Someone modifying those documented expectations, e.g. by
changing the locking calls in the surrounding core code, knows that this
tracehook call has to be updated to resolve the conflict, and will ask
around for the right people to update the tracing infrastructure to match
the new core code. All the while, this poor kernel hacker was never
required to think about utrace and what its implementation might need.
(People who don't care what utrace is, shouldn't have to find out.
People who didn't care what ptrace was, knew they were supposed to be afraid.)
Certainly the benefits of simple entry points from core code whose
expectations of their callers are thoroughly documented can be retained
with everything named utrace_* and tracehook.h removed. In either event,
keeping all the entry points clean and their documentation complete and
correct requires continuous diligent maintenance effort. Nonetheless, I
do believe the separation helps. Those only interested in what they must
avoid breaking incidentally have something simple to contend with in
tracehook.h, rather than feeling obliged to digest utrace.txt and
utrace.h to get up to speed. It may turn out that utrace is no good, or
winds up being drastically different (at the least, maybe I'll think of a
decent name for something, for a change). In any event, the set of
tracehook entry points is unlikely to change very much, and new work
won't need to touch core code all over the kernel to change the tracing
infrastructure completely.
> Also kill the CONFIG_UTRACE config option, there's very little reason
> in not having a core debugging mechanisms, and this allows to get rid
> of another layer of wrapping again.
I spend most of my time debugging, so a configuration with fewer
debugging facilities rather than more is somewhat hypothetical to me
personally too. But I don't buy the rationale for not making this
configurable. CONFIG_PROC_FS can be turned off, and I dare say /proc is
used by more people more often, for what they would broadly term
debugging, than is ptrace. If someone builds a special-purpose
configuration for a fixed installation that has no way to attach any kind
of debugger, then why should they have to compile in more dead code?
Moreover, it's a good test that the interfaces between core code and the
tracing infrastructure remain simple and clean that you can build a
working kernel without it.
Thanks,
Roland
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2007-04-30 4:02 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-04-18 18:03 [PATCH] utrace: remove indirections Christoph Hellwig
2007-04-30 4:02 ` Roland McGrath
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®