| .. | .. |
|---|
| 190 | 190 | spin_lock_irq(&task->sighand->siglock); |
|---|
| 191 | 191 | if (task_is_traced(task) && !looks_like_a_spurious_pid(task) && |
|---|
| 192 | 192 | !__fatal_signal_pending(task)) { |
|---|
| 193 | | - task->state = __TASK_TRACED; |
|---|
| 193 | + unsigned long flags; |
|---|
| 194 | + |
|---|
| 195 | + raw_spin_lock_irqsave(&task->pi_lock, flags); |
|---|
| 196 | + if (task->state & __TASK_TRACED) |
|---|
| 197 | + task->state = __TASK_TRACED; |
|---|
| 198 | + else |
|---|
| 199 | + task->saved_state = __TASK_TRACED; |
|---|
| 200 | + raw_spin_unlock_irqrestore(&task->pi_lock, flags); |
|---|
| 194 | 201 | ret = true; |
|---|
| 195 | 202 | } |
|---|
| 196 | 203 | spin_unlock_irq(&task->sighand->siglock); |
|---|
| .. | .. |
|---|
| 200 | 207 | |
|---|
| 201 | 208 | static void ptrace_unfreeze_traced(struct task_struct *task) |
|---|
| 202 | 209 | { |
|---|
| 203 | | - if (task->state != __TASK_TRACED) |
|---|
| 204 | | - return; |
|---|
| 210 | + unsigned long flags; |
|---|
| 211 | + bool frozen = true; |
|---|
| 205 | 212 | |
|---|
| 206 | 213 | WARN_ON(!task->ptrace || task->parent != current); |
|---|
| 207 | 214 | |
|---|
| .. | .. |
|---|
| 210 | 217 | * Recheck state under the lock to close this race. |
|---|
| 211 | 218 | */ |
|---|
| 212 | 219 | spin_lock_irq(&task->sighand->siglock); |
|---|
| 213 | | - if (task->state == __TASK_TRACED) { |
|---|
| 214 | | - if (__fatal_signal_pending(task)) |
|---|
| 215 | | - wake_up_state(task, __TASK_TRACED); |
|---|
| 216 | | - else |
|---|
| 217 | | - task->state = TASK_TRACED; |
|---|
| 218 | | - } |
|---|
| 220 | + |
|---|
| 221 | + raw_spin_lock_irqsave(&task->pi_lock, flags); |
|---|
| 222 | + if (task->state == __TASK_TRACED) |
|---|
| 223 | + task->state = TASK_TRACED; |
|---|
| 224 | + else if (task->saved_state == __TASK_TRACED) |
|---|
| 225 | + task->saved_state = TASK_TRACED; |
|---|
| 226 | + else |
|---|
| 227 | + frozen = false; |
|---|
| 228 | + raw_spin_unlock_irqrestore(&task->pi_lock, flags); |
|---|
| 229 | + |
|---|
| 230 | + if (frozen && __fatal_signal_pending(task)) |
|---|
| 231 | + wake_up_state(task, __TASK_TRACED); |
|---|
| 232 | + |
|---|
| 219 | 233 | spin_unlock_irq(&task->sighand->siglock); |
|---|
| 220 | 234 | } |
|---|
| 221 | 235 | |
|---|