Subject: Changes to kern/exec_elf.c
To: None <netbsd-bugs@NetBSD.ORG>
From: None <r_friedl@informatik.uni-kl.de>
List: netbsd-bugs
Date: 11/22/1995 15:58:43
elf_copyargs:
Writes directly to user-space instead of using copyout.
Also use 'copyargs' to copy the normal args.

elf_read_from:
To return 'error' on short read is wrong, because 'error' is 0 in this
case.

exec_elf_makecmds:
It is not necessary to read the program header, it is already in the
text segment of the executable, at the address given in the header.

The vnode for the file to exec must be unlocked while looking for the
interpreter, or the system can deadlock.

--- kern/exec_elf.c.orig	Fri Jun 30 09:05:41 1995
+++ kern/exec_elf.c	Wed Oct 11 16:33:05 1995
@@ -84,84 +171,37 @@
 	void *stack;
 	void *argp;
 {
-	char **cpp = stack;
-	char *dp, *sp;
-	size_t len;
-	void *nullp = NULL;
-	int argc = arginfo->ps_nargvstr;
-	int envc = arginfo->ps_nenvstr;
-	AuxInfo *a;
 	struct elf_args *ap;
 
-	if (copyout(&argc, cpp++, sizeof(argc)))
-		return NULL;
-
-	dp = (char *) (cpp + argc + envc + 2 + pack->ep_emul->e_arglen);
-	sp = argp;
-
-	/* XXX don't copy them out, remap them! */
-	arginfo->ps_argvstr = cpp; /* remember location of argv for later */
-
-	for (; --argc >= 0; sp += len, dp += len)
-		if (copyout(&dp, cpp++, sizeof(dp)) ||
-		    copyoutstr(sp, dp, ARG_MAX, &len))
-			return NULL;
-
-	if (copyout(&nullp, cpp++, sizeof(nullp)))
-		return NULL;
-
-	arginfo->ps_envstr = cpp; /* remember location of envp for later */
-
-	for (; --envc >= 0; sp += len, dp += len)
-		if (copyout(&dp, cpp++, sizeof(dp)) ||
-		    copyoutstr(sp, dp, ARG_MAX, &len))
-			return NULL;
-
-	if (copyout(&nullp, cpp++, sizeof(nullp)))
+	stack = copyargs(pack, arginfo, stack, argp);
+	if (!stack)
 		return NULL;
 
 	/*
 	 * Push extra arguments on the stack needed by dynamically
 	 * linked binaries
 	 */
-	a = (AuxInfo *) cpp;
 	if ((ap = (struct elf_args *) pack->ep_emul_arg)) {
-
-		a->au_id = AUX_phdr;
-		a->au_v = ap->arg_phaddr;
-		a++;
-
-		a->au_id = AUX_phent;
-		a->au_v = ap->arg_phentsize;
-		a++;
-
-		a->au_id = AUX_phnum;
-		a->au_v = ap->arg_phnum;
-		a++;
-
-		a->au_id = AUX_pagesz;
-		a->au_v = NBPG;
-		a++;
-
-		a->au_id = AUX_base;
-		a->au_v = ap->arg_interp;
-		a++;
-
-		a->au_id = AUX_flags;
-		a->au_v = 0;
-		a++;
-
-		a->au_id = AUX_entry;
-		a->au_v = ap->arg_entry;
-		a++;
-
-		a->au_id = AUX_null;
-		a->au_v = 0;
-		a++;
-
+		AuxInfo ai[8], *a;
+		u_int len;
+		a = ai;
+#define	AddInfo(i, v)	(a->au_id = (i), a->au_v = (v), a++)
+		AddInfo (AUX_phdr, ap->arg_phaddr);
+		AddInfo (AUX_phent, ap->arg_phentsize);
+		AddInfo (AUX_phnum, ap->arg_phnum);
+		AddInfo (AUX_pagesz, NBPG);
+		AddInfo (AUX_base, ap->arg_interp);
+		AddInfo (AUX_flags, 0);
+		AddInfo (AUX_entry, ap->arg_entry);
+		AddInfo (AUX_null, 0);
+#undef	AddInfo
 		free((char *) ap, M_TEMP);
+		len = (caddr_t)a - (caddr_t)ai;
+		if (copyout (ai, stack, len))
+			return NULL;
+		stack += len;
 	}
-	return a;
+	return stack;
 }
 
 /*
@@ -328,7 +368,7 @@
          * See if we got all of it
          */
 	if (resid != 0)
-		return error;
+		return ENOEXEC;
 	return 0;
 }
 
@@ -436,6 +476,7 @@
 {
 	Elf32_Ehdr *eh = epp->ep_hdr;
 	Elf32_Phdr *ph, *pp;
+	Elf32_Addr phdr = 0;
 	int error, i, n;
 	char interp[MAXPATHLEN];
 	u_long pos = 0, phsize;
@@ -530,9 +571,11 @@
 		case Elf32_pt_interp:
 			/* Already did this one */
 		case Elf32_pt_dynamic:
-		case Elf32_pt_phdr:
 		case Elf32_pt_note:
 			break;
+		case Elf32_pt_phdr:
+			phdr = pp->p_vaddr;
+			break;
 
 		default:
 			/*
@@ -552,18 +595,15 @@
 
 		ap = (struct elf_args *) malloc(sizeof(struct elf_args),
 						 M_TEMP, M_WAITOK);
-		if ((error = elf_load_file(p, interp, &epp->ep_vmcmds,
-				&epp->ep_entry, ap, &pos)) != 0) {
+		VOP_UNLOCK(epp->ep_vp);
+		error = elf_load_file(p, interp, &epp->ep_vmcmds,
+				&epp->ep_entry, ap, &pos);
+		VOP_LOCK(epp->ep_vp);
+		if (error != 0) {
 			free((char *) ap, M_TEMP);
 			goto bad;
 		}
-		/* Arrange to load the program headers. */
-		pos = ELF_ALIGN(pos + NBPG, NBPG);
-		ap->arg_phaddr = pos;
-		NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_readvn, phsize,
-			  pos, epp->ep_vp, eh->e_phoff,
-			  VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE);
-		pos += phsize;
+		ap->arg_phaddr = phdr;
 
 		ap->arg_phentsize = eh->e_phentsize;
 		ap->arg_phnum = eh->e_phnum;