Index: sys/kern/exec_elf_common.c =================================================================== RCS file: /cvsroot/syssrc/sys/kern/exec_elf_common.c,v retrieving revision 1.15 diff -u -r1.15 exec_elf_common.c --- sys/kern/exec_elf_common.c 2002/05/31 16:49:12 1.15 +++ sys/kern/exec_elf_common.c 2002/07/08 00:50:22 @@ -62,6 +62,9 @@ int exec_elf_setup_stack(struct proc *p, struct exec_package *epp) { + u_long max_stack_size; + u_long access_linear_min, access_size; + u_long noaccess_linear_min, noaccess_size; #ifndef USRSTACK32 #define USRSTACK32 (0x00000000ffffffffL&~PGOFSET) @@ -69,11 +72,13 @@ if (epp->ep_flags & EXEC_32) { epp->ep_minsaddr = USRSTACK32; - epp->ep_maxsaddr = epp->ep_minsaddr - MAXSSIZ; + max_stack_size = MAXSSIZ; } else { - epp->ep_maxsaddr = USRSTACK - MAXSSIZ; epp->ep_minsaddr = USRSTACK; + max_stack_size = MAXSSIZ; } + epp->ep_maxsaddr = (u_long)__STACK_GROW(epp->ep_minsaddr, + max_stack_size); epp->ep_ssize = p->p_rlimit[RLIMIT_STACK].rlim_cur; /* @@ -83,15 +88,17 @@ * * arguably, it could be made into one, but that would require the * addition of another mapping proc, which is unnecessary - * - * note that in memory, things assumed to be: 0 ... ep_maxsaddr - * ep_minsaddr */ - NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero, - ((epp->ep_minsaddr - epp->ep_ssize) - epp->ep_maxsaddr), - epp->ep_maxsaddr, NULLVP, 0, VM_PROT_NONE); - NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero, epp->ep_ssize, - (epp->ep_minsaddr - epp->ep_ssize), NULLVP, 0, + access_size = epp->ep_ssize; + access_linear_min = (u_long)__STACK_ALLOC(epp->ep_minsaddr, + access_size); + noaccess_size = max_stack_size - access_size; + noaccess_linear_min = (u_long)__STACK_ALLOC( + __STACK_GROW(epp->ep_minsaddr, access_size), noaccess_size); + NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero, noaccess_size, + noaccess_linear_min, NULLVP, 0, VM_PROT_NONE); + NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero, access_size, + access_linear_min, NULLVP, 0, VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE); return 0; Index: sys/kern/init_main.c =================================================================== RCS file: /cvsroot/syssrc/sys/kern/init_main.c,v retrieving revision 1.201 diff -u -r1.201 init_main.c --- sys/kern/init_main.c 2002/06/17 16:22:50 1.201 +++ sys/kern/init_main.c 2002/07/08 00:50:22 @@ -598,17 +598,17 @@ /* * Need just enough stack to hold the faked-up "execve()" arguments. */ - addr = USRSTACK - PAGE_SIZE; + addr = (vaddr_t)__STACK_ALLOC(USRSTACK, PAGE_SIZE); if (uvm_map(&p->p_vmspace->vm_map, &addr, PAGE_SIZE, NULL, UVM_UNKNOWN_OFFSET, 0, UVM_MAPFLAG(UVM_PROT_ALL, UVM_PROT_ALL, UVM_INH_COPY, UVM_ADV_NORMAL, UVM_FLAG_FIXED|UVM_FLAG_OVERLAY|UVM_FLAG_COPYONW)) != 0) panic("init: couldn't allocate argument space"); - p->p_vmspace->vm_maxsaddr = (caddr_t)addr; + p->p_vmspace->vm_maxsaddr = (caddr_t)__STACK_MAX(addr, PAGE_SIZE); for (pathp = &initpaths[0]; (path = *pathp) != NULL; pathp++) { - ucp = (char *)(addr + PAGE_SIZE); + ucp = (char *)USRSTACK; /* * Construct the boot flag argument. @@ -637,8 +637,9 @@ #ifdef DEBUG printf("init: copying out flags `%s' %d\n", flags, i); #endif - (void)copyout((caddr_t)flags, (caddr_t)(ucp -= i), i); - arg1 = ucp; + arg1 = __STACK_ALLOC(ucp, i); + ucp = __STACK_MAX(arg1, i); + (void)copyout((caddr_t)flags, arg1, i); } /* @@ -648,29 +649,27 @@ #ifdef DEBUG printf("init: copying out path `%s' %d\n", path, i); #endif - (void)copyout((caddr_t)path, (caddr_t)(ucp -= i), i); - arg0 = ucp; + arg0 = __STACK_ALLOC(ucp, i); + ucp = __STACK_MAX(arg0, i); + (void)copyout((caddr_t)path, arg0, i); /* * Move out the arg pointers. */ - uap = (char **)((long)ucp & ~ALIGNBYTES); - (void)suword((caddr_t)--uap, 0); /* terminator */ - if (options != 0) - (void)suword((caddr_t)--uap, (long)arg1); + ucp = (caddr_t)__STACK_ALIGN(ucp, ALIGNBYTES); + uap = (char **)__STACK_ALLOC(ucp, sizeof(char *) * 3); + SCARG(&args, path) = arg0; + SCARG(&args, argp) = uap; + SCARG(&args, envp) = NULL; slash = strrchr(path, '/'); if (slash) - (void)suword((caddr_t)--uap, + (void)suword((caddr_t)uap++, (long)arg0 + (slash + 1 - path)); else - (void)suword((caddr_t)--uap, (long)arg0); - - /* - * Point at the arguments. - */ - SCARG(&args, path) = arg0; - SCARG(&args, argp) = uap; - SCARG(&args, envp) = NULL; + (void)suword((caddr_t)uap++, (long)arg0); + if (options != 0) + (void)suword((caddr_t)uap++, (long)arg1); + (void)suword((caddr_t)uap++, 0); /* terminator */ /* * Now try to exec the program. If can't for any reason Index: sys/kern/kern_exec.c =================================================================== RCS file: /cvsroot/syssrc/sys/kern/kern_exec.c,v retrieving revision 1.152 diff -u -r1.152 kern_exec.c --- sys/kern/kern_exec.c 2002/04/23 15:11:25 1.152 +++ sys/kern/kern_exec.c 2002/07/08 00:50:22 @@ -545,7 +545,36 @@ arginfo.ps_nargvstr = argc; arginfo.ps_nenvstr = envc; - stack = (char *) (vm->vm_minsaddr - len); + stack = (char *)__STACK_ALLOC(__STACK_GROW(vm->vm_minsaddr, + sizeof(struct ps_strings) + szsigcode), + len - (sizeof(struct ps_strings) + szsigcode)); +#ifdef __MACHINE_STACK_GROWS_UP + /* + * The copyargs call always copies into lower addresses + * first, moving towards higher addresses, starting with + * the stack pointer that we give. When the stack grows + * down, this puts argc/argv/envp very shallow on the + * stack, right at the first user stack pointer, and puts + * STACKGAPLEN very deep in the stack. When the stack + * grows up, the situation is reversed. + * + * Normally, this is no big deal. But the ld_elf.so _rtld() + * function expects to be called with a single pointer to + * a region that has a few words it can stash values into, + * followed by argc/argv/envp. When the stack grows down, + * it's easy to decrement the stack pointer a little bit to + * allocate the space for these few words and pass the new + * stack pointer to _rtld. When the stack grows up, however, + * a few words before argc is part of the signal trampoline, + * so we have a problem. + * + * Instead of changing how _rtld works, we take the easy way + * out and steal 32 bytes before we call copyargs. This + * space is effectively stolen from STACKGAPLEN. + */ + stack += 32; +#endif /* __MACHINE_STACK_GROWS_UP */ + /* Now copy argc, args & environ to new stack */ error = (*pack.ep_es->es_copyargs)(&pack, &arginfo, &stack, argp); if (error) { @@ -553,11 +582,11 @@ goto exec_abort; } /* Move the stack back to original point */ - stack = (char *) (vm->vm_minsaddr - len); + stack = (char *)__STACK_GROW(vm->vm_minsaddr, len); /* fill process ps_strings info */ - p->p_psstr = (struct ps_strings *)(vm->vm_minsaddr - - sizeof(struct ps_strings)); + p->p_psstr = (struct ps_strings *)__STACK_ALLOC(vm->vm_minsaddr, + sizeof(struct ps_strings)); p->p_psargv = offsetof(struct ps_strings, ps_argvstr); p->p_psnargv = offsetof(struct ps_strings, ps_nargvstr); p->p_psenv = offsetof(struct ps_strings, ps_envstr); @@ -573,9 +602,10 @@ /* copy out the process's signal trapoline code */ if (szsigcode) { + p->p_sigctx.ps_sigcode = __STACK_ALLOC(__STACK_MAX(p->p_psstr, + sizeof(struct ps_strings)), szsigcode); if ((error = copyout((char *)pack.ep_es->es_emul->e_sigcode, - p->p_sigctx.ps_sigcode = (char *)p->p_psstr - szsigcode, - szsigcode)) != 0) { + p->p_sigctx.ps_sigcode, szsigcode)) != 0) { DPRINTF(("execve: sig trampoline copyout failed\n")); goto exec_abort; } Index: sys/sys/param.h =================================================================== RCS file: /cvsroot/syssrc/sys/sys/param.h,v retrieving revision 1.143 diff -u -r1.143 param.h --- sys/sys/param.h 2002/07/06 01:31:33 1.143 +++ sys/sys/param.h 2002/07/08 00:50:23 @@ -145,6 +145,35 @@ #include /* + * Stack macros. On most architectures, the stack grows down, + * towards lower addresses; it is the rare architecture where + * it grows up, towards higher addresses. + * + * __STACK_GROW and __STACK_SHRINK adjust a stack pointer by some + * size, no questions asked. __STACK_ALIGN aligns a stack pointer. + * + * __STACK_ALLOC returns a pointer to allocated stack space of + * some size; given such a pointer and a size, __STACK_MAX gives + * the maximum (in the "maxsaddr" sense) stack address of the + * allocated memory. + */ +#ifdef __MACHINE_STACK_GROWS_UP +#define __STACK_GROW(sp, _size) (((caddr_t)(sp)) + (_size)) +#define __STACK_SHRINK(sp, _size) (((caddr_t)(sp)) - (_size)) +#define __STACK_ALIGN(sp, bytes) \ + ((caddr_t)((((unsigned long)(sp)) + (bytes)) & ~(bytes))) +#define __STACK_ALLOC(sp, _size) ((caddr_t)(sp)) +#define __STACK_MAX(p, _size) (((caddr_t)(p)) + (_size)) +#else +#define __STACK_GROW(sp, _size) (((caddr_t)(sp)) - (_size)) +#define __STACK_SHRINK(sp, _size) (((caddr_t)(sp)) + (_size)) +#define __STACK_ALIGN(sp, bytes) \ + ((caddr_t)(((unsigned long)(sp)) & ~(bytes))) +#define __STACK_ALLOC(sp, _size) (((caddr_t)(sp)) - (_size)) +#define __STACK_MAX(p, _size) ((caddr_t)(p)) +#endif + +/* * Priorities. Note that with 32 run queues, differences less than 4 are * insignificant. */