Add PTRACE_SYSCALL_MASK, which allows system calls to be selectively
traced. It takes a bitmask and a length. A system call is traced
if its bit is one. Otherwise, it executes normally, and is
invisible to the ptracing parent.
This is not just useful for UML - strace -e could make good use of it as well.
Index: linux-2.6.17-mm-vtime/arch/um/kernel/ptrace.c
===================================================================
--- linux-2.6.17-mm-vtime.orig/arch/um/kernel/ptrace.c 2006-04-13 13:48:02.000000000 -0400
+++ linux-2.6.17-mm-vtime/arch/um/kernel/ptrace.c 2006-04-13 13:49:32.000000000 -0400
@@ -83,7 +83,7 @@ long arch_ptrace(struct task_struct *chi
break;
case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
- case PTRACE_CONT: { /* restart after signal. */
+ case PTRACE_CONT: /* restart after signal. */
ret = -EIO;
if (!valid_signal(data))
break;
@@ -99,7 +99,9 @@ long arch_ptrace(struct task_struct *chi
wake_up_process(child);
ret = 0;
break;
- }
+ case PTRACE_SYSCALL_MASK:
+ ret = set_syscall_mask(child, (char __user *) addr, data);
+ break;
/*
* make the child exit. Best I can do is send it a sigkill.
@@ -295,6 +297,12 @@ void syscall_trace(union uml_pt_regs *re
if (!(current->ptrace & PT_PTRACED))
return;
+ if((current->syscall_mask != NULL) &&
+ ((long) UPT_SYSCALL_NR(regs) != -1) &&
+ !(current->syscall_mask[UPT_SYSCALL_NR(regs) / (8 * sizeof(long))] &
+ (1 << (UPT_SYSCALL_NR(regs) % (8 * sizeof(long))))))
+ return;
+
/* the 0x80 provides a way for the tracing parent to distinguish
between a syscall stop and SIGTRAP delivery */
tracesysgood = (current->ptrace & PT_TRACESYSGOOD);
Index: linux-2.6.17-mm-vtime/include/linux/ptrace.h
===================================================================
--- linux-2.6.17-mm-vtime.orig/include/linux/ptrace.h 2006-04-13 13:48:02.000000000 -0400
+++ linux-2.6.17-mm-vtime/include/linux/ptrace.h 2006-04-13 13:49:32.000000000 -0400
@@ -93,6 +93,8 @@ extern void __ptrace_link(struct task_st
extern void __ptrace_unlink(struct task_struct *child);
extern void ptrace_untrace(struct task_struct *child);
extern int ptrace_may_attach(struct task_struct *task);
+extern int set_syscall_mask(struct task_struct *child, char __user *mask,
+ unsigned long len);
static inline void ptrace_link(struct task_struct *child,
struct task_struct *new_parent)
Index: linux-2.6.17-mm-vtime/arch/i386/kernel/ptrace.c
===================================================================
--- linux-2.6.17-mm-vtime.orig/arch/i386/kernel/ptrace.c 2006-04-13 13:48:02.000000000 -0400
+++ linux-2.6.17-mm-vtime/arch/i386/kernel/ptrace.c 2006-04-13 13:49:32.000000000 -0400
@@ -500,6 +500,9 @@ long arch_ptrace(struct task_struct *chi
ret = 0;
break;
+ case PTRACE_SYSCALL_MASK:
+ ret = set_syscall_mask(child, (char __user *) addr, data);
+ break;
/*
* make the child exit. Best I can do is send it a sigkill.
* perhaps it should be put in the status that it wants to
@@ -690,6 +693,11 @@ int do_syscall_trace(struct pt_regs *reg
if (!(current->ptrace & PT_PTRACED))
goto out;
+ if((current->syscall_mask != NULL) && ((long) regs->orig_eax != -1) &&
+ !(current->syscall_mask[regs->orig_eax / (8 * sizeof(long))] &
+ (1 << (regs->orig_eax % (8 * sizeof(long))))))
+ goto out;
+
/* If a process stops on the 1st tracepoint with SYSCALL_TRACE
* and then is resumed with SYSEMU_SINGLESTEP, it will come in
* here. We have to check this and return */
Index: linux-2.6.17-mm-vtime/include/asm-i386/ptrace.h
===================================================================
--- linux-2.6.17-mm-vtime.orig/include/asm-i386/ptrace.h 2006-04-13 13:48:02.000000000 -0400
+++ linux-2.6.17-mm-vtime/include/asm-i386/ptrace.h 2006-04-13 13:49:32.000000000 -0400
@@ -53,6 +53,7 @@ struct pt_regs {
#define PTRACE_GET_THREAD_AREA 25
#define PTRACE_SET_THREAD_AREA 26
+#define PTRACE_SYSCALL_MASK 27
#define PTRACE_SYSEMU 31
#define PTRACE_SYSEMU_SINGLESTEP 32
Index: linux-2.6.17-mm-vtime/include/linux/sched.h
===================================================================
--- linux-2.6.17-mm-vtime.orig/include/linux/sched.h 2006-04-13 13:49:11.000000000 -0400
+++ linux-2.6.17-mm-vtime/include/linux/sched.h 2006-04-13 13:49:32.000000000 -0400
@@ -899,6 +899,7 @@ struct task_struct {
unsigned long ptrace_message;
siginfo_t *last_siginfo; /* For ptrace use. */
+ unsigned long *syscall_mask;
/*
* current io wait handle: wait queue entry to use for io waits
* If this thread is processing aio, this points at the waitqueue
Index: linux-2.6.17-mm-vtime/kernel/ptrace.c
===================================================================
--- linux-2.6.17-mm-vtime.orig/kernel/ptrace.c 2006-04-13 13:48:02.000000000 -0400
+++ linux-2.6.17-mm-vtime/kernel/ptrace.c 2006-04-13 13:49:32.000000000 -0400
@@ -21,6 +21,7 @@
#include <asm/pgtable.h>
#include <asm/uaccess.h>
+#include <asm/unistd.h>
/*
* ptrace a task: make the debugger its new parent and
@@ -450,6 +451,41 @@ int ptrace_traceme(void)
return 0;
}
+int set_syscall_mask(struct task_struct *child, char __user *mask,
+ unsigned long len)
+{
+ int i, n = (NR_syscalls + 7) / 8;
+ char c;
+
+ if(len > n){
+ for(i = NR_syscalls; i < len * 8; i++){
+ get_user(c, &mask[i / 8]);
+ if(!(c & (1 << (i % 8)))){
+ printk("Out of range syscall at %d\n", i);
+ return -EINVAL;
+ }
+ }
+
+ len = n;
+ }
+
+ if(child->syscall_mask == NULL){
+ child->syscall_mask = kmalloc(n, GFP_KERNEL);
+ if(child->syscall_mask == NULL)
+ return -ENOMEM;
+
+ memset(child->syscall_mask, 0xff, n);
+ }
+
+ /* XXX If this partially fails, we will have a partially updated
+ * mask.
+ */
+ if(copy_from_user(child->syscall_mask, mask, len))
+ return -EFAULT;
+
+ return 0;
+}
+
/**
* ptrace_get_task_struct -- grab a task struct reference for ptrace
* @pid: process id to grab a task_struct reference of
Index: linux-2.6.17-mm-vtime/include/linux/init_task.h
===================================================================
--- linux-2.6.17-mm-vtime.orig/include/linux/init_task.h 2006-04-13 13:48:32.000000000 -0400
+++ linux-2.6.17-mm-vtime/include/linux/init_task.h 2006-04-13 13:50:21.000000000 -0400
@@ -124,6 +124,7 @@ extern struct group_info init_groups;
.journal_info = NULL, \
.cpu_timers = INIT_CPU_TIMERS(tsk.cpu_timers), \
.fs_excl = ATOMIC_INIT(0), \
+ .syscall_mask = NULL \
INIT_RT_MUTEXES(tsk) \
}
Index: linux-2.6.17-mm-vtime/kernel/fork.c
===================================================================
--- linux-2.6.17-mm-vtime.orig/kernel/fork.c 2006-04-13 13:49:11.000000000 -0400
+++ linux-2.6.17-mm-vtime/kernel/fork.c 2006-04-13 13:49:32.000000000 -0400
@@ -1110,6 +1110,7 @@ static task_t *copy_process(unsigned lon
#ifdef TIF_SYSCALL_EMU
clear_tsk_thread_flag(p, TIF_SYSCALL_EMU);
#endif
+ p->syscall_mask = NULL;
/* Our parent execution domain becomes current domain
These must match for thread signalling to apply */
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[Index of Archives]
[Kernel Newbies]
[Netfilter]
[Bugtraq]
[Photo]
[Stuff]
[Gimp]
[Yosemite News]
[MIPS Linux]
[ARM Linux]
[Linux Security]
[Linux RAID]
[Video 4 Linux]
[Linux for the blind]
[Linux Resources]