[PATCH] binfmt_elf: CodingStyle cleanup and remove some pointless casts

Do a CodingStyle cleanup of fs/binfmt_elf.c and also remove some pointless
casts of kmalloc() return values in the same file.

Signed-off-by: Jesper Juhl <jesper.juhl@gmail.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
Jesper Juhl 2006-06-23 02:05:35 -07:00 committed by Linus Torvalds
parent 11420211b8
commit f4e5cc2c44
1 changed files with 177 additions and 155 deletions

View File

@ -38,15 +38,13 @@
#include <linux/security.h> #include <linux/security.h>
#include <linux/syscalls.h> #include <linux/syscalls.h>
#include <linux/random.h> #include <linux/random.h>
#include <linux/elf.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/param.h> #include <asm/param.h>
#include <asm/page.h> #include <asm/page.h>
#include <linux/elf.h> static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs);
static int load_elf_library(struct file *);
static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs);
static int load_elf_library(struct file*);
static unsigned long elf_map (struct file *, unsigned long, struct elf_phdr *, int, int); static unsigned long elf_map (struct file *, unsigned long, struct elf_phdr *, int, int);
extern int dump_fpu (struct pt_regs *, elf_fpregset_t *); extern int dump_fpu (struct pt_regs *, elf_fpregset_t *);
@ -59,15 +57,15 @@ extern int dump_fpu (struct pt_regs *, elf_fpregset_t *);
* don't even try. * don't even try.
*/ */
#if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE) #if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE)
static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file); static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file);
#else #else
#define elf_core_dump NULL #define elf_core_dump NULL
#endif #endif
#if ELF_EXEC_PAGESIZE > PAGE_SIZE #if ELF_EXEC_PAGESIZE > PAGE_SIZE
# define ELF_MIN_ALIGN ELF_EXEC_PAGESIZE #define ELF_MIN_ALIGN ELF_EXEC_PAGESIZE
#else #else
# define ELF_MIN_ALIGN PAGE_SIZE #define ELF_MIN_ALIGN PAGE_SIZE
#endif #endif
#ifndef ELF_CORE_EFLAGS #ifndef ELF_CORE_EFLAGS
@ -86,7 +84,7 @@ static struct linux_binfmt elf_format = {
.min_coredump = ELF_EXEC_PAGESIZE .min_coredump = ELF_EXEC_PAGESIZE
}; };
#define BAD_ADDR(x) ((unsigned long)(x) > TASK_SIZE) #define BAD_ADDR(x) ((unsigned long)(x) > TASK_SIZE)
static int set_brk(unsigned long start, unsigned long end) static int set_brk(unsigned long start, unsigned long end)
{ {
@ -104,13 +102,11 @@ static int set_brk(unsigned long start, unsigned long end)
return 0; return 0;
} }
/* We need to explicitly zero any fractional pages /* We need to explicitly zero any fractional pages
after the data section (i.e. bss). This would after the data section (i.e. bss). This would
contain the junk from the file that should not contain the junk from the file that should not
be in memory */ be in memory
*/
static int padzero(unsigned long elf_bss) static int padzero(unsigned long elf_bss)
{ {
unsigned long nbyte; unsigned long nbyte;
@ -129,7 +125,9 @@ static int padzero(unsigned long elf_bss)
#define STACK_ADD(sp, items) ((elf_addr_t __user *)(sp) + (items)) #define STACK_ADD(sp, items) ((elf_addr_t __user *)(sp) + (items))
#define STACK_ROUND(sp, items) \ #define STACK_ROUND(sp, items) \
((15 + (unsigned long) ((sp) + (items))) &~ 15UL) ((15 + (unsigned long) ((sp) + (items))) &~ 15UL)
#define STACK_ALLOC(sp, len) ({ elf_addr_t __user *old_sp = (elf_addr_t __user *)sp; sp += len; old_sp; }) #define STACK_ALLOC(sp, len) ({ \
elf_addr_t __user *old_sp = (elf_addr_t __user *)sp; sp += len; \
old_sp; })
#else #else
#define STACK_ADD(sp, items) ((elf_addr_t __user *)(sp) - (items)) #define STACK_ADD(sp, items) ((elf_addr_t __user *)(sp) - (items))
#define STACK_ROUND(sp, items) \ #define STACK_ROUND(sp, items) \
@ -138,7 +136,7 @@ static int padzero(unsigned long elf_bss)
#endif #endif
static int static int
create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec, create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
int interp_aout, unsigned long load_addr, int interp_aout, unsigned long load_addr,
unsigned long interp_load_addr) unsigned long interp_load_addr)
{ {
@ -161,7 +159,6 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec,
* for userspace to get any other way, in others (i386) it is * for userspace to get any other way, in others (i386) it is
* merely difficult. * merely difficult.
*/ */
u_platform = NULL; u_platform = NULL;
if (k_platform) { if (k_platform) {
size_t len = strlen(k_platform) + 1; size_t len = strlen(k_platform) + 1;
@ -171,7 +168,7 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec,
* evictions by the processes running on the same package. One * evictions by the processes running on the same package. One
* thing we can do is to shuffle the initial stack for them. * thing we can do is to shuffle the initial stack for them.
*/ */
p = arch_align_stack(p); p = arch_align_stack(p);
u_platform = (elf_addr_t __user *)STACK_ALLOC(p, len); u_platform = (elf_addr_t __user *)STACK_ALLOC(p, len);
@ -182,7 +179,9 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec,
/* Create the ELF interpreter info */ /* Create the ELF interpreter info */
elf_info = (elf_addr_t *) current->mm->saved_auxv; elf_info = (elf_addr_t *) current->mm->saved_auxv;
#define NEW_AUX_ENT(id, val) \ #define NEW_AUX_ENT(id, val) \
do { elf_info[ei_index++] = id; elf_info[ei_index++] = val; } while (0) do { \
elf_info[ei_index++] = id; elf_info[ei_index++] = val; \
} while (0)
#ifdef ARCH_DLINFO #ifdef ARCH_DLINFO
/* /*
@ -195,21 +194,22 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec,
NEW_AUX_ENT(AT_PAGESZ, ELF_EXEC_PAGESIZE); NEW_AUX_ENT(AT_PAGESZ, ELF_EXEC_PAGESIZE);
NEW_AUX_ENT(AT_CLKTCK, CLOCKS_PER_SEC); NEW_AUX_ENT(AT_CLKTCK, CLOCKS_PER_SEC);
NEW_AUX_ENT(AT_PHDR, load_addr + exec->e_phoff); NEW_AUX_ENT(AT_PHDR, load_addr + exec->e_phoff);
NEW_AUX_ENT(AT_PHENT, sizeof (struct elf_phdr)); NEW_AUX_ENT(AT_PHENT, sizeof(struct elf_phdr));
NEW_AUX_ENT(AT_PHNUM, exec->e_phnum); NEW_AUX_ENT(AT_PHNUM, exec->e_phnum);
NEW_AUX_ENT(AT_BASE, interp_load_addr); NEW_AUX_ENT(AT_BASE, interp_load_addr);
NEW_AUX_ENT(AT_FLAGS, 0); NEW_AUX_ENT(AT_FLAGS, 0);
NEW_AUX_ENT(AT_ENTRY, exec->e_entry); NEW_AUX_ENT(AT_ENTRY, exec->e_entry);
NEW_AUX_ENT(AT_UID, (elf_addr_t) tsk->uid); NEW_AUX_ENT(AT_UID, (elf_addr_t)tsk->uid);
NEW_AUX_ENT(AT_EUID, (elf_addr_t) tsk->euid); NEW_AUX_ENT(AT_EUID, (elf_addr_t)tsk->euid);
NEW_AUX_ENT(AT_GID, (elf_addr_t) tsk->gid); NEW_AUX_ENT(AT_GID, (elf_addr_t)tsk->gid);
NEW_AUX_ENT(AT_EGID, (elf_addr_t) tsk->egid); NEW_AUX_ENT(AT_EGID, (elf_addr_t)tsk->egid);
NEW_AUX_ENT(AT_SECURE, (elf_addr_t) security_bprm_secureexec(bprm)); NEW_AUX_ENT(AT_SECURE, (elf_addr_t)security_bprm_secureexec(bprm));
if (k_platform) { if (k_platform) {
NEW_AUX_ENT(AT_PLATFORM, (elf_addr_t)(unsigned long)u_platform); NEW_AUX_ENT(AT_PLATFORM,
(elf_addr_t)(unsigned long)u_platform);
} }
if (bprm->interp_flags & BINPRM_FLAGS_EXECFD) { if (bprm->interp_flags & BINPRM_FLAGS_EXECFD) {
NEW_AUX_ENT(AT_EXECFD, (elf_addr_t) bprm->interp_data); NEW_AUX_ENT(AT_EXECFD, (elf_addr_t)bprm->interp_data);
} }
#undef NEW_AUX_ENT #undef NEW_AUX_ENT
/* AT_NULL is zero; clear the rest too */ /* AT_NULL is zero; clear the rest too */
@ -232,7 +232,7 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec,
/* Point sp at the lowest address on the stack */ /* Point sp at the lowest address on the stack */
#ifdef CONFIG_STACK_GROWSUP #ifdef CONFIG_STACK_GROWSUP
sp = (elf_addr_t __user *)bprm->p - items - ei_index; sp = (elf_addr_t __user *)bprm->p - items - ei_index;
bprm->exec = (unsigned long) sp; /* XXX: PARISC HACK */ bprm->exec = (unsigned long)sp; /* XXX: PARISC HACK */
#else #else
sp = (elf_addr_t __user *)bprm->p; sp = (elf_addr_t __user *)bprm->p;
#endif #endif
@ -285,7 +285,7 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec,
#ifndef elf_map #ifndef elf_map
static unsigned long elf_map(struct file *filep, unsigned long addr, static unsigned long elf_map(struct file *filep, unsigned long addr,
struct elf_phdr *eppnt, int prot, int type) struct elf_phdr *eppnt, int prot, int type)
{ {
unsigned long map_addr; unsigned long map_addr;
unsigned long pageoffset = ELF_PAGEOFFSET(eppnt->p_vaddr); unsigned long pageoffset = ELF_PAGEOFFSET(eppnt->p_vaddr);
@ -310,9 +310,8 @@ static unsigned long elf_map(struct file *filep, unsigned long addr,
is only provided so that we can read a.out libraries that have is only provided so that we can read a.out libraries that have
an ELF header */ an ELF header */
static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex, static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
struct file * interpreter, struct file *interpreter, unsigned long *interp_load_addr)
unsigned long *interp_load_addr)
{ {
struct elf_phdr *elf_phdata; struct elf_phdr *elf_phdata;
struct elf_phdr *eppnt; struct elf_phdr *eppnt;
@ -342,15 +341,15 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
goto out; goto out;
/* Now read in all of the header information */ /* Now read in all of the header information */
size = sizeof(struct elf_phdr) * interp_elf_ex->e_phnum; size = sizeof(struct elf_phdr) * interp_elf_ex->e_phnum;
if (size > ELF_MIN_ALIGN) if (size > ELF_MIN_ALIGN)
goto out; goto out;
elf_phdata = (struct elf_phdr *) kmalloc(size, GFP_KERNEL); elf_phdata = kmalloc(size, GFP_KERNEL);
if (!elf_phdata) if (!elf_phdata)
goto out; goto out;
retval = kernel_read(interpreter,interp_elf_ex->e_phoff,(char *)elf_phdata,size); retval = kernel_read(interpreter, interp_elf_ex->e_phoff,
(char *)elf_phdata,size);
error = -EIO; error = -EIO;
if (retval != size) { if (retval != size) {
if (retval < 0) if (retval < 0)
@ -359,58 +358,65 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
} }
eppnt = elf_phdata; eppnt = elf_phdata;
for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) { for (i = 0; i < interp_elf_ex->e_phnum; i++, eppnt++) {
if (eppnt->p_type == PT_LOAD) { if (eppnt->p_type == PT_LOAD) {
int elf_type = MAP_PRIVATE | MAP_DENYWRITE; int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
int elf_prot = 0; int elf_prot = 0;
unsigned long vaddr = 0; unsigned long vaddr = 0;
unsigned long k, map_addr; unsigned long k, map_addr;
if (eppnt->p_flags & PF_R) elf_prot = PROT_READ; if (eppnt->p_flags & PF_R)
if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE; elf_prot = PROT_READ;
if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC; if (eppnt->p_flags & PF_W)
vaddr = eppnt->p_vaddr; elf_prot |= PROT_WRITE;
if (interp_elf_ex->e_type == ET_EXEC || load_addr_set) if (eppnt->p_flags & PF_X)
elf_type |= MAP_FIXED; elf_prot |= PROT_EXEC;
vaddr = eppnt->p_vaddr;
if (interp_elf_ex->e_type == ET_EXEC || load_addr_set)
elf_type |= MAP_FIXED;
map_addr = elf_map(interpreter, load_addr + vaddr, eppnt, elf_prot, elf_type); map_addr = elf_map(interpreter, load_addr + vaddr,
error = map_addr; eppnt, elf_prot, elf_type);
if (BAD_ADDR(map_addr)) error = map_addr;
goto out_close; if (BAD_ADDR(map_addr))
goto out_close;
if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) { if (!load_addr_set &&
load_addr = map_addr - ELF_PAGESTART(vaddr); interp_elf_ex->e_type == ET_DYN) {
load_addr_set = 1; load_addr = map_addr - ELF_PAGESTART(vaddr);
} load_addr_set = 1;
}
/* /*
* Check to see if the section's size will overflow the * Check to see if the section's size will overflow the
* allowed task size. Note that p_filesz must always be * allowed task size. Note that p_filesz must always be
* <= p_memsize so it is only necessary to check p_memsz. * <= p_memsize so it's only necessary to check p_memsz.
*/ */
k = load_addr + eppnt->p_vaddr; k = load_addr + eppnt->p_vaddr;
if (k > TASK_SIZE || eppnt->p_filesz > eppnt->p_memsz || if (k > TASK_SIZE ||
eppnt->p_memsz > TASK_SIZE || TASK_SIZE - eppnt->p_memsz < k) { eppnt->p_filesz > eppnt->p_memsz ||
error = -ENOMEM; eppnt->p_memsz > TASK_SIZE ||
goto out_close; TASK_SIZE - eppnt->p_memsz < k) {
} error = -ENOMEM;
goto out_close;
}
/* /*
* Find the end of the file mapping for this phdr, and keep * Find the end of the file mapping for this phdr, and
* track of the largest address we see for this. * keep track of the largest address we see for this.
*/ */
k = load_addr + eppnt->p_vaddr + eppnt->p_filesz; k = load_addr + eppnt->p_vaddr + eppnt->p_filesz;
if (k > elf_bss) if (k > elf_bss)
elf_bss = k; elf_bss = k;
/* /*
* Do the same thing for the memory mapping - between * Do the same thing for the memory mapping - between
* elf_bss and last_bss is the bss section. * elf_bss and last_bss is the bss section.
*/ */
k = load_addr + eppnt->p_memsz + eppnt->p_vaddr; k = load_addr + eppnt->p_memsz + eppnt->p_vaddr;
if (k > last_bss) if (k > last_bss)
last_bss = k; last_bss = k;
} }
} }
/* /*
@ -424,7 +430,8 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
goto out_close; goto out_close;
} }
elf_bss = ELF_PAGESTART(elf_bss + ELF_MIN_ALIGN - 1); /* What we have mapped so far */ /* What we have mapped so far */
elf_bss = ELF_PAGESTART(elf_bss + ELF_MIN_ALIGN - 1);
/* Map the last of the bss segment */ /* Map the last of the bss segment */
if (last_bss > elf_bss) { if (last_bss > elf_bss) {
@ -436,7 +443,7 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
} }
*interp_load_addr = load_addr; *interp_load_addr = load_addr;
error = ((unsigned long) interp_elf_ex->e_entry) + load_addr; error = ((unsigned long)interp_elf_ex->e_entry) + load_addr;
out_close: out_close:
kfree(elf_phdata); kfree(elf_phdata);
@ -444,8 +451,8 @@ out:
return error; return error;
} }
static unsigned long load_aout_interp(struct exec * interp_ex, static unsigned long load_aout_interp(struct exec *interp_ex,
struct file * interpreter) struct file *interpreter)
{ {
unsigned long text_data, elf_entry = ~0UL; unsigned long text_data, elf_entry = ~0UL;
char __user * addr; char __user * addr;
@ -464,7 +471,7 @@ static unsigned long load_aout_interp(struct exec * interp_ex,
case ZMAGIC: case ZMAGIC:
case QMAGIC: case QMAGIC:
offset = N_TXTOFF(*interp_ex); offset = N_TXTOFF(*interp_ex);
addr = (char __user *) N_TXTADDR(*interp_ex); addr = (char __user *)N_TXTADDR(*interp_ex);
break; break;
default: default:
goto out; goto out;
@ -480,7 +487,6 @@ static unsigned long load_aout_interp(struct exec * interp_ex,
flush_icache_range((unsigned long)addr, flush_icache_range((unsigned long)addr,
(unsigned long)addr + text_data); (unsigned long)addr + text_data);
down_write(&current->mm->mmap_sem); down_write(&current->mm->mmap_sem);
do_brk(ELF_PAGESTART(text_data + ELF_MIN_ALIGN - 1), do_brk(ELF_PAGESTART(text_data + ELF_MIN_ALIGN - 1),
interp_ex->a_bss); interp_ex->a_bss);
@ -519,7 +525,7 @@ static unsigned long randomize_stack_top(unsigned long stack_top)
#endif #endif
} }
static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
{ {
struct file *interpreter = NULL; /* to shut gcc up */ struct file *interpreter = NULL; /* to shut gcc up */
unsigned long load_addr = 0, load_bias = 0; unsigned long load_addr = 0, load_bias = 0;
@ -528,7 +534,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
unsigned int interpreter_type = INTERPRETER_NONE; unsigned int interpreter_type = INTERPRETER_NONE;
unsigned char ibcs2_interpreter = 0; unsigned char ibcs2_interpreter = 0;
unsigned long error; unsigned long error;
struct elf_phdr * elf_ppnt, *elf_phdata; struct elf_phdr *elf_ppnt, *elf_phdata;
unsigned long elf_bss, elf_brk; unsigned long elf_bss, elf_brk;
int elf_exec_fileno; int elf_exec_fileno;
int retval, i; int retval, i;
@ -553,7 +559,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
} }
/* Get the exec-header */ /* Get the exec-header */
loc->elf_ex = *((struct elfhdr *) bprm->buf); loc->elf_ex = *((struct elfhdr *)bprm->buf);
retval = -ENOEXEC; retval = -ENOEXEC;
/* First of all, some simple consistency checks */ /* First of all, some simple consistency checks */
@ -568,7 +574,6 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
goto out; goto out;
/* Now read in all of the header information */ /* Now read in all of the header information */
if (loc->elf_ex.e_phentsize != sizeof(struct elf_phdr)) if (loc->elf_ex.e_phentsize != sizeof(struct elf_phdr))
goto out; goto out;
if (loc->elf_ex.e_phnum < 1 || if (loc->elf_ex.e_phnum < 1 ||
@ -576,18 +581,19 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
goto out; goto out;
size = loc->elf_ex.e_phnum * sizeof(struct elf_phdr); size = loc->elf_ex.e_phnum * sizeof(struct elf_phdr);
retval = -ENOMEM; retval = -ENOMEM;
elf_phdata = (struct elf_phdr *) kmalloc(size, GFP_KERNEL); elf_phdata = kmalloc(size, GFP_KERNEL);
if (!elf_phdata) if (!elf_phdata)
goto out; goto out;
retval = kernel_read(bprm->file, loc->elf_ex.e_phoff, (char *) elf_phdata, size); retval = kernel_read(bprm->file, loc->elf_ex.e_phoff,
(char *)elf_phdata, size);
if (retval != size) { if (retval != size) {
if (retval >= 0) if (retval >= 0)
retval = -EIO; retval = -EIO;
goto out_free_ph; goto out_free_ph;
} }
files = current->files; /* Refcounted so ok */ files = current->files; /* Refcounted so ok */
retval = unshare_files(); retval = unshare_files();
if (retval < 0) if (retval < 0)
goto out_free_ph; goto out_free_ph;
@ -598,7 +604,6 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
/* exec will make our files private anyway, but for the a.out /* exec will make our files private anyway, but for the a.out
loader stuff we need to do it earlier */ loader stuff we need to do it earlier */
retval = get_unused_fd(); retval = get_unused_fd();
if (retval < 0) if (retval < 0)
goto out_free_fh; goto out_free_fh;
@ -620,7 +625,6 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
* shared libraries - for now assume that this * shared libraries - for now assume that this
* is an a.out format binary * is an a.out format binary
*/ */
retval = -ENOEXEC; retval = -ENOEXEC;
if (elf_ppnt->p_filesz > PATH_MAX || if (elf_ppnt->p_filesz > PATH_MAX ||
elf_ppnt->p_filesz < 2) elf_ppnt->p_filesz < 2)
@ -628,13 +632,13 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
retval = -ENOMEM; retval = -ENOMEM;
elf_interpreter = kmalloc(elf_ppnt->p_filesz, elf_interpreter = kmalloc(elf_ppnt->p_filesz,
GFP_KERNEL); GFP_KERNEL);
if (!elf_interpreter) if (!elf_interpreter)
goto out_free_file; goto out_free_file;
retval = kernel_read(bprm->file, elf_ppnt->p_offset, retval = kernel_read(bprm->file, elf_ppnt->p_offset,
elf_interpreter, elf_interpreter,
elf_ppnt->p_filesz); elf_ppnt->p_filesz);
if (retval != elf_ppnt->p_filesz) { if (retval != elf_ppnt->p_filesz) {
if (retval >= 0) if (retval >= 0)
retval = -EIO; retval = -EIO;
@ -678,7 +682,8 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
retval = PTR_ERR(interpreter); retval = PTR_ERR(interpreter);
if (IS_ERR(interpreter)) if (IS_ERR(interpreter))
goto out_free_interp; goto out_free_interp;
retval = kernel_read(interpreter, 0, bprm->buf, BINPRM_BUF_SIZE); retval = kernel_read(interpreter, 0, bprm->buf,
BINPRM_BUF_SIZE);
if (retval != BINPRM_BUF_SIZE) { if (retval != BINPRM_BUF_SIZE) {
if (retval >= 0) if (retval >= 0)
retval = -EIO; retval = -EIO;
@ -686,8 +691,8 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
} }
/* Get the exec headers */ /* Get the exec headers */
loc->interp_ex = *((struct exec *) bprm->buf); loc->interp_ex = *((struct exec *)bprm->buf);
loc->interp_elf_ex = *((struct elfhdr *) bprm->buf); loc->interp_elf_ex = *((struct elfhdr *)bprm->buf);
break; break;
} }
elf_ppnt++; elf_ppnt++;
@ -739,7 +744,6 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
/* OK, we are done with that, now set up the arg stuff, /* OK, we are done with that, now set up the arg stuff,
and then start this sucker up */ and then start this sucker up */
if ((!bprm->sh_bang) && (interpreter_type == INTERPRETER_AOUT)) { if ((!bprm->sh_bang) && (interpreter_type == INTERPRETER_AOUT)) {
char *passed_p = passed_fileno; char *passed_p = passed_fileno;
sprintf(passed_fileno, "%d", elf_exec_fileno); sprintf(passed_fileno, "%d", elf_exec_fileno);
@ -777,7 +781,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
if (elf_read_implies_exec(loc->elf_ex, executable_stack)) if (elf_read_implies_exec(loc->elf_ex, executable_stack))
current->personality |= READ_IMPLIES_EXEC; current->personality |= READ_IMPLIES_EXEC;
if ( !(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space) if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
current->flags |= PF_RANDOMIZE; current->flags |= PF_RANDOMIZE;
arch_pick_mmap_layout(current->mm); arch_pick_mmap_layout(current->mm);
@ -798,8 +802,8 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
the correct location in memory. At this point, we assume that the correct location in memory. At this point, we assume that
the image should be loaded at fixed address, not at a variable the image should be loaded at fixed address, not at a variable
address. */ address. */
for(i = 0, elf_ppnt = elf_phdata;
for(i = 0, elf_ppnt = elf_phdata; i < loc->elf_ex.e_phnum; i++, elf_ppnt++) { i < loc->elf_ex.e_phnum; i++, elf_ppnt++) {
int elf_prot = 0, elf_flags; int elf_prot = 0, elf_flags;
unsigned long k, vaddr; unsigned long k, vaddr;
@ -827,30 +831,35 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
load_bias, nbyte)) { load_bias, nbyte)) {
/* /*
* This bss-zeroing can fail if the ELF * This bss-zeroing can fail if the ELF
* file specifies odd protections. So * file specifies odd protections. So
* we don't check the return value * we don't check the return value
*/ */
} }
} }
} }
if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ; if (elf_ppnt->p_flags & PF_R)
if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE; elf_prot |= PROT_READ;
if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC; if (elf_ppnt->p_flags & PF_W)
elf_prot |= PROT_WRITE;
if (elf_ppnt->p_flags & PF_X)
elf_prot |= PROT_EXEC;
elf_flags = MAP_PRIVATE|MAP_DENYWRITE|MAP_EXECUTABLE; elf_flags = MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE;
vaddr = elf_ppnt->p_vaddr; vaddr = elf_ppnt->p_vaddr;
if (loc->elf_ex.e_type == ET_EXEC || load_addr_set) { if (loc->elf_ex.e_type == ET_EXEC || load_addr_set) {
elf_flags |= MAP_FIXED; elf_flags |= MAP_FIXED;
} else if (loc->elf_ex.e_type == ET_DYN) { } else if (loc->elf_ex.e_type == ET_DYN) {
/* Try and get dynamic programs out of the way of the default mmap /* Try and get dynamic programs out of the way of the
base, as well as whatever program they might try to exec. This * default mmap base, as well as whatever program they
is because the brk will follow the loader, and is not movable. */ * might try to exec. This is because the brk will
* follow the loader, and is not movable. */
load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr); load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr);
} }
error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, elf_prot, elf_flags); error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt,
elf_prot, elf_flags);
if (BAD_ADDR(error)) { if (BAD_ADDR(error)) {
send_sig(SIGKILL, current, 0); send_sig(SIGKILL, current, 0);
goto out_free_dentry; goto out_free_dentry;
@ -867,8 +876,10 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
} }
} }
k = elf_ppnt->p_vaddr; k = elf_ppnt->p_vaddr;
if (k < start_code) start_code = k; if (k < start_code)
if (start_data < k) start_data = k; start_code = k;
if (start_data < k)
start_data = k;
/* /*
* Check to see if the section's size will overflow the * Check to see if the section's size will overflow the
@ -878,7 +889,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
if (k > TASK_SIZE || elf_ppnt->p_filesz > elf_ppnt->p_memsz || if (k > TASK_SIZE || elf_ppnt->p_filesz > elf_ppnt->p_memsz ||
elf_ppnt->p_memsz > TASK_SIZE || elf_ppnt->p_memsz > TASK_SIZE ||
TASK_SIZE - elf_ppnt->p_memsz < k) { TASK_SIZE - elf_ppnt->p_memsz < k) {
/* set_brk can never work. Avoid overflows. */ /* set_brk can never work. Avoid overflows. */
send_sig(SIGKILL, current, 0); send_sig(SIGKILL, current, 0);
goto out_free_dentry; goto out_free_dentry;
} }
@ -966,8 +977,9 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
compute_creds(bprm); compute_creds(bprm);
current->flags &= ~PF_FORKNOEXEC; current->flags &= ~PF_FORKNOEXEC;
create_elf_tables(bprm, &loc->elf_ex, (interpreter_type == INTERPRETER_AOUT), create_elf_tables(bprm, &loc->elf_ex,
load_addr, interp_load_addr); (interpreter_type == INTERPRETER_AOUT),
load_addr, interp_load_addr);
/* N.B. passed_fileno might not be initialized? */ /* N.B. passed_fileno might not be initialized? */
if (interpreter_type == INTERPRETER_AOUT) if (interpreter_type == INTERPRETER_AOUT)
current->mm->arg_start += strlen(passed_fileno) + 1; current->mm->arg_start += strlen(passed_fileno) + 1;
@ -981,7 +993,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
/* Why this, you ask??? Well SVr4 maps page 0 as read-only, /* Why this, you ask??? Well SVr4 maps page 0 as read-only,
and some applications "depend" upon this behavior. and some applications "depend" upon this behavior.
Since we do not have the power to recompile these, we Since we do not have the power to recompile these, we
emulate the SVr4 behavior. Sigh. */ emulate the SVr4 behavior. Sigh. */
down_write(&current->mm->mmap_sem); down_write(&current->mm->mmap_sem);
error = do_mmap(NULL, 0, PAGE_SIZE, PROT_READ | PROT_EXEC, error = do_mmap(NULL, 0, PAGE_SIZE, PROT_READ | PROT_EXEC,
MAP_FIXED | MAP_PRIVATE, 0); MAP_FIXED | MAP_PRIVATE, 0);
@ -1036,7 +1048,6 @@ out_free_ph:
/* This is really simpleminded and specialized - we are loading an /* This is really simpleminded and specialized - we are loading an
a.out library that is given an ELF header. */ a.out library that is given an ELF header. */
static int load_elf_library(struct file *file) static int load_elf_library(struct file *file)
{ {
struct elf_phdr *elf_phdata; struct elf_phdr *elf_phdata;
@ -1046,7 +1057,7 @@ static int load_elf_library(struct file *file)
struct elfhdr elf_ex; struct elfhdr elf_ex;
error = -ENOEXEC; error = -ENOEXEC;
retval = kernel_read(file, 0, (char *) &elf_ex, sizeof(elf_ex)); retval = kernel_read(file, 0, (char *)&elf_ex, sizeof(elf_ex));
if (retval != sizeof(elf_ex)) if (retval != sizeof(elf_ex))
goto out; goto out;
@ -1055,7 +1066,7 @@ static int load_elf_library(struct file *file)
/* First of all, some simple consistency checks */ /* First of all, some simple consistency checks */
if (elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 || if (elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 ||
!elf_check_arch(&elf_ex) || !file->f_op || !file->f_op->mmap) !elf_check_arch(&elf_ex) || !file->f_op || !file->f_op->mmap)
goto out; goto out;
/* Now read in all of the header information */ /* Now read in all of the header information */
@ -1103,7 +1114,8 @@ static int load_elf_library(struct file *file)
goto out_free_ph; goto out_free_ph;
} }
len = ELF_PAGESTART(eppnt->p_filesz + eppnt->p_vaddr + ELF_MIN_ALIGN - 1); len = ELF_PAGESTART(eppnt->p_filesz + eppnt->p_vaddr +
ELF_MIN_ALIGN - 1);
bss = eppnt->p_memsz + eppnt->p_vaddr; bss = eppnt->p_memsz + eppnt->p_vaddr;
if (bss > len) { if (bss > len) {
down_write(&current->mm->mmap_sem); down_write(&current->mm->mmap_sem);
@ -1162,7 +1174,7 @@ static int maydump(struct vm_area_struct *vma)
if (vma->vm_flags & (VM_IO | VM_RESERVED)) if (vma->vm_flags & (VM_IO | VM_RESERVED))
return 0; return 0;
/* Dump shared memory only if mapped from an anonymous file. */ /* Dump shared memory only if mapped from an anonymous file. */
if (vma->vm_flags & VM_SHARED) if (vma->vm_flags & VM_SHARED)
return vma->vm_file->f_dentry->d_inode->i_nlink == 0; return vma->vm_file->f_dentry->d_inode->i_nlink == 0;
@ -1173,7 +1185,7 @@ static int maydump(struct vm_area_struct *vma)
return 1; return 1;
} }
#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) #define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
/* An ELF note in memory */ /* An ELF note in memory */
struct memelfnote struct memelfnote
@ -1276,11 +1288,11 @@ static void fill_note(struct memelfnote *note, const char *name, int type,
} }
/* /*
* fill up all the fields in prstatus from the given task struct, except registers * fill up all the fields in prstatus from the given task struct, except
* which need to be filled up separately. * registers which need to be filled up separately.
*/ */
static void fill_prstatus(struct elf_prstatus *prstatus, static void fill_prstatus(struct elf_prstatus *prstatus,
struct task_struct *p, long signr) struct task_struct *p, long signr)
{ {
prstatus->pr_info.si_signo = prstatus->pr_cursig = signr; prstatus->pr_info.si_signo = prstatus->pr_cursig = signr;
prstatus->pr_sigpend = p->pending.signal.sig[0]; prstatus->pr_sigpend = p->pending.signal.sig[0];
@ -1365,8 +1377,8 @@ struct elf_thread_status
/* /*
* In order to add the specific thread information for the elf file format, * In order to add the specific thread information for the elf file format,
* we need to keep a linked list of every threads pr_status and then * we need to keep a linked list of every threads pr_status and then create
* create a single section for them in the final core file. * a single section for them in the final core file.
*/ */
static int elf_dump_thread_status(long signr, struct elf_thread_status *t) static int elf_dump_thread_status(long signr, struct elf_thread_status *t)
{ {
@ -1377,19 +1389,23 @@ static int elf_dump_thread_status(long signr, struct elf_thread_status *t)
fill_prstatus(&t->prstatus, p, signr); fill_prstatus(&t->prstatus, p, signr);
elf_core_copy_task_regs(p, &t->prstatus.pr_reg); elf_core_copy_task_regs(p, &t->prstatus.pr_reg);
fill_note(&t->notes[0], "CORE", NT_PRSTATUS, sizeof(t->prstatus), &(t->prstatus)); fill_note(&t->notes[0], "CORE", NT_PRSTATUS, sizeof(t->prstatus),
&(t->prstatus));
t->num_notes++; t->num_notes++;
sz += notesize(&t->notes[0]); sz += notesize(&t->notes[0]);
if ((t->prstatus.pr_fpvalid = elf_core_copy_task_fpregs(p, NULL, &t->fpu))) { if ((t->prstatus.pr_fpvalid = elf_core_copy_task_fpregs(p, NULL,
fill_note(&t->notes[1], "CORE", NT_PRFPREG, sizeof(t->fpu), &(t->fpu)); &t->fpu))) {
fill_note(&t->notes[1], "CORE", NT_PRFPREG, sizeof(t->fpu),
&(t->fpu));
t->num_notes++; t->num_notes++;
sz += notesize(&t->notes[1]); sz += notesize(&t->notes[1]);
} }
#ifdef ELF_CORE_COPY_XFPREGS #ifdef ELF_CORE_COPY_XFPREGS
if (elf_core_copy_task_xfpregs(p, &t->xfpu)) { if (elf_core_copy_task_xfpregs(p, &t->xfpu)) {
fill_note(&t->notes[2], "LINUX", NT_PRXFPREG, sizeof(t->xfpu), &t->xfpu); fill_note(&t->notes[2], "LINUX", NT_PRXFPREG, sizeof(t->xfpu),
&t->xfpu);
t->num_notes++; t->num_notes++;
sz += notesize(&t->notes[2]); sz += notesize(&t->notes[2]);
} }
@ -1404,7 +1420,7 @@ static int elf_dump_thread_status(long signr, struct elf_thread_status *t)
* and then they are actually written out. If we run out of core limit * and then they are actually written out. If we run out of core limit
* we just truncate. * we just truncate.
*/ */
static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file) static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
{ {
#define NUM_NOTES 6 #define NUM_NOTES 6
int has_dumped = 0; int has_dumped = 0;
@ -1433,12 +1449,12 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file)
/* /*
* We no longer stop all VM operations. * We no longer stop all VM operations.
* *
* This is because those proceses that could possibly change map_count or * This is because those proceses that could possibly change map_count
* the mmap / vma pages are now blocked in do_exit on current finishing * or the mmap / vma pages are now blocked in do_exit on current
* this core dump. * finishing this core dump.
* *
* Only ptrace can touch these memory addresses, but it doesn't change * Only ptrace can touch these memory addresses, but it doesn't change
* the map_count or the pages allocated. So no possibility of crashing * the map_count or the pages allocated. So no possibility of crashing
* exists while dumping the mm->vm_next areas to the core file. * exists while dumping the mm->vm_next areas to the core file.
*/ */
@ -1500,7 +1516,7 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file)
#endif #endif
/* Set up header */ /* Set up header */
fill_elf_header(elf, segs+1); /* including notes section */ fill_elf_header(elf, segs + 1); /* including notes section */
has_dumped = 1; has_dumped = 1;
current->flags |= PF_DUMPCORE; current->flags |= PF_DUMPCORE;
@ -1510,24 +1526,24 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file)
* with info from their /proc. * with info from their /proc.
*/ */
fill_note(notes +0, "CORE", NT_PRSTATUS, sizeof(*prstatus), prstatus); fill_note(notes + 0, "CORE", NT_PRSTATUS, sizeof(*prstatus), prstatus);
fill_psinfo(psinfo, current->group_leader, current->mm); fill_psinfo(psinfo, current->group_leader, current->mm);
fill_note(notes +1, "CORE", NT_PRPSINFO, sizeof(*psinfo), psinfo); fill_note(notes + 1, "CORE", NT_PRPSINFO, sizeof(*psinfo), psinfo);
numnote = 2; numnote = 2;
auxv = (elf_addr_t *) current->mm->saved_auxv; auxv = (elf_addr_t *)current->mm->saved_auxv;
i = 0; i = 0;
do do
i += 2; i += 2;
while (auxv[i - 2] != AT_NULL); while (auxv[i - 2] != AT_NULL);
fill_note(&notes[numnote++], "CORE", NT_AUXV, fill_note(&notes[numnote++], "CORE", NT_AUXV,
i * sizeof (elf_addr_t), auxv); i * sizeof(elf_addr_t), auxv);
/* Try to dump the FPU. */ /* Try to dump the FPU. */
if ((prstatus->pr_fpvalid = elf_core_copy_task_fpregs(current, regs, fpu))) if ((prstatus->pr_fpvalid =
elf_core_copy_task_fpregs(current, regs, fpu)))
fill_note(notes + numnote++, fill_note(notes + numnote++,
"CORE", NT_PRFPREG, sizeof(*fpu), fpu); "CORE", NT_PRFPREG, sizeof(*fpu), fpu);
#ifdef ELF_CORE_COPY_XFPREGS #ifdef ELF_CORE_COPY_XFPREGS
@ -1576,8 +1592,10 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file)
phdr.p_memsz = sz; phdr.p_memsz = sz;
offset += phdr.p_filesz; offset += phdr.p_filesz;
phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0; phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0;
if (vma->vm_flags & VM_WRITE) phdr.p_flags |= PF_W; if (vma->vm_flags & VM_WRITE)
if (vma->vm_flags & VM_EXEC) phdr.p_flags |= PF_X; phdr.p_flags |= PF_W;
if (vma->vm_flags & VM_EXEC)
phdr.p_flags |= PF_X;
phdr.p_align = ELF_EXEC_PAGESIZE; phdr.p_align = ELF_EXEC_PAGESIZE;
DUMP_WRITE(&phdr, sizeof(phdr)); DUMP_WRITE(&phdr, sizeof(phdr));
@ -1594,7 +1612,9 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file)
/* write out the thread status notes section */ /* write out the thread status notes section */
list_for_each(t, &thread_list) { list_for_each(t, &thread_list) {
struct elf_thread_status *tmp = list_entry(t, struct elf_thread_status, list); struct elf_thread_status *tmp =
list_entry(t, struct elf_thread_status, list);
for (i = 0; i < tmp->num_notes; i++) for (i = 0; i < tmp->num_notes; i++)
if (!writenote(&tmp->notes[i], file)) if (!writenote(&tmp->notes[i], file))
goto end_coredump; goto end_coredump;
@ -1611,18 +1631,19 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file)
for (addr = vma->vm_start; for (addr = vma->vm_start;
addr < vma->vm_end; addr < vma->vm_end;
addr += PAGE_SIZE) { addr += PAGE_SIZE) {
struct page* page; struct page *page;
struct vm_area_struct *vma; struct vm_area_struct *vma;
if (get_user_pages(current, current->mm, addr, 1, 0, 1, if (get_user_pages(current, current->mm, addr, 1, 0, 1,
&page, &vma) <= 0) { &page, &vma) <= 0) {
DUMP_SEEK (file->f_pos + PAGE_SIZE); DUMP_SEEK(file->f_pos + PAGE_SIZE);
} else { } else {
if (page == ZERO_PAGE(addr)) { if (page == ZERO_PAGE(addr)) {
DUMP_SEEK (file->f_pos + PAGE_SIZE); DUMP_SEEK(file->f_pos + PAGE_SIZE);
} else { } else {
void *kaddr; void *kaddr;
flush_cache_page(vma, addr, page_to_pfn(page)); flush_cache_page(vma, addr,
page_to_pfn(page));
kaddr = kmap(page); kaddr = kmap(page);
if ((size += PAGE_SIZE) > limit || if ((size += PAGE_SIZE) > limit ||
!dump_write(file, kaddr, !dump_write(file, kaddr,
@ -1644,7 +1665,8 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file)
if ((off_t)file->f_pos != offset) { if ((off_t)file->f_pos != offset) {
/* Sanity check */ /* Sanity check */
printk(KERN_WARNING "elf_core_dump: file->f_pos (%ld) != offset (%ld)\n", printk(KERN_WARNING
"elf_core_dump: file->f_pos (%ld) != offset (%ld)\n",
(off_t)file->f_pos, offset); (off_t)file->f_pos, offset);
} }