[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <Pine.LNX.4.61.0609080919130.22545@yvahk01.tjqt.qr>
Date: Fri, 8 Sep 2006 10:11:52 +0200 (MEST)
From: Jan Engelhardt <jengelh@...ux01.gwdg.de>
To: Edward Falk <efalk@...gle.com>
cc: linux-kernel@...r.kernel.org
Subject: Re: 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
\000MANPATH=/usr/local/man:/usr/share/man:/usr/X11R6/man:/opt/gnome/sha
re/man\000INFODIR=/usr/local/info:/usr/share/info:/usr/info\000NNTPSERV
ER=news\000SSH"...
$3 = "/dev/shm/a.out\000123\000LESSKEY=/etc/lesskey.bin\000GREP_COLOR=1
^ ^ ^ ^
argv[0] argv[1]envp[0] envp[1]
\000MANPATH=/usr/local/man:/usr/share/man:/usr/X11R6/man:/opt/gnome/sha
re/man\000INFODIR=/usr/local/info:/usr/share/info:/usr/info\000NNTPSERV
ER=news\000SSH"...
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 majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists