Duplicate environment variables have been a source of bugs, so perhaps the kernel should fail an execve with an invalid envp. Diff below checks that each environment string contains a '=' and that there are no duplicates up to the equals sign.
So far I haven't noticed any breakage except for a purposefully misbehaving program to test that execve will fail. EINVAL gives a somewhat confusing error message, but nothing in intro(2) looked like a better choice. Idea from Martin Brandenburg. - Matthew Martin diff --git kern_exec.c kern_exec.c index 7784d5f4165..3c3f0aa6266 100644 --- kern_exec.c +++ kern_exec.c @@ -239,10 +239,8 @@ sys_execve(struct proc *p, void *v, register_t *retval) struct vattr attr; struct ucred *cred = p->p_ucred; char *argp; - char * const *cpp, *dp, *sp; -#ifdef KTRACE + char * const *cpp, *dp, *ep, *op, *sp; char *env_start; -#endif struct process *pr = p->p_p; long argc, envc; size_t len, sgap; @@ -357,9 +355,7 @@ sys_execve(struct proc *p, void *v, register_t *retval) envc = 0; /* environment does not need to be there */ if ((cpp = SCARG(uap, envp)) != NULL ) { -#ifdef KTRACE env_start = dp; -#endif while (1) { len = argp + ARG_MAX - dp; if ((error = copyin(cpp, &sp, sizeof(sp))) != 0) @@ -371,6 +367,19 @@ sys_execve(struct proc *p, void *v, register_t *retval) error = E2BIG; goto bad; } + + /* Check for duplicate environment variables */ + if ((ep = strchr(dp, '=')) == NULL) { + error = EINVAL; + goto bad; + } + for (op = env_start; op != dp; op = strchr(op, '\0') + 1) { + if (strncmp(dp, op, (ep - dp + 1)) == 0) { + error = EINVAL; + goto bad; + } + } + dp += len; cpp++; envc++;