summaryrefslogtreecommitdiffstats
path: root/fs/binfmt_elf.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/binfmt_elf.c')
-rw-r--r--fs/binfmt_elf.c126
1 files changed, 47 insertions, 79 deletions
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index fd5e41cdc..ecdffb85a 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -8,6 +8,15 @@
*
* Copyright 1993, 1994: Eric Youngdale (ericy@cais.com).
*/
+
+#ifdef MODULE
+#include <linux/module.h>
+#include <linux/version.h>
+#else
+#define MOD_INC_USE_COUNT
+#define MOD_DEC_USE_COUNT
+#endif
+
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/mm.h>
@@ -24,16 +33,12 @@
#include <linux/personality.h>
#include <asm/segment.h>
+#include <asm/pgtable.h>
#include <linux/config.h>
-#ifndef CONFIG_BINFMT_ELF
-#include <linux/module.h>
-#include "../tools/version.h"
-#endif
-
#include <linux/unistd.h>
-typedef int (*sysfun_p)();
+typedef int (*sysfun_p)(int);
extern sysfun_p sys_call_table[];
#define SYS(name) (sys_call_table[__NR_##name])
@@ -45,7 +50,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs);
static int load_elf_library(int fd);
struct linux_binfmt elf_format = {
-#ifdef CONFIG_BINFMT_ELF
+#ifndef MODULE
NULL, NULL, load_elf_binary, load_elf_library, NULL
#else
NULL, &mod_use_count_, load_elf_binary, load_elf_library, NULL
@@ -58,19 +63,19 @@ struct linux_binfmt elf_format = {
be in memory */
-static void padzero(int elf_bss){
- unsigned int fpnt, nbyte;
+static void padzero(unsigned long elf_bss)
+{
+ unsigned long fpnt, nbyte;
- if(elf_bss & 0xfff) {
-
- nbyte = (PAGE_SIZE - (elf_bss & 0xfff)) & 0xfff;
- if(nbyte){
- verify_area(VERIFY_WRITE, (void *) elf_bss, nbyte);
-
- fpnt = elf_bss;
- while(fpnt & 0xfff) put_fs_byte(0, fpnt++);
- };
- };
+ nbyte = elf_bss & (PAGE_SIZE-1);
+ if (nbyte) {
+ nbyte = PAGE_SIZE - nbyte;
+ verify_area(VERIFY_WRITE, (void *) elf_bss, nbyte);
+ fpnt = elf_bss;
+ do {
+ put_fs_byte(0, fpnt++);
+ } while (--nbyte);
+ }
}
unsigned long * create_elf_tables(char * p,int argc,int envc,struct elfhdr * exec, unsigned int load_addr, int ibcs)
@@ -84,7 +89,7 @@ unsigned long * create_elf_tables(char * p,int argc,int envc,struct elfhdr * exe
mpnt->vm_task = current;
mpnt->vm_start = PAGE_MASK & (unsigned long) p;
mpnt->vm_end = TASK_SIZE;
- mpnt->vm_page_prot = PAGE_PRIVATE|PAGE_DIRTY;
+ mpnt->vm_page_prot = PAGE_COPY;
#ifdef VM_STACK_FLAGS
mpnt->vm_flags = VM_STACK_FLAGS;
mpnt->vm_pte = 0;
@@ -93,7 +98,6 @@ unsigned long * create_elf_tables(char * p,int argc,int envc,struct elfhdr * exe
mpnt->vm_flags = VM_GROWSDOWN;
# endif
#endif
- mpnt->vm_share = NULL;
mpnt->vm_inode = NULL;
mpnt->vm_offset = 0;
mpnt->vm_ops = NULL;
@@ -204,10 +208,13 @@ static unsigned int load_elf_interp(struct elfhdr * interp_elf_ex,
eppnt = elf_phdata;
for(i=0; i<interp_elf_ex->e_phnum; i++, eppnt++)
if(eppnt->p_type == PT_LOAD) {
+ int elf_prot = (eppnt->p_flags & PF_R) ? PROT_READ : 0;
+ if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
+ if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
error = do_mmap(file,
eppnt->p_vaddr & 0xfffff000,
eppnt->p_filesz + (eppnt->p_vaddr & 0xfff),
- PROT_READ | PROT_WRITE | PROT_EXEC,
+ elf_prot,
MAP_PRIVATE | MAP_DENYWRITE | (interp_elf_ex->e_type == ET_EXEC ? MAP_FIXED : 0),
eppnt->p_offset & 0xfffff000);
@@ -315,9 +322,7 @@ load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
unsigned int elf_stack;
char passed_fileno[6];
-#ifndef CONFIG_BINFMT_ELF
MOD_INC_USE_COUNT;
-#endif
ibcs2_interpreter = 0;
status = 0;
@@ -326,9 +331,7 @@ load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
if (elf_ex.e_ident[0] != 0x7f ||
strncmp(&elf_ex.e_ident[1], "ELF",3) != 0) {
-#ifndef CONFIG_BINFMT_ELF
MOD_DEC_USE_COUNT;
-#endif
return -ENOEXEC;
}
@@ -338,9 +341,7 @@ load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
(elf_ex.e_machine != EM_386 && elf_ex.e_machine != EM_486) ||
(!bprm->inode->i_op || !bprm->inode->i_op->default_file_ops ||
!bprm->inode->i_op->default_file_ops->mmap)){
-#ifndef CONFIG_BINFMT_ELF
MOD_DEC_USE_COUNT;
-#endif
return -ENOEXEC;
};
@@ -356,9 +357,7 @@ load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
set_fs(old_fs);
if (retval < 0) {
kfree (elf_phdata);
-#ifndef CONFIG_BINFMT_ELF
MOD_DEC_USE_COUNT;
-#endif
return retval;
}
@@ -371,9 +370,7 @@ load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
if (elf_exec_fileno < 0) {
kfree (elf_phdata);
-#ifndef CONFIG_BINFMT_ELF
MOD_DEC_USE_COUNT;
-#endif
return elf_exec_fileno;
}
@@ -420,9 +417,7 @@ load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
if(retval < 0) {
kfree (elf_phdata);
kfree(elf_interpreter);
-#ifndef CONFIG_BINFMT_ELF
MOD_DEC_USE_COUNT;
-#endif
return retval;
};
};
@@ -437,9 +432,7 @@ load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
if(retval < 0) {
kfree(elf_interpreter);
kfree(elf_phdata);
-#ifndef CONFIG_BINFMT_ELF
MOD_DEC_USE_COUNT;
-#endif
return -ELIBACC;
};
/* Now figure out which format our binary is */
@@ -456,9 +449,7 @@ load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
{
kfree(elf_interpreter);
kfree(elf_phdata);
-#ifndef CONFIG_BINFMT_ELF
MOD_DEC_USE_COUNT;
-#endif
return -ELIBBAD;
};
}
@@ -483,9 +474,7 @@ load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
kfree(elf_interpreter);
}
kfree (elf_phdata);
-#ifndef CONFIG_BINFMT_ELF
MOD_DEC_USE_COUNT;
-#endif
return -E2BIG;
}
}
@@ -502,7 +491,7 @@ load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
/* Do this so that we can load the interpreter, if need be. We will
change some of these later */
current->mm->rss = 0;
- bprm->p += change_ldt(0, bprm->page);
+ bprm->p += setup_arg_pages(0, bprm->page);
current->mm->start_stack = bprm->p;
/* Now we do a little grungy work by mmaping the ELF image into
@@ -537,20 +526,21 @@ load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
printk("Unable to load interpreter\n");
kfree(elf_phdata);
send_sig(SIGSEGV, current, 0);
-#ifndef CONFIG_BINFMT_ELF
MOD_DEC_USE_COUNT;
-#endif
return 0;
};
};
if(elf_ppnt->p_type == PT_LOAD) {
+ int elf_prot = (elf_ppnt->p_flags & PF_R) ? PROT_READ : 0;
+ if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
+ if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
error = do_mmap(file,
elf_ppnt->p_vaddr & 0xfffff000,
elf_ppnt->p_filesz + (elf_ppnt->p_vaddr & 0xfff),
- PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
+ elf_prot,
+ MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
elf_ppnt->p_offset & 0xfffff000);
#ifdef LOW_ELF_STACK
@@ -631,25 +621,20 @@ load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
printk("(brk) %x\n" , current->mm->brk);
#endif
- /* Why this, you ask??? Well SVr4 maps page 0 as read-only,
- and some applications "depend" upon this behavior.
- Since we do not have the power to recompile these, we
- emulate the SVr4 behavior. Sigh. */
- error = do_mmap(NULL, 0, 4096, PROT_READ | PROT_EXEC,
- MAP_FIXED | MAP_PRIVATE, 0);
-
-#if defined (__i386__)
- regs->eip = elf_entry; /* eip, magic happens :-) */
- regs->esp = bprm->p; /* stack pointer */
-#elif defined (__mips__)
- regs->cp0_epc = elf_entry; /* eip, magic happens :-) */
- regs->reg29 = bprm->p; /* stack pointer */
-#endif
+ if( current->personality == PER_SVR4 )
+ {
+ /* Why this, you ask??? Well SVr4 maps page 0 as read-only,
+ and some applications "depend" upon this behavior.
+ Since we do not have the power to recompile these, we
+ emulate the SVr4 behavior. Sigh. */
+ error = do_mmap(NULL, 0, 4096, PROT_READ | PROT_EXEC,
+ MAP_FIXED | MAP_PRIVATE, 0);
+ }
+
+ start_thread(regs, elf_entry, bprm->p);
if (current->flags & PF_PTRACED)
send_sig(SIGTRAP, current, 0);
-#ifndef CONFIG_BINFMT_ELF
MOD_DEC_USE_COUNT;
-#endif
return 0;
}
@@ -669,10 +654,7 @@ load_elf_library(int fd){
int error;
int i,j, k;
-#ifndef CONFIG_BINFMT_ELF
MOD_INC_USE_COUNT;
-#endif
-
len = 0;
file = current->files->fd[fd];
inode = file->f_inode;
@@ -681,18 +663,14 @@ load_elf_library(int fd){
set_fs(KERNEL_DS);
if (file->f_op->read(inode, file, (char *) &elf_ex, sizeof(elf_ex)) != sizeof(elf_ex)) {
SYS(close)(fd);
-#ifndef CONFIG_BINFMT_ELF
MOD_DEC_USE_COUNT;
-#endif
return -EACCES;
}
set_fs(USER_DS);
if (elf_ex.e_ident[0] != 0x7f ||
strncmp(&elf_ex.e_ident[1], "ELF",3) != 0) {
-#ifndef CONFIG_BINFMT_ELF
MOD_DEC_USE_COUNT;
-#endif
return -ENOEXEC;
}
@@ -700,18 +678,14 @@ load_elf_library(int fd){
if(elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 ||
(elf_ex.e_machine != EM_386 && elf_ex.e_machine != EM_486) ||
(!inode->i_op || !inode->i_op->default_file_ops->mmap)){
-#ifndef CONFIG_BINFMT_ELF
MOD_DEC_USE_COUNT;
-#endif
return -ENOEXEC;
};
/* Now read in all of the header information */
if(sizeof(struct elf_phdr) * elf_ex.e_phnum > PAGE_SIZE) {
-#ifndef CONFIG_BINFMT_ELF
MOD_DEC_USE_COUNT;
-#endif
return -ENOEXEC;
}
@@ -730,9 +704,7 @@ load_elf_library(int fd){
if(j != 1) {
kfree(elf_phdata);
-#ifndef CONFIG_BINFMT_ELF
MOD_DEC_USE_COUNT;
-#endif
return -ENOEXEC;
};
@@ -752,9 +724,7 @@ load_elf_library(int fd){
SYS(close)(fd);
if (error != elf_phdata->p_vaddr & 0xfffff000) {
kfree(elf_phdata);
-#ifndef CONFIG_BINFMT_ELF
MOD_DEC_USE_COUNT;
-#endif
return error;
}
@@ -767,13 +737,11 @@ load_elf_library(int fd){
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_FIXED|MAP_PRIVATE, 0);
kfree(elf_phdata);
-#ifndef CONFIG_BINFMT_ELF
MOD_DEC_USE_COUNT;
-#endif
return 0;
}
-#ifndef CONFIG_BINFMT_ELF
+#ifdef MODULE
char kernel_version[] = UTS_RELEASE;
int init_module(void) {