| Summary: | [libc] execve() doesn't conform to execve(2) spec in syscall manual | ||||||
|---|---|---|---|---|---|---|---|
| Product: | Base System | Reporter: | jyliu <jyliu> | ||||
| Component: | kern | Assignee: | freebsd-standards (Nobody) <standards> | ||||
| Status: | Closed FIXED | ||||||
| Severity: | Affects Only Me | ||||||
| Priority: | Normal | ||||||
| Version: | 4.3-STABLE | ||||||
| Hardware: | Any | ||||||
| OS: | Any | ||||||
| Attachments: |
|
||||||
Responsible Changed From-To: freebsd-bugs->freebsd-standards Assign to freebsd-standards, who may have a view on whether our code or documentation should be fixed. POSIX says that passing 0 arguments in execve() is allowed, but an
application doing it is not strictly POSIX compliant, and that
applications must handle being started with 0 arguments. The Solaris 10
man page says something similar.
The test program fails with EFAULT on 7.x, but passing 0 arguments is
still possible by changing the execve call to
execve("/bin/sh", (char*[]){ NULL }, NULL)
That change is good because a null pointer for argv yields undefined
behaviour (like any function parameter outside the permitted domain).
Another reason not to apply the patch to the kernel is that it uses
EINVAL which POSIX already defines for a different purpose that seems
useful to me: to indicate binaries with correct permissions and a valid
file format that are not supported (e.g. wrong architecture). This
situation currently results in ENOEXEC. Implementing the POSIX EINVAL
could improve the 'Syntax error: "(" unexpected' message you get when
trying to execute an ELF binary for the wrong architecture in sh; some
other shells and the execlp(3) and execvp(3) libc functions also assume
an executable is a shell script when they get ENOEXEC.
--
Jilles Tjoelker
State Changed From-To: open->closed The problem noted by the submitter was fixed some time between 4.3-STABLE and 7.0-RELEASE. The problem noted in Jilles Tjoelker's follow-up is a bug in the application, not a bug in the kernel, according to POSIX. (In other words, don't do that!) |
According to execve(2), the argument argv is a pointer to a null-terminated array of character pointers to null-terminated character strings and at least one argument must be presented in the array. But execve("/bin/sh", NULL, NULL) runs without any error. Maybe it's harmless, but it doesn't conform to the syscall spec and it may tempt people to write non-portable code. Fix: Following is an attampt to fix this problem. The part of ERRORS in execve(2) manual need to be updated for a new entry, EINVAL. ---begins here--- How-To-Repeat: Run the following code. Notice it runs without the expected error, EINVAL. #include <unistd.h> int main() { if(execve("/bin/sh", NULL, NULL) < 0) perror("execve"); }