Re: setproctitle()

From: Bryan Donlan
Date: Fri Oct 02 2009 - 18:53:42 EST


On Fri, Oct 2, 2009 at 5:37 PM, Timo Sirainen <tss@xxxxxx> wrote:
> I'd like to get BSD's setproctitle() implemented for glibc so that more
> programs could start using it. The current method of messing around with
> argv and environment to implement it is horribly ugly, fragile and I
> find it dangerous enough that I haven't dared to use it in my programs.
>
> Any chance of making all this easier so it could actually be implemented
> in a generic and safe way in glibc?
>
> I guess there are several different ways it could be done. My first idea
> was to have some magic value in beginning of cmdline (\0 followed by a
> few characters) followed by a pointer to the actual string. But that's a
> bit ugly and userspace can't easily figure out if this is supported by
> kernel.
>
> So the second idea, perhaps this will work? Reserve space for the
> pointer between arg_end and env_start. If it's NULL, use the old way. If
> it's non-NULL, use it for the cmdline. Userspace can check if this is
> supported by seeing if environ[0] - (argv[argc-1] + strlen(argv[argc-1])
> + 1) == sizeof(void *).
>

This won't work - the start of the env variables is _defined_ by the
end of the argument vector, as found on the initial stack when the
program is loaded - see the initial stack diagram at [1].

Interestingly, there is some code that purports to handle
setproctitle(): (fs/proc/base.c)
res = access_process_vm(task, mm->arg_start, buffer, len, 0);

// If the nul at the end of args has been overwritten, then
// assume application is using setproctitle(3).
if (res > 0 && buffer[res-1] != '\0' && len < PAGE_SIZE) {
len = strnlen(buffer, res);
if (len < res) {
res = len;
} else {
len = mm->env_end - mm->env_start;
if (len > PAGE_SIZE - res)
len = PAGE_SIZE - res;
res += access_process_vm(task, mm->env_start, buffer+res, len, 0);
res = strnlen(buffer, res);
}
}

This would seem to allow the argument space to be extended up until
the end of the environment variable area (although it seems to have a
bug where it will ignore errors when reading this extra bit!)

Nevertheless, if one were to insist on a more controllable method, a
better way might be to simply define a syscall that userspace can use
to select a new command line buffer. Overwrite mm->arg_end and
mm->arg_start, and there you go. Of course, the logic over here needs
to be disabled in this case, as env variables will no longer be found
immediately after the argument vector.

[1] - http://manugarg.googlepages.com/aboutelfauxiliaryvectors
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/