execvpe limits PATH environment variable to PATH_MAX
Zack Weinberg
zackw@panix.com
Mon Mar 30 18:10:52 GMT 2020
On Mon, Mar 30, 2020 at 1:23 PM Adhemerval Zanella via Libc-alpha
<libc-alpha@sourceware.org> wrote:
> On 30/03/2020 13:57, Nils Andre wrote:
> > Regardless of the whether the limit is narrow or not, I find that
> > setting a hard limit for `PATH` to be unintuitive as there is no reason
> > to assume that `PATH` will fall under a certain limit. Even more so,
> > when using `PATH_MAX` (as the limit) because it is unrelated.
> >
> > Would it be possible to know the reason for this limit?
>
> The change was to make it semantically similar to execl and execle
> where POSIX requires to be async-signal-safe. It also fixes an
> possible issue when used internally by posix_spawn, since the
> helper process that eventually spawns the new process is created
> with CLONE_VM.
>
> And I don't think it would be a good practice to use a different
> semantic for execvpe, i.e, allow arbitrary size paths. It would
> require either dynamic allocation or an unbounded static
> allocation (such some systems do, for instance FreeBSD).
I can see why execvpe needs to impose a limit on the length of *one
element* of the $PATH list, but not why it needs to impose a limit on
the length of *the entire list*. Regardless of the length of $PATH,
code vaguely like this should work, ne?
execvpe(const char *program, const char **argv, const char **envp)
{
size_t proglen = strlen(program);
char candidate[PATH_MAX];
const char *path = getenv("PATH");
const char *p = path, *q;
while (*p) {
q = p;
while (*q && *q != ':') q++;
size_t dirlen = q - p + 1;
size_t needed = dirlen + proglen + 1;
if (needed > PATH_MAX) {
errno = ENAMETOOLONG;
return -1;
}
memcpy(candidate, p, dirlen);
candidate[dirlen] = '/';
memcpy(candidate + dirlen + 1, program, proglen + 1);
execve(candidate, argv, envp);
if (errno != ENOENT && errno != ENOTDIR) {
return -1;
}
}
return -1;
}
(Completely untested, several corner cases ignored, may contain
off-by-one errors.)
zw
More information about the Libc-alpha
mailing list