Blame view

kernel/ptrace.c 29.9 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
  /*
   * linux/kernel/ptrace.c
   *
   * (C) Copyright 1999 Linus Torvalds
   *
   * Common interfaces for "ptrace()" which we do not want
   * to continually duplicate across every architecture.
   */
c59ede7b7   Randy.Dunlap   [PATCH] move capa...
9
  #include <linux/capability.h>
9984de1a5   Paul Gortmaker   kernel: Map most ...
10
  #include <linux/export.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
11
12
13
14
15
  #include <linux/sched.h>
  #include <linux/errno.h>
  #include <linux/mm.h>
  #include <linux/highmem.h>
  #include <linux/pagemap.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
16
17
  #include <linux/ptrace.h>
  #include <linux/security.h>
7ed20e1ad   Jesper Juhl   [PATCH] convert t...
18
  #include <linux/signal.h>
a27bb332c   Kent Overstreet   aio: don't includ...
19
  #include <linux/uio.h>
a5cb013da   Al Viro   [PATCH] auditing ...
20
  #include <linux/audit.h>
b488893a3   Pavel Emelyanov   pid namespaces: c...
21
  #include <linux/pid_namespace.h>
f17d30a80   Adrian Bunk   kernel/ptrace.c s...
22
  #include <linux/syscalls.h>
3a7097035   Roland McGrath   ptrace: some chec...
23
  #include <linux/uaccess.h>
2225a122a   Suresh Siddha   ptrace: Add suppo...
24
  #include <linux/regset.h>
bf26c0184   Frederic Weisbecker   ptrace: Prepare t...
25
  #include <linux/hw_breakpoint.h>
f701e5b73   Vladimir Zapolskiy   connector: add an...
26
  #include <linux/cn_proc.h>
84c751bd4   Andrey Vagin   ptrace: add abili...
27
  #include <linux/compat.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28

bf53de907   Markus Metzger   x86, bts: add for...
29

62c124ff3   Tejun Heo   ptrace: use bit_w...
30
31
32
33
34
  static int ptrace_trapping_sleep_fn(void *flags)
  {
  	schedule();
  	return 0;
  }
bf53de907   Markus Metzger   x86, bts: add for...
35
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
36
37
38
39
40
   * ptrace a task: make the debugger its new parent and
   * move it to the ptrace list.
   *
   * Must be called with the tasklist lock write-held.
   */
36c8b5868   Ingo Molnar   [PATCH] sched: cl...
41
  void __ptrace_link(struct task_struct *child, struct task_struct *new_parent)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42
  {
f470021ad   Roland McGrath   ptrace children r...
43
44
  	BUG_ON(!list_empty(&child->ptrace_entry));
  	list_add(&child->ptrace_entry, &new_parent->ptraced);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45
  	child->parent = new_parent;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46
  }
3a7097035   Roland McGrath   ptrace: some chec...
47

e3bd058f6   Tejun Heo   ptrace: Collapse ...
48
49
50
  /**
   * __ptrace_unlink - unlink ptracee and restore its execution state
   * @child: ptracee to be unlinked
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
   *
0e9f0a4ab   Tejun Heo   ptrace: Always pu...
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
   * Remove @child from the ptrace list, move it back to the original parent,
   * and restore the execution state so that it conforms to the group stop
   * state.
   *
   * Unlinking can happen via two paths - explicit PTRACE_DETACH or ptracer
   * exiting.  For PTRACE_DETACH, unless the ptracee has been killed between
   * ptrace_check_attach() and here, it's guaranteed to be in TASK_TRACED.
   * If the ptracer is exiting, the ptracee can be in any state.
   *
   * After detach, the ptracee should be in a state which conforms to the
   * group stop.  If the group is stopped or in the process of stopping, the
   * ptracee should be put into TASK_STOPPED; otherwise, it should be woken
   * up from TASK_TRACED.
   *
   * If the ptracee is in TASK_TRACED and needs to be moved to TASK_STOPPED,
   * it goes through TRACED -> RUNNING -> STOPPED transition which is similar
   * to but in the opposite direction of what happens while attaching to a
   * stopped task.  However, in this direction, the intermediate RUNNING
   * state is not hidden even from the current ptracer and if it immediately
   * re-attaches and performs a WNOHANG wait(2), it may fail.
e3bd058f6   Tejun Heo   ptrace: Collapse ...
72
73
74
   *
   * CONTEXT:
   * write_lock_irq(tasklist_lock)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
75
   */
36c8b5868   Ingo Molnar   [PATCH] sched: cl...
76
  void __ptrace_unlink(struct task_struct *child)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
77
  {
5ecfbae09   Oleg Nesterov   [PATCH] fix zap_t...
78
  	BUG_ON(!child->ptrace);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
79
  	child->ptrace = 0;
f470021ad   Roland McGrath   ptrace children r...
80
81
  	child->parent = child->real_parent;
  	list_del_init(&child->ptrace_entry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
82

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
83
  	spin_lock(&child->sighand->siglock);
0e9f0a4ab   Tejun Heo   ptrace: Always pu...
84
85
  
  	/*
73ddff2be   Tejun Heo   job control: intr...
86
87
88
89
90
91
92
  	 * Clear all pending traps and TRAPPING.  TRAPPING should be
  	 * cleared regardless of JOBCTL_STOP_PENDING.  Do it explicitly.
  	 */
  	task_clear_jobctl_pending(child, JOBCTL_TRAP_MASK);
  	task_clear_jobctl_trapping(child);
  
  	/*
a8f072c1d   Tejun Heo   job control: rena...
93
  	 * Reinstate JOBCTL_STOP_PENDING if group stop is in effect and
0e9f0a4ab   Tejun Heo   ptrace: Always pu...
94
95
96
97
  	 * @child isn't dead.
  	 */
  	if (!(child->flags & PF_EXITING) &&
  	    (child->signal->flags & SIGNAL_STOP_STOPPED ||
8a88951b5   Oleg Nesterov   ptrace: ensure JO...
98
  	     child->signal->group_stop_count)) {
a8f072c1d   Tejun Heo   job control: rena...
99
  		child->jobctl |= JOBCTL_STOP_PENDING;
0e9f0a4ab   Tejun Heo   ptrace: Always pu...
100

8a88951b5   Oleg Nesterov   ptrace: ensure JO...
101
102
103
104
105
106
107
108
109
110
  		/*
  		 * This is only possible if this thread was cloned by the
  		 * traced task running in the stopped group, set the signal
  		 * for the future reports.
  		 * FIXME: we should change ptrace_init_task() to handle this
  		 * case.
  		 */
  		if (!(child->jobctl & JOBCTL_STOP_SIGMASK))
  			child->jobctl |= SIGSTOP;
  	}
0e9f0a4ab   Tejun Heo   ptrace: Always pu...
111
112
113
114
115
116
  	/*
  	 * If transition to TASK_STOPPED is pending or in TASK_TRACED, kick
  	 * @child in the butt.  Note that @resume should be used iff @child
  	 * is in TASK_TRACED; otherwise, we might unduly disrupt
  	 * TASK_KILLABLE sleeps.
  	 */
a8f072c1d   Tejun Heo   job control: rena...
117
  	if (child->jobctl & JOBCTL_STOP_PENDING || task_is_traced(child))
910ffdb18   Oleg Nesterov   ptrace: introduce...
118
  		ptrace_signal_wake_up(child, true);
0e9f0a4ab   Tejun Heo   ptrace: Always pu...
119

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
120
  	spin_unlock(&child->sighand->siglock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
121
  }
9899d11f6   Oleg Nesterov   ptrace: ensure ar...
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
  /* Ensure that nothing can wake it up, even SIGKILL */
  static bool ptrace_freeze_traced(struct task_struct *task)
  {
  	bool ret = false;
  
  	/* Lockless, nobody but us can set this flag */
  	if (task->jobctl & JOBCTL_LISTENING)
  		return ret;
  
  	spin_lock_irq(&task->sighand->siglock);
  	if (task_is_traced(task) && !__fatal_signal_pending(task)) {
  		task->state = __TASK_TRACED;
  		ret = true;
  	}
  	spin_unlock_irq(&task->sighand->siglock);
  
  	return ret;
  }
  
  static void ptrace_unfreeze_traced(struct task_struct *task)
  {
  	if (task->state != __TASK_TRACED)
  		return;
  
  	WARN_ON(!task->ptrace || task->parent != current);
  
  	spin_lock_irq(&task->sighand->siglock);
  	if (__fatal_signal_pending(task))
  		wake_up_state(task, __TASK_TRACED);
  	else
  		task->state = TASK_TRACED;
  	spin_unlock_irq(&task->sighand->siglock);
  }
755e276b3   Tejun Heo   ptrace: ptrace_ch...
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
  /**
   * ptrace_check_attach - check whether ptracee is ready for ptrace operation
   * @child: ptracee to check for
   * @ignore_state: don't check whether @child is currently %TASK_TRACED
   *
   * Check whether @child is being ptraced by %current and ready for further
   * ptrace operations.  If @ignore_state is %false, @child also should be in
   * %TASK_TRACED state and on return the child is guaranteed to be traced
   * and not executing.  If @ignore_state is %true, @child can be in any
   * state.
   *
   * CONTEXT:
   * Grabs and releases tasklist_lock and @child->sighand->siglock.
   *
   * RETURNS:
   * 0 on success, -ESRCH if %child is not ready.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
171
   */
edea0d03e   Oleg Nesterov   ia64: kill thread...
172
  static int ptrace_check_attach(struct task_struct *child, bool ignore_state)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
173
174
175
176
177
178
179
180
181
182
183
  {
  	int ret = -ESRCH;
  
  	/*
  	 * We take the read lock around doing both checks to close a
  	 * possible race where someone else was tracing our child and
  	 * detached between these two checks.  After this locked check,
  	 * we are sure that this is our traced child and that can only
  	 * be changed by us so it's not changing right after this.
  	 */
  	read_lock(&tasklist_lock);
9899d11f6   Oleg Nesterov   ptrace: ensure ar...
184
185
  	if (child->ptrace && child->parent == current) {
  		WARN_ON(child->state == __TASK_TRACED);
c0c0b649d   Oleg Nesterov   ptrace_check_atta...
186
187
188
189
  		/*
  		 * child->sighand can't be NULL, release_task()
  		 * does ptrace_unlink() before __exit_signal().
  		 */
9899d11f6   Oleg Nesterov   ptrace: ensure ar...
190
  		if (ignore_state || ptrace_freeze_traced(child))
321fb5619   Oleg Nesterov   ptrace: ptrace_ch...
191
  			ret = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
192
193
  	}
  	read_unlock(&tasklist_lock);
9899d11f6   Oleg Nesterov   ptrace: ensure ar...
194
195
196
197
198
199
200
201
202
203
204
  	if (!ret && !ignore_state) {
  		if (!wait_task_inactive(child, __TASK_TRACED)) {
  			/*
  			 * This can only happen if may_ptrace_stop() fails and
  			 * ptrace_stop() changes ->state back to TASK_RUNNING,
  			 * so we should not worry about leaking __TASK_TRACED.
  			 */
  			WARN_ON(child->state == __TASK_TRACED);
  			ret = -ESRCH;
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
205

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
206
207
  	return ret;
  }
69f594a38   Eric Paris   ptrace: do not au...
208
209
210
211
212
213
214
  static int ptrace_has_cap(struct user_namespace *ns, unsigned int mode)
  {
  	if (mode & PTRACE_MODE_NOAUDIT)
  		return has_ns_capability_noaudit(current, ns, CAP_SYS_PTRACE);
  	else
  		return has_ns_capability(current, ns, CAP_SYS_PTRACE);
  }
9f99798ff   Tetsuo Handa   ptrace: mark __pt...
215
216
  /* Returns 0 on success, -errno on denial. */
  static int __ptrace_may_access(struct task_struct *task, unsigned int mode)
ab8d11beb   Miklos Szeredi   [PATCH] remove du...
217
  {
c69e8d9c0   David Howells   CRED: Use RCU to ...
218
  	const struct cred *cred = current_cred(), *tcred;
b6dff3ec5   David Howells   CRED: Separate ta...
219

df26c40e5   Eric W. Biederman   [PATCH] proc: Cle...
220
221
222
223
224
225
226
227
228
229
  	/* May we inspect the given task?
  	 * This check is used both for attaching with ptrace
  	 * and for allowing access to sensitive information in /proc.
  	 *
  	 * ptrace_attach denies several cases that /proc allows
  	 * because setting up the necessary parent/child relationship
  	 * or halting the specified task is impossible.
  	 */
  	int dumpable = 0;
  	/* Don't let security modules deny introspection */
73af963f9   Mark Grondona   __ptrace_may_acce...
230
  	if (same_thread_group(task, current))
df26c40e5   Eric W. Biederman   [PATCH] proc: Cle...
231
  		return 0;
c69e8d9c0   David Howells   CRED: Use RCU to ...
232
233
  	rcu_read_lock();
  	tcred = __task_cred(task);
5af662030   Eric W. Biederman   userns: Convert p...
234
235
236
237
238
239
  	if (uid_eq(cred->uid, tcred->euid) &&
  	    uid_eq(cred->uid, tcred->suid) &&
  	    uid_eq(cred->uid, tcred->uid)  &&
  	    gid_eq(cred->gid, tcred->egid) &&
  	    gid_eq(cred->gid, tcred->sgid) &&
  	    gid_eq(cred->gid, tcred->gid))
8409cca70   Serge E. Hallyn   userns: allow ptr...
240
  		goto ok;
c4a4d6037   Eric W. Biederman   userns: Use cred-...
241
  	if (ptrace_has_cap(tcred->user_ns, mode))
8409cca70   Serge E. Hallyn   userns: allow ptr...
242
243
244
245
  		goto ok;
  	rcu_read_unlock();
  	return -EPERM;
  ok:
c69e8d9c0   David Howells   CRED: Use RCU to ...
246
  	rcu_read_unlock();
ab8d11beb   Miklos Szeredi   [PATCH] remove du...
247
  	smp_rmb();
df26c40e5   Eric W. Biederman   [PATCH] proc: Cle...
248
  	if (task->mm)
6c5d52382   Kawai, Hidehiro   coredump masking:...
249
  		dumpable = get_dumpable(task->mm);
4c44aaafa   Eric W. Biederman   userns: Kill task...
250
251
252
  	rcu_read_lock();
  	if (!dumpable && !ptrace_has_cap(__task_cred(task)->user_ns, mode)) {
  		rcu_read_unlock();
ab8d11beb   Miklos Szeredi   [PATCH] remove du...
253
  		return -EPERM;
4c44aaafa   Eric W. Biederman   userns: Kill task...
254
255
  	}
  	rcu_read_unlock();
ab8d11beb   Miklos Szeredi   [PATCH] remove du...
256

9e48858f7   Ingo Molnar   security: rename ...
257
  	return security_ptrace_access_check(task, mode);
ab8d11beb   Miklos Szeredi   [PATCH] remove du...
258
  }
006ebb40d   Stephen Smalley   Security: split p...
259
  bool ptrace_may_access(struct task_struct *task, unsigned int mode)
ab8d11beb   Miklos Szeredi   [PATCH] remove du...
260
261
262
  {
  	int err;
  	task_lock(task);
006ebb40d   Stephen Smalley   Security: split p...
263
  	err = __ptrace_may_access(task, mode);
ab8d11beb   Miklos Szeredi   [PATCH] remove du...
264
  	task_unlock(task);
3a7097035   Roland McGrath   ptrace: some chec...
265
  	return !err;
ab8d11beb   Miklos Szeredi   [PATCH] remove du...
266
  }
3544d72a0   Tejun Heo   ptrace: implement...
267
  static int ptrace_attach(struct task_struct *task, long request,
aa9147c98   Denys Vlasenko   ptrace: make PTRA...
268
  			 unsigned long addr,
3544d72a0   Tejun Heo   ptrace: implement...
269
  			 unsigned long flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
270
  {
3544d72a0   Tejun Heo   ptrace: implement...
271
  	bool seize = (request == PTRACE_SEIZE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
272
  	int retval;
f5b40e363   Linus Torvalds   Fix ptrace_attach...
273

3544d72a0   Tejun Heo   ptrace: implement...
274
  	retval = -EIO;
aa9147c98   Denys Vlasenko   ptrace: make PTRA...
275
276
277
  	if (seize) {
  		if (addr != 0)
  			goto out;
aa9147c98   Denys Vlasenko   ptrace: make PTRA...
278
279
280
281
282
283
  		if (flags & ~(unsigned long)PTRACE_O_MASK)
  			goto out;
  		flags = PT_PTRACED | PT_SEIZED | (flags << PT_OPT_FLAG_SHIFT);
  	} else {
  		flags = PT_PTRACED;
  	}
3544d72a0   Tejun Heo   ptrace: implement...
284

a5cb013da   Al Viro   [PATCH] auditing ...
285
  	audit_ptrace(task);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
286
  	retval = -EPERM;
b79b7ba93   Oleg Nesterov   ptrace: ptrace_at...
287
288
  	if (unlikely(task->flags & PF_KTHREAD))
  		goto out;
bac0abd61   Pavel Emelyanov   Isolate some expl...
289
  	if (same_thread_group(task, current))
f5b40e363   Linus Torvalds   Fix ptrace_attach...
290
  		goto out;
f2f0b00ad   Oleg Nesterov   ptrace: cleanup c...
291
292
  	/*
  	 * Protect exec's credential calculations against our interference;
86b6c1f30   Denys Vlasenko   ptrace: simplify ...
293
  	 * SUID, SGID and LSM creds get determined differently
5e751e992   David Howells   CRED: Rename cred...
294
  	 * under ptrace.
d84f4f992   David Howells   CRED: Inaugurate ...
295
  	 */
793285fca   Oleg Nesterov   cred_guard_mutex:...
296
  	retval = -ERESTARTNOINTR;
9b1bf12d5   KOSAKI Motohiro   signals: move cre...
297
  	if (mutex_lock_interruptible(&task->signal->cred_guard_mutex))
d84f4f992   David Howells   CRED: Inaugurate ...
298
  		goto out;
f5b40e363   Linus Torvalds   Fix ptrace_attach...
299

4b105cbba   Oleg Nesterov   ptrace: do not us...
300
  	task_lock(task);
006ebb40d   Stephen Smalley   Security: split p...
301
  	retval = __ptrace_may_access(task, PTRACE_MODE_ATTACH);
4b105cbba   Oleg Nesterov   ptrace: do not us...
302
  	task_unlock(task);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
303
  	if (retval)
4b105cbba   Oleg Nesterov   ptrace: do not us...
304
  		goto unlock_creds;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
305

4b105cbba   Oleg Nesterov   ptrace: do not us...
306
  	write_lock_irq(&tasklist_lock);
b79b7ba93   Oleg Nesterov   ptrace: ptrace_at...
307
308
  	retval = -EPERM;
  	if (unlikely(task->exit_state))
4b105cbba   Oleg Nesterov   ptrace: do not us...
309
  		goto unlock_tasklist;
f2f0b00ad   Oleg Nesterov   ptrace: cleanup c...
310
  	if (task->ptrace)
4b105cbba   Oleg Nesterov   ptrace: do not us...
311
  		goto unlock_tasklist;
b79b7ba93   Oleg Nesterov   ptrace: ptrace_at...
312

3544d72a0   Tejun Heo   ptrace: implement...
313
  	if (seize)
aa9147c98   Denys Vlasenko   ptrace: make PTRA...
314
  		flags |= PT_SEIZED;
4c44aaafa   Eric W. Biederman   userns: Kill task...
315
316
  	rcu_read_lock();
  	if (ns_capable(__task_cred(task)->user_ns, CAP_SYS_PTRACE))
aa9147c98   Denys Vlasenko   ptrace: make PTRA...
317
  		flags |= PT_PTRACE_CAP;
4c44aaafa   Eric W. Biederman   userns: Kill task...
318
  	rcu_read_unlock();
aa9147c98   Denys Vlasenko   ptrace: make PTRA...
319
  	task->ptrace = flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
320

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
321
  	__ptrace_link(task, current);
3544d72a0   Tejun Heo   ptrace: implement...
322
323
324
325
  
  	/* SEIZE doesn't trap tracee on attach */
  	if (!seize)
  		send_sig_info(SIGSTOP, SEND_SIG_FORCED, task);
b79b7ba93   Oleg Nesterov   ptrace: ptrace_at...
326

d79fdd6d9   Tejun Heo   ptrace: Clean tra...
327
328
329
  	spin_lock(&task->sighand->siglock);
  
  	/*
73ddff2be   Tejun Heo   job control: intr...
330
  	 * If the task is already STOPPED, set JOBCTL_TRAP_STOP and
d79fdd6d9   Tejun Heo   ptrace: Clean tra...
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
  	 * TRAPPING, and kick it so that it transits to TRACED.  TRAPPING
  	 * will be cleared if the child completes the transition or any
  	 * event which clears the group stop states happens.  We'll wait
  	 * for the transition to complete before returning from this
  	 * function.
  	 *
  	 * This hides STOPPED -> RUNNING -> TRACED transition from the
  	 * attaching thread but a different thread in the same group can
  	 * still observe the transient RUNNING state.  IOW, if another
  	 * thread's WNOHANG wait(2) on the stopped tracee races against
  	 * ATTACH, the wait(2) may fail due to the transient RUNNING.
  	 *
  	 * The following task_is_stopped() test is safe as both transitions
  	 * in and out of STOPPED are protected by siglock.
  	 */
7dd3db54e   Tejun Heo   job control: intr...
346
  	if (task_is_stopped(task) &&
73ddff2be   Tejun Heo   job control: intr...
347
  	    task_set_jobctl_pending(task, JOBCTL_TRAP_STOP | JOBCTL_TRAPPING))
910ffdb18   Oleg Nesterov   ptrace: introduce...
348
  		signal_wake_up_state(task, __TASK_STOPPED);
d79fdd6d9   Tejun Heo   ptrace: Clean tra...
349
350
  
  	spin_unlock(&task->sighand->siglock);
b79b7ba93   Oleg Nesterov   ptrace: ptrace_at...
351
  	retval = 0;
4b105cbba   Oleg Nesterov   ptrace: do not us...
352
353
354
  unlock_tasklist:
  	write_unlock_irq(&tasklist_lock);
  unlock_creds:
9b1bf12d5   KOSAKI Motohiro   signals: move cre...
355
  	mutex_unlock(&task->signal->cred_guard_mutex);
f5b40e363   Linus Torvalds   Fix ptrace_attach...
356
  out:
f701e5b73   Vladimir Zapolskiy   connector: add an...
357
  	if (!retval) {
62c124ff3   Tejun Heo   ptrace: use bit_w...
358
359
  		wait_on_bit(&task->jobctl, JOBCTL_TRAPPING_BIT,
  			    ptrace_trapping_sleep_fn, TASK_UNINTERRUPTIBLE);
f701e5b73   Vladimir Zapolskiy   connector: add an...
360
361
  		proc_ptrace_connector(task, PTRACE_ATTACH);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
362
363
  	return retval;
  }
f2f0b00ad   Oleg Nesterov   ptrace: cleanup c...
364
365
366
367
368
369
  /**
   * ptrace_traceme  --  helper for PTRACE_TRACEME
   *
   * Performs checks and sets PT_PTRACED.
   * Should be used by all ptrace implementations for PTRACE_TRACEME.
   */
e3e89cc53   Linus Torvalds   Mark ptrace_{trac...
370
  static int ptrace_traceme(void)
f2f0b00ad   Oleg Nesterov   ptrace: cleanup c...
371
372
  {
  	int ret = -EPERM;
4b105cbba   Oleg Nesterov   ptrace: do not us...
373
374
  	write_lock_irq(&tasklist_lock);
  	/* Are we already being traced? */
f2f0b00ad   Oleg Nesterov   ptrace: cleanup c...
375
  	if (!current->ptrace) {
f2f0b00ad   Oleg Nesterov   ptrace: cleanup c...
376
  		ret = security_ptrace_traceme(current->parent);
f2f0b00ad   Oleg Nesterov   ptrace: cleanup c...
377
378
379
380
381
382
383
384
385
  		/*
  		 * Check PF_EXITING to ensure ->real_parent has not passed
  		 * exit_ptrace(). Otherwise we don't report the error but
  		 * pretend ->real_parent untraces us right after return.
  		 */
  		if (!ret && !(current->real_parent->flags & PF_EXITING)) {
  			current->ptrace = PT_PTRACED;
  			__ptrace_link(current, current->real_parent);
  		}
f2f0b00ad   Oleg Nesterov   ptrace: cleanup c...
386
  	}
4b105cbba   Oleg Nesterov   ptrace: do not us...
387
  	write_unlock_irq(&tasklist_lock);
f2f0b00ad   Oleg Nesterov   ptrace: cleanup c...
388
389
  	return ret;
  }
39c626ae4   Oleg Nesterov   forget_original_p...
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
  /*
   * Called with irqs disabled, returns true if childs should reap themselves.
   */
  static int ignoring_children(struct sighand_struct *sigh)
  {
  	int ret;
  	spin_lock(&sigh->siglock);
  	ret = (sigh->action[SIGCHLD-1].sa.sa_handler == SIG_IGN) ||
  	      (sigh->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDWAIT);
  	spin_unlock(&sigh->siglock);
  	return ret;
  }
  
  /*
   * Called with tasklist_lock held for writing.
   * Unlink a traced task, and clean it up if it was a traced zombie.
   * Return true if it needs to be reaped with release_task().
   * (We can't call release_task() here because we already hold tasklist_lock.)
   *
   * If it's a zombie, our attachedness prevented normal parent notification
   * or self-reaping.  Do notification now if it would have happened earlier.
   * If it should reap itself, return true.
   *
a7f0765ed   Oleg Nesterov   ptrace: __ptrace_...
413
414
415
416
   * If it's our own child, there is no notification to do. But if our normal
   * children self-reap, then this child was prevented by ptrace and we must
   * reap it now, in that case we must also wake up sub-threads sleeping in
   * do_wait().
39c626ae4   Oleg Nesterov   forget_original_p...
417
418
419
   */
  static bool __ptrace_detach(struct task_struct *tracer, struct task_struct *p)
  {
9843a1e97   Oleg Nesterov   __ptrace_detach: ...
420
  	bool dead;
39c626ae4   Oleg Nesterov   forget_original_p...
421
  	__ptrace_unlink(p);
9843a1e97   Oleg Nesterov   __ptrace_detach: ...
422
423
424
425
426
427
428
429
430
431
  	if (p->exit_state != EXIT_ZOMBIE)
  		return false;
  
  	dead = !thread_group_leader(p);
  
  	if (!dead && thread_group_empty(p)) {
  		if (!same_thread_group(p->real_parent, tracer))
  			dead = do_notify_parent(p, p->exit_signal);
  		else if (ignoring_children(tracer->sighand)) {
  			__wake_up_parent(p, tracer);
9843a1e97   Oleg Nesterov   __ptrace_detach: ...
432
  			dead = true;
39c626ae4   Oleg Nesterov   forget_original_p...
433
434
  		}
  	}
9843a1e97   Oleg Nesterov   __ptrace_detach: ...
435
436
437
438
  	/* Mark it as in the process of being reaped. */
  	if (dead)
  		p->exit_state = EXIT_DEAD;
  	return dead;
39c626ae4   Oleg Nesterov   forget_original_p...
439
  }
e3e89cc53   Linus Torvalds   Mark ptrace_{trac...
440
  static int ptrace_detach(struct task_struct *child, unsigned int data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
441
  {
39c626ae4   Oleg Nesterov   forget_original_p...
442
  	bool dead = false;
4576145c1   Oleg Nesterov   ptrace: fix possi...
443

7ed20e1ad   Jesper Juhl   [PATCH] convert t...
444
  	if (!valid_signal(data))
5ecfbae09   Oleg Nesterov   [PATCH] fix zap_t...
445
  		return -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
446
447
448
  
  	/* Architecture-specific hardware disable .. */
  	ptrace_disable(child);
7d9414329   Roland McGrath   Fix spurious sysc...
449
  	clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
450

95c3eb76d   Oleg Nesterov   ptrace: kill __pt...
451
  	write_lock_irq(&tasklist_lock);
39c626ae4   Oleg Nesterov   forget_original_p...
452
453
454
455
  	/*
  	 * This child can be already killed. Make sure de_thread() or
  	 * our sub-thread doing do_wait() didn't do release_task() yet.
  	 */
95c3eb76d   Oleg Nesterov   ptrace: kill __pt...
456
457
  	if (child->ptrace) {
  		child->exit_code = data;
4576145c1   Oleg Nesterov   ptrace: fix possi...
458
  		dead = __ptrace_detach(current, child);
95c3eb76d   Oleg Nesterov   ptrace: kill __pt...
459
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
460
  	write_unlock_irq(&tasklist_lock);
f701e5b73   Vladimir Zapolskiy   connector: add an...
461
  	proc_ptrace_connector(child, PTRACE_DETACH);
4576145c1   Oleg Nesterov   ptrace: fix possi...
462
463
  	if (unlikely(dead))
  		release_task(child);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
464
465
  	return 0;
  }
39c626ae4   Oleg Nesterov   forget_original_p...
466
  /*
c7e49c148   Oleg Nesterov   ptrace: optimize ...
467
468
469
   * Detach all tasks we were using ptrace on. Called with tasklist held
   * for writing, and returns with it held too. But note it can release
   * and reacquire the lock.
39c626ae4   Oleg Nesterov   forget_original_p...
470
471
   */
  void exit_ptrace(struct task_struct *tracer)
c4b5ed250   Namhyung Kim   ptrace: annotate ...
472
473
  	__releases(&tasklist_lock)
  	__acquires(&tasklist_lock)
39c626ae4   Oleg Nesterov   forget_original_p...
474
475
476
  {
  	struct task_struct *p, *n;
  	LIST_HEAD(ptrace_dead);
c7e49c148   Oleg Nesterov   ptrace: optimize ...
477
478
  	if (likely(list_empty(&tracer->ptraced)))
  		return;
39c626ae4   Oleg Nesterov   forget_original_p...
479
  	list_for_each_entry_safe(p, n, &tracer->ptraced, ptrace_entry) {
992fb6e17   Oleg Nesterov   ptrace: introduce...
480
481
  		if (unlikely(p->ptrace & PT_EXITKILL))
  			send_sig_info(SIGKILL, SEND_SIG_FORCED, p);
39c626ae4   Oleg Nesterov   forget_original_p...
482
483
484
  		if (__ptrace_detach(tracer, p))
  			list_add(&p->ptrace_entry, &ptrace_dead);
  	}
39c626ae4   Oleg Nesterov   forget_original_p...
485

c7e49c148   Oleg Nesterov   ptrace: optimize ...
486
  	write_unlock_irq(&tasklist_lock);
39c626ae4   Oleg Nesterov   forget_original_p...
487
488
489
490
491
492
  	BUG_ON(!list_empty(&tracer->ptraced));
  
  	list_for_each_entry_safe(p, n, &ptrace_dead, ptrace_entry) {
  		list_del_init(&p->ptrace_entry);
  		release_task(p);
  	}
c7e49c148   Oleg Nesterov   ptrace: optimize ...
493
494
  
  	write_lock_irq(&tasklist_lock);
39c626ae4   Oleg Nesterov   forget_original_p...
495
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
  int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len)
  {
  	int copied = 0;
  
  	while (len > 0) {
  		char buf[128];
  		int this_len, retval;
  
  		this_len = (len > sizeof(buf)) ? sizeof(buf) : len;
  		retval = access_process_vm(tsk, src, buf, this_len, 0);
  		if (!retval) {
  			if (copied)
  				break;
  			return -EIO;
  		}
  		if (copy_to_user(dst, buf, retval))
  			return -EFAULT;
  		copied += retval;
  		src += retval;
  		dst += retval;
3a7097035   Roland McGrath   ptrace: some chec...
516
  		len -= retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
  	}
  	return copied;
  }
  
  int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len)
  {
  	int copied = 0;
  
  	while (len > 0) {
  		char buf[128];
  		int this_len, retval;
  
  		this_len = (len > sizeof(buf)) ? sizeof(buf) : len;
  		if (copy_from_user(buf, src, this_len))
  			return -EFAULT;
  		retval = access_process_vm(tsk, dst, buf, this_len, 1);
  		if (!retval) {
  			if (copied)
  				break;
  			return -EIO;
  		}
  		copied += retval;
  		src += retval;
  		dst += retval;
3a7097035   Roland McGrath   ptrace: some chec...
541
  		len -= retval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
542
543
544
  	}
  	return copied;
  }
4abf98696   Namhyung Kim   ptrace: change si...
545
  static int ptrace_setoptions(struct task_struct *child, unsigned long data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
546
  {
86b6c1f30   Denys Vlasenko   ptrace: simplify ...
547
  	unsigned flags;
8c5cf9e5c   Denys Vlasenko   ptrace: don't mod...
548
549
  	if (data & ~(unsigned long)PTRACE_O_MASK)
  		return -EINVAL;
86b6c1f30   Denys Vlasenko   ptrace: simplify ...
550
551
552
553
554
  	/* Avoid intermediate state when all opts are cleared */
  	flags = child->ptrace;
  	flags &= ~(PTRACE_O_MASK << PT_OPT_FLAG_SHIFT);
  	flags |= (data << PT_OPT_FLAG_SHIFT);
  	child->ptrace = flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
555

8c5cf9e5c   Denys Vlasenko   ptrace: don't mod...
556
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
557
  }
e16b27816   Roland McGrath   ptrace: compat_pt...
558
  static int ptrace_getsiginfo(struct task_struct *child, siginfo_t *info)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
559
  {
e49612544   Oleg Nesterov   ptrace: don't tak...
560
  	unsigned long flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
561
  	int error = -ESRCH;
e49612544   Oleg Nesterov   ptrace: don't tak...
562
  	if (lock_task_sighand(child, &flags)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
563
  		error = -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
564
  		if (likely(child->last_siginfo != NULL)) {
e16b27816   Roland McGrath   ptrace: compat_pt...
565
  			*info = *child->last_siginfo;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
566
567
  			error = 0;
  		}
e49612544   Oleg Nesterov   ptrace: don't tak...
568
  		unlock_task_sighand(child, &flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
569
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
570
571
  	return error;
  }
e16b27816   Roland McGrath   ptrace: compat_pt...
572
  static int ptrace_setsiginfo(struct task_struct *child, const siginfo_t *info)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
573
  {
e49612544   Oleg Nesterov   ptrace: don't tak...
574
  	unsigned long flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
575
  	int error = -ESRCH;
e49612544   Oleg Nesterov   ptrace: don't tak...
576
  	if (lock_task_sighand(child, &flags)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
577
  		error = -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
578
  		if (likely(child->last_siginfo != NULL)) {
e16b27816   Roland McGrath   ptrace: compat_pt...
579
  			*child->last_siginfo = *info;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
580
581
  			error = 0;
  		}
e49612544   Oleg Nesterov   ptrace: don't tak...
582
  		unlock_task_sighand(child, &flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
583
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
584
585
  	return error;
  }
84c751bd4   Andrey Vagin   ptrace: add abili...
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
  static int ptrace_peek_siginfo(struct task_struct *child,
  				unsigned long addr,
  				unsigned long data)
  {
  	struct ptrace_peeksiginfo_args arg;
  	struct sigpending *pending;
  	struct sigqueue *q;
  	int ret, i;
  
  	ret = copy_from_user(&arg, (void __user *) addr,
  				sizeof(struct ptrace_peeksiginfo_args));
  	if (ret)
  		return -EFAULT;
  
  	if (arg.flags & ~PTRACE_PEEKSIGINFO_SHARED)
  		return -EINVAL; /* unknown flags */
  
  	if (arg.nr < 0)
  		return -EINVAL;
  
  	if (arg.flags & PTRACE_PEEKSIGINFO_SHARED)
  		pending = &child->signal->shared_pending;
  	else
  		pending = &child->pending;
  
  	for (i = 0; i < arg.nr; ) {
  		siginfo_t info;
  		s32 off = arg.off + i;
  
  		spin_lock_irq(&child->sighand->siglock);
  		list_for_each_entry(q, &pending->list, list) {
  			if (!off--) {
  				copy_siginfo(&info, &q->info);
  				break;
  			}
  		}
  		spin_unlock_irq(&child->sighand->siglock);
  
  		if (off >= 0) /* beyond the end of the list */
  			break;
  
  #ifdef CONFIG_COMPAT
  		if (unlikely(is_compat_task())) {
  			compat_siginfo_t __user *uinfo = compat_ptr(data);
706b23bde   Mathieu Desnoyers   Fix: kernel/ptrac...
630
631
632
633
634
  			if (copy_siginfo_to_user32(uinfo, &info) ||
  			    __put_user(info.si_code, &uinfo->si_code)) {
  				ret = -EFAULT;
  				break;
  			}
84c751bd4   Andrey Vagin   ptrace: add abili...
635
636
637
638
  		} else
  #endif
  		{
  			siginfo_t __user *uinfo = (siginfo_t __user *) data;
706b23bde   Mathieu Desnoyers   Fix: kernel/ptrac...
639
640
641
642
643
  			if (copy_siginfo_to_user(uinfo, &info) ||
  			    __put_user(info.si_code, &uinfo->si_code)) {
  				ret = -EFAULT;
  				break;
  			}
84c751bd4   Andrey Vagin   ptrace: add abili...
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
  		}
  
  		data += sizeof(siginfo_t);
  		i++;
  
  		if (signal_pending(current))
  			break;
  
  		cond_resched();
  	}
  
  	if (i > 0)
  		return i;
  
  	return ret;
  }
36df29d79   Roland McGrath   ptrace: generic r...
660
661
662
663
664
665
  
  #ifdef PTRACE_SINGLESTEP
  #define is_singlestep(request)		((request) == PTRACE_SINGLESTEP)
  #else
  #define is_singlestep(request)		0
  #endif
5b88abbf7   Roland McGrath   ptrace: generic P...
666
667
668
669
670
  #ifdef PTRACE_SINGLEBLOCK
  #define is_singleblock(request)		((request) == PTRACE_SINGLEBLOCK)
  #else
  #define is_singleblock(request)		0
  #endif
36df29d79   Roland McGrath   ptrace: generic r...
671
672
673
674
675
  #ifdef PTRACE_SYSEMU
  #define is_sysemu_singlestep(request)	((request) == PTRACE_SYSEMU_SINGLESTEP)
  #else
  #define is_sysemu_singlestep(request)	0
  #endif
4abf98696   Namhyung Kim   ptrace: change si...
676
677
  static int ptrace_resume(struct task_struct *child, long request,
  			 unsigned long data)
36df29d79   Roland McGrath   ptrace: generic r...
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
  {
  	if (!valid_signal(data))
  		return -EIO;
  
  	if (request == PTRACE_SYSCALL)
  		set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
  	else
  		clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
  
  #ifdef TIF_SYSCALL_EMU
  	if (request == PTRACE_SYSEMU || request == PTRACE_SYSEMU_SINGLESTEP)
  		set_tsk_thread_flag(child, TIF_SYSCALL_EMU);
  	else
  		clear_tsk_thread_flag(child, TIF_SYSCALL_EMU);
  #endif
5b88abbf7   Roland McGrath   ptrace: generic P...
693
694
695
696
697
  	if (is_singleblock(request)) {
  		if (unlikely(!arch_has_block_step()))
  			return -EIO;
  		user_enable_block_step(child);
  	} else if (is_singlestep(request) || is_sysemu_singlestep(request)) {
36df29d79   Roland McGrath   ptrace: generic r...
698
699
700
  		if (unlikely(!arch_has_single_step()))
  			return -EIO;
  		user_enable_single_step(child);
3a7097035   Roland McGrath   ptrace: some chec...
701
  	} else {
36df29d79   Roland McGrath   ptrace: generic r...
702
  		user_disable_single_step(child);
3a7097035   Roland McGrath   ptrace: some chec...
703
  	}
36df29d79   Roland McGrath   ptrace: generic r...
704
705
  
  	child->exit_code = data;
0666fb51b   Oleg Nesterov   ptrace: ptrace_re...
706
  	wake_up_state(child, __TASK_TRACED);
36df29d79   Roland McGrath   ptrace: generic r...
707
708
709
  
  	return 0;
  }
2225a122a   Suresh Siddha   ptrace: Add suppo...
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
  #ifdef CONFIG_HAVE_ARCH_TRACEHOOK
  
  static const struct user_regset *
  find_regset(const struct user_regset_view *view, unsigned int type)
  {
  	const struct user_regset *regset;
  	int n;
  
  	for (n = 0; n < view->n; ++n) {
  		regset = view->regsets + n;
  		if (regset->core_note_type == type)
  			return regset;
  	}
  
  	return NULL;
  }
  
  static int ptrace_regset(struct task_struct *task, int req, unsigned int type,
  			 struct iovec *kiov)
  {
  	const struct user_regset_view *view = task_user_regset_view(task);
  	const struct user_regset *regset = find_regset(view, type);
  	int regset_no;
  
  	if (!regset || (kiov->iov_len % regset->size) != 0)
c6a0dd7ec   Suresh Siddha   ptrace: Fix ptrac...
735
  		return -EINVAL;
2225a122a   Suresh Siddha   ptrace: Add suppo...
736
737
738
739
740
741
742
743
744
745
746
747
  
  	regset_no = regset - view->regsets;
  	kiov->iov_len = min(kiov->iov_len,
  			    (__kernel_size_t) (regset->n * regset->size));
  
  	if (req == PTRACE_GETREGSET)
  		return copy_regset_to_user(task, view, regset_no, 0,
  					   kiov->iov_len, kiov->iov_base);
  	else
  		return copy_regset_from_user(task, view, regset_no, 0,
  					     kiov->iov_len, kiov->iov_base);
  }
e8440c145   Josh Stone   uprobes: Add expo...
748
749
750
751
752
753
  /*
   * This is declared in linux/regset.h and defined in machine-dependent
   * code.  We put the export here, near the primary machine-neutral use,
   * to ensure no machine forgets it.
   */
  EXPORT_SYMBOL_GPL(task_user_regset_view);
2225a122a   Suresh Siddha   ptrace: Add suppo...
754
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
755
  int ptrace_request(struct task_struct *child, long request,
4abf98696   Namhyung Kim   ptrace: change si...
756
  		   unsigned long addr, unsigned long data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
757
  {
fca26f260   Tejun Heo   ptrace: implement...
758
  	bool seized = child->ptrace & PT_SEIZED;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
759
  	int ret = -EIO;
544b2c91a   Tejun Heo   ptrace: implement...
760
  	siginfo_t siginfo, *si;
9fed81dc4   Namhyung Kim   ptrace: cleanup p...
761
762
  	void __user *datavp = (void __user *) data;
  	unsigned long __user *datalp = datavp;
fca26f260   Tejun Heo   ptrace: implement...
763
  	unsigned long flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
764
765
  
  	switch (request) {
16c3e389e   Roland McGrath   x86: ptrace_reque...
766
767
768
769
770
771
  	case PTRACE_PEEKTEXT:
  	case PTRACE_PEEKDATA:
  		return generic_ptrace_peekdata(child, addr, data);
  	case PTRACE_POKETEXT:
  	case PTRACE_POKEDATA:
  		return generic_ptrace_pokedata(child, addr, data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
772
773
774
775
776
777
778
  #ifdef PTRACE_OLDSETOPTIONS
  	case PTRACE_OLDSETOPTIONS:
  #endif
  	case PTRACE_SETOPTIONS:
  		ret = ptrace_setoptions(child, data);
  		break;
  	case PTRACE_GETEVENTMSG:
9fed81dc4   Namhyung Kim   ptrace: cleanup p...
779
  		ret = put_user(child->ptrace_message, datalp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
780
  		break;
e16b27816   Roland McGrath   ptrace: compat_pt...
781

84c751bd4   Andrey Vagin   ptrace: add abili...
782
783
784
  	case PTRACE_PEEKSIGINFO:
  		ret = ptrace_peek_siginfo(child, addr, data);
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
785
  	case PTRACE_GETSIGINFO:
e16b27816   Roland McGrath   ptrace: compat_pt...
786
787
  		ret = ptrace_getsiginfo(child, &siginfo);
  		if (!ret)
9fed81dc4   Namhyung Kim   ptrace: cleanup p...
788
  			ret = copy_siginfo_to_user(datavp, &siginfo);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
789
  		break;
e16b27816   Roland McGrath   ptrace: compat_pt...
790

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
791
  	case PTRACE_SETSIGINFO:
9fed81dc4   Namhyung Kim   ptrace: cleanup p...
792
  		if (copy_from_user(&siginfo, datavp, sizeof siginfo))
e16b27816   Roland McGrath   ptrace: compat_pt...
793
794
795
  			ret = -EFAULT;
  		else
  			ret = ptrace_setsiginfo(child, &siginfo);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
796
  		break;
e16b27816   Roland McGrath   ptrace: compat_pt...
797

29000caec   Andrey Vagin   ptrace: add abili...
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
  	case PTRACE_GETSIGMASK:
  		if (addr != sizeof(sigset_t)) {
  			ret = -EINVAL;
  			break;
  		}
  
  		if (copy_to_user(datavp, &child->blocked, sizeof(sigset_t)))
  			ret = -EFAULT;
  		else
  			ret = 0;
  
  		break;
  
  	case PTRACE_SETSIGMASK: {
  		sigset_t new_set;
  
  		if (addr != sizeof(sigset_t)) {
  			ret = -EINVAL;
  			break;
  		}
  
  		if (copy_from_user(&new_set, datavp, sizeof(sigset_t))) {
  			ret = -EFAULT;
  			break;
  		}
  
  		sigdelsetmask(&new_set, sigmask(SIGKILL)|sigmask(SIGSTOP));
  
  		/*
  		 * Every thread does recalc_sigpending() after resume, so
  		 * retarget_shared_pending() and recalc_sigpending() are not
  		 * called here.
  		 */
  		spin_lock_irq(&child->sighand->siglock);
  		child->blocked = new_set;
  		spin_unlock_irq(&child->sighand->siglock);
  
  		ret = 0;
  		break;
  	}
fca26f260   Tejun Heo   ptrace: implement...
838
839
840
841
842
843
844
845
846
847
848
849
850
  	case PTRACE_INTERRUPT:
  		/*
  		 * Stop tracee without any side-effect on signal or job
  		 * control.  At least one trap is guaranteed to happen
  		 * after this request.  If @child is already trapped, the
  		 * current trap is not disturbed and another trap will
  		 * happen after the current trap is ended with PTRACE_CONT.
  		 *
  		 * The actual trap might not be PTRACE_EVENT_STOP trap but
  		 * the pending condition is cleared regardless.
  		 */
  		if (unlikely(!seized || !lock_task_sighand(child, &flags)))
  			break;
544b2c91a   Tejun Heo   ptrace: implement...
851
852
853
854
855
856
  		/*
  		 * INTERRUPT doesn't disturb existing trap sans one
  		 * exception.  If ptracer issued LISTEN for the current
  		 * STOP, this INTERRUPT should clear LISTEN and re-trap
  		 * tracee into STOP.
  		 */
fca26f260   Tejun Heo   ptrace: implement...
857
  		if (likely(task_set_jobctl_pending(child, JOBCTL_TRAP_STOP)))
910ffdb18   Oleg Nesterov   ptrace: introduce...
858
  			ptrace_signal_wake_up(child, child->jobctl & JOBCTL_LISTENING);
544b2c91a   Tejun Heo   ptrace: implement...
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
  
  		unlock_task_sighand(child, &flags);
  		ret = 0;
  		break;
  
  	case PTRACE_LISTEN:
  		/*
  		 * Listen for events.  Tracee must be in STOP.  It's not
  		 * resumed per-se but is not considered to be in TRACED by
  		 * wait(2) or ptrace(2).  If an async event (e.g. group
  		 * stop state change) happens, tracee will enter STOP trap
  		 * again.  Alternatively, ptracer can issue INTERRUPT to
  		 * finish listening and re-trap tracee into STOP.
  		 */
  		if (unlikely(!seized || !lock_task_sighand(child, &flags)))
  			break;
  
  		si = child->last_siginfo;
f9d81f61c   Oleg Nesterov   ptrace: PTRACE_LI...
877
878
879
880
881
882
883
  		if (likely(si && (si->si_code >> 8) == PTRACE_EVENT_STOP)) {
  			child->jobctl |= JOBCTL_LISTENING;
  			/*
  			 * If NOTIFY is set, it means event happened between
  			 * start of this trap and now.  Trigger re-trap.
  			 */
  			if (child->jobctl & JOBCTL_TRAP_NOTIFY)
910ffdb18   Oleg Nesterov   ptrace: introduce...
884
  				ptrace_signal_wake_up(child, true);
f9d81f61c   Oleg Nesterov   ptrace: PTRACE_LI...
885
886
  			ret = 0;
  		}
fca26f260   Tejun Heo   ptrace: implement...
887
  		unlock_task_sighand(child, &flags);
fca26f260   Tejun Heo   ptrace: implement...
888
  		break;
1bcf54829   Alexey Dobriyan   Consolidate PTRAC...
889
890
891
  	case PTRACE_DETACH:	 /* detach a process that was attached. */
  		ret = ptrace_detach(child, data);
  		break;
36df29d79   Roland McGrath   ptrace: generic r...
892

9c1a12592   Mike Frysinger   ptrace: unify FDP...
893
894
  #ifdef CONFIG_BINFMT_ELF_FDPIC
  	case PTRACE_GETFDPIC: {
e0129ef91   Oleg Nesterov   ptrace: PTRACE_GE...
895
  		struct mm_struct *mm = get_task_mm(child);
9c1a12592   Mike Frysinger   ptrace: unify FDP...
896
  		unsigned long tmp = 0;
e0129ef91   Oleg Nesterov   ptrace: PTRACE_GE...
897
898
899
  		ret = -ESRCH;
  		if (!mm)
  			break;
9c1a12592   Mike Frysinger   ptrace: unify FDP...
900
901
  		switch (addr) {
  		case PTRACE_GETFDPIC_EXEC:
e0129ef91   Oleg Nesterov   ptrace: PTRACE_GE...
902
  			tmp = mm->context.exec_fdpic_loadmap;
9c1a12592   Mike Frysinger   ptrace: unify FDP...
903
904
  			break;
  		case PTRACE_GETFDPIC_INTERP:
e0129ef91   Oleg Nesterov   ptrace: PTRACE_GE...
905
  			tmp = mm->context.interp_fdpic_loadmap;
9c1a12592   Mike Frysinger   ptrace: unify FDP...
906
907
908
909
  			break;
  		default:
  			break;
  		}
e0129ef91   Oleg Nesterov   ptrace: PTRACE_GE...
910
  		mmput(mm);
9c1a12592   Mike Frysinger   ptrace: unify FDP...
911

9fed81dc4   Namhyung Kim   ptrace: cleanup p...
912
  		ret = put_user(tmp, datalp);
9c1a12592   Mike Frysinger   ptrace: unify FDP...
913
914
915
  		break;
  	}
  #endif
36df29d79   Roland McGrath   ptrace: generic r...
916
917
918
  #ifdef PTRACE_SINGLESTEP
  	case PTRACE_SINGLESTEP:
  #endif
5b88abbf7   Roland McGrath   ptrace: generic P...
919
920
921
  #ifdef PTRACE_SINGLEBLOCK
  	case PTRACE_SINGLEBLOCK:
  #endif
36df29d79   Roland McGrath   ptrace: generic r...
922
923
924
925
926
927
928
929
930
931
932
933
  #ifdef PTRACE_SYSEMU
  	case PTRACE_SYSEMU:
  	case PTRACE_SYSEMU_SINGLESTEP:
  #endif
  	case PTRACE_SYSCALL:
  	case PTRACE_CONT:
  		return ptrace_resume(child, request, data);
  
  	case PTRACE_KILL:
  		if (child->exit_state)	/* already dead */
  			return 0;
  		return ptrace_resume(child, request, SIGKILL);
2225a122a   Suresh Siddha   ptrace: Add suppo...
934
935
  #ifdef CONFIG_HAVE_ARCH_TRACEHOOK
  	case PTRACE_GETREGSET:
29000caec   Andrey Vagin   ptrace: add abili...
936
  	case PTRACE_SETREGSET: {
2225a122a   Suresh Siddha   ptrace: Add suppo...
937
  		struct iovec kiov;
9fed81dc4   Namhyung Kim   ptrace: cleanup p...
938
  		struct iovec __user *uiov = datavp;
2225a122a   Suresh Siddha   ptrace: Add suppo...
939
940
941
942
943
944
945
946
947
948
949
950
951
952
  
  		if (!access_ok(VERIFY_WRITE, uiov, sizeof(*uiov)))
  			return -EFAULT;
  
  		if (__get_user(kiov.iov_base, &uiov->iov_base) ||
  		    __get_user(kiov.iov_len, &uiov->iov_len))
  			return -EFAULT;
  
  		ret = ptrace_regset(child, request, addr, &kiov);
  		if (!ret)
  			ret = __put_user(kiov.iov_len, &uiov->iov_len);
  		break;
  	}
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
953
954
955
956
957
958
  	default:
  		break;
  	}
  
  	return ret;
  }
481bed454   Christoph Hellwig   [PATCH] consolida...
959

8053bdd5c   Oleg Nesterov   ptrace_get_task_s...
960
  static struct task_struct *ptrace_get_task_struct(pid_t pid)
6b9c7ed84   Christoph Hellwig   [PATCH] use ptrac...
961
962
  {
  	struct task_struct *child;
481bed454   Christoph Hellwig   [PATCH] consolida...
963

8053bdd5c   Oleg Nesterov   ptrace_get_task_s...
964
  	rcu_read_lock();
228ebcbe6   Pavel Emelyanov   Uninline find_tas...
965
  	child = find_task_by_vpid(pid);
481bed454   Christoph Hellwig   [PATCH] consolida...
966
967
  	if (child)
  		get_task_struct(child);
8053bdd5c   Oleg Nesterov   ptrace_get_task_s...
968
  	rcu_read_unlock();
f400e198b   Sukadev Bhattiprolu   [PATCH] pidspace:...
969

481bed454   Christoph Hellwig   [PATCH] consolida...
970
  	if (!child)
6b9c7ed84   Christoph Hellwig   [PATCH] use ptrac...
971
972
  		return ERR_PTR(-ESRCH);
  	return child;
481bed454   Christoph Hellwig   [PATCH] consolida...
973
  }
0ac155591   Christoph Hellwig   m32r: convert to ...
974
975
976
  #ifndef arch_ptrace_attach
  #define arch_ptrace_attach(child)	do { } while (0)
  #endif
4abf98696   Namhyung Kim   ptrace: change si...
977
978
  SYSCALL_DEFINE4(ptrace, long, request, long, pid, unsigned long, addr,
  		unsigned long, data)
481bed454   Christoph Hellwig   [PATCH] consolida...
979
980
981
  {
  	struct task_struct *child;
  	long ret;
6b9c7ed84   Christoph Hellwig   [PATCH] use ptrac...
982
983
  	if (request == PTRACE_TRACEME) {
  		ret = ptrace_traceme();
6ea6dd93c   Haavard Skinnemoen   ptrace: Call arch...
984
985
  		if (!ret)
  			arch_ptrace_attach(current);
481bed454   Christoph Hellwig   [PATCH] consolida...
986
  		goto out;
6b9c7ed84   Christoph Hellwig   [PATCH] use ptrac...
987
988
989
990
991
992
993
  	}
  
  	child = ptrace_get_task_struct(pid);
  	if (IS_ERR(child)) {
  		ret = PTR_ERR(child);
  		goto out;
  	}
481bed454   Christoph Hellwig   [PATCH] consolida...
994

3544d72a0   Tejun Heo   ptrace: implement...
995
  	if (request == PTRACE_ATTACH || request == PTRACE_SEIZE) {
aa9147c98   Denys Vlasenko   ptrace: make PTRA...
996
  		ret = ptrace_attach(child, request, addr, data);
0ac155591   Christoph Hellwig   m32r: convert to ...
997
998
999
1000
1001
1002
  		/*
  		 * Some architectures need to do book-keeping after
  		 * a ptrace attach.
  		 */
  		if (!ret)
  			arch_ptrace_attach(child);
005f18dfd   Christoph Hellwig   [PATCH] fix task_...
1003
  		goto out_put_task_struct;
481bed454   Christoph Hellwig   [PATCH] consolida...
1004
  	}
fca26f260   Tejun Heo   ptrace: implement...
1005
1006
  	ret = ptrace_check_attach(child, request == PTRACE_KILL ||
  				  request == PTRACE_INTERRUPT);
481bed454   Christoph Hellwig   [PATCH] consolida...
1007
1008
1009
1010
  	if (ret < 0)
  		goto out_put_task_struct;
  
  	ret = arch_ptrace(child, request, addr, data);
9899d11f6   Oleg Nesterov   ptrace: ensure ar...
1011
1012
  	if (ret || request != PTRACE_DETACH)
  		ptrace_unfreeze_traced(child);
481bed454   Christoph Hellwig   [PATCH] consolida...
1013
1014
1015
1016
  
   out_put_task_struct:
  	put_task_struct(child);
   out:
481bed454   Christoph Hellwig   [PATCH] consolida...
1017
1018
  	return ret;
  }
766473231   Alexey Dobriyan   PTRACE_PEEKDATA c...
1019

4abf98696   Namhyung Kim   ptrace: change si...
1020
1021
  int generic_ptrace_peekdata(struct task_struct *tsk, unsigned long addr,
  			    unsigned long data)
766473231   Alexey Dobriyan   PTRACE_PEEKDATA c...
1022
1023
1024
1025
1026
1027
1028
1029
1030
  {
  	unsigned long tmp;
  	int copied;
  
  	copied = access_process_vm(tsk, addr, &tmp, sizeof(tmp), 0);
  	if (copied != sizeof(tmp))
  		return -EIO;
  	return put_user(tmp, (unsigned long __user *)data);
  }
f284ce726   Alexey Dobriyan   PTRACE_POKEDATA c...
1031

4abf98696   Namhyung Kim   ptrace: change si...
1032
1033
  int generic_ptrace_pokedata(struct task_struct *tsk, unsigned long addr,
  			    unsigned long data)
f284ce726   Alexey Dobriyan   PTRACE_POKEDATA c...
1034
1035
1036
1037
1038
1039
  {
  	int copied;
  
  	copied = access_process_vm(tsk, addr, &data, sizeof(data), 1);
  	return (copied == sizeof(data)) ? 0 : -EIO;
  }
032d82d90   Roland McGrath   x86: compat_ptrac...
1040

96b8936a9   Christoph Hellwig   remove __ARCH_WAN...
1041
  #if defined CONFIG_COMPAT
032d82d90   Roland McGrath   x86: compat_ptrac...
1042
1043
1044
1045
1046
1047
1048
  #include <linux/compat.h>
  
  int compat_ptrace_request(struct task_struct *child, compat_long_t request,
  			  compat_ulong_t addr, compat_ulong_t data)
  {
  	compat_ulong_t __user *datap = compat_ptr(data);
  	compat_ulong_t word;
e16b27816   Roland McGrath   ptrace: compat_pt...
1049
  	siginfo_t siginfo;
032d82d90   Roland McGrath   x86: compat_ptrac...
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
  	int ret;
  
  	switch (request) {
  	case PTRACE_PEEKTEXT:
  	case PTRACE_PEEKDATA:
  		ret = access_process_vm(child, addr, &word, sizeof(word), 0);
  		if (ret != sizeof(word))
  			ret = -EIO;
  		else
  			ret = put_user(word, datap);
  		break;
  
  	case PTRACE_POKETEXT:
  	case PTRACE_POKEDATA:
  		ret = access_process_vm(child, addr, &data, sizeof(data), 1);
  		ret = (ret != sizeof(data) ? -EIO : 0);
  		break;
  
  	case PTRACE_GETEVENTMSG:
  		ret = put_user((compat_ulong_t) child->ptrace_message, datap);
  		break;
e16b27816   Roland McGrath   ptrace: compat_pt...
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
  	case PTRACE_GETSIGINFO:
  		ret = ptrace_getsiginfo(child, &siginfo);
  		if (!ret)
  			ret = copy_siginfo_to_user32(
  				(struct compat_siginfo __user *) datap,
  				&siginfo);
  		break;
  
  	case PTRACE_SETSIGINFO:
  		memset(&siginfo, 0, sizeof siginfo);
  		if (copy_siginfo_from_user32(
  			    &siginfo, (struct compat_siginfo __user *) datap))
  			ret = -EFAULT;
  		else
  			ret = ptrace_setsiginfo(child, &siginfo);
  		break;
2225a122a   Suresh Siddha   ptrace: Add suppo...
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
  #ifdef CONFIG_HAVE_ARCH_TRACEHOOK
  	case PTRACE_GETREGSET:
  	case PTRACE_SETREGSET:
  	{
  		struct iovec kiov;
  		struct compat_iovec __user *uiov =
  			(struct compat_iovec __user *) datap;
  		compat_uptr_t ptr;
  		compat_size_t len;
  
  		if (!access_ok(VERIFY_WRITE, uiov, sizeof(*uiov)))
  			return -EFAULT;
  
  		if (__get_user(ptr, &uiov->iov_base) ||
  		    __get_user(len, &uiov->iov_len))
  			return -EFAULT;
  
  		kiov.iov_base = compat_ptr(ptr);
  		kiov.iov_len = len;
  
  		ret = ptrace_regset(child, request, addr, &kiov);
  		if (!ret)
  			ret = __put_user(kiov.iov_len, &uiov->iov_len);
  		break;
  	}
  #endif
e16b27816   Roland McGrath   ptrace: compat_pt...
1113

032d82d90   Roland McGrath   x86: compat_ptrac...
1114
1115
1116
1117
1118
1119
  	default:
  		ret = ptrace_request(child, request, addr, data);
  	}
  
  	return ret;
  }
c269f1961   Roland McGrath   x86: compat_sys_p...
1120

c269f1961   Roland McGrath   x86: compat_sys_p...
1121
1122
1123
1124
1125
  asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid,
  				  compat_long_t addr, compat_long_t data)
  {
  	struct task_struct *child;
  	long ret;
c269f1961   Roland McGrath   x86: compat_sys_p...
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
  	if (request == PTRACE_TRACEME) {
  		ret = ptrace_traceme();
  		goto out;
  	}
  
  	child = ptrace_get_task_struct(pid);
  	if (IS_ERR(child)) {
  		ret = PTR_ERR(child);
  		goto out;
  	}
3544d72a0   Tejun Heo   ptrace: implement...
1136
  	if (request == PTRACE_ATTACH || request == PTRACE_SEIZE) {
aa9147c98   Denys Vlasenko   ptrace: make PTRA...
1137
  		ret = ptrace_attach(child, request, addr, data);
c269f1961   Roland McGrath   x86: compat_sys_p...
1138
1139
1140
1141
1142
1143
1144
1145
  		/*
  		 * Some architectures need to do book-keeping after
  		 * a ptrace attach.
  		 */
  		if (!ret)
  			arch_ptrace_attach(child);
  		goto out_put_task_struct;
  	}
fca26f260   Tejun Heo   ptrace: implement...
1146
1147
  	ret = ptrace_check_attach(child, request == PTRACE_KILL ||
  				  request == PTRACE_INTERRUPT);
9899d11f6   Oleg Nesterov   ptrace: ensure ar...
1148
  	if (!ret) {
c269f1961   Roland McGrath   x86: compat_sys_p...
1149
  		ret = compat_arch_ptrace(child, request, addr, data);
9899d11f6   Oleg Nesterov   ptrace: ensure ar...
1150
1151
1152
  		if (ret || request != PTRACE_DETACH)
  			ptrace_unfreeze_traced(child);
  	}
c269f1961   Roland McGrath   x86: compat_sys_p...
1153
1154
1155
1156
  
   out_put_task_struct:
  	put_task_struct(child);
   out:
c269f1961   Roland McGrath   x86: compat_sys_p...
1157
1158
  	return ret;
  }
96b8936a9   Christoph Hellwig   remove __ARCH_WAN...
1159
  #endif	/* CONFIG_COMPAT */