Bug 8408
Summary: | execve() wrongly permits argv and envp to be NULL | ||
---|---|---|---|
Product: | Process Management | Reporter: | Michael Kerrisk (michael.kerrisk) |
Component: | Other | Assignee: | Alan (alan) |
Status: | REJECTED DOCUMENTED | ||
Severity: | normal | CC: | akpm, drepper, leonard.r.koenig, mtk.manpages, protasnb |
Priority: | P2 | ||
Hardware: | i386 | ||
OS: | Linux | ||
Kernel Version: | 2.6.20 and all earlier kernels | Subsystem: | |
Regression: | No | Bisected commit-id: |
Description
Michael Kerrisk
2007-04-30 03:34:47 UTC
Probably the best would be to post this bug on LKML, for general discussion on the issue. We definitely need a category for issues of this kind. Placing it in process management for now. Thanks. This isn't a kernel bug. If address zero is mapped then it is valid for it to contain environment or argument. On systems where page zero isn't mapped it'll fault as expected. NULL is a valid pointer in some cases, it points to a page which contains NULL as its start so happens to be a valid argument vector, by chance. (In reply to comment #2) > This isn't a kernel bug. If address zero is mapped then it is valid for it to > contain environment or argument. On systems where page zero isn't mapped > it'll > fault as expected. > > NULL is a valid pointer in some cases, it points to a page which contains > NULL > as its start so happens to be a valid argument vector, by chance. > I missed the closure of this bug. As initially formulated, my bug report was faulty. Indeed it seems that most systems permit envp to be NULL (I tested FreeBSD and Solaris), with the meaning that the environment list for the new program is empty. However, my report is correct regarding argv: most other systems (e.g., FreeBSD, Solaris) fail the execve() with EFAULT in the example below. (The man pages on FreeBSD and Solaris are explicit in specifying that at least one argument must be supplied in argv.) Alan, your comments about NULL as a pointer to a mapping at page 0 are bogus. Whether or not there is mapping there does not even come into play, because in fs/exec.c, use is made of this function to check argv and envp: static int count(char __user * __user * argv, int max) { int i = 0; if (argv != NULL) { ... } return i; } Given a count of 0, copy_strings() then copies no arguments, providing behavior as though (argv != NULL && argv[0] == NULL). Linux should be giving -EFAULT here, for consistency with other systems. ===== #include <unistd.h> #include <stdlib.h> #include <stdio.h> int main() { char *argv[10]; argv[0] = "date"; argv[1] = NULL; execve("/bin/date", NULL, NULL); perror("execve"); exit(EXIT_FAILURE); } Well the spec doesn't say what has to happen if you pass invalid values (-EFAULT is just the correct error if we error it for this). It is an ABI change and that makes it seem rather excessive for a philosophical point upon which no app will depend on receiving -EFAULT in normal usage, but old Linux code might use NULL NULL So I still don't think we should fix it. Add a link, just to track a relevant discussion 14 years later: https://lore.kernel.org/lkml/20220126043947.10058-1-ariadne@dereferenced.org/ (In reply to Michael Kerrisk from comment #5) I don't think that's the same issue, isn't it? This bug report is about disallowing argv == NULL while the linked patch has a stricter requirement, namely that argv[0] != NULL i.e., argc >= 1. This bug here would still allow for: char *argv[] = { NULL }; execve("/bin/date", argv, NULL); While the linked patch would require: char *argv[] = { "foo", NULL }; // ideally "/bin/date" or suchlike execve("/bin/date", argv, NULL); Note that the former is actually required by POSIX: > The argument argv is an array of character pointers to null-terminated > strings. The application shall ensure that the last member of this array is a > null pointer. (https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/functions/execve.html) While the latter is explicitly not part of POSIX (see RATIONALE): > Early proposals required that the value of argc passed to main() be "one or > greater". This was driven by the same requirement in drafts of the ISO C > standard. In fact, historical implementations have passed a value of zero > when no arguments are supplied to the caller of the exec functions. This > requirement was removed from the ISO C standard and subsequently removed from > this volume of POSIX.1-2017 as well. |