Commit 8a2ab7f5 authored by David Howells's avatar David Howells Committed by Linus Torvalds

[PATCH] FDPIC: Adjust the ELF-FDPIC driver to conform more to the CodingStyle

Adjust the ELF-FDPIC binfmt driver to conform much more to the CodingStyle,
silly though it may be.

Further changes:

 (*) Drop the casts to long for addresses in kdebug() statements (they're
     unsigned long already).

 (*) Use extra variables to avoid expressions longer than 80 chars by splitting
     the statement into multiple statements and letting the compiler optimise
     them back together.

 (*) Eliminate duplicate call of ksize() when working out how much space was
     actually allocated for the stack.

 (*) Discard the commented-out load_shlib prototype and op pointer as this will
     not be supported in ELF-FDPIC for the foreseeable future.
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 21ff8216
/* binfmt_elf_fdpic.c: FDPIC ELF binary format /* binfmt_elf_fdpic.c: FDPIC ELF binary format
* *
* Copyright (C) 2003, 2004 Red Hat, Inc. All Rights Reserved. * Copyright (C) 2003, 2004, 2006 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com) * Written by David Howells (dhowells@redhat.com)
* Derived from binfmt_elf.c * Derived from binfmt_elf.c
* *
...@@ -50,43 +50,45 @@ typedef char *elf_caddr_t; ...@@ -50,43 +50,45 @@ typedef char *elf_caddr_t;
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
static int load_elf_fdpic_binary(struct linux_binprm *bprm, struct pt_regs *regs); static int load_elf_fdpic_binary(struct linux_binprm *, struct pt_regs *);
//static int load_elf_fdpic_library(struct file *); static int elf_fdpic_fetch_phdrs(struct elf_fdpic_params *, struct file *);
static int elf_fdpic_fetch_phdrs(struct elf_fdpic_params *params, struct file *file); static int elf_fdpic_map_file(struct elf_fdpic_params *, struct file *,
static int elf_fdpic_map_file(struct elf_fdpic_params *params, struct mm_struct *, const char *);
struct file *file,
struct mm_struct *mm,
const char *what);
static int create_elf_fdpic_tables(struct linux_binprm *bprm, static int create_elf_fdpic_tables(struct linux_binprm *, struct mm_struct *,
struct mm_struct *mm, struct elf_fdpic_params *,
struct elf_fdpic_params *exec_params, struct elf_fdpic_params *);
struct elf_fdpic_params *interp_params);
#ifndef CONFIG_MMU #ifndef CONFIG_MMU
static int elf_fdpic_transfer_args_to_stack(struct linux_binprm *bprm, unsigned long *_sp); static int elf_fdpic_transfer_args_to_stack(struct linux_binprm *,
static int elf_fdpic_map_file_constdisp_on_uclinux(struct elf_fdpic_params *params, unsigned long *);
struct file *file, static int elf_fdpic_map_file_constdisp_on_uclinux(struct elf_fdpic_params *,
struct mm_struct *mm); struct file *,
struct mm_struct *);
#endif #endif
static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params, static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *,
struct file *file, struct file *, struct mm_struct *);
struct mm_struct *mm);
static struct linux_binfmt elf_fdpic_format = { static struct linux_binfmt elf_fdpic_format = {
.module = THIS_MODULE, .module = THIS_MODULE,
.load_binary = load_elf_fdpic_binary, .load_binary = load_elf_fdpic_binary,
// .load_shlib = load_elf_fdpic_library,
// .core_dump = elf_fdpic_core_dump, // .core_dump = elf_fdpic_core_dump,
.min_coredump = ELF_EXEC_PAGESIZE, .min_coredump = ELF_EXEC_PAGESIZE,
}; };
static int __init init_elf_fdpic_binfmt(void) { return register_binfmt(&elf_fdpic_format); } static int __init init_elf_fdpic_binfmt(void)
static void __exit exit_elf_fdpic_binfmt(void) { unregister_binfmt(&elf_fdpic_format); } {
return register_binfmt(&elf_fdpic_format);
}
module_init(init_elf_fdpic_binfmt) static void __exit exit_elf_fdpic_binfmt(void)
module_exit(exit_elf_fdpic_binfmt) {
unregister_binfmt(&elf_fdpic_format);
}
module_init(init_elf_fdpic_binfmt);
module_exit(exit_elf_fdpic_binfmt);
static int is_elf_fdpic(struct elfhdr *hdr, struct file *file) static int is_elf_fdpic(struct elfhdr *hdr, struct file *file)
{ {
...@@ -105,7 +107,8 @@ static int is_elf_fdpic(struct elfhdr *hdr, struct file *file) ...@@ -105,7 +107,8 @@ static int is_elf_fdpic(struct elfhdr *hdr, struct file *file)
/* /*
* read the program headers table into memory * read the program headers table into memory
*/ */
static int elf_fdpic_fetch_phdrs(struct elf_fdpic_params *params, struct file *file) static int elf_fdpic_fetch_phdrs(struct elf_fdpic_params *params,
struct file *file)
{ {
struct elf32_phdr *phdr; struct elf32_phdr *phdr;
unsigned long size; unsigned long size;
...@@ -121,7 +124,8 @@ static int elf_fdpic_fetch_phdrs(struct elf_fdpic_params *params, struct file *f ...@@ -121,7 +124,8 @@ static int elf_fdpic_fetch_phdrs(struct elf_fdpic_params *params, struct file *f
if (!params->phdrs) if (!params->phdrs)
return -ENOMEM; return -ENOMEM;
retval = kernel_read(file, params->hdr.e_phoff, (char *) params->phdrs, size); retval = kernel_read(file, params->hdr.e_phoff,
(char *) params->phdrs, size);
if (retval < 0) if (retval < 0)
return retval; return retval;
...@@ -141,17 +145,24 @@ static int elf_fdpic_fetch_phdrs(struct elf_fdpic_params *params, struct file *f ...@@ -141,17 +145,24 @@ static int elf_fdpic_fetch_phdrs(struct elf_fdpic_params *params, struct file *f
} }
return 0; return 0;
} /* end elf_fdpic_fetch_phdrs() */ }
/*****************************************************************************/ /*****************************************************************************/
/* /*
* load an fdpic binary into various bits of memory * load an fdpic binary into various bits of memory
*/ */
static int load_elf_fdpic_binary(struct linux_binprm *bprm, struct pt_regs *regs) static int load_elf_fdpic_binary(struct linux_binprm *bprm,
struct pt_regs *regs)
{ {
struct elf_fdpic_params exec_params, interp_params; struct elf_fdpic_params exec_params, interp_params;
struct elf_phdr *phdr; struct elf_phdr *phdr;
unsigned long stack_size; unsigned long stack_size, entryaddr;
#ifndef CONFIG_MMU
unsigned long fullsize;
#endif
#ifdef ELF_FDPIC_PLAT_INIT
unsigned long dynaddr;
#endif
struct file *interpreter = NULL; /* to shut gcc up */ struct file *interpreter = NULL; /* to shut gcc up */
char *interpreter_name = NULL; char *interpreter_name = NULL;
int executable_stack; int executable_stack;
...@@ -212,7 +223,8 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm, struct pt_regs *regs ...@@ -212,7 +223,8 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm, struct pt_regs *regs
goto error; goto error;
} }
retval = kernel_read(interpreter, 0, bprm->buf, BINPRM_BUF_SIZE); retval = kernel_read(interpreter, 0, bprm->buf,
BINPRM_BUF_SIZE);
if (retval < 0) if (retval < 0)
goto error; goto error;
...@@ -295,7 +307,8 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm, struct pt_regs *regs ...@@ -295,7 +307,8 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm, struct pt_regs *regs
&current->mm->start_stack, &current->mm->start_stack,
&current->mm->start_brk); &current->mm->start_brk);
retval = setup_arg_pages(bprm, current->mm->start_stack, executable_stack); retval = setup_arg_pages(bprm, current->mm->start_stack,
executable_stack);
if (retval < 0) { if (retval < 0) {
send_sig(SIGKILL, current, 0); send_sig(SIGKILL, current, 0);
goto error_kill; goto error_kill;
...@@ -303,7 +316,8 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm, struct pt_regs *regs ...@@ -303,7 +316,8 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm, struct pt_regs *regs
#endif #endif
/* load the executable and interpreter into memory */ /* load the executable and interpreter into memory */
retval = elf_fdpic_map_file(&exec_params, bprm->file, current->mm, "executable"); retval = elf_fdpic_map_file(&exec_params, bprm->file, current->mm,
"executable");
if (retval < 0) if (retval < 0)
goto error_kill; goto error_kill;
...@@ -324,7 +338,8 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm, struct pt_regs *regs ...@@ -324,7 +338,8 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm, struct pt_regs *regs
if (!current->mm->start_brk) if (!current->mm->start_brk)
current->mm->start_brk = current->mm->end_data; current->mm->start_brk = current->mm->end_data;
current->mm->brk = current->mm->start_brk = PAGE_ALIGN(current->mm->start_brk); current->mm->brk = current->mm->start_brk =
PAGE_ALIGN(current->mm->start_brk);
#else #else
/* create a stack and brk area big enough for everyone /* create a stack and brk area big enough for everyone
...@@ -336,47 +351,45 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm, struct pt_regs *regs ...@@ -336,47 +351,45 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm, struct pt_regs *regs
stack_size = PAGE_SIZE * 2; stack_size = PAGE_SIZE * 2;
down_write(&current->mm->mmap_sem); down_write(&current->mm->mmap_sem);
current->mm->start_brk = do_mmap(NULL, current->mm->start_brk = do_mmap(NULL, 0, stack_size,
0,
stack_size,
PROT_READ | PROT_WRITE | PROT_EXEC, PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_PRIVATE | MAP_ANON | MAP_GROWSDOWN, MAP_PRIVATE | MAP_ANON | MAP_GROWSDOWN,
0); 0);
if (IS_ERR((void *) current->mm->start_brk)) { if (IS_ERR_VALUE(current->mm->start_brk)) {
up_write(&current->mm->mmap_sem); up_write(&current->mm->mmap_sem);
retval = current->mm->start_brk; retval = current->mm->start_brk;
current->mm->start_brk = 0; current->mm->start_brk = 0;
goto error_kill; goto error_kill;
} }
if (do_mremap(current->mm->start_brk, /* expand the stack mapping to use up the entire allocation granule */
stack_size, fullsize = ksize((char *) current->mm->start_brk);
ksize((char *) current->mm->start_brk), if (!IS_ERR_VALUE(do_mremap(current->mm->start_brk, stack_size,
0, 0 fullsize, 0, 0)))
) == current->mm->start_brk stack_size = fullsize;
)
stack_size = ksize((char *) current->mm->start_brk);
up_write(&current->mm->mmap_sem); up_write(&current->mm->mmap_sem);
current->mm->brk = current->mm->start_brk; current->mm->brk = current->mm->start_brk;
current->mm->context.end_brk = current->mm->start_brk; current->mm->context.end_brk = current->mm->start_brk;
current->mm->context.end_brk += (stack_size > PAGE_SIZE) ? (stack_size - PAGE_SIZE) : 0; current->mm->context.end_brk +=
(stack_size > PAGE_SIZE) ? (stack_size - PAGE_SIZE) : 0;
current->mm->start_stack = current->mm->start_brk + stack_size; current->mm->start_stack = current->mm->start_brk + stack_size;
#endif #endif
compute_creds(bprm); compute_creds(bprm);
current->flags &= ~PF_FORKNOEXEC; current->flags &= ~PF_FORKNOEXEC;
if (create_elf_fdpic_tables(bprm, current->mm, &exec_params, &interp_params) < 0) if (create_elf_fdpic_tables(bprm, current->mm,
&exec_params, &interp_params) < 0)
goto error_kill; goto error_kill;
kdebug("- start_code %lx", (long) current->mm->start_code); kdebug("- start_code %lx", current->mm->start_code);
kdebug("- end_code %lx", (long) current->mm->end_code); kdebug("- end_code %lx", current->mm->end_code);
kdebug("- start_data %lx", (long) current->mm->start_data); kdebug("- start_data %lx", current->mm->start_data);
kdebug("- end_data %lx", (long) current->mm->end_data); kdebug("- end_data %lx", current->mm->end_data);
kdebug("- start_brk %lx", (long) current->mm->start_brk); kdebug("- start_brk %lx", current->mm->start_brk);
kdebug("- brk %lx", (long) current->mm->brk); kdebug("- brk %lx", current->mm->brk);
kdebug("- start_stack %lx", (long) current->mm->start_stack); kdebug("- start_stack %lx", current->mm->start_stack);
#ifdef ELF_FDPIC_PLAT_INIT #ifdef ELF_FDPIC_PLAT_INIT
/* /*
...@@ -385,21 +398,18 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm, struct pt_regs *regs ...@@ -385,21 +398,18 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm, struct pt_regs *regs
* example. This macro performs whatever initialization to * example. This macro performs whatever initialization to
* the regs structure is required. * the regs structure is required.
*/ */
ELF_FDPIC_PLAT_INIT(regs, dynaddr = interp_params.dynamic_addr ?: exec_params.dynamic_addr;
exec_params.map_addr, ELF_FDPIC_PLAT_INIT(regs, exec_params.map_addr, interp_params.map_addr,
interp_params.map_addr, dynaddr);
interp_params.dynamic_addr ?: exec_params.dynamic_addr
);
#endif #endif
/* everything is now ready... get the userspace context ready to roll */ /* everything is now ready... get the userspace context ready to roll */
start_thread(regs, entryaddr = interp_params.entry_addr ?: exec_params.entry_addr;
interp_params.entry_addr ?: exec_params.entry_addr, start_thread(regs, entryaddr, current->mm->start_stack);
current->mm->start_stack);
if (unlikely(current->ptrace & PT_PTRACED)) { if (unlikely(current->ptrace & PT_PTRACED)) {
if (current->ptrace & PT_TRACE_EXEC) if (current->ptrace & PT_TRACE_EXEC)
ptrace_notify ((PTRACE_EVENT_EXEC << 8) | SIGTRAP); ptrace_notify((PTRACE_EVENT_EXEC << 8) | SIGTRAP);
else else
send_sig(SIGTRAP, current, 0); send_sig(SIGTRAP, current, 0);
} }
...@@ -419,11 +429,11 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm, struct pt_regs *regs ...@@ -419,11 +429,11 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm, struct pt_regs *regs
return retval; return retval;
/* unrecoverable error - kill the process */ /* unrecoverable error - kill the process */
error_kill: error_kill:
send_sig(SIGSEGV, current, 0); send_sig(SIGSEGV, current, 0);
goto error; goto error;
} /* end load_elf_fdpic_binary() */ }
/*****************************************************************************/ /*****************************************************************************/
/* /*
...@@ -471,11 +481,11 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm, ...@@ -471,11 +481,11 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
#if defined(__i386__) && defined(CONFIG_SMP) #if defined(__i386__) && defined(CONFIG_SMP)
/* in some cases (e.g. Hyper-Threading), we want to avoid L1 evictions /* in some cases (e.g. Hyper-Threading), we want to avoid L1 evictions
* by the processes running on the same package. One thing we can do * by the processes running on the same package. One thing we can do is
* is to shuffle the initial stack for them. * to shuffle the initial stack for them.
* *
* the conditionals here are unneeded, but kept in to make the * the conditionals here are unneeded, but kept in to make the code
* code behaviour the same as pre change unless we have hyperthreaded * behaviour the same as pre change unless we have hyperthreaded
* processors. This keeps Mr Marcelo Person happier but should be * processors. This keeps Mr Marcelo Person happier but should be
* removed for 2.5 * removed for 2.5
*/ */
...@@ -498,11 +508,13 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm, ...@@ -498,11 +508,13 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
if (interp_params->loadmap) { if (interp_params->loadmap) {
len = sizeof(struct elf32_fdpic_loadmap); len = sizeof(struct elf32_fdpic_loadmap);
len += sizeof(struct elf32_fdpic_loadseg) * interp_params->loadmap->nsegs; len += sizeof(struct elf32_fdpic_loadseg) *
interp_params->loadmap->nsegs;
sp = (sp - len) & ~7UL; sp = (sp - len) & ~7UL;
interp_params->map_addr = sp; interp_params->map_addr = sp;
if (copy_to_user((void __user *) sp, interp_params->loadmap, len) != 0) if (copy_to_user((void __user *) sp, interp_params->loadmap,
len) != 0)
return -EFAULT; return -EFAULT;
current->mm->context.interp_fdpic_loadmap = (unsigned long) sp; current->mm->context.interp_fdpic_loadmap = (unsigned long) sp;
...@@ -526,34 +538,37 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm, ...@@ -526,34 +538,37 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
sp -= sp & 15UL; sp -= sp & 15UL;
/* put the ELF interpreter info on the stack */ /* put the ELF interpreter info on the stack */
#define NEW_AUX_ENT(nr, id, val) \ #define NEW_AUX_ENT(nr, id, val) \
do { \ do { \
struct { unsigned long _id, _val; } __user *ent = (void __user *) csp; \ struct { unsigned long _id, _val; } __user *ent; \
__put_user((id), &ent[nr]._id); \ \
__put_user((val), &ent[nr]._val); \ ent = (void __user *) csp; \
__put_user((id), &ent[nr]._id); \
__put_user((val), &ent[nr]._val); \
} while (0) } while (0)
csp -= 2 * sizeof(unsigned long); csp -= 2 * sizeof(unsigned long);
NEW_AUX_ENT(0, AT_NULL, 0); NEW_AUX_ENT(0, AT_NULL, 0);
if (k_platform) { if (k_platform) {
csp -= 2 * sizeof(unsigned long); csp -= 2 * sizeof(unsigned long);
NEW_AUX_ENT(0, AT_PLATFORM, (elf_addr_t)(unsigned long) u_platform); NEW_AUX_ENT(0, AT_PLATFORM,
(elf_addr_t) (unsigned long) u_platform);
} }
csp -= DLINFO_ITEMS * 2 * sizeof(unsigned long); csp -= DLINFO_ITEMS * 2 * sizeof(unsigned long);
NEW_AUX_ENT( 0, AT_HWCAP, hwcap); NEW_AUX_ENT( 0, AT_HWCAP, hwcap);
NEW_AUX_ENT( 1, AT_PAGESZ, PAGE_SIZE); NEW_AUX_ENT( 1, AT_PAGESZ, PAGE_SIZE);
NEW_AUX_ENT( 2, AT_CLKTCK, CLOCKS_PER_SEC); NEW_AUX_ENT( 2, AT_CLKTCK, CLOCKS_PER_SEC);
NEW_AUX_ENT( 3, AT_PHDR, exec_params->ph_addr); NEW_AUX_ENT( 3, AT_PHDR, exec_params->ph_addr);
NEW_AUX_ENT( 4, AT_PHENT, sizeof(struct elf_phdr)); NEW_AUX_ENT( 4, AT_PHENT, sizeof(struct elf_phdr));
NEW_AUX_ENT( 5, AT_PHNUM, exec_params->hdr.e_phnum); NEW_AUX_ENT( 5, AT_PHNUM, exec_params->hdr.e_phnum);
NEW_AUX_ENT( 6, AT_BASE, interp_params->elfhdr_addr); NEW_AUX_ENT( 6, AT_BASE, interp_params->elfhdr_addr);
NEW_AUX_ENT( 7, AT_FLAGS, 0); NEW_AUX_ENT( 7, AT_FLAGS, 0);
NEW_AUX_ENT( 8, AT_ENTRY, exec_params->entry_addr); NEW_AUX_ENT( 8, AT_ENTRY, exec_params->entry_addr);
NEW_AUX_ENT( 9, AT_UID, (elf_addr_t) current->uid); NEW_AUX_ENT( 9, AT_UID, (elf_addr_t) current->uid);
NEW_AUX_ENT(10, AT_EUID, (elf_addr_t) current->euid); NEW_AUX_ENT(10, AT_EUID, (elf_addr_t) current->euid);
NEW_AUX_ENT(11, AT_GID, (elf_addr_t) current->gid); NEW_AUX_ENT(11, AT_GID, (elf_addr_t) current->gid);
NEW_AUX_ENT(12, AT_EGID, (elf_addr_t) current->egid); NEW_AUX_ENT(12, AT_EGID, (elf_addr_t) current->egid);
#ifdef ARCH_DLINFO #ifdef ARCH_DLINFO
/* ARCH_DLINFO must come last so platform specific code can enforce /* ARCH_DLINFO must come last so platform specific code can enforce
...@@ -579,7 +594,8 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm, ...@@ -579,7 +594,8 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
#ifdef CONFIG_MMU #ifdef CONFIG_MMU
current->mm->arg_start = bprm->p; current->mm->arg_start = bprm->p;
#else #else
current->mm->arg_start = current->mm->start_stack - (MAX_ARG_PAGES * PAGE_SIZE - bprm->p); current->mm->arg_start = current->mm->start_stack -
(MAX_ARG_PAGES * PAGE_SIZE - bprm->p);
#endif #endif
p = (char __user *) current->mm->arg_start; p = (char __user *) current->mm->arg_start;
...@@ -607,7 +623,7 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm, ...@@ -607,7 +623,7 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
mm->start_stack = (unsigned long) sp; mm->start_stack = (unsigned long) sp;
return 0; return 0;
} /* end create_elf_fdpic_tables() */ }
/*****************************************************************************/ /*****************************************************************************/
/* /*
...@@ -615,7 +631,8 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm, ...@@ -615,7 +631,8 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
* the stack * the stack
*/ */
#ifndef CONFIG_MMU #ifndef CONFIG_MMU
static int elf_fdpic_transfer_args_to_stack(struct linux_binprm *bprm, unsigned long *_sp) static int elf_fdpic_transfer_args_to_stack(struct linux_binprm *bprm,
unsigned long *_sp)
{ {
unsigned long index, stop, sp; unsigned long index, stop, sp;
char *src; char *src;
...@@ -636,9 +653,9 @@ static int elf_fdpic_transfer_args_to_stack(struct linux_binprm *bprm, unsigned ...@@ -636,9 +653,9 @@ static int elf_fdpic_transfer_args_to_stack(struct linux_binprm *bprm, unsigned
*_sp = (*_sp - (MAX_ARG_PAGES * PAGE_SIZE - bprm->p)) & ~15; *_sp = (*_sp - (MAX_ARG_PAGES * PAGE_SIZE - bprm->p)) & ~15;
out: out:
return ret; return ret;
} /* end elf_fdpic_transfer_args_to_stack() */ }
#endif #endif
/*****************************************************************************/ /*****************************************************************************/
...@@ -713,17 +730,18 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params, ...@@ -713,17 +730,18 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params,
seg = loadmap->segs; seg = loadmap->segs;
for (loop = loadmap->nsegs; loop > 0; loop--, seg++) { for (loop = loadmap->nsegs; loop > 0; loop--, seg++) {
if (params->hdr.e_entry >= seg->p_vaddr && if (params->hdr.e_entry >= seg->p_vaddr &&
params->hdr.e_entry < seg->p_vaddr + seg->p_memsz params->hdr.e_entry < seg->p_vaddr + seg->p_memsz) {
) {
params->entry_addr = params->entry_addr =
(params->hdr.e_entry - seg->p_vaddr) + seg->addr; (params->hdr.e_entry - seg->p_vaddr) +
seg->addr;
break; break;
} }
} }
} }
/* determine where the program header table has wound up if mapped */ /* determine where the program header table has wound up if mapped */
stop = params->hdr.e_phoff + params->hdr.e_phnum * sizeof (struct elf_phdr); stop = params->hdr.e_phoff;
stop += params->hdr.e_phnum * sizeof (struct elf_phdr);
phdr = params->phdrs; phdr = params->phdrs;
for (loop = 0; loop < params->hdr.e_phnum; loop++, phdr++) { for (loop = 0; loop < params->hdr.e_phnum; loop++, phdr++) {
...@@ -737,9 +755,11 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params, ...@@ -737,9 +755,11 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params,
seg = loadmap->segs; seg = loadmap->segs;
for (loop = loadmap->nsegs; loop > 0; loop--, seg++) { for (loop = loadmap->nsegs; loop > 0; loop--, seg++) {
if (phdr->p_vaddr >= seg->p_vaddr && if (phdr->p_vaddr >= seg->p_vaddr &&
phdr->p_vaddr + phdr->p_filesz <= seg->p_vaddr + seg->p_memsz phdr->p_vaddr + phdr->p_filesz <=
) { seg->p_vaddr + seg->p_memsz) {
params->ph_addr = (phdr->p_vaddr - seg->p_vaddr) + seg->addr + params->ph_addr =
(phdr->p_vaddr - seg->p_vaddr) +
seg->addr +
params->hdr.e_phoff - phdr->p_offset; params->hdr.e_phoff - phdr->p_offset;
break; break;
} }
...@@ -756,18 +776,22 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params, ...@@ -756,18 +776,22 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params,
seg = loadmap->segs; seg = loadmap->segs;
for (loop = loadmap->nsegs; loop > 0; loop--, seg++) { for (loop = loadmap->nsegs; loop > 0; loop--, seg++) {
if (phdr->p_vaddr >= seg->p_vaddr && if (phdr->p_vaddr >= seg->p_vaddr &&
phdr->p_vaddr + phdr->p_memsz <= seg->p_vaddr + seg->p_memsz phdr->p_vaddr + phdr->p_memsz <=
) { seg->p_vaddr + seg->p_memsz) {
params->dynamic_addr = (phdr->p_vaddr - seg->p_vaddr) + seg->addr; params->dynamic_addr =
(phdr->p_vaddr - seg->p_vaddr) +
/* check the dynamic section contains at least one item, and that seg->addr;
* the last item is a NULL entry */
/* check the dynamic section contains at least
* one item, and that the last item is a NULL
* entry */
if (phdr->p_memsz == 0 || if (phdr->p_memsz == 0 ||
phdr->p_memsz % sizeof(Elf32_Dyn) != 0) phdr->p_memsz % sizeof(Elf32_Dyn) != 0)
goto dynamic_error; goto dynamic_error;
tmp = phdr->p_memsz / sizeof(Elf32_Dyn); tmp = phdr->p_memsz / sizeof(Elf32_Dyn);
if (((Elf32_Dyn *) params->dynamic_addr)[tmp - 1].d_tag != 0) if (((Elf32_Dyn *)
params->dynamic_addr)[tmp - 1].d_tag != 0)
goto dynamic_error; goto dynamic_error;
break; break;
} }
...@@ -776,8 +800,8 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params, ...@@ -776,8 +800,8 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params,
} }
/* now elide adjacent segments in the load map on MMU linux /* now elide adjacent segments in the load map on MMU linux
* - on uClinux the holes between may actually be filled with system stuff or stuff from * - on uClinux the holes between may actually be filled with system
* other processes * stuff or stuff from other processes
*/ */
#ifdef CONFIG_MMU #ifdef CONFIG_MMU
nloads = loadmap->nsegs; nloads = loadmap->nsegs;
...@@ -788,7 +812,9 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params, ...@@ -788,7 +812,9 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params,
if (seg->p_vaddr - mseg->p_vaddr == seg->addr - mseg->addr) { if (seg->p_vaddr - mseg->p_vaddr == seg->addr - mseg->addr) {
load_addr = PAGE_ALIGN(mseg->addr + mseg->p_memsz); load_addr = PAGE_ALIGN(mseg->addr + mseg->p_memsz);
if (load_addr == (seg->addr & PAGE_MASK)) { if (load_addr == (seg->addr & PAGE_MASK)) {
mseg->p_memsz += load_addr - (mseg->addr + mseg->p_memsz); mseg->p_memsz +=
load_addr -
(mseg->addr + mseg->p_memsz);
mseg->p_memsz += seg->addr & ~PAGE_MASK; mseg->p_memsz += seg->addr & ~PAGE_MASK;
mseg->p_memsz += seg->p_memsz; mseg->p_memsz += seg->p_memsz;
loadmap->nsegs--; loadmap->nsegs--;
...@@ -816,20 +842,21 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params, ...@@ -816,20 +842,21 @@ static int elf_fdpic_map_file(struct elf_fdpic_params *params,
return 0; return 0;
dynamic_error: dynamic_error:
printk("ELF FDPIC %s with invalid DYNAMIC section (inode=%lu)\n", printk("ELF FDPIC %s with invalid DYNAMIC section (inode=%lu)\n",
what, file->f_dentry->d_inode->i_ino); what, file->f_dentry->d_inode->i_ino);
return -ELIBBAD; return -ELIBBAD;
} /* end elf_fdpic_map_file() */ }
/*****************************************************************************/ /*****************************************************************************/
/* /*
* map a file with constant displacement under uClinux * map a file with constant displacement under uClinux
*/ */
#ifndef CONFIG_MMU #ifndef CONFIG_MMU
static int elf_fdpic_map_file_constdisp_on_uclinux(struct elf_fdpic_params *params, static int elf_fdpic_map_file_constdisp_on_uclinux(
struct file *file, struct elf_fdpic_params *params,
struct mm_struct *mm) struct file *file,
struct mm_struct *mm)
{ {
struct elf32_fdpic_loadseg *seg; struct elf32_fdpic_loadseg *seg;
struct elf32_phdr *phdr; struct elf32_phdr *phdr;
...@@ -840,7 +867,8 @@ static int elf_fdpic_map_file_constdisp_on_uclinux(struct elf_fdpic_params *para ...@@ -840,7 +867,8 @@ static int elf_fdpic_map_file_constdisp_on_uclinux(struct elf_fdpic_params *para
load_addr = params->load_addr; load_addr = params->load_addr;
seg = params->loadmap->segs; seg = params->loadmap->segs;
/* determine the bounds of the contiguous overall allocation we must make */ /* determine the bounds of the contiguous overall allocation we must
* make */
phdr = params->phdrs; phdr = params->phdrs;
for (loop = 0; loop < params->hdr.e_phnum; loop++, phdr++) { for (loop = 0; loop < params->hdr.e_phnum; loop++, phdr++) {
if (params->phdrs[loop].p_type != PT_LOAD) if (params->phdrs[loop].p_type != PT_LOAD)
...@@ -861,7 +889,7 @@ static int elf_fdpic_map_file_constdisp_on_uclinux(struct elf_fdpic_params *para ...@@ -861,7 +889,7 @@ static int elf_fdpic_map_file_constdisp_on_uclinux(struct elf_fdpic_params *para
maddr = do_mmap(NULL, load_addr, top - base, maddr = do_mmap(NULL, load_addr, top - base,
PROT_READ | PROT_WRITE | PROT_EXEC, mflags, 0); PROT_READ | PROT_WRITE | PROT_EXEC, mflags, 0);
up_write(&mm->mmap_sem); up_write(&mm->mmap_sem);
if (IS_ERR((void *) maddr)) if (IS_ERR_VALUE(maddr))
return (int) maddr; return (int) maddr;
if (load_addr != 0) if (load_addr != 0)
...@@ -879,7 +907,8 @@ static int elf_fdpic_map_file_constdisp_on_uclinux(struct elf_fdpic_params *para ...@@ -879,7 +907,8 @@ static int elf_fdpic_map_file_constdisp_on_uclinux(struct elf_fdpic_params *para
seg->p_vaddr = phdr->p_vaddr; seg->p_vaddr = phdr->p_vaddr;
seg->p_memsz = phdr->p_memsz; seg->p_memsz = phdr->p_memsz;
ret = file->f_op->read(file, (void *) seg->addr, phdr->p_filesz, &fpos); ret = file->f_op->read(file, (void *) seg->addr,
phdr->p_filesz, &fpos);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -896,8 +925,7 @@ static int elf_fdpic_map_file_constdisp_on_uclinux(struct elf_fdpic_params *para ...@@ -896,8 +925,7 @@ static int elf_fdpic_map_file_constdisp_on_uclinux(struct elf_fdpic_params *para
if (phdr->p_flags & PF_X) { if (phdr->p_flags & PF_X) {
mm->start_code = seg->addr; mm->start_code = seg->addr;
mm->end_code = seg->addr + phdr->p_memsz; mm->end_code = seg->addr + phdr->p_memsz;
} } else if (!mm->start_data) {
else if (!mm->start_data) {
mm->start_data = seg->addr; mm->start_data = seg->addr;
#ifndef CONFIG_MMU #ifndef CONFIG_MMU
mm->end_data = seg->addr + phdr->p_memsz; mm->end_data = seg->addr + phdr->p_memsz;
...@@ -914,7 +942,7 @@ static int elf_fdpic_map_file_constdisp_on_uclinux(struct elf_fdpic_params *para ...@@ -914,7 +942,7 @@ static int elf_fdpic_map_file_constdisp_on_uclinux(struct elf_fdpic_params *para
} }
return 0; return 0;
} /* end elf_fdpic_map_file_constdisp_on_uclinux() */ }
#endif #endif
/*****************************************************************************/ /*****************************************************************************/
...@@ -975,14 +1003,14 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params, ...@@ -975,14 +1003,14 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params,
case ELF_FDPIC_FLAG_CONSTDISP: case ELF_FDPIC_FLAG_CONSTDISP:
/* constant displacement /* constant displacement
* - can be mapped anywhere, but must be mapped as a unit * - can be mapped anywhere, but must be mapped as a
* unit
*/ */
if (!dvset) { if (!dvset) {
maddr = load_addr; maddr = load_addr;
delta_vaddr = phdr->p_vaddr; delta_vaddr = phdr->p_vaddr;
dvset = 1; dvset = 1;
} } else {
else {
maddr = load_addr + phdr->p_vaddr - delta_vaddr; maddr = load_addr + phdr->p_vaddr - delta_vaddr;
flags |= MAP_FIXED; flags |= MAP_FIXED;
} }
...@@ -1006,13 +1034,14 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params, ...@@ -1006,13 +1034,14 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params,
up_write(&mm->mmap_sem); up_write(&mm->mmap_sem);
kdebug("mmap[%d] <file> sz=%lx pr=%x fl=%x of=%lx --> %08lx", kdebug("mmap[%d] <file> sz=%lx pr=%x fl=%x of=%lx --> %08lx",
loop, phdr->p_memsz + disp, prot, flags, phdr->p_offset - disp, loop, phdr->p_memsz + disp, prot, flags,
maddr); phdr->p_offset - disp, maddr);
if (IS_ERR((void *) maddr)) if (IS_ERR_VALUE(maddr))
return (int) maddr; return (int) maddr;
if ((params->flags & ELF_FDPIC_FLAG_ARRANGEMENT) == ELF_FDPIC_FLAG_CONTIGUOUS) if ((params->flags & ELF_FDPIC_FLAG_ARRANGEMENT) ==
ELF_FDPIC_FLAG_CONTIGUOUS)
load_addr += PAGE_ALIGN(phdr->p_memsz + disp); load_addr += PAGE_ALIGN(phdr->p_memsz + disp);
seg->addr = maddr + disp; seg->addr = maddr + disp;
...@@ -1023,7 +1052,8 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params, ...@@ -1023,7 +1052,8 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params,
if (phdr->p_offset == 0) if (phdr->p_offset == 0)
params->elfhdr_addr = seg->addr; params->elfhdr_addr = seg->addr;
/* clear the bit between beginning of mapping and beginning of PT_LOAD */ /* clear the bit between beginning of mapping and beginning of
* PT_LOAD */
if (prot & PROT_WRITE && disp > 0) { if (prot & PROT_WRITE && disp > 0) {
kdebug("clear[%d] ad=%lx sz=%lx", loop, maddr, disp); kdebug("clear[%d] ad=%lx sz=%lx", loop, maddr, disp);
clear_user((void __user *) maddr, disp); clear_user((void __user *) maddr, disp);
...@@ -1039,19 +1069,20 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params, ...@@ -1039,19 +1069,20 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params,
excess1 = PAGE_SIZE - ((maddr + phdr->p_filesz) & ~PAGE_MASK); excess1 = PAGE_SIZE - ((maddr + phdr->p_filesz) & ~PAGE_MASK);
#ifdef CONFIG_MMU #ifdef CONFIG_MMU
if (excess > excess1) { if (excess > excess1) {
unsigned long xaddr = maddr + phdr->p_filesz + excess1; unsigned long xaddr = maddr + phdr->p_filesz + excess1;
unsigned long xmaddr; unsigned long xmaddr;
flags |= MAP_FIXED | MAP_ANONYMOUS; flags |= MAP_FIXED | MAP_ANONYMOUS;
down_write(&mm->mmap_sem); down_write(&mm->mmap_sem);
xmaddr = do_mmap(NULL, xaddr, excess - excess1, prot, flags, 0); xmaddr = do_mmap(NULL, xaddr, excess - excess1,
prot, flags, 0);
up_write(&mm->mmap_sem); up_write(&mm->mmap_sem);
kdebug("mmap[%d] <anon>" kdebug("mmap[%d] <anon>"
" ad=%lx sz=%lx pr=%x fl=%x of=0 --> %08lx", " ad=%lx sz=%lx pr=%x fl=%x of=0 --> %08lx",
loop, xaddr, excess - excess1, prot, flags, xmaddr); loop, xaddr, excess - excess1, prot, flags,
xmaddr);
if (xmaddr != xaddr) if (xmaddr != xaddr)
return -ENOMEM; return -ENOMEM;
...@@ -1060,7 +1091,8 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params, ...@@ -1060,7 +1091,8 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params,
if (prot & PROT_WRITE && excess1 > 0) { if (prot & PROT_WRITE && excess1 > 0) {
kdebug("clear[%d] ad=%lx sz=%lx", kdebug("clear[%d] ad=%lx sz=%lx",
loop, maddr + phdr->p_filesz, excess1); loop, maddr + phdr->p_filesz, excess1);
clear_user((void __user *) maddr + phdr->p_filesz, excess1); clear_user((void __user *) maddr + phdr->p_filesz,
excess1);
} }
#else #else
...@@ -1075,8 +1107,7 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params, ...@@ -1075,8 +1107,7 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params,
if (phdr->p_flags & PF_X) { if (phdr->p_flags & PF_X) {
mm->start_code = maddr; mm->start_code = maddr;
mm->end_code = maddr + phdr->p_memsz; mm->end_code = maddr + phdr->p_memsz;
} } else if (!mm->start_data) {
else if (!mm->start_data) {
mm->start_data = maddr; mm->start_data = maddr;
mm->end_data = maddr + phdr->p_memsz; mm->end_data = maddr + phdr->p_memsz;
} }
...@@ -1086,4 +1117,4 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params, ...@@ -1086,4 +1117,4 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params,
} }
return 0; return 0;
} /* end elf_fdpic_map_file_by_direct_mmap() */ }
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