diff options
Diffstat (limited to 'kernel/ptrace.c')
-rw-r--r-- | kernel/ptrace.c | 19 |
1 files changed, 10 insertions, 9 deletions
diff --git a/kernel/ptrace.c b/kernel/ptrace.c index f6d8b8cb5e34..9439bd3331a6 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c | |||
@@ -172,6 +172,8 @@ int ptrace_attach(struct task_struct *task) | |||
172 | audit_ptrace(task); | 172 | audit_ptrace(task); |
173 | 173 | ||
174 | retval = -EPERM; | 174 | retval = -EPERM; |
175 | if (unlikely(task->flags & PF_KTHREAD)) | ||
176 | goto out; | ||
175 | if (same_thread_group(task, current)) | 177 | if (same_thread_group(task, current)) |
176 | goto out; | 178 | goto out; |
177 | 179 | ||
@@ -182,8 +184,6 @@ int ptrace_attach(struct task_struct *task) | |||
182 | retval = mutex_lock_interruptible(&task->cred_guard_mutex); | 184 | retval = mutex_lock_interruptible(&task->cred_guard_mutex); |
183 | if (retval < 0) | 185 | if (retval < 0) |
184 | goto out; | 186 | goto out; |
185 | |||
186 | retval = -EPERM; | ||
187 | repeat: | 187 | repeat: |
188 | /* | 188 | /* |
189 | * Nasty, nasty. | 189 | * Nasty, nasty. |
@@ -203,23 +203,24 @@ repeat: | |||
203 | goto repeat; | 203 | goto repeat; |
204 | } | 204 | } |
205 | 205 | ||
206 | if (!task->mm) | ||
207 | goto bad; | ||
208 | /* the same process cannot be attached many times */ | ||
209 | if (task->ptrace & PT_PTRACED) | ||
210 | goto bad; | ||
211 | retval = __ptrace_may_access(task, PTRACE_MODE_ATTACH); | 206 | retval = __ptrace_may_access(task, PTRACE_MODE_ATTACH); |
212 | if (retval) | 207 | if (retval) |
213 | goto bad; | 208 | goto bad; |
214 | 209 | ||
215 | /* Go */ | 210 | retval = -EPERM; |
211 | if (unlikely(task->exit_state)) | ||
212 | goto bad; | ||
213 | if (task->ptrace & PT_PTRACED) | ||
214 | goto bad; | ||
215 | |||
216 | task->ptrace |= PT_PTRACED; | 216 | task->ptrace |= PT_PTRACED; |
217 | if (capable(CAP_SYS_PTRACE)) | 217 | if (capable(CAP_SYS_PTRACE)) |
218 | task->ptrace |= PT_PTRACE_CAP; | 218 | task->ptrace |= PT_PTRACE_CAP; |
219 | 219 | ||
220 | __ptrace_link(task, current); | 220 | __ptrace_link(task, current); |
221 | |||
222 | send_sig_info(SIGSTOP, SEND_SIG_FORCED, task); | 221 | send_sig_info(SIGSTOP, SEND_SIG_FORCED, task); |
222 | |||
223 | retval = 0; | ||
223 | bad: | 224 | bad: |
224 | write_unlock_irqrestore(&tasklist_lock, flags); | 225 | write_unlock_irqrestore(&tasklist_lock, flags); |
225 | task_unlock(task); | 226 | task_unlock(task); |