Commit ea3bc13f authored by Matthew Wilcox's avatar Matthew Wilcox Committed by Linus Torvalds

[PATCH] More support for upward growing stacks

 - remove elf_caddr_t. It's positively dangerous to #define this since
   elf_caddr_t foo, bar; creates variables of different types (foo is
   char *, bar is char).
 - rewrite large chunks of create_elf_tables(), it needed cleaning anyway.
 - add upwards-growing stack support to create_elf_tables.
 - redefine the ARCH_DLINFO stuff on powerpc -- it's tested, works.
 - add upwards-growing-stack support to exec.c too.
parent b4093e0c
......@@ -54,7 +54,6 @@ static struct linux_binfmt irix_format = {
#ifndef elf_addr_t
#define elf_addr_t unsigned long
#define elf_caddr_t char *
#endif
#ifdef DEBUG_ELF
......@@ -155,8 +154,8 @@ unsigned long * create_irix_tables(char * p, int argc, int envc,
unsigned int interp_load_addr,
struct pt_regs *regs, struct elf_phdr *ephdr)
{
elf_caddr_t *argv;
elf_caddr_t *envp;
elf_addr_t *argv;
elf_addr_t *envp;
elf_addr_t *sp, *csp;
#ifdef DEBUG_ELF
......@@ -202,20 +201,20 @@ unsigned long * create_irix_tables(char * p, int argc, int envc,
#undef NEW_AUX_ENT
sp -= envc+1;
envp = (elf_caddr_t *) sp;
envp = sp;
sp -= argc+1;
argv = (elf_caddr_t *) sp;
argv = sp;
__put_user((elf_addr_t)argc,--sp);
current->mm->arg_start = (unsigned long) p;
while (argc-->0) {
__put_user((elf_caddr_t)(unsigned long)p,argv++);
__put_user((unsigned long)p,argv++);
p += strlen_user(p);
}
__put_user(NULL, argv);
current->mm->arg_end = current->mm->env_start = (unsigned long) p;
while (envc-->0) {
__put_user((elf_caddr_t)(unsigned long)p,envp++);
__put_user((unsigned long)p,envp++);
p += strlen_user(p);
}
__put_user(NULL, envp);
......
......@@ -80,7 +80,6 @@ struct elf_prpsinfo32
};
#define elf_addr_t u32
#define elf_caddr_t u32
#define init_elf_binfmt init_elf32_binfmt
#undef CONFIG_BINFMT_ELF
#ifdef CONFIG_BINFMT_ELF32
......
......@@ -166,7 +166,6 @@ struct elf_prpsinfo32
#define NEW_TO_OLD_GID(gid) ((gid) > 65535) ? (u16)overflowgid : (u16)(gid)
#define elf_addr_t u32
#define elf_caddr_t u32
/*
#define init_elf_binfmt init_elf32_binfmt
*/
......
......@@ -147,7 +147,6 @@ jiffies_to_timeval32(unsigned long jiffies, struct timeval32 *value)
}
#define elf_addr_t u32
#define elf_caddr_t u32
#undef start_thread
#define start_thread start_thread32
#define init_elf_binfmt init_elf32_binfmt
......
......@@ -186,7 +186,6 @@ MODULE_AUTHOR("Eric Youngdale, Andi Kleen");
#undef MODULE_AUTHOR
#define elf_addr_t __u32
#define elf_caddr_t __u32
static void elf32_init(struct pt_regs *);
......
This diff is collapsed.
......@@ -323,9 +323,50 @@ int setup_arg_pages(struct linux_binprm *bprm)
{
unsigned long stack_base;
struct vm_area_struct *mpnt;
struct mm_struct *mm = current->mm;
int i;
stack_base = STACK_TOP - MAX_ARG_PAGES*PAGE_SIZE;
#ifdef ARCH_STACK_GROWSUP
/* Move the argument and environment strings to the bottom of the
* stack space.
*/
int offset, j;
char *to, *from;
/* Start by shifting all the pages down */
i = 0;
for (j = 0; j < MAX_ARG_PAGES; j++) {
struct page *page = bprm->page[j];
if (!page)
continue;
bprm->page[i++] = page;
}
/* Now move them within their pages */
offset = bprm->p % PAGE_SIZE;
to = kmap(bprm->page[0]);
for (j = 1; j < i; j++) {
memmove(to, to + offset, PAGE_SIZE - offset);
from = kmap(bprm->page[j]);
memcpy(to + PAGE_SIZE - offset, from, offset);
kunmap(bprm[j - 1]);
to = from;
}
memmove(to, to + offset, PAGE_SIZE - offset);
kunmap(bprm[j - 1]);
/* Adjust bprm->p to point to the end of the strings. */
bprm->p = PAGE_SIZE * i - offset;
stack_base = STACK_TOP - current->rlim[RLIMIT_STACK].rlim_max;
mm->arg_start = stack_base;
/* zero pages that were copied above */
while (i < MAX_ARG_PAGES)
bprm->page[i++] = NULL;
#else
stack_base = STACK_TOP - MAX_ARG_PAGES * PAGE_SIZE;
mm->arg_start = bprm->p + stack_base;
#endif
bprm->p += stack_base;
if (bprm->loader)
......@@ -333,7 +374,7 @@ int setup_arg_pages(struct linux_binprm *bprm)
bprm->exec += stack_base;
mpnt = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
if (!mpnt)
if (!mpnt)
return -ENOMEM;
if (!vm_enough_memory((STACK_TOP - (PAGE_MASK & (unsigned long) bprm->p))>>PAGE_SHIFT)) {
......@@ -341,19 +382,25 @@ int setup_arg_pages(struct linux_binprm *bprm)
return -ENOMEM;
}
down_write(&current->mm->mmap_sem);
down_write(&mm->mmap_sem);
{
mpnt->vm_mm = current->mm;
mpnt->vm_mm = mm;
#ifdef ARCH_STACK_GROWSUP
mpnt->vm_start = stack_base;
mpnt->vm_end = PAGE_MASK &
(PAGE_SIZE - 1 + (unsigned long) bprm->p);
#else
mpnt->vm_start = PAGE_MASK & (unsigned long) bprm->p;
mpnt->vm_end = STACK_TOP;
#endif
mpnt->vm_page_prot = PAGE_COPY;
mpnt->vm_flags = VM_STACK_FLAGS;
mpnt->vm_ops = NULL;
mpnt->vm_pgoff = 0;
mpnt->vm_file = NULL;
mpnt->vm_private_data = (void *) 0;
insert_vm_struct(current->mm, mpnt);
current->mm->total_vm = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT;
insert_vm_struct(mm, mpnt);
mm->total_vm = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT;
}
for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
......@@ -364,7 +411,7 @@ int setup_arg_pages(struct linux_binprm *bprm)
}
stack_base += PAGE_SIZE;
}
up_write(&current->mm->mmap_sem);
up_write(&mm->mmap_sem);
return 0;
}
......@@ -732,7 +779,6 @@ void compute_creds(struct linux_binprm *bprm)
security_ops->bprm_compute_creds(bprm);
}
void remove_arg_zero(struct linux_binprm *bprm)
{
if (bprm->argc) {
......@@ -854,7 +900,6 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
return retval;
}
/*
* sys_execve() executes a new program.
*/
......
......@@ -334,7 +334,6 @@ void ia64_elf32_init(struct pt_regs *regs);
#define ELF_PLAT_INIT(_r) ia64_elf32_init(_r)
#define elf_addr_t u32
#define elf_caddr_t u32
/* ELF register definitions. This is needed for core dump support. */
......
......@@ -31,7 +31,7 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
\
if (__h->e_machine != EM_MIPS) \
__res = 0; \
if (sizeof(elf_caddr_t) == 8 && \
if (sizeof(elf_addr_t) == 8 && \
__h->e_ident[EI_CLASS] == ELFCLASS32) \
__res = 0; \
\
......
......@@ -98,19 +98,14 @@ extern int ucache_bsize;
* - for compatibility with glibc ARCH_DLINFO must always be defined on PPC,
* even if DLINFO_ARCH_ITEMS goes to zero or is undefined.
*/
#define DLINFO_ARCH_ITEMS 3
#define ARCH_DLINFO \
do { \
sp -= DLINFO_ARCH_ITEMS * 2; \
NEW_AUX_ENT(0, AT_DCACHEBSIZE, dcache_bsize); \
NEW_AUX_ENT(1, AT_ICACHEBSIZE, icache_bsize); \
NEW_AUX_ENT(2, AT_UCACHEBSIZE, ucache_bsize); \
/* \
* Now handle glibc compatibility. \
*/ \
sp -= 2*2; \
NEW_AUX_ENT(0, AT_IGNOREPPC, AT_IGNOREPPC); \
NEW_AUX_ENT(1, AT_IGNOREPPC, AT_IGNOREPPC); \
NEW_AUX_ENT(AT_DCACHEBSIZE, dcache_bsize); \
NEW_AUX_ENT(AT_ICACHEBSIZE, icache_bsize); \
NEW_AUX_ENT(AT_UCACHEBSIZE, ucache_bsize); \
/* Now handle glibc compatibility. */ \
NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \
NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \
} while (0)
#endif /* __KERNEL__ */
......
......@@ -31,13 +31,11 @@ typedef elf_greg_t32 elf_gregset_t32[ELF_NGREG];
typedef elf_greg_t64 elf_greg_t;
typedef elf_gregset_t64 elf_gregset_t;
# define elf_addr_t unsigned long
# define elf_caddr_t char *
#else
/* Assumption: ELF_ARCH == EM_PPC and ELF_CLASS == ELFCLASS32 */
typedef elf_greg_t32 elf_greg_t;
typedef elf_gregset_t32 elf_gregset_t;
# define elf_addr_t u32
# define elf_caddr_t u32
#endif
typedef double elf_fpreg_t;
......@@ -122,19 +120,14 @@ extern int ucache_bsize;
* - for compatibility with glibc ARCH_DLINFO must always be defined on PPC,
* even if DLINFO_ARCH_ITEMS goes to zero or is undefined.
*/
#define DLINFO_ARCH_ITEMS 3
#define ARCH_DLINFO \
do { \
sp -= DLINFO_ARCH_ITEMS * 2; \
NEW_AUX_ENT(0, AT_DCACHEBSIZE, dcache_bsize); \
NEW_AUX_ENT(1, AT_ICACHEBSIZE, icache_bsize); \
NEW_AUX_ENT(2, AT_UCACHEBSIZE, ucache_bsize); \
/* \
* Now handle glibc compatibility. \
*/ \
sp -= 2*2; \
NEW_AUX_ENT(0, AT_IGNOREPPC, AT_IGNOREPPC); \
NEW_AUX_ENT(1, AT_IGNOREPPC, AT_IGNOREPPC); \
NEW_AUX_ENT(AT_DCACHEBSIZE, dcache_bsize); \
NEW_AUX_ENT(AT_ICACHEBSIZE, icache_bsize); \
NEW_AUX_ENT(AT_UCACHEBSIZE, ucache_bsize); \
/* Now handle glibc compatibility. */ \
NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \
NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \
} while (0)
#endif /* __PPC64_ELF_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment