aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc/base.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/proc/base.c')
-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 5485a5388ecb..662ddf2ec4f1 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -198,65 +198,7 @@ static int proc_root_link(struct dentry *dentry, struct path *path)
198 return result; 198 return result;
199} 199}
200 200
201static struct mm_struct *__check_mem_permission(struct task_struct *task) 201static struct mm_struct *mm_access(struct task_struct *task, unsigned int mode)
202{
203 struct mm_struct *mm;
204
205 mm = get_task_mm(task);
206 if (!mm)
207 return ERR_PTR(-EINVAL);
208
209 /*
210 * A task can always look at itself, in case it chooses
211 * to use system calls instead of load instructions.
212 */
213 if (task == current)
214 return mm;
215
216 /*
217 * If current is actively ptrace'ing, and would also be
218 * permitted to freshly attach with ptrace now, permit it.
219 */
220 if (task_is_stopped_or_traced(task)) {
221 int match;
222 rcu_read_lock();
223 match = (ptrace_parent(task) == current);
224 rcu_read_unlock();
225 if (match && ptrace_may_access(task, PTRACE_MODE_ATTACH))
226 return mm;
227 }
228
229 /*
230 * No one else is allowed.
231 */
232 mmput(mm);
233 return ERR_PTR(-EPERM);
234}
235
236/*
237 * If current may access user memory in @task return a reference to the
238 * corresponding mm, otherwise ERR_PTR.
239 */
240static struct mm_struct *check_mem_permission(struct task_struct *task)
241{
242 struct mm_struct *mm;
243 int err;
244
245 /*
246 * Avoid racing if task exec's as we might get a new mm but validate
247 * against old credentials.
248 */
249 err = mutex_lock_killable(&task->signal->cred_guard_mutex);
250 if (err)
251 return ERR_PTR(err);
252
253 mm = __check_mem_permission(task);
254 mutex_unlock(&task->signal->cred_guard_mutex);
255
256 return mm;
257}
258
259struct mm_struct *mm_for_maps(struct task_struct *task)
260{ 202{
261 struct mm_struct *mm; 203 struct mm_struct *mm;
262 int err; 204 int err;
@@ -267,7 +209,7 @@ struct mm_struct *mm_for_maps(struct task_struct *task)
267 209
268 mm = get_task_mm(task); 210 mm = get_task_mm(task);
269 if (mm && mm != current->mm && 211 if (mm && mm != current->mm &&
270 !ptrace_may_access(task, PTRACE_MODE_READ)) { 212 !ptrace_may_access(task, mode)) {
271 mmput(mm); 213 mmput(mm);
272 mm = ERR_PTR(-EACCES); 214 mm = ERR_PTR(-EACCES);
273 } 215 }
@@ -276,6 +218,11 @@ struct mm_struct *mm_for_maps(struct task_struct *task)
276 return mm; 218 return mm;
277} 219}
278 220
221struct mm_struct *mm_for_maps(struct task_struct *task)
222{
223 return mm_access(task, PTRACE_MODE_READ);
224}
225
279static int proc_pid_cmdline(struct task_struct *task, char * buffer) 226static int proc_pid_cmdline(struct task_struct *task, char * buffer)
280{ 227{
281 int res = 0; 228 int res = 0;
@@ -752,38 +699,39 @@ static const struct file_operations proc_single_file_operations = {
752 699
753static int mem_open(struct inode* inode, struct file* file) 700static int mem_open(struct inode* inode, struct file* file)
754{ 701{
755 file->private_data = (void*)((long)current->self_exec_id); 702 struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);
703 struct mm_struct *mm;
704
705 if (!task)
706 return -ESRCH;
707
708 mm = mm_access(task, PTRACE_MODE_ATTACH);
709 put_task_struct(task);
710
711 if (IS_ERR(mm))
712 return PTR_ERR(mm);
713
756 /* OK to pass negative loff_t, we can catch out-of-range */ 714 /* OK to pass negative loff_t, we can catch out-of-range */
757 file->f_mode |= FMODE_UNSIGNED_OFFSET; 715 file->f_mode |= FMODE_UNSIGNED_OFFSET;
716 file->private_data = mm;
717
758 return 0; 718 return 0;
759} 719}
760 720
761static ssize_t mem_read(struct file * file, char __user * buf, 721static ssize_t mem_read(struct file * file, char __user * buf,
762 size_t count, loff_t *ppos) 722 size_t count, loff_t *ppos)
763{ 723{
764 struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode); 724 int ret;
765 char *page; 725 char *page;
766 unsigned long src = *ppos; 726 unsigned long src = *ppos;
767 int ret = -ESRCH; 727 struct mm_struct *mm = file->private_data;
768 struct mm_struct *mm;
769 728
770 if (!task) 729 if (!mm)
771 goto out_no_task; 730 return 0;
772 731
773 ret = -ENOMEM;
774 page = (char *)__get_free_page(GFP_TEMPORARY); 732 page = (char *)__get_free_page(GFP_TEMPORARY);
775 if (!page) 733 if (!page)
776 goto out; 734 return -ENOMEM;
777
778 mm = check_mem_permission(task);
779 ret = PTR_ERR(mm);
780 if (IS_ERR(mm))
781 goto out_free;
782
783 ret = -EIO;
784
785 if (file->private_data != (void*)((long)current->self_exec_id))
786 goto out_put;
787 735
788 ret = 0; 736 ret = 0;
789 737
@@ -810,13 +758,7 @@ static ssize_t mem_read(struct file * file, char __user * buf,
810 } 758 }
811 *ppos = src; 759 *ppos = src;
812 760
813out_put:
814 mmput(mm);
815out_free:
816 free_page((unsigned long) page); 761 free_page((unsigned long) page);
817out:
818 put_task_struct(task);
819out_no_task:
820 return ret; 762 return ret;
821} 763}
822 764
@@ -825,27 +767,15 @@ static ssize_t mem_write(struct file * file, const char __user *buf,
825{ 767{
826 int copied; 768 int copied;
827 char *page; 769 char *page;
828 struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);
829 unsigned long dst = *ppos; 770 unsigned long dst = *ppos;
830 struct mm_struct *mm; 771 struct mm_struct *mm = file->private_data;
831 772
832 copied = -ESRCH; 773 if (!mm)
833 if (!task) 774 return 0;
834 goto out_no_task;
835 775
836 copied = -ENOMEM;
837 page = (char *)__get_free_page(GFP_TEMPORARY); 776 page = (char *)__get_free_page(GFP_TEMPORARY);
838 if (!page) 777 if (!page)
839 goto out_task; 778 return -ENOMEM;
840
841 mm = check_mem_permission(task);
842 copied = PTR_ERR(mm);
843 if (IS_ERR(mm))
844 goto out_free;
845
846 copied = -EIO;
847 if (file->private_data != (void *)((long)current->self_exec_id))
848 goto out_mm;
849 779
850 copied = 0; 780 copied = 0;
851 while (count > 0) { 781 while (count > 0) {
@@ -869,13 +799,7 @@ static ssize_t mem_write(struct file * file, const char __user *buf,
869 } 799 }
870 *ppos = dst; 800 *ppos = dst;
871 801
872out_mm:
873 mmput(mm);
874out_free:
875 free_page((unsigned long) page); 802 free_page((unsigned long) page);
876out_task:
877 put_task_struct(task);
878out_no_task:
879 return copied; 803 return copied;
880} 804}
881 805
@@ -895,11 +819,20 @@ loff_t mem_lseek(struct file *file, loff_t offset, int orig)
895 return file->f_pos; 819 return file->f_pos;
896} 820}
897 821
822static int mem_release(struct inode *inode, struct file *file)
823{
824 struct mm_struct *mm = file->private_data;
825
826 mmput(mm);
827 return 0;
828}
829
898static const struct file_operations proc_mem_operations = { 830static const struct file_operations proc_mem_operations = {
899 .llseek = mem_lseek, 831 .llseek = mem_lseek,
900 .read = mem_read, 832 .read = mem_read,
901 .write = mem_write, 833 .write = mem_write,
902 .open = mem_open, 834 .open = mem_open,
835 .release = mem_release,
903}; 836};
904 837
905static ssize_t environ_read(struct file *file, char __user *buf, 838static ssize_t environ_read(struct file *file, char __user *buf,