Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/kaber/nf-next-2.6
[safe/jmp/linux-2.6] / include / linux / ptrace.h
index ebe0c17..56f2d63 100644 (file)
@@ -81,7 +81,6 @@
 
 
 extern long arch_ptrace(struct task_struct *child, long request, long addr, long data);
-extern struct task_struct *ptrace_get_task_struct(pid_t pid);
 extern int ptrace_traceme(void);
 extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len);
 extern int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len);
@@ -94,16 +93,19 @@ extern void ptrace_notify(int exit_code);
 extern void __ptrace_link(struct task_struct *child,
                          struct task_struct *new_parent);
 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 __ptrace_may_attach(struct task_struct *task);
+extern void exit_ptrace(struct task_struct *tracer);
+#define PTRACE_MODE_READ   1
+#define PTRACE_MODE_ATTACH 2
+/* Returns 0 on success, -errno on denial. */
+extern int __ptrace_may_access(struct task_struct *task, unsigned int mode);
+/* Returns true on success, false on denial. */
+extern bool ptrace_may_access(struct task_struct *task, unsigned int mode);
 
-static inline void ptrace_link(struct task_struct *child,
-                              struct task_struct *new_parent)
+static inline int ptrace_reparented(struct task_struct *child)
 {
-       if (unlikely(child->ptrace))
-               __ptrace_link(child, new_parent);
+       return child->real_parent != child->parent;
 }
+
 static inline void ptrace_unlink(struct task_struct *child)
 {
        if (unlikely(child->ptrace))
@@ -113,6 +115,74 @@ static inline void ptrace_unlink(struct task_struct *child)
 int generic_ptrace_peekdata(struct task_struct *tsk, long addr, long data);
 int generic_ptrace_pokedata(struct task_struct *tsk, long addr, long data);
 
+/**
+ * task_ptrace - return %PT_* flags that apply to a task
+ * @task:      pointer to &task_struct in question
+ *
+ * Returns the %PT_* flags that apply to @task.
+ */
+static inline int task_ptrace(struct task_struct *task)
+{
+       return task->ptrace;
+}
+
+/**
+ * ptrace_event - possibly stop for a ptrace event notification
+ * @mask:      %PT_* bit to check in @current->ptrace
+ * @event:     %PTRACE_EVENT_* value to report if @mask is set
+ * @message:   value for %PTRACE_GETEVENTMSG to return
+ *
+ * This checks the @mask bit to see if ptrace wants stops for this event.
+ * If so we stop, reporting @event and @message to the ptrace parent.
+ *
+ * Returns nonzero if we did a ptrace notification, zero if not.
+ *
+ * Called without locks.
+ */
+static inline int ptrace_event(int mask, int event, unsigned long message)
+{
+       if (mask && likely(!(current->ptrace & mask)))
+               return 0;
+       current->ptrace_message = message;
+       ptrace_notify((event << 8) | SIGTRAP);
+       return 1;
+}
+
+/**
+ * ptrace_init_task - initialize ptrace state for a new child
+ * @child:             new child task
+ * @ptrace:            true if child should be ptrace'd by parent's tracer
+ *
+ * This is called immediately after adding @child to its parent's children
+ * list.  @ptrace is false in the normal case, and true to ptrace @child.
+ *
+ * Called with current's siglock and write_lock_irq(&tasklist_lock) held.
+ */
+static inline void ptrace_init_task(struct task_struct *child, bool ptrace)
+{
+       INIT_LIST_HEAD(&child->ptrace_entry);
+       INIT_LIST_HEAD(&child->ptraced);
+       child->parent = child->real_parent;
+       child->ptrace = 0;
+       if (unlikely(ptrace) && (current->ptrace & PT_PTRACED)) {
+               child->ptrace = current->ptrace;
+               __ptrace_link(child, current->parent);
+       }
+}
+
+/**
+ * ptrace_release_task - final ptrace-related cleanup of a zombie being reaped
+ * @task:      task in %EXIT_DEAD state
+ *
+ * Called with write_lock(&tasklist_lock) held.
+ */
+static inline void ptrace_release_task(struct task_struct *task)
+{
+       BUG_ON(!list_empty(&task->ptraced));
+       ptrace_unlink(task);
+       BUG_ON(!list_empty(&task->ptrace_entry));
+}
+
 #ifndef force_successful_syscall_return
 /*
  * System call handlers that, upon successful completion, need to return a
@@ -203,6 +273,18 @@ static inline void user_enable_block_step(struct task_struct *task)
 }
 #endif /* arch_has_block_step */
 
+#ifdef ARCH_HAS_USER_SINGLE_STEP_INFO
+extern void user_single_step_siginfo(struct task_struct *tsk,
+                               struct pt_regs *regs, siginfo_t *info);
+#else
+static inline void user_single_step_siginfo(struct task_struct *tsk,
+                               struct pt_regs *regs, siginfo_t *info)
+{
+       memset(info, 0, sizeof(*info));
+       info->si_signo = SIGTRAP;
+}
+#endif
+
 #ifndef arch_ptrace_stop_needed
 /**
  * arch_ptrace_stop_needed - Decide whether arch_ptrace_stop() should be called
@@ -238,6 +320,22 @@ static inline void user_enable_block_step(struct task_struct *task)
 #define arch_ptrace_stop(code, info)           do { } while (0)
 #endif
 
+#ifndef arch_ptrace_untrace
+/*
+ * Do machine-specific work before untracing child.
+ *
+ * This is called for a normal detach as well as from ptrace_exit()
+ * when the tracing task dies.
+ *
+ * Called with write_lock(&tasklist_lock) held.
+ */
+#define arch_ptrace_untrace(task)              do { } while (0)
+#endif
+
+extern int task_current_syscall(struct task_struct *target, long *callno,
+                               unsigned long args[6], unsigned int maxargs,
+                               unsigned long *sp, unsigned long *pc);
+
 #endif
 
 #endif