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++;

Reply via email to