diff options
| -rw-r--r-- | kernel/ptrace.c | 39 |
1 files changed, 21 insertions, 18 deletions
diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 4e0f0ec003f7..b0f8da80d7d4 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c | |||
| @@ -148,12 +148,16 @@ int ptrace_may_attach(struct task_struct *task) | |||
| 148 | int ptrace_attach(struct task_struct *task) | 148 | int ptrace_attach(struct task_struct *task) |
| 149 | { | 149 | { |
| 150 | int retval; | 150 | int retval; |
| 151 | task_lock(task); | 151 | |
| 152 | retval = -EPERM; | 152 | retval = -EPERM; |
| 153 | if (task->pid <= 1) | 153 | if (task->pid <= 1) |
| 154 | goto bad; | 154 | goto out; |
| 155 | if (task->tgid == current->tgid) | 155 | if (task->tgid == current->tgid) |
| 156 | goto bad; | 156 | goto out; |
| 157 | |||
| 158 | write_lock_irq(&tasklist_lock); | ||
| 159 | task_lock(task); | ||
| 160 | |||
| 157 | /* the same process cannot be attached many times */ | 161 | /* the same process cannot be attached many times */ |
| 158 | if (task->ptrace & PT_PTRACED) | 162 | if (task->ptrace & PT_PTRACED) |
| 159 | goto bad; | 163 | goto bad; |
| @@ -166,17 +170,15 @@ int ptrace_attach(struct task_struct *task) | |||
| 166 | ? PT_ATTACHED : 0); | 170 | ? PT_ATTACHED : 0); |
| 167 | if (capable(CAP_SYS_PTRACE)) | 171 | if (capable(CAP_SYS_PTRACE)) |
| 168 | task->ptrace |= PT_PTRACE_CAP; | 172 | task->ptrace |= PT_PTRACE_CAP; |
| 169 | task_unlock(task); | ||
| 170 | 173 | ||
| 171 | write_lock_irq(&tasklist_lock); | ||
| 172 | __ptrace_link(task, current); | 174 | __ptrace_link(task, current); |
| 173 | write_unlock_irq(&tasklist_lock); | ||
| 174 | 175 | ||
| 175 | force_sig_specific(SIGSTOP, task); | 176 | force_sig_specific(SIGSTOP, task); |
| 176 | return 0; | ||
| 177 | 177 | ||
| 178 | bad: | 178 | bad: |
| 179 | write_unlock_irq(&tasklist_lock); | ||
| 179 | task_unlock(task); | 180 | task_unlock(task); |
| 181 | out: | ||
| 180 | return retval; | 182 | return retval; |
| 181 | } | 183 | } |
| 182 | 184 | ||
| @@ -417,21 +419,22 @@ int ptrace_request(struct task_struct *child, long request, | |||
| 417 | */ | 419 | */ |
| 418 | int ptrace_traceme(void) | 420 | int ptrace_traceme(void) |
| 419 | { | 421 | { |
| 420 | int ret; | 422 | int ret = -EPERM; |
| 421 | 423 | ||
| 422 | /* | 424 | /* |
| 423 | * Are we already being traced? | 425 | * Are we already being traced? |
| 424 | */ | 426 | */ |
| 425 | if (current->ptrace & PT_PTRACED) | 427 | task_lock(current); |
| 426 | return -EPERM; | 428 | if (!(current->ptrace & PT_PTRACED)) { |
| 427 | ret = security_ptrace(current->parent, current); | 429 | ret = security_ptrace(current->parent, current); |
| 428 | if (ret) | 430 | /* |
| 429 | return -EPERM; | 431 | * Set the ptrace bit in the process ptrace flags. |
| 430 | /* | 432 | */ |
| 431 | * Set the ptrace bit in the process ptrace flags. | 433 | if (!ret) |
| 432 | */ | 434 | current->ptrace |= PT_PTRACED; |
| 433 | current->ptrace |= PT_PTRACED; | 435 | } |
| 434 | return 0; | 436 | task_unlock(current); |
| 437 | return ret; | ||
| 435 | } | 438 | } |
| 436 | 439 | ||
| 437 | /** | 440 | /** |
