Lines 191-255
Link Here
|
191 |
return result; |
191 |
return result; |
192 |
} |
192 |
} |
193 |
|
193 |
|
194 |
static struct mm_struct *__check_mem_permission(struct task_struct *task) |
|
|
195 |
{ |
196 |
struct mm_struct *mm; |
197 |
|
198 |
mm = get_task_mm(task); |
199 |
if (!mm) |
200 |
return ERR_PTR(-EINVAL); |
201 |
|
194 |
|
202 |
/* |
195 |
static struct mm_struct *mm_access(struct task_struct *task, unsigned int mode) |
203 |
* A task can always look at itself, in case it chooses |
|
|
204 |
* to use system calls instead of load instructions. |
205 |
*/ |
206 |
if (task == current) |
207 |
return mm; |
208 |
|
209 |
/* |
210 |
* If current is actively ptrace'ing, and would also be |
211 |
* permitted to freshly attach with ptrace now, permit it. |
212 |
*/ |
213 |
if (task_is_stopped_or_traced(task)) { |
214 |
int match; |
215 |
rcu_read_lock(); |
216 |
match = (tracehook_tracer_task(task) == current); |
217 |
rcu_read_unlock(); |
218 |
if (match && ptrace_may_access(task, PTRACE_MODE_ATTACH)) |
219 |
return mm; |
220 |
} |
221 |
|
222 |
/* |
223 |
* No one else is allowed. |
224 |
*/ |
225 |
mmput(mm); |
226 |
return ERR_PTR(-EPERM); |
227 |
} |
228 |
|
229 |
/* |
230 |
* If current may access user memory in @task return a reference to the |
231 |
* corresponding mm, otherwise ERR_PTR. |
232 |
*/ |
233 |
static struct mm_struct *check_mem_permission(struct task_struct *task) |
234 |
{ |
235 |
struct mm_struct *mm; |
236 |
int err; |
237 |
|
238 |
/* |
239 |
* Avoid racing if task exec's as we might get a new mm but validate |
240 |
* against old credentials. |
241 |
*/ |
242 |
err = mutex_lock_killable(&task->signal->cred_guard_mutex); |
243 |
if (err) |
244 |
return ERR_PTR(err); |
245 |
|
246 |
mm = __check_mem_permission(task); |
247 |
mutex_unlock(&task->signal->cred_guard_mutex); |
248 |
|
249 |
return mm; |
250 |
} |
251 |
|
252 |
struct mm_struct *mm_for_maps(struct task_struct *task) |
253 |
{ |
196 |
{ |
254 |
struct mm_struct *mm; |
197 |
struct mm_struct *mm; |
255 |
int err; |
198 |
int err; |
Lines 260-266
Link Here
|
260 |
|
203 |
|
261 |
mm = get_task_mm(task); |
204 |
mm = get_task_mm(task); |
262 |
if (mm && mm != current->mm && |
205 |
if (mm && mm != current->mm && |
263 |
!ptrace_may_access(task, PTRACE_MODE_READ)) { |
206 |
!ptrace_may_access(task, mode)) { |
264 |
mmput(mm); |
207 |
mmput(mm); |
265 |
mm = ERR_PTR(-EACCES); |
208 |
mm = ERR_PTR(-EACCES); |
266 |
} |
209 |
} |
Lines 269-274
Link Here
|
269 |
return mm; |
212 |
return mm; |
270 |
} |
213 |
} |
271 |
|
214 |
|
|
|
215 |
struct mm_struct *mm_for_maps(struct task_struct *task) |
216 |
{ |
217 |
return mm_access(task, PTRACE_MODE_READ); |
218 |
} |
219 |
|
272 |
static int proc_pid_cmdline(struct task_struct *task, char * buffer) |
220 |
static int proc_pid_cmdline(struct task_struct *task, char * buffer) |
273 |
{ |
221 |
{ |
274 |
int res = 0; |
222 |
int res = 0; |
Lines 813-850
Link Here
|
813 |
|
761 |
|
814 |
static int mem_open(struct inode* inode, struct file* file) |
762 |
static int mem_open(struct inode* inode, struct file* file) |
815 |
{ |
763 |
{ |
816 |
file->private_data = (void*)((long)current->self_exec_id); |
764 |
struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode); |
|
|
765 |
struct mm_struct *mm; |
766 |
|
767 |
if (!task) |
768 |
return -ESRCH; |
769 |
|
770 |
mm = mm_access(task, PTRACE_MODE_ATTACH); |
771 |
put_task_struct(task); |
772 |
|
773 |
if (IS_ERR(mm)) |
774 |
return PTR_ERR(mm); |
775 |
|
817 |
/* OK to pass negative loff_t, we can catch out-of-range */ |
776 |
/* OK to pass negative loff_t, we can catch out-of-range */ |
818 |
file->f_mode |= FMODE_UNSIGNED_OFFSET; |
777 |
file->f_mode |= FMODE_UNSIGNED_OFFSET; |
|
|
778 |
file->private_data = mm; |
779 |
|
819 |
return 0; |
780 |
return 0; |
820 |
} |
781 |
} |
821 |
|
782 |
|
822 |
static ssize_t mem_read(struct file * file, char __user * buf, |
783 |
static ssize_t mem_read(struct file * file, char __user * buf, |
823 |
size_t count, loff_t *ppos) |
784 |
size_t count, loff_t *ppos) |
824 |
{ |
785 |
{ |
825 |
struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode); |
786 |
int ret; |
826 |
char *page; |
787 |
char *page; |
827 |
unsigned long src = *ppos; |
788 |
unsigned long src = *ppos; |
828 |
int ret = -ESRCH; |
789 |
struct mm_struct *mm = file->private_data; |
829 |
struct mm_struct *mm; |
|
|
830 |
|
790 |
|
831 |
if (!task) |
|
|
832 |
goto out_no_task; |
833 |
|
791 |
|
834 |
ret = -ENOMEM; |
792 |
if (!mm) |
|
|
793 |
return 0; |
794 |
|
835 |
page = (char *)__get_free_page(GFP_TEMPORARY); |
795 |
page = (char *)__get_free_page(GFP_TEMPORARY); |
836 |
if (!page) |
796 |
if (!page) |
837 |
goto out; |
797 |
return -ENOMEM; |
838 |
|
|
|
839 |
mm = check_mem_permission(task); |
840 |
ret = PTR_ERR(mm); |
841 |
if (IS_ERR(mm)) |
842 |
goto out_free; |
843 |
|
844 |
ret = -EIO; |
845 |
|
846 |
if (file->private_data != (void*)((long)current->self_exec_id)) |
847 |
goto out_put; |
848 |
|
798 |
|
849 |
ret = 0; |
799 |
ret = 0; |
850 |
|
800 |
|
Lines 871-883
Link Here
|
871 |
} |
821 |
} |
872 |
*ppos = src; |
822 |
*ppos = src; |
873 |
|
823 |
|
874 |
out_put: |
|
|
875 |
mmput(mm); |
876 |
out_free: |
877 |
free_page((unsigned long) page); |
824 |
free_page((unsigned long) page); |
878 |
out: |
|
|
879 |
put_task_struct(task); |
880 |
out_no_task: |
881 |
return ret; |
825 |
return ret; |
882 |
} |
826 |
} |
883 |
|
827 |
|
Lines 886-912
Link Here
|
886 |
{ |
830 |
{ |
887 |
int copied; |
831 |
int copied; |
888 |
char *page; |
832 |
char *page; |
889 |
struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode); |
|
|
890 |
unsigned long dst = *ppos; |
833 |
unsigned long dst = *ppos; |
891 |
struct mm_struct *mm; |
834 |
struct mm_struct *mm = file->private_data; |
892 |
|
|
|
893 |
copied = -ESRCH; |
894 |
if (!task) |
895 |
goto out_no_task; |
896 |
|
835 |
|
897 |
mm = check_mem_permission(task); |
836 |
if (!mm) |
898 |
copied = PTR_ERR(mm); |
837 |
return 0; |
899 |
if (IS_ERR(mm)) |
|
|
900 |
goto out_task; |
901 |
|
902 |
copied = -EIO; |
903 |
if (file->private_data != (void *)((long)current->self_exec_id)) |
904 |
goto out_mm; |
905 |
|
838 |
|
906 |
copied = -ENOMEM; |
|
|
907 |
page = (char *)__get_free_page(GFP_TEMPORARY); |
839 |
page = (char *)__get_free_page(GFP_TEMPORARY); |
908 |
if (!page) |
840 |
if (!page) |
909 |
goto out_mm; |
841 |
return -ENOMEM; |
910 |
|
842 |
|
911 |
copied = 0; |
843 |
copied = 0; |
912 |
while (count > 0) { |
844 |
while (count > 0) { |
Lines 930-940
Link Here
|
930 |
} |
862 |
} |
931 |
*ppos = dst; |
863 |
*ppos = dst; |
932 |
free_page((unsigned long) page); |
864 |
free_page((unsigned long) page); |
933 |
out_mm: |
|
|
934 |
mmput(mm); |
935 |
out_task: |
936 |
put_task_struct(task); |
937 |
out_no_task: |
938 |
return copied; |
865 |
return copied; |
939 |
} |
866 |
} |
940 |
|
867 |
|
Lines 954-964
Link Here
|
954 |
return file->f_pos; |
881 |
return file->f_pos; |
955 |
} |
882 |
} |
956 |
|
883 |
|
|
|
884 |
static int mem_release(struct inode *inode, struct file *file) |
885 |
{ |
886 |
struct mm_struct *mm = file->private_data; |
887 |
|
888 |
mmput(mm); |
889 |
return 0; |
890 |
} |
891 |
|
957 |
static const struct file_operations proc_mem_operations = { |
892 |
static const struct file_operations proc_mem_operations = { |
958 |
.llseek = mem_lseek, |
893 |
.llseek = mem_lseek, |
959 |
.read = mem_read, |
894 |
.read = mem_read, |
960 |
.write = mem_write, |
895 |
.write = mem_write, |
961 |
.open = mem_open, |
896 |
.open = mem_open, |
|
|
897 |
.release = mem_release, |
962 |
}; |
898 |
}; |
963 |
|
899 |
|
964 |
static ssize_t environ_read(struct file *file, char __user *buf, |
900 |
static ssize_t environ_read(struct file *file, char __user *buf, |