Commit b79b7ba93df14a1fc0b8d4d6d78a0e097de03bbd
Committed by
Linus Torvalds
1 parent
5cb1144689
Exists in
master
and in
7 other branches
ptrace: ptrace_attach: check PF_KTHREAD + exit_state instead of ->mm
- Add PF_KTHREAD check to prevent attaching to the kernel thread with a borrowed ->mm. With or without this change we can race with daemonize() which can set PF_KTHREAD or clear ->mm after ptrace_attach() does the check, but this doesn't matter because reparent_to_kthreadd() does ptrace_unlink(). - Kill "!task->mm" check. We don't really care about ->mm != NULL, and the task can call exit_mm() right after we drop task_lock(). What we need is to make sure we can't attach after exit_notify(), check task->exit_state != 0 instead. Also, move the "already traced" check down for cosmetic reasons. Signed-off-by: Oleg Nesterov <oleg@redhat.com> Cc: Chris Wright <chrisw@sous-sol.org> Acked-by: Roland McGrath <roland@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 1 changed file with 10 additions and 9 deletions Side-by-side Diff
kernel/ptrace.c
... | ... | @@ -172,6 +172,8 @@ |
172 | 172 | audit_ptrace(task); |
173 | 173 | |
174 | 174 | retval = -EPERM; |
175 | + if (unlikely(task->flags & PF_KTHREAD)) | |
176 | + goto out; | |
175 | 177 | if (same_thread_group(task, current)) |
176 | 178 | goto out; |
177 | 179 | |
... | ... | @@ -182,8 +184,6 @@ |
182 | 184 | retval = mutex_lock_interruptible(&task->cred_guard_mutex); |
183 | 185 | if (retval < 0) |
184 | 186 | goto out; |
185 | - | |
186 | - retval = -EPERM; | |
187 | 187 | repeat: |
188 | 188 | /* |
189 | 189 | * Nasty, nasty. |
190 | 190 | |
191 | 191 | |
192 | 192 | |
... | ... | @@ -203,23 +203,24 @@ |
203 | 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 | 206 | retval = __ptrace_may_access(task, PTRACE_MODE_ATTACH); |
212 | 207 | if (retval) |
213 | 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 | 216 | task->ptrace |= PT_PTRACED; |
217 | 217 | if (capable(CAP_SYS_PTRACE)) |
218 | 218 | task->ptrace |= PT_PTRACE_CAP; |
219 | 219 | |
220 | 220 | __ptrace_link(task, current); |
221 | - | |
222 | 221 | send_sig_info(SIGSTOP, SEND_SIG_FORCED, task); |
222 | + | |
223 | + retval = 0; | |
223 | 224 | bad: |
224 | 225 | write_unlock_irqrestore(&tasklist_lock, flags); |
225 | 226 | task_unlock(task); |