diff options
author | James Pearson <james-p@moving-picture.com> | 2007-10-17 02:30:17 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-17 11:43:00 -0400 |
commit | 315e28c8d61560e90c7d9c7c56c1b661187ab307 (patch) | |
tree | 21edcc6d63a5cfb55cadfbfba9f205bb557d343c | |
parent | 3ad90ec0908e453ba89947fcf7b5f6821b6c1e0c (diff) |
Don't truncate /proc/PID/environ at 4096 characters
/proc/PID/environ currently truncates at 4096 characters, patch based on
the /proc/PID/mem code.
Signed-off-by: James Pearson <james-p@moving-picture.com>
Cc: Anton Arapov <aarapov@redhat.com>
Cc: Jan Engelhardt <jengelh@computergmbh.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Alexey Dobriyan <adobriyan@gmail.com>
Cc: Randy Dunlap <randy.dunlap@oracle.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | fs/proc/base.c | 95 |
1 files changed, 72 insertions, 23 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c index ea115d4c9f59..4fe74d156416 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -199,27 +199,6 @@ static int proc_root_link(struct inode *inode, struct dentry **dentry, struct vf | |||
199 | (task->state == TASK_STOPPED || task->state == TASK_TRACED) && \ | 199 | (task->state == TASK_STOPPED || task->state == TASK_TRACED) && \ |
200 | security_ptrace(current,task) == 0)) | 200 | security_ptrace(current,task) == 0)) |
201 | 201 | ||
202 | static int proc_pid_environ(struct task_struct *task, char * buffer) | ||
203 | { | ||
204 | int res = 0; | ||
205 | struct mm_struct *mm = get_task_mm(task); | ||
206 | if (mm) { | ||
207 | unsigned int len; | ||
208 | |||
209 | res = -ESRCH; | ||
210 | if (!ptrace_may_attach(task)) | ||
211 | goto out; | ||
212 | |||
213 | len = mm->env_end - mm->env_start; | ||
214 | if (len > PAGE_SIZE) | ||
215 | len = PAGE_SIZE; | ||
216 | res = access_process_vm(task, mm->env_start, buffer, len, 0); | ||
217 | out: | ||
218 | mmput(mm); | ||
219 | } | ||
220 | return res; | ||
221 | } | ||
222 | |||
223 | static int proc_pid_cmdline(struct task_struct *task, char * buffer) | 202 | static int proc_pid_cmdline(struct task_struct *task, char * buffer) |
224 | { | 203 | { |
225 | int res = 0; | 204 | int res = 0; |
@@ -658,6 +637,76 @@ static const struct file_operations proc_mem_operations = { | |||
658 | .open = mem_open, | 637 | .open = mem_open, |
659 | }; | 638 | }; |
660 | 639 | ||
640 | static ssize_t environ_read(struct file *file, char __user *buf, | ||
641 | size_t count, loff_t *ppos) | ||
642 | { | ||
643 | struct task_struct *task = get_proc_task(file->f_dentry->d_inode); | ||
644 | char *page; | ||
645 | unsigned long src = *ppos; | ||
646 | int ret = -ESRCH; | ||
647 | struct mm_struct *mm; | ||
648 | |||
649 | if (!task) | ||
650 | goto out_no_task; | ||
651 | |||
652 | if (!ptrace_may_attach(task)) | ||
653 | goto out; | ||
654 | |||
655 | ret = -ENOMEM; | ||
656 | page = (char *)__get_free_page(GFP_TEMPORARY); | ||
657 | if (!page) | ||
658 | goto out; | ||
659 | |||
660 | ret = 0; | ||
661 | |||
662 | mm = get_task_mm(task); | ||
663 | if (!mm) | ||
664 | goto out_free; | ||
665 | |||
666 | while (count > 0) { | ||
667 | int this_len, retval, max_len; | ||
668 | |||
669 | this_len = mm->env_end - (mm->env_start + src); | ||
670 | |||
671 | if (this_len <= 0) | ||
672 | break; | ||
673 | |||
674 | max_len = (count > PAGE_SIZE) ? PAGE_SIZE : count; | ||
675 | this_len = (this_len > max_len) ? max_len : this_len; | ||
676 | |||
677 | retval = access_process_vm(task, (mm->env_start + src), | ||
678 | page, this_len, 0); | ||
679 | |||
680 | if (retval <= 0) { | ||
681 | ret = retval; | ||
682 | break; | ||
683 | } | ||
684 | |||
685 | if (copy_to_user(buf, page, retval)) { | ||
686 | ret = -EFAULT; | ||
687 | break; | ||
688 | } | ||
689 | |||
690 | ret += retval; | ||
691 | src += retval; | ||
692 | buf += retval; | ||
693 | count -= retval; | ||
694 | } | ||
695 | *ppos = src; | ||
696 | |||
697 | mmput(mm); | ||
698 | out_free: | ||
699 | free_page((unsigned long) page); | ||
700 | out: | ||
701 | put_task_struct(task); | ||
702 | out_no_task: | ||
703 | return ret; | ||
704 | } | ||
705 | |||
706 | static const struct file_operations proc_environ_operations = { | ||
707 | .read = environ_read, | ||
708 | }; | ||
709 | |||
661 | static ssize_t oom_adjust_read(struct file *file, char __user *buf, | 710 | static ssize_t oom_adjust_read(struct file *file, char __user *buf, |
662 | size_t count, loff_t *ppos) | 711 | size_t count, loff_t *ppos) |
663 | { | 712 | { |
@@ -2049,7 +2098,7 @@ static const struct pid_entry tgid_base_stuff[] = { | |||
2049 | DIR("task", S_IRUGO|S_IXUGO, task), | 2098 | DIR("task", S_IRUGO|S_IXUGO, task), |
2050 | DIR("fd", S_IRUSR|S_IXUSR, fd), | 2099 | DIR("fd", S_IRUSR|S_IXUSR, fd), |
2051 | DIR("fdinfo", S_IRUSR|S_IXUSR, fdinfo), | 2100 | DIR("fdinfo", S_IRUSR|S_IXUSR, fdinfo), |
2052 | INF("environ", S_IRUSR, pid_environ), | 2101 | REG("environ", S_IRUSR, environ), |
2053 | INF("auxv", S_IRUSR, pid_auxv), | 2102 | INF("auxv", S_IRUSR, pid_auxv), |
2054 | INF("status", S_IRUGO, pid_status), | 2103 | INF("status", S_IRUGO, pid_status), |
2055 | #ifdef CONFIG_SCHED_DEBUG | 2104 | #ifdef CONFIG_SCHED_DEBUG |
@@ -2336,7 +2385,7 @@ out_no_task: | |||
2336 | static const struct pid_entry tid_base_stuff[] = { | 2385 | static const struct pid_entry tid_base_stuff[] = { |
2337 | DIR("fd", S_IRUSR|S_IXUSR, fd), | 2386 | DIR("fd", S_IRUSR|S_IXUSR, fd), |
2338 | DIR("fdinfo", S_IRUSR|S_IXUSR, fdinfo), | 2387 | DIR("fdinfo", S_IRUSR|S_IXUSR, fdinfo), |
2339 | INF("environ", S_IRUSR, pid_environ), | 2388 | REG("environ", S_IRUSR, environ), |
2340 | INF("auxv", S_IRUSR, pid_auxv), | 2389 | INF("auxv", S_IRUSR, pid_auxv), |
2341 | INF("status", S_IRUGO, pid_status), | 2390 | INF("status", S_IRUGO, pid_status), |
2342 | #ifdef CONFIG_SCHED_DEBUG | 2391 | #ifdef CONFIG_SCHED_DEBUG |