The glibc implementation of posix_spawn tries sending the file to /bin/sh if execve() fails with ENOEXEC:
__execve (file, argv, envp);
if (errn开发者_JAVA技巧o == ENOEXEC)
script_execute (file, argv, envp)
The POSIX sample implementation simply fails if execve() fails in any way:
execve(path, argv, envp);
exit(127); /* exec failed */
The POSIX specification for posix_spawn() does not specify anything about how to handle files that would result in ENOEXEC if sent to execve(). As a possible contrast, the POSIX specification for the exec* family of functions specifically states that execlp() and execvp() should invoke sh in the case of an unrecognized executable type:
There are two distinct ways in which the contents of the process image file may cause the execution to fail, distinguished by the setting of errno to either [ENOEXEC] or [EINVAL] (see the ERRORS section). In the cases where the other members of the exec family of functions would fail and set errno to [ENOEXEC], the execlp() and execvp() functions shall execute a command interpreter and the environment of the executed command shall be as if the process invoked the sh utility using execl() as follows:
execl([shell path], arg0, file, arg1, ..., (char *)0);
where [shell path] is an unspecified pathname for the sh utility, file is the process image file, and for execvp(), where arg0, arg1, and so on correspond to the values passed to execvp() in argv[0], argv[1], and so on.
So, is the glibc implementation non-conforming? Or is the POSIX specification just a bit vague here? Isn't there a security risk in the glibc implementation?
This behavior might be acceptable (by analogy) for posix_spawnp
, even if not officially sanctioned, but I think you're right that it's non-conformant, and moreover that it's dangerously non-conformant for plain posix_spawn
. The shell invocation code should simply be removed.
精彩评论