[lkml]   [2006]   [Sep]   [8]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
Messages in this thread
SubjectRe: Proper /proc/pid/cmdline behavior when command line is corrupt?
Hi Edward,

> there's a few lines of code in fs/proc/base.c:proc_pid_cmdline() that
> I'm unable to make sense of. There are a few lines that check the
> returned buffer to see if it's properly nul-terminated. If not, the
> code assumes the user has overwritten and corrupted the command line
> buffer.
> The next step is to search for the first embedded nul, and truncate
> the buffer at that point.
> If no embedded nul is found, enough data is copied from the user's
> environment to fill the buffer. Another search for an embedded nul
> is then made.
> Does anybody know what on earth this code is trying to accomplish?
> Is this the intended behavior? The best I can guess is that the user
> is assumed to have overwritten the end of the command line buffer and
> that the environment buffer is assumed to immediately follow the
> command line buffer.

The environment buffer is not assumed to be there, it is _known_ to come right
after the argument string, because that is how the kernel sets it up on execve
(for x86 at least). GDB verifies this:

(gdb) b main
(gdb) r 123
(gdb) p *argv[0]@3072
$3 = "/dev/shm/a.out\000123\000LESSKEY=/etc/lesskey.bin\000GREP_COLOR=1

$3 = "/dev/shm/a.out\000123\000LESSKEY=/etc/lesskey.bin\000GREP_COLOR=1
^ ^ ^ ^
argv[0] argv[1]envp[0] envp[1]

As you can see above, libc will set up the ARGV and ENVP arrays with
pointers to the respective strings. Writing over the end of the ENVP
string will cause

- a segfault in the user program
- a "cannot access that memory" in GDB
- more bad things, if done in kernelspace

> I'm currently working on a patch that removes the one page limit on
> the returned command line buffer but I'm not convinced I should
> retain this behavior.

I think yes. proc_pid_cmdline() has these lines:

len = mm->arg_end - mm->arg_start
* if (len > PAGE_SIZE)
* len = PAGE_SIZE;
res = access_process_vm(task, mm->arg_start, buffer, len, 0);

and @buffer is allocated in the caller as only one page:

static ssize_t proc_info_read(struct file * file, char __user * buf,
size_t count, loff_t *ppos)
if (!(page = __get_free_page(GFP_KERNEL)))
return -ENOMEM;
length = PROC_I(inode)->op.proc_read(task, (char*)page);

> Is it possible that there's any code out there
> that depends on this behavior. It would help if I knew why it was
> done this way.

Jan Engelhardt
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to
More majordomo info at
Please read the FAQ at

 \ /
  Last update: 2006-09-08 10:17    [W:0.045 / U:2.892 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site