diff options
-rw-r--r-- | fs/proc/base.c | 35 | ||||
-rw-r--r-- | include/linux/ptrace.h | 1 | ||||
-rw-r--r-- | kernel/ptrace.c | 41 |
3 files changed, 33 insertions, 44 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c index 24eed139e54e..84751f3f52d5 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -346,33 +346,6 @@ static int proc_root_link(struct inode *inode, struct dentry **dentry, struct vf | |||
346 | (task->state == TASK_STOPPED || task->state == TASK_TRACED) && \ | 346 | (task->state == TASK_STOPPED || task->state == TASK_TRACED) && \ |
347 | security_ptrace(current,task) == 0)) | 347 | security_ptrace(current,task) == 0)) |
348 | 348 | ||
349 | static int may_ptrace_attach(struct task_struct *task) | ||
350 | { | ||
351 | int retval = 0; | ||
352 | |||
353 | task_lock(task); | ||
354 | |||
355 | if (!task->mm) | ||
356 | goto out; | ||
357 | if (((current->uid != task->euid) || | ||
358 | (current->uid != task->suid) || | ||
359 | (current->uid != task->uid) || | ||
360 | (current->gid != task->egid) || | ||
361 | (current->gid != task->sgid) || | ||
362 | (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE)) | ||
363 | goto out; | ||
364 | rmb(); | ||
365 | if (task->mm->dumpable != 1 && !capable(CAP_SYS_PTRACE)) | ||
366 | goto out; | ||
367 | if (security_ptrace(current, task)) | ||
368 | goto out; | ||
369 | |||
370 | retval = 1; | ||
371 | out: | ||
372 | task_unlock(task); | ||
373 | return retval; | ||
374 | } | ||
375 | |||
376 | static int proc_pid_environ(struct task_struct *task, char * buffer) | 349 | static int proc_pid_environ(struct task_struct *task, char * buffer) |
377 | { | 350 | { |
378 | int res = 0; | 351 | int res = 0; |
@@ -382,7 +355,7 @@ static int proc_pid_environ(struct task_struct *task, char * buffer) | |||
382 | if (len > PAGE_SIZE) | 355 | if (len > PAGE_SIZE) |
383 | len = PAGE_SIZE; | 356 | len = PAGE_SIZE; |
384 | res = access_process_vm(task, mm->env_start, buffer, len, 0); | 357 | res = access_process_vm(task, mm->env_start, buffer, len, 0); |
385 | if (!may_ptrace_attach(task)) | 358 | if (!ptrace_may_attach(task)) |
386 | res = -ESRCH; | 359 | res = -ESRCH; |
387 | mmput(mm); | 360 | mmput(mm); |
388 | } | 361 | } |
@@ -685,7 +658,7 @@ static ssize_t mem_read(struct file * file, char __user * buf, | |||
685 | int ret = -ESRCH; | 658 | int ret = -ESRCH; |
686 | struct mm_struct *mm; | 659 | struct mm_struct *mm; |
687 | 660 | ||
688 | if (!MAY_PTRACE(task) || !may_ptrace_attach(task)) | 661 | if (!MAY_PTRACE(task) || !ptrace_may_attach(task)) |
689 | goto out; | 662 | goto out; |
690 | 663 | ||
691 | ret = -ENOMEM; | 664 | ret = -ENOMEM; |
@@ -711,7 +684,7 @@ static ssize_t mem_read(struct file * file, char __user * buf, | |||
711 | 684 | ||
712 | this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count; | 685 | this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count; |
713 | retval = access_process_vm(task, src, page, this_len, 0); | 686 | retval = access_process_vm(task, src, page, this_len, 0); |
714 | if (!retval || !MAY_PTRACE(task) || !may_ptrace_attach(task)) { | 687 | if (!retval || !MAY_PTRACE(task) || !ptrace_may_attach(task)) { |
715 | if (!ret) | 688 | if (!ret) |
716 | ret = -EIO; | 689 | ret = -EIO; |
717 | break; | 690 | break; |
@@ -749,7 +722,7 @@ static ssize_t mem_write(struct file * file, const char * buf, | |||
749 | struct task_struct *task = proc_task(file->f_dentry->d_inode); | 722 | struct task_struct *task = proc_task(file->f_dentry->d_inode); |
750 | unsigned long dst = *ppos; | 723 | unsigned long dst = *ppos; |
751 | 724 | ||
752 | if (!MAY_PTRACE(task) || !may_ptrace_attach(task)) | 725 | if (!MAY_PTRACE(task) || !ptrace_may_attach(task)) |
753 | return -ESRCH; | 726 | return -ESRCH; |
754 | 727 | ||
755 | page = (char *)__get_free_page(GFP_USER); | 728 | page = (char *)__get_free_page(GFP_USER); |
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h index 2afdafb62123..dc6f3647bfbc 100644 --- a/include/linux/ptrace.h +++ b/include/linux/ptrace.h | |||
@@ -90,6 +90,7 @@ extern void __ptrace_link(struct task_struct *child, | |||
90 | struct task_struct *new_parent); | 90 | struct task_struct *new_parent); |
91 | extern void __ptrace_unlink(struct task_struct *child); | 91 | extern void __ptrace_unlink(struct task_struct *child); |
92 | extern void ptrace_untrace(struct task_struct *child); | 92 | extern void ptrace_untrace(struct task_struct *child); |
93 | extern int ptrace_may_attach(struct task_struct *task); | ||
93 | 94 | ||
94 | static inline void ptrace_link(struct task_struct *child, | 95 | static inline void ptrace_link(struct task_struct *child, |
95 | struct task_struct *new_parent) | 96 | struct task_struct *new_parent) |
diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 8dcb8f6288bc..019e04ec065a 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c | |||
@@ -118,6 +118,33 @@ int ptrace_check_attach(struct task_struct *child, int kill) | |||
118 | return ret; | 118 | return ret; |
119 | } | 119 | } |
120 | 120 | ||
121 | static int may_attach(struct task_struct *task) | ||
122 | { | ||
123 | if (!task->mm) | ||
124 | return -EPERM; | ||
125 | if (((current->uid != task->euid) || | ||
126 | (current->uid != task->suid) || | ||
127 | (current->uid != task->uid) || | ||
128 | (current->gid != task->egid) || | ||
129 | (current->gid != task->sgid) || | ||
130 | (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE)) | ||
131 | return -EPERM; | ||
132 | smp_rmb(); | ||
133 | if (!task->mm->dumpable && !capable(CAP_SYS_PTRACE)) | ||
134 | return -EPERM; | ||
135 | |||
136 | return security_ptrace(current, task); | ||
137 | } | ||
138 | |||
139 | int ptrace_may_attach(struct task_struct *task) | ||
140 | { | ||
141 | int err; | ||
142 | task_lock(task); | ||
143 | err = may_attach(task); | ||
144 | task_unlock(task); | ||
145 | return !err; | ||
146 | } | ||
147 | |||
121 | int ptrace_attach(struct task_struct *task) | 148 | int ptrace_attach(struct task_struct *task) |
122 | { | 149 | { |
123 | int retval; | 150 | int retval; |
@@ -127,22 +154,10 @@ int ptrace_attach(struct task_struct *task) | |||
127 | goto bad; | 154 | goto bad; |
128 | if (task == current) | 155 | if (task == current) |
129 | goto bad; | 156 | goto bad; |
130 | if (!task->mm) | ||
131 | goto bad; | ||
132 | if(((current->uid != task->euid) || | ||
133 | (current->uid != task->suid) || | ||
134 | (current->uid != task->uid) || | ||
135 | (current->gid != task->egid) || | ||
136 | (current->gid != task->sgid) || | ||
137 | (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE)) | ||
138 | goto bad; | ||
139 | smp_rmb(); | ||
140 | if (!task->mm->dumpable && !capable(CAP_SYS_PTRACE)) | ||
141 | goto bad; | ||
142 | /* the same process cannot be attached many times */ | 157 | /* the same process cannot be attached many times */ |
143 | if (task->ptrace & PT_PTRACED) | 158 | if (task->ptrace & PT_PTRACED) |
144 | goto bad; | 159 | goto bad; |
145 | retval = security_ptrace(current, task); | 160 | retval = may_attach(task); |
146 | if (retval) | 161 | if (retval) |
147 | goto bad; | 162 | goto bad; |
148 | 163 | ||