aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/ptrace.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-10-15 07:46:29 -0400
committerIngo Molnar <mingo@elte.hu>2008-10-15 07:46:29 -0400
commitb2aaf8f74cdc84a9182f6cabf198b7763bcb9d40 (patch)
tree53ccb1c2c14751fe69cf93102e76e97021f6df07 /kernel/ptrace.c
parent4f962d4d65923d7b722192e729840cfb79af0a5a (diff)
parent278429cff8809958d25415ba0ed32b59866ab1a8 (diff)
Merge branch 'linus' into stackprotector
Conflicts: arch/x86/kernel/Makefile include/asm-x86/pda.h
Diffstat (limited to 'kernel/ptrace.c')
-rw-r--r--kernel/ptrace.c53
1 files changed, 32 insertions, 21 deletions
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 6c19e94fd0a5..356699a96d56 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -33,13 +33,9 @@
33 */ 33 */
34void __ptrace_link(struct task_struct *child, struct task_struct *new_parent) 34void __ptrace_link(struct task_struct *child, struct task_struct *new_parent)
35{ 35{
36 BUG_ON(!list_empty(&child->ptrace_list)); 36 BUG_ON(!list_empty(&child->ptrace_entry));
37 if (child->parent == new_parent) 37 list_add(&child->ptrace_entry, &new_parent->ptraced);
38 return;
39 list_add(&child->ptrace_list, &child->parent->ptrace_children);
40 remove_parent(child);
41 child->parent = new_parent; 38 child->parent = new_parent;
42 add_parent(child);
43} 39}
44 40
45/* 41/*
@@ -73,12 +69,8 @@ void __ptrace_unlink(struct task_struct *child)
73 BUG_ON(!child->ptrace); 69 BUG_ON(!child->ptrace);
74 70
75 child->ptrace = 0; 71 child->ptrace = 0;
76 if (ptrace_reparented(child)) { 72 child->parent = child->real_parent;
77 list_del_init(&child->ptrace_list); 73 list_del_init(&child->ptrace_entry);
78 remove_parent(child);
79 child->parent = child->real_parent;
80 add_parent(child);
81 }
82 74
83 if (task_is_traced(child)) 75 if (task_is_traced(child))
84 ptrace_untrace(child); 76 ptrace_untrace(child);
@@ -115,13 +107,13 @@ int ptrace_check_attach(struct task_struct *child, int kill)
115 read_unlock(&tasklist_lock); 107 read_unlock(&tasklist_lock);
116 108
117 if (!ret && !kill) 109 if (!ret && !kill)
118 wait_task_inactive(child); 110 ret = wait_task_inactive(child, TASK_TRACED) ? 0 : -ESRCH;
119 111
120 /* All systems go.. */ 112 /* All systems go.. */
121 return ret; 113 return ret;
122} 114}
123 115
124int __ptrace_may_attach(struct task_struct *task) 116int __ptrace_may_access(struct task_struct *task, unsigned int mode)
125{ 117{
126 /* May we inspect the given task? 118 /* May we inspect the given task?
127 * This check is used both for attaching with ptrace 119 * This check is used both for attaching with ptrace
@@ -148,16 +140,16 @@ int __ptrace_may_attach(struct task_struct *task)
148 if (!dumpable && !capable(CAP_SYS_PTRACE)) 140 if (!dumpable && !capable(CAP_SYS_PTRACE))
149 return -EPERM; 141 return -EPERM;
150 142
151 return security_ptrace(current, task); 143 return security_ptrace_may_access(task, mode);
152} 144}
153 145
154int ptrace_may_attach(struct task_struct *task) 146bool ptrace_may_access(struct task_struct *task, unsigned int mode)
155{ 147{
156 int err; 148 int err;
157 task_lock(task); 149 task_lock(task);
158 err = __ptrace_may_attach(task); 150 err = __ptrace_may_access(task, mode);
159 task_unlock(task); 151 task_unlock(task);
160 return !err; 152 return (!err ? true : false);
161} 153}
162 154
163int ptrace_attach(struct task_struct *task) 155int ptrace_attach(struct task_struct *task)
@@ -195,7 +187,7 @@ repeat:
195 /* the same process cannot be attached many times */ 187 /* the same process cannot be attached many times */
196 if (task->ptrace & PT_PTRACED) 188 if (task->ptrace & PT_PTRACED)
197 goto bad; 189 goto bad;
198 retval = __ptrace_may_attach(task); 190 retval = __ptrace_may_access(task, PTRACE_MODE_ATTACH);
199 if (retval) 191 if (retval)
200 goto bad; 192 goto bad;
201 193
@@ -492,14 +484,33 @@ int ptrace_traceme(void)
492 /* 484 /*
493 * Are we already being traced? 485 * Are we already being traced?
494 */ 486 */
487repeat:
495 task_lock(current); 488 task_lock(current);
496 if (!(current->ptrace & PT_PTRACED)) { 489 if (!(current->ptrace & PT_PTRACED)) {
497 ret = security_ptrace(current->parent, current); 490 /*
491 * See ptrace_attach() comments about the locking here.
492 */
493 unsigned long flags;
494 if (!write_trylock_irqsave(&tasklist_lock, flags)) {
495 task_unlock(current);
496 do {
497 cpu_relax();
498 } while (!write_can_lock(&tasklist_lock));
499 goto repeat;
500 }
501
502 ret = security_ptrace_traceme(current->parent);
503
498 /* 504 /*
499 * Set the ptrace bit in the process ptrace flags. 505 * Set the ptrace bit in the process ptrace flags.
506 * Then link us on our parent's ptraced list.
500 */ 507 */
501 if (!ret) 508 if (!ret) {
502 current->ptrace |= PT_PTRACED; 509 current->ptrace |= PT_PTRACED;
510 __ptrace_link(current, current->real_parent);
511 }
512
513 write_unlock_irqrestore(&tasklist_lock, flags);
503 } 514 }
504 task_unlock(current); 515 task_unlock(current);
505 return ret; 516 return ret;