aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc
diff options
context:
space:
mode:
Diffstat (limited to 'fs/proc')
-rw-r--r--fs/proc/base.c145
1 files changed, 39 insertions, 106 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 22511548d90..a70150ae505 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -195,65 +195,7 @@ static int proc_root_link(struct inode *inode, struct path *path)
195 return result; 195 return result;
196} 196}
197 197
198static struct mm_struct *__check_mem_permission(struct task_struct *task) 198static struct mm_struct *mm_access(struct task_struct *task, unsigned int mode)
199{
200 struct mm_struct *mm;
201
202 mm = get_task_mm(task);
203 if (!mm)
204 return ERR_PTR(-EINVAL);
205
206 /*
207 * A task can always look at itself, in case it chooses
208 * to use system calls instead of load instructions.
209 */
210 if (task == current)
211 return mm;
212
213 /*
214 * If current is actively ptrace'ing, and would also be
215 * permitted to freshly attach with ptrace now, permit it.
216 */
217 if (task_is_stopped_or_traced(task)) {
218 int match;
219 rcu_read_lock();
220 match = (tracehook_tracer_task(task) == current);
221 rcu_read_unlock();
222 if (match && ptrace_may_access(task, PTRACE_MODE_ATTACH))
223 return mm;
224 }
225
226 /*
227 * No one else is allowed.
228 */
229 mmput(mm);
230 return ERR_PTR(-EPERM);
231}
232
233/*
234 * If current may access user memory in @task return a reference to the
235 * corresponding mm, otherwise ERR_PTR.
236 */
237static struct mm_struct *check_mem_permission(struct task_struct *task)
238{
239 struct mm_struct *mm;
240 int err;
241
242 /*
243 * Avoid racing if task exec's as we might get a new mm but validate
244 * against old credentials.
245 */
246 err = mutex_lock_killable(&task->signal->cred_guard_mutex);
247 if (err)
248 return ERR_PTR(err);
249
250 mm = __check_mem_permission(task);
251 mutex_unlock(&task->signal->cred_guard_mutex);
252
253 return mm;
254}
255
256struct mm_struct *mm_for_maps(struct task_struct *task)
257{ 199{
258 struct mm_struct *mm; 200 struct mm_struct *mm;
259 int err; 201 int err;
@@ -264,7 +206,7 @@ struct mm_struct *mm_for_maps(struct task_struct *task)
264 206
265 mm = get_task_mm(task); 207 mm = get_task_mm(task);
266 if (mm && mm != current->mm && 208 if (mm && mm != current->mm &&
267 !ptrace_may_access(task, PTRACE_MODE_READ)) { 209 !ptrace_may_access(task, mode)) {
268 mmput(mm); 210 mmput(mm);
269 mm = ERR_PTR(-EACCES); 211 mm = ERR_PTR(-EACCES);
270 } 212 }
@@ -273,6 +215,11 @@ struct mm_struct *mm_for_maps(struct task_struct *task)
273 return mm; 215 return mm;
274} 216}
275 217
218struct mm_struct *mm_for_maps(struct task_struct *task)
219{
220 return mm_access(task, PTRACE_MODE_READ);
221}
222
276static int proc_pid_cmdline(struct task_struct *task, char * buffer) 223static int proc_pid_cmdline(struct task_struct *task, char * buffer)
277{ 224{
278 int res = 0; 225 int res = 0;
@@ -841,38 +788,39 @@ static const struct file_operations proc_single_file_operations = {
841 788
842static int mem_open(struct inode* inode, struct file* file) 789static int mem_open(struct inode* inode, struct file* file)
843{ 790{
844 file->private_data = (void*)((long)current->self_exec_id); 791 struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);
792 struct mm_struct *mm;
793
794 if (!task)
795 return -ESRCH;
796
797 mm = mm_access(task, PTRACE_MODE_ATTACH);
798 put_task_struct(task);
799
800 if (IS_ERR(mm))
801 return PTR_ERR(mm);
802
845 /* OK to pass negative loff_t, we can catch out-of-range */ 803 /* OK to pass negative loff_t, we can catch out-of-range */
846 file->f_mode |= FMODE_UNSIGNED_OFFSET; 804 file->f_mode |= FMODE_UNSIGNED_OFFSET;
805 file->private_data = mm;
806
847 return 0; 807 return 0;
848} 808}
849 809
850static ssize_t mem_read(struct file * file, char __user * buf, 810static ssize_t mem_read(struct file * file, char __user * buf,
851 size_t count, loff_t *ppos) 811 size_t count, loff_t *ppos)
852{ 812{
853 struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode); 813 int ret;
854 char *page; 814 char *page;
855 unsigned long src = *ppos; 815 unsigned long src = *ppos;
856 int ret = -ESRCH; 816 struct mm_struct *mm = file->private_data;
857 struct mm_struct *mm;
858 817
859 if (!task) 818 if (!mm)
860 goto out_no_task; 819 return 0;
861 820
862 ret = -ENOMEM;
863 page = (char *)__get_free_page(GFP_TEMPORARY); 821 page = (char *)__get_free_page(GFP_TEMPORARY);
864 if (!page) 822 if (!page)
865 goto out; 823 return -ENOMEM;
866
867 mm = check_mem_permission(task);
868 ret = PTR_ERR(mm);
869 if (IS_ERR(mm))
870 goto out_free;
871
872 ret = -EIO;
873
874 if (file->private_data != (void*)((long)current->self_exec_id))
875 goto out_put;
876 824
877 ret = 0; 825 ret = 0;
878 826
@@ -899,13 +847,7 @@ static ssize_t mem_read(struct file * file, char __user * buf,
899 } 847 }
900 *ppos = src; 848 *ppos = src;
901 849
902out_put:
903 mmput(mm);
904out_free:
905 free_page((unsigned long) page); 850 free_page((unsigned long) page);
906out:
907 put_task_struct(task);
908out_no_task:
909 return ret; 851 return ret;
910} 852}
911 853
@@ -914,27 +856,15 @@ static ssize_t mem_write(struct file * file, const char __user *buf,
914{ 856{
915 int copied; 857 int copied;
916 char *page; 858 char *page;
917 struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);
918 unsigned long dst = *ppos; 859 unsigned long dst = *ppos;
919 struct mm_struct *mm; 860 struct mm_struct *mm = file->private_data;
920 861
921 copied = -ESRCH; 862 if (!mm)
922 if (!task) 863 return 0;
923 goto out_no_task;
924 864
925 copied = -ENOMEM;
926 page = (char *)__get_free_page(GFP_TEMPORARY); 865 page = (char *)__get_free_page(GFP_TEMPORARY);
927 if (!page) 866 if (!page)
928 goto out_task; 867 return -ENOMEM;
929
930 mm = check_mem_permission(task);
931 copied = PTR_ERR(mm);
932 if (IS_ERR(mm))
933 goto out_free;
934
935 copied = -EIO;
936 if (file->private_data != (void *)((long)current->self_exec_id))
937 goto out_mm;
938 868
939 copied = 0; 869 copied = 0;
940 while (count > 0) { 870 while (count > 0) {
@@ -958,13 +888,7 @@ static ssize_t mem_write(struct file * file, const char __user *buf,
958 } 888 }
959 *ppos = dst; 889 *ppos = dst;
960 890
961out_mm:
962 mmput(mm);
963out_free:
964 free_page((unsigned long) page); 891 free_page((unsigned long) page);
965out_task:
966 put_task_struct(task);
967out_no_task:
968 return copied; 892 return copied;
969} 893}
970 894
@@ -984,11 +908,20 @@ loff_t mem_lseek(struct file *file, loff_t offset, int orig)
984 return file->f_pos; 908 return file->f_pos;
985} 909}
986 910
911static int mem_release(struct inode *inode, struct file *file)
912{
913 struct mm_struct *mm = file->private_data;
914
915 mmput(mm);
916 return 0;
917}
918
987static const struct file_operations proc_mem_operations = { 919static const struct file_operations proc_mem_operations = {
988 .llseek = mem_lseek, 920 .llseek = mem_lseek,
989 .read = mem_read, 921 .read = mem_read,
990 .write = mem_write, 922 .write = mem_write,
991 .open = mem_open, 923 .open = mem_open,
924 .release = mem_release,
992}; 925};
993 926
994static ssize_t environ_read(struct file *file, char __user *buf, 927static ssize_t environ_read(struct file *file, char __user *buf,