diff options
Diffstat (limited to 'fs/proc/base.c')
-rw-r--r-- | fs/proc/base.c | 38 |
1 files changed, 29 insertions, 9 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c index b48ddb119945..fcf02f2deeba 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -195,12 +195,32 @@ static int proc_root_link(struct inode *inode, struct path *path) | |||
195 | return result; | 195 | return result; |
196 | } | 196 | } |
197 | 197 | ||
198 | #define MAY_PTRACE(task) \ | 198 | /* |
199 | (task == current || \ | 199 | * Return zero if current may access user memory in @task, -error if not. |
200 | (task->parent == current && \ | 200 | */ |
201 | (task->ptrace & PT_PTRACED) && \ | 201 | static int check_mem_permission(struct task_struct *task) |
202 | (task_is_stopped_or_traced(task)) && \ | 202 | { |
203 | security_ptrace(current,task) == 0)) | 203 | /* |
204 | * A task can always look at itself, in case it chooses | ||
205 | * to use system calls instead of load instructions. | ||
206 | */ | ||
207 | if (task == current) | ||
208 | return 0; | ||
209 | |||
210 | /* | ||
211 | * If current is actively ptrace'ing, and would also be | ||
212 | * permitted to freshly attach with ptrace now, permit it. | ||
213 | */ | ||
214 | if (task->parent == current && (task->ptrace & PT_PTRACED) && | ||
215 | task_is_stopped_or_traced(task) && | ||
216 | ptrace_may_attach(task)) | ||
217 | return 0; | ||
218 | |||
219 | /* | ||
220 | * Noone else is allowed. | ||
221 | */ | ||
222 | return -EPERM; | ||
223 | } | ||
204 | 224 | ||
205 | struct mm_struct *mm_for_maps(struct task_struct *task) | 225 | struct mm_struct *mm_for_maps(struct task_struct *task) |
206 | { | 226 | { |
@@ -722,7 +742,7 @@ static ssize_t mem_read(struct file * file, char __user * buf, | |||
722 | if (!task) | 742 | if (!task) |
723 | goto out_no_task; | 743 | goto out_no_task; |
724 | 744 | ||
725 | if (!MAY_PTRACE(task) || !ptrace_may_attach(task)) | 745 | if (check_mem_permission(task)) |
726 | goto out; | 746 | goto out; |
727 | 747 | ||
728 | ret = -ENOMEM; | 748 | ret = -ENOMEM; |
@@ -748,7 +768,7 @@ static ssize_t mem_read(struct file * file, char __user * buf, | |||
748 | 768 | ||
749 | this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count; | 769 | this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count; |
750 | retval = access_process_vm(task, src, page, this_len, 0); | 770 | retval = access_process_vm(task, src, page, this_len, 0); |
751 | if (!retval || !MAY_PTRACE(task) || !ptrace_may_attach(task)) { | 771 | if (!retval || check_mem_permission(task)) { |
752 | if (!ret) | 772 | if (!ret) |
753 | ret = -EIO; | 773 | ret = -EIO; |
754 | break; | 774 | break; |
@@ -792,7 +812,7 @@ static ssize_t mem_write(struct file * file, const char __user *buf, | |||
792 | if (!task) | 812 | if (!task) |
793 | goto out_no_task; | 813 | goto out_no_task; |
794 | 814 | ||
795 | if (!MAY_PTRACE(task) || !ptrace_may_attach(task)) | 815 | if (check_mem_permission(task)) |
796 | goto out; | 816 | goto out; |
797 | 817 | ||
798 | copied = -ENOMEM; | 818 | copied = -ENOMEM; |