Messages in this thread | | | Date | Fri, 8 Sep 2006 10:11:52 +0200 (MEST) | From | Jan Engelhardt <> | 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@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |