aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/ptrace.h2
-rw-r--r--kernel/ptrace.c24
2 files changed, 20 insertions, 6 deletions
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
index 9178d5cc0b01..e93ef1a54fc7 100644
--- a/include/linux/ptrace.h
+++ b/include/linux/ptrace.h
@@ -105,7 +105,7 @@ extern long arch_ptrace(struct task_struct *child, long request,
105extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len); 105extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len);
106extern int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len); 106extern int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len);
107extern void ptrace_disable(struct task_struct *); 107extern void ptrace_disable(struct task_struct *);
108extern int ptrace_check_attach(struct task_struct *task, int kill); 108extern int ptrace_check_attach(struct task_struct *task, bool ignore_state);
109extern int ptrace_request(struct task_struct *child, long request, 109extern int ptrace_request(struct task_struct *child, long request,
110 unsigned long addr, unsigned long data); 110 unsigned long addr, unsigned long data);
111extern void ptrace_notify(int exit_code); 111extern void ptrace_notify(int exit_code);
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 134f34cb142b..eb191116edf7 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -97,10 +97,24 @@ void __ptrace_unlink(struct task_struct *child)
97 spin_unlock(&child->sighand->siglock); 97 spin_unlock(&child->sighand->siglock);
98} 98}
99 99
100/* 100/**
101 * Check that we have indeed attached to the thing.. 101 * ptrace_check_attach - check whether ptracee is ready for ptrace operation
102 * @child: ptracee to check for
103 * @ignore_state: don't check whether @child is currently %TASK_TRACED
104 *
105 * Check whether @child is being ptraced by %current and ready for further
106 * ptrace operations. If @ignore_state is %false, @child also should be in
107 * %TASK_TRACED state and on return the child is guaranteed to be traced
108 * and not executing. If @ignore_state is %true, @child can be in any
109 * state.
110 *
111 * CONTEXT:
112 * Grabs and releases tasklist_lock and @child->sighand->siglock.
113 *
114 * RETURNS:
115 * 0 on success, -ESRCH if %child is not ready.
102 */ 116 */
103int ptrace_check_attach(struct task_struct *child, int kill) 117int ptrace_check_attach(struct task_struct *child, bool ignore_state)
104{ 118{
105 int ret = -ESRCH; 119 int ret = -ESRCH;
106 120
@@ -119,13 +133,13 @@ int ptrace_check_attach(struct task_struct *child, int kill)
119 */ 133 */
120 spin_lock_irq(&child->sighand->siglock); 134 spin_lock_irq(&child->sighand->siglock);
121 WARN_ON_ONCE(task_is_stopped(child)); 135 WARN_ON_ONCE(task_is_stopped(child));
122 if (task_is_traced(child) || kill) 136 if (task_is_traced(child) || ignore_state)
123 ret = 0; 137 ret = 0;
124 spin_unlock_irq(&child->sighand->siglock); 138 spin_unlock_irq(&child->sighand->siglock);
125 } 139 }
126 read_unlock(&tasklist_lock); 140 read_unlock(&tasklist_lock);
127 141
128 if (!ret && !kill) 142 if (!ret && !ignore_state)
129 ret = wait_task_inactive(child, TASK_TRACED) ? 0 : -ESRCH; 143 ret = wait_task_inactive(child, TASK_TRACED) ? 0 : -ESRCH;
130 144
131 /* All systems go.. */ 145 /* All systems go.. */