All of lore.kernel.org
 help / color / mirror / Atom feed
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);


             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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.