Page MenuHomeFreeBSD

D25038.id72387.diff
No OneTemporary

D25038.id72387.diff

Index: lib/libc/gen/exec.c
===================================================================
--- lib/libc/gen/exec.c
+++ lib/libc/gen/exec.c
@@ -49,6 +49,9 @@
extern char **environ;
+static const char execvPe_err_preamble[] = "execvP: ";
+static const char execvPe_err_trailer[] = ": path too long\n";
+
int
execl(const char *name, const char *arg, ...)
{
@@ -149,8 +152,8 @@
const char **memp;
size_t cnt, lp, ln;
int eacces, save_errno;
- char *cur, buf[MAXPATHLEN];
- const char *p, *bp;
+ char buf[MAXPATHLEN];
+ const char *bp, *np, *op, *p;
struct stat sb;
eacces = 0;
@@ -158,7 +161,7 @@
/* If it's an absolute or relative path name, it's easy. */
if (strchr(name, '/')) {
bp = name;
- cur = NULL;
+ op = NULL;
goto retry;
}
bp = buf;
@@ -169,23 +172,24 @@
return (-1);
}
- cur = alloca(strlen(path) + 1);
- if (cur == NULL) {
- errno = ENOMEM;
- return (-1);
- }
- strcpy(cur, path);
- while ((p = strsep(&cur, ":")) != NULL) {
+ op = path;
+ ln = strlen(name);
+ while (op != NULL) {
+ np = strchrnul(op, ':');
+
/*
* It's a SHELL path -- double, leading and trailing colons
* mean the current directory.
*/
- if (*p == '\0') {
+ if (np == op) {
+ /* Empty component. */
p = ".";
lp = 1;
- } else
- lp = strlen(p);
- ln = strlen(name);
+ } else {
+ /* Non-empty component. */
+ p = op;
+ lp = np - op;
+ }
/*
* If the path is too long complain. This is a possible
@@ -193,10 +197,11 @@
* the user may execute the wrong program.
*/
if (lp + ln + 2 > sizeof(buf)) {
- (void)_write(STDERR_FILENO, "execvP: ", 8);
+ (void)_write(STDERR_FILENO, execvPe_err_preamble,
+ sizeof(execvPe_err_preamble) - 1);
(void)_write(STDERR_FILENO, p, lp);
- (void)_write(STDERR_FILENO, ": path too long\n",
- 16);
+ (void)_write(STDERR_FILENO, execvPe_err_trailer,
+ sizeof(execvPe_err_trailer) - 1);
continue;
}
bcopy(p, buf, lp);
@@ -204,6 +209,12 @@
bcopy(name, buf + lp + 1, ln);
buf[lp + ln + 1] = '\0';
+ /* Advance to the next component or terminate after this. */
+ if (*np == '\0')
+ op = NULL;
+ else
+ op = np + 1;
+
retry: (void)_execve(bp, argv, envp);
switch (errno) {
case E2BIG:
Index: lib/libc/gen/posix_spawn.c
===================================================================
--- lib/libc/gen/posix_spawn.c
+++ lib/libc/gen/posix_spawn.c
@@ -246,8 +246,23 @@
pid_t p;
#ifdef _RFORK_THREAD_STACK_SIZE
char *stack;
-
- stack = malloc(_RFORK_THREAD_STACK_SIZE);
+ size_t cnt, stacksz;
+
+ stacksz = _RFORK_THREAD_STACK_SIZE;
+ if (use_env_path) {
+ /*
+ * We need to make sure we have enough room on the stack for the
+ * potential alloca() in execvPe if it gets kicked back an
+ * ENOEXEC from execve(2), plus the original buffer we gave
+ * ourselves; this protects us in the event that the caller
+ * intentionally or inadvertently supplies enough arguments to
+ * make us blow past the stack we've allocated from it.
+ */
+ stacksz += (2 * sizeof(char *));
+ for (cnt = 0; argv[cnt] != NULL; ++cnt)
+ stacksz += sizeof(char *);
+ }
+ stack = malloc(stacksz);
if (stack == NULL)
return (ENOMEM);
#endif
@@ -273,8 +288,7 @@
* parent. Because of this, we must use rfork_thread instead while
* almost every other arch stores the return address in a register.
*/
- p = rfork_thread(RFSPAWN, stack + _RFORK_THREAD_STACK_SIZE,
- _posix_spawn_thr, &psa);
+ p = rfork_thread(RFSPAWN, stack + stacksz, _posix_spawn_thr, &psa);
free(stack);
#else
p = rfork(RFSPAWN);

File Metadata

Mime Type
text/plain
Expires
Tue, Feb 10, 2:20 PM (3 h, 58 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28626043
Default Alt Text
D25038.id72387.diff (3 KB)

Event Timeline