From: James Pearson <james-p@moving-picture.com>
To: linux-kernel@vger.kernel.org
Subject: Re: 4096 byte limit to /proc/PID/environ ?
Date: Wed, 24 May 2006 20:45:31 +0100 [thread overview]
Message-ID: <4474B7DB.8000304@moving-picture.com> (raw)
H. Peter Anvin wrote:
>>
>> I'm not worried about that - more the fact that when I do:
>>
>> % cat /proc/$$/environ | wc -c
>> 4096
>> % env | wc -c
>> 7329
>>
>> /proc/PID/environ is truncated ...
>>
>
> Funny enough, I was looking at this yesterday. I think there is a
> pretty clean solution for it, I just haven't had a chance to attack it
> yet.
Having a poke about in fs/proc/, I came up with this - probably isn't
pretty or clean, but it works ...
James Pearson
--- ./include/linux/proc_fs.h.dist 2006-05-11 02:56:24.000000000 +0100
+++ ./include/linux/proc_fs.h 2006-05-24 13:43:55.964159897 +0100
@@ -250,7 +250,7 @@
int type;
union {
int (*proc_get_link)(struct inode *, struct dentry **,
struct vfsmount **);
- int (*proc_read)(struct task_struct *task, char *page);
+ int (*proc_read)(struct task_struct *task, char *page,
loff_t *pos);
} op;
struct proc_dir_entry *pde;
struct inode vfs_inode;
--- ./fs/proc/base.c.dist 2006-05-11 02:56:24.000000000 +0100
+++ ./fs/proc/base.c 2006-05-24 13:54:26.370965292 +0100
@@ -409,15 +409,27 @@
(task->state == TASK_STOPPED || task->state == TASK_TRACED) && \
security_ptrace(current,task) == 0))
-static int proc_pid_environ(struct task_struct *task, char * buffer)
+static int proc_pid_environ(struct task_struct *task, char * buffer,
loff_t *pos)
{
int res = 0;
+ int p = *pos;
struct mm_struct *mm = get_task_mm(task);
+
+ /* proc_pid_environ is a 'special case' - the required data could
+ be larger than a page, so we read sequential chunks of the
+ environment data into the buffer using the supplied offset */
+ if (p < 0)
+ return -EINVAL;
+
if (mm) {
- unsigned int len = mm->env_end - mm->env_start;
+ unsigned int len = mm->env_end - (mm->env_start + p);
if (len > PAGE_SIZE)
len = PAGE_SIZE;
- res = access_process_vm(task, mm->env_start, buffer,
len, 0);
+ res = access_process_vm(task, (mm->env_start + p),
buffer, len, 0);
+ /* the calling routine (proc_info_read) needs to know we've
+ used the offset to read the pid data */
+ *pos += res;
+
if (!ptrace_may_attach(task))
res = -ESRCH;
mmput(mm);
@@ -425,7 +437,7 @@
return res;
}
-static int proc_pid_cmdline(struct task_struct *task, char * buffer)
+static int proc_pid_cmdline(struct task_struct *task, char * buffer,
loff_t *pos)
{
int res = 0;
unsigned int len;
@@ -462,7 +474,7 @@
return res;
}
-static int proc_pid_auxv(struct task_struct *task, char *buffer)
+static int proc_pid_auxv(struct task_struct *task, char *buffer, loff_t
*pos)
{
int res = 0;
struct mm_struct *mm = get_task_mm(task);
@@ -486,7 +498,7 @@
* Provides a wchan file via kallsyms in a proper one-value-per-file
format.
* Returns the resolved symbol. If that fails, simply return the address.
*/
-static int proc_pid_wchan(struct task_struct *task, char *buffer)
+static int proc_pid_wchan(struct task_struct *task, char *buffer,
loff_t *pos)
{
char *modname;
const char *sym_name;
@@ -506,7 +518,7 @@
/*
* Provides /proc/PID/schedstat
*/
-static int proc_pid_schedstat(struct task_struct *task, char *buffer)
+static int proc_pid_schedstat(struct task_struct *task, char *buffer,
loff_t *pos)
{
return sprintf(buffer, "%lu %lu %lu\n",
task->sched_info.cpu_time,
@@ -517,7 +529,7 @@
/* The badness from the OOM killer */
unsigned long badness(struct task_struct *p, unsigned long uptime);
-static int proc_oom_score(struct task_struct *task, char *buffer)
+static int proc_oom_score(struct task_struct *task, char *buffer,
loff_t *pos)
{
unsigned long points;
struct timespec uptime;
@@ -745,16 +757,30 @@
unsigned long page;
ssize_t length;
struct task_struct *task = proc_task(inode);
+ loff_t pos = *ppos;
if (count > PROC_BLOCK_SIZE)
count = PROC_BLOCK_SIZE;
if (!(page = __get_free_page(GFP_KERNEL)))
return -ENOMEM;
- length = PROC_I(inode)->op.proc_read(task, (char*)page);
+ length = PROC_I(inode)->op.proc_read(task, (char*)page, &pos);
- if (length >= 0)
- length = simple_read_from_buffer(buf, count, ppos, (char
*)page, length);
+ if (length >= 0) {
+ if (pos != *ppos) {
+ /* we are using the buffer to store subsequent
sections
+ of the proc_pid data - so the offset into the
buffer
+ will always be 0 - the offset is used to get the
+ original data */
+ pos = 0;
+ length = simple_read_from_buffer(buf, count,
&pos, (char *)page, length);
+ /* need to update the 'real' offset into the data we
+ are reading ... */
+ *ppos += length;
+ }
+ else
+ length = simple_read_from_buffer(buf, count,
ppos, (char *)page, length);
+ }
free_page(page);
return length;
}
--- ./fs/proc/internal.h.dist 2006-05-11 02:56:24.000000000 +0100
+++ ./fs/proc/internal.h 2006-05-24 13:52:53.568391757 +0100
@@ -32,10 +32,10 @@
extern void create_seq_entry(char *name, mode_t mode, struct
file_operations *f);
extern int proc_exe_link(struct inode *, struct dentry **, struct
vfsmount **);
-extern int proc_tid_stat(struct task_struct *, char *);
-extern int proc_tgid_stat(struct task_struct *, char *);
-extern int proc_pid_status(struct task_struct *, char *);
-extern int proc_pid_statm(struct task_struct *, char *);
+extern int proc_tid_stat(struct task_struct *, char *, loff_t *);
+extern int proc_tgid_stat(struct task_struct *, char *, loff_t *);
+extern int proc_pid_status(struct task_struct *, char *, loff_t *);
+extern int proc_pid_statm(struct task_struct *, char *, loff_t *);
void free_proc_entry(struct proc_dir_entry *de);
--- ./fs/proc/array.c.dist 2006-05-11 02:56:24.000000000 +0100
+++ ./fs/proc/array.c 2006-05-24 13:43:09.327905203 +0100
@@ -293,7 +293,7 @@
cap_t(p->cap_effective));
}
-int proc_pid_status(struct task_struct *task, char * buffer)
+int proc_pid_status(struct task_struct *task, char * buffer, loff_t *pos)
{
char * orig = buffer;
struct mm_struct *mm = get_task_mm(task);
@@ -465,17 +465,17 @@
return res;
}
-int proc_tid_stat(struct task_struct *task, char * buffer)
+int proc_tid_stat(struct task_struct *task, char * buffer, loff_t *pos)
{
return do_task_stat(task, buffer, 0);
}
-int proc_tgid_stat(struct task_struct *task, char * buffer)
+int proc_tgid_stat(struct task_struct *task, char * buffer, loff_t *pos)
{
return do_task_stat(task, buffer, 1);
}
-int proc_pid_statm(struct task_struct *task, char *buffer)
+int proc_pid_statm(struct task_struct *task, char *buffer, loff_t *pos)
{
int size = 0, resident = 0, shared = 0, text = 0, lib = 0, data
= 0;
struct mm_struct *mm = get_task_mm(task);
next reply other threads:[~2006-05-24 19:44 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-05-24 19:45 James Pearson [this message]
2006-05-24 20:29 ` 4096 byte limit to /proc/PID/environ ? H. Peter Anvin
[not found] ` <200605242029.k4OKTn9C031700@terminus.zytor.com>
2006-06-01 14:11 ` James Pearson
2007-08-15 16:54 ` Guy Streeter
2007-08-15 17:25 ` H. Peter Anvin
2007-08-21 14:40 ` Guy Streeter
2007-08-30 13:53 ` James Pearson
2007-09-03 8:17 ` Anton Arapov
2007-09-05 7:49 ` Anton Arapov
2007-09-05 7:58 ` H. Peter Anvin
2007-09-05 17:00 ` James Pearson
2007-09-05 17:18 ` Randy Dunlap
2007-09-06 9:23 ` James Pearson
2007-09-05 17:22 ` Alexey Dobriyan
2007-09-06 9:31 ` James Pearson
2007-09-06 12:31 ` Jan Engelhardt
2007-09-06 12:34 ` H. Peter Anvin
2007-09-06 12:34 ` Anton Arapov
-- strict thread matches above, loose matches on Subject: below --
2007-09-06 16:38 James Pearson
2007-09-18 14:09 ` Anton Arapov
2007-09-18 17:09 ` H. Peter Anvin
2006-05-24 15:54 James Pearson
2006-05-24 16:46 ` linux-os (Dick Johnson)
2006-05-24 16:59 ` James Pearson
2006-05-24 17:56 ` H. Peter Anvin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4474B7DB.8000304@moving-picture.com \
--to=james-p@moving-picture.com \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox