Bug 27835

Summary: [libc] execve() doesn't conform to execve(2) spec in syscall manual
Product: Base System Reporter: jyliu <jyliu>
Component: kernAssignee: freebsd-standards (Nobody) <standards>
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: 4.3-STABLE   
Hardware: Any   
OS: Any   
Attachments:
Description Flags
file.diff none

Description jyliu 2001-06-02 13:30:01 UTC
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");
}
Comment 1 Robert Watson freebsd_committer freebsd_triage 2008-03-08 20:48:55 UTC
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.
Comment 2 Jilles Tjoelker freebsd_committer freebsd_triage 2009-04-16 23:26:57 UTC
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
Comment 3 David Schultz freebsd_committer freebsd_triage 2010-12-07 05:23:24 UTC
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!)