diff options
Diffstat (limited to 'kernel/ptrace.c')
-rw-r--r-- | kernel/ptrace.c | 35 |
1 files changed, 29 insertions, 6 deletions
diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 45a8a4c5d8b2..dcf9f974198c 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c | |||
@@ -209,10 +209,28 @@ bool ptrace_may_access(struct task_struct *task, unsigned int mode) | |||
209 | return !err; | 209 | return !err; |
210 | } | 210 | } |
211 | 211 | ||
212 | static int ptrace_attach(struct task_struct *task) | 212 | static int ptrace_attach(struct task_struct *task, long request, |
213 | unsigned long flags) | ||
213 | { | 214 | { |
215 | bool seize = (request == PTRACE_SEIZE); | ||
214 | int retval; | 216 | int retval; |
215 | 217 | ||
218 | /* | ||
219 | * SEIZE will enable new ptrace behaviors which will be implemented | ||
220 | * gradually. SEIZE_DEVEL is used to prevent applications | ||
221 | * expecting full SEIZE behaviors trapping on kernel commits which | ||
222 | * are still in the process of implementing them. | ||
223 | * | ||
224 | * Only test programs for new ptrace behaviors being implemented | ||
225 | * should set SEIZE_DEVEL. If unset, SEIZE will fail with -EIO. | ||
226 | * | ||
227 | * Once SEIZE behaviors are completely implemented, this flag and | ||
228 | * the following test will be removed. | ||
229 | */ | ||
230 | retval = -EIO; | ||
231 | if (seize && !(flags & PTRACE_SEIZE_DEVEL)) | ||
232 | goto out; | ||
233 | |||
216 | audit_ptrace(task); | 234 | audit_ptrace(task); |
217 | 235 | ||
218 | retval = -EPERM; | 236 | retval = -EPERM; |
@@ -244,11 +262,16 @@ static int ptrace_attach(struct task_struct *task) | |||
244 | goto unlock_tasklist; | 262 | goto unlock_tasklist; |
245 | 263 | ||
246 | task->ptrace = PT_PTRACED; | 264 | task->ptrace = PT_PTRACED; |
265 | if (seize) | ||
266 | task->ptrace |= PT_SEIZED; | ||
247 | if (task_ns_capable(task, CAP_SYS_PTRACE)) | 267 | if (task_ns_capable(task, CAP_SYS_PTRACE)) |
248 | task->ptrace |= PT_PTRACE_CAP; | 268 | task->ptrace |= PT_PTRACE_CAP; |
249 | 269 | ||
250 | __ptrace_link(task, current); | 270 | __ptrace_link(task, current); |
251 | send_sig_info(SIGSTOP, SEND_SIG_FORCED, task); | 271 | |
272 | /* SEIZE doesn't trap tracee on attach */ | ||
273 | if (!seize) | ||
274 | send_sig_info(SIGSTOP, SEND_SIG_FORCED, task); | ||
252 | 275 | ||
253 | spin_lock(&task->sighand->siglock); | 276 | spin_lock(&task->sighand->siglock); |
254 | 277 | ||
@@ -785,8 +808,8 @@ SYSCALL_DEFINE4(ptrace, long, request, long, pid, unsigned long, addr, | |||
785 | goto out; | 808 | goto out; |
786 | } | 809 | } |
787 | 810 | ||
788 | if (request == PTRACE_ATTACH) { | 811 | if (request == PTRACE_ATTACH || request == PTRACE_SEIZE) { |
789 | ret = ptrace_attach(child); | 812 | ret = ptrace_attach(child, request, data); |
790 | /* | 813 | /* |
791 | * Some architectures need to do book-keeping after | 814 | * Some architectures need to do book-keeping after |
792 | * a ptrace attach. | 815 | * a ptrace attach. |
@@ -927,8 +950,8 @@ asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid, | |||
927 | goto out; | 950 | goto out; |
928 | } | 951 | } |
929 | 952 | ||
930 | if (request == PTRACE_ATTACH) { | 953 | if (request == PTRACE_ATTACH || request == PTRACE_SEIZE) { |
931 | ret = ptrace_attach(child); | 954 | ret = ptrace_attach(child, request, data); |
932 | /* | 955 | /* |
933 | * Some architectures need to do book-keeping after | 956 | * Some architectures need to do book-keeping after |
934 | * a ptrace attach. | 957 | * a ptrace attach. |