root/fs/binfmt_elf.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. load_elf_binary
  2. load_elf_library

   1 #include <linux/fs.h>
   2 #include <linux/sched.h>
   3 #include <linux/mm.h>
   4 #include <linux/mman.h>
   5 #include <linux/a.out.h>
   6 #include <linux/errno.h>
   7 #include <linux/signal.h>
   8 #include <linux/binfmts.h>
   9 #include <asm/segment.h>
  10 #include <linux/string.h>
  11 #include <linux/fcntl.h>
  12 #include <linux/ptrace.h>
  13 
  14 asmlinkage int sys_exit(int exit_code);
  15 asmlinkage int sys_close(unsigned fd);
  16 asmlinkage int sys_open(const char *, int, int);
  17 
  18 /*
  19  * These are the functions used to load ELF style executables and shared
  20  * libraries.  There is no binary dependent code anywhere else.
  21  */
  22 
  23 #include <linux/elf.h>
  24 
  25 int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
     /* [previous][next][first][last][top][bottom][index][help] */
  26 {
  27         struct elfhdr elf_ex;
  28         struct file * file;
  29         struct exec ex;
  30         struct inode *interpreter_inode;
  31         int i;
  32         int old_fs;
  33         int error;
  34         struct elf_phdr * elf_ppnt, *elf_phdata;
  35         int elf_exec_fileno;
  36         unsigned int elf_bss, k, elf_brk;
  37         int retval;
  38         char * elf_interpreter;
  39         unsigned int elf_entry;
  40         int status;
  41         unsigned int start_code, end_code, end_data;
  42         unsigned int elf_stack;
  43         char passed_fileno[6];
  44         
  45         status = 0;
  46         elf_ex = *((struct elfhdr *) bprm->buf);          /* exec-header */
  47         
  48         if (elf_ex.e_ident[0] != 0x7f ||
  49             strncmp(&elf_ex.e_ident[1], "ELF",3) != 0)
  50                 return  -ENOEXEC;
  51         
  52         
  53         /* First of all, some simple consistency checks */
  54         if(elf_ex.e_type != ET_EXEC || 
  55            (elf_ex.e_machine != EM_386 && elf_ex.e_machine != EM_486) ||
  56            (!bprm->inode->i_op || !bprm->inode->i_op->default_file_ops ||
  57             !bprm->inode->i_op->default_file_ops->mmap)){
  58                 return -ENOEXEC;
  59         };
  60         
  61         /* Now read in all of the header information */
  62         
  63         elf_phdata = (struct elf_phdr *) kmalloc(elf_ex.e_phentsize * 
  64                                                  elf_ex.e_phnum, GFP_KERNEL);
  65         
  66         old_fs = get_fs();
  67         set_fs(get_ds());
  68         retval = read_exec(bprm->inode, elf_ex.e_phoff, (char *) elf_phdata,
  69                            elf_ex.e_phentsize * elf_ex.e_phnum);
  70         set_fs(old_fs);
  71         if (retval < 0) {
  72                 kfree (elf_phdata);
  73                 return retval;
  74         }
  75         
  76         elf_ppnt = elf_phdata;
  77         
  78         elf_bss = 0;
  79         elf_brk = 0;
  80         
  81         elf_exec_fileno = open_inode(bprm->inode, O_RDONLY);
  82 
  83         if (elf_exec_fileno < 0) {
  84                 kfree (elf_phdata);
  85                 return elf_exec_fileno;
  86         }
  87         
  88         file = current->filp[elf_exec_fileno];
  89         
  90         elf_stack = 0xffffffff;
  91         elf_interpreter = NULL;
  92         start_code = 0;
  93         end_code = 0;
  94         end_data = 0;
  95         
  96         old_fs = get_fs();
  97         set_fs(get_ds());
  98         
  99         for(i=0;i < elf_ex.e_phnum; i++){
 100                 if(elf_ppnt->p_type == PT_INTERP) {
 101                         /* This is the program interpreter used for shared libraries - 
 102                            for now assume that this is an a.out format binary */
 103                         
 104                         elf_interpreter = (char *) kmalloc(elf_ppnt->p_filesz, 
 105                                                            GFP_KERNEL);
 106                         
 107                         retval = read_exec(bprm->inode,elf_ppnt->p_offset,elf_interpreter,
 108                                            elf_ppnt->p_filesz);
 109                         printk("Using ELF interpreter %s\n", elf_interpreter);
 110                         if(retval >= 0)
 111                                 retval = namei(elf_interpreter, &interpreter_inode);
 112                         if(retval >= 0)
 113                                 retval = read_exec(interpreter_inode,0,bprm->buf,128);
 114                         
 115                         if(retval >= 0){
 116                                 ex = *((struct exec *) bprm->buf);              /* exec-header */
 117                                 
 118 #if 0
 119                                 printk("Interpreter: %x %x %x\n",N_MAGIC(ex), ex.a_text,ex.a_data);
 120 #endif
 121                         };
 122                 };
 123                 elf_ppnt++;
 124         };
 125         
 126         set_fs(old_fs);
 127         
 128         /* Some simple consistency checks for the interpreter */
 129         if(elf_interpreter){
 130                 if(retval < 0) {
 131                         kfree(elf_interpreter);
 132                         kfree(elf_phdata);
 133                         return -ELIBACC;
 134                 };
 135                 if((N_MAGIC(ex) != OMAGIC) && (N_MAGIC(ex) != ZMAGIC)) {
 136                         kfree(elf_interpreter);
 137                         kfree(elf_phdata);
 138                         return -ELIBBAD;
 139                 };
 140         }
 141         
 142         /* OK, we are done with that, now set up the arg stuff,
 143            and then start this sucker up */
 144         
 145         if (!bprm->sh_bang) {
 146                 char * passed_p;
 147                 
 148                 sprintf(passed_fileno, "%d", elf_exec_fileno);
 149                 passed_p = passed_fileno;
 150                 
 151                 if(elf_interpreter) {
 152                         bprm->p = copy_strings(1,&passed_p,bprm->page,bprm->p,2);
 153                         bprm->argc++;
 154                 };
 155                 if (!bprm->p) {
 156                         if(elf_interpreter) {
 157                               kfree(elf_interpreter);
 158                         }
 159                         kfree (elf_phdata);
 160                         return -E2BIG;
 161                 }
 162         }
 163         
 164         /* OK, This is the point of no return */
 165         flush_old_exec(bprm);
 166 
 167         current->end_data = 0;
 168         current->end_code = 0;
 169         current->start_mmap = ELF_START_MMAP;
 170         current->mmap = NULL;
 171         elf_entry = (unsigned int) elf_ex.e_entry;
 172         
 173         /* Do this so that we can load the interpreter, if need be.  We will
 174            change some of these later */
 175         current->rss = 0;
 176         bprm->p += change_ldt(0, bprm->page);
 177         current->start_stack = bprm->p;
 178         
 179         /* Now we do a little grungy work by mmaping the ELF image into
 180            the correct location in memory.  At this point, we assume that
 181            the image should be loaded at fixed address, not at a variable
 182            address. */
 183         
 184         old_fs = get_fs();
 185         set_fs(get_ds());
 186         
 187         elf_ppnt = elf_phdata;
 188         for(i=0;i < elf_ex.e_phnum; i++){
 189                 
 190                 if(elf_ppnt->p_type == PT_INTERP) {
 191                         /* Set these up so that we are able to load the interpreter */
 192                         current->brk = ex.a_bss +
 193                                 (current->end_data = ex.a_data +
 194                                  (current->end_code = ex.a_text));
 195                         elf_entry = ex.a_entry;
 196                         
 197                         /* Now load the interpreter into user address space */
 198                         set_fs(old_fs);
 199                         
 200                         if (N_MAGIC(ex) == OMAGIC) {
 201                                 retval = read_exec(interpreter_inode, 32, (char *) 0, 
 202                                                    ex.a_text+ex.a_data);
 203                                 iput(interpreter_inode);
 204                         } else if (N_MAGIC(ex) == ZMAGIC || N_MAGIC(ex) == QMAGIC) {
 205                                 retval = read_exec(interpreter_inode,
 206                                                    N_TXTOFF(ex) ,
 207                                                    (char *) N_TXTADDR(ex),
 208                                                    ex.a_text+ex.a_data);
 209                                 iput(interpreter_inode);
 210                         } else
 211                                 retval = -1;
 212                         
 213                         old_fs = get_fs();
 214                         set_fs(get_ds());
 215                         
 216                         if(retval >= 0)
 217                                 zeromap_page_range((ex.a_text + ex.a_data + 0xfff) & 
 218                                                    0xfffff000, ex.a_bss, PAGE_COPY);
 219                         kfree(elf_interpreter);
 220                         
 221                         if(retval < 0) { 
 222                                 kfree(elf_phdata);
 223                                 send_sig(SIGSEGV, current, 0);
 224                                 return 0;
 225                         };
 226                 };
 227                 
 228                 
 229                 if(elf_ppnt->p_type == PT_LOAD) {
 230                         error = do_mmap(file,
 231                                         elf_ppnt->p_vaddr & 0xfffff000,
 232                                         elf_ppnt->p_filesz + (elf_ppnt->p_vaddr & 0xfff),
 233                                         PROT_READ | PROT_WRITE | PROT_EXEC,
 234                                         MAP_FIXED | MAP_PRIVATE,
 235                                         elf_ppnt->p_offset & 0xfffff000);
 236                         
 237 #ifdef LOW_ELF_STACK
 238                         if(elf_ppnt->p_vaddr & 0xfffff000 < elf_stack) 
 239                                 elf_stack = elf_ppnt->p_vaddr & 0xfffff000;
 240 #endif
 241                         
 242                         k = elf_ppnt->p_vaddr;
 243                         if(k > start_code) start_code = k;
 244                         k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
 245                         if(k > elf_bss) elf_bss = k;
 246                         if((elf_ppnt->p_flags | PROT_WRITE) && end_code <  k)
 247                                 end_code = k; 
 248                         if(end_data < k) end_data = k; 
 249                         k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
 250                         if(k > elf_brk) elf_brk = k;                 
 251                         
 252                         if(status == 0xffffffff) {
 253                                 set_fs(old_fs);
 254                                 kfree(elf_phdata);
 255                                 send_sig(SIGSEGV, current, 0);
 256                                 return 0;
 257                         };
 258                 };
 259                 elf_ppnt++;
 260         };
 261         set_fs(old_fs);
 262         
 263         kfree(elf_phdata);
 264         
 265         if(!elf_interpreter) sys_close(elf_exec_fileno);
 266         current->elf_executable = 1;
 267         current->executable = bprm->inode;
 268         bprm->inode->i_count++;
 269 #ifdef LOW_ELF_STACK
 270         current->start_stack = p = elf_stack - 4;
 271 #endif
 272         bprm->p -= MAX_ARG_PAGES*PAGE_SIZE;
 273         bprm->p = (unsigned long) create_tables((char *)bprm->p,bprm->argc,bprm->envc);
 274         if(elf_interpreter) current->arg_start += strlen(passed_fileno) + 1;
 275         current->start_brk = current->brk = elf_brk;
 276         current->end_code = end_code;
 277         current->start_code = start_code;
 278         current->start_stack = bprm->p;
 279         current->suid = current->euid = bprm->e_uid;
 280         current->sgid = current->egid = bprm->e_gid;
 281         zeromap_page_range((elf_bss + 0xfff) & 0xfffff000, elf_brk - elf_bss,
 282                            PAGE_COPY);
 283         regs->eip = elf_entry;          /* eip, magic happens :-) */
 284         regs->esp = bprm->p;                    /* stack pointer */
 285         if (current->flags & PF_PTRACED)
 286                 send_sig(SIGTRAP, current, 0);
 287         
 288         return 0;
 289 }
 290 
 291 
 292 int load_elf_library(int fd){
     /* [previous][next][first][last][top][bottom][index][help] */
 293         struct file * file;
 294         struct elfhdr elf_ex;
 295         struct elf_phdr *elf_phdata  =  NULL;
 296         struct  inode * inode;
 297         unsigned int len;
 298         int old_fs, retval;
 299         unsigned int bss;
 300         int error;
 301         int i,j;
 302         
 303         len = 0;
 304         file = current->filp[fd];
 305         inode = file->f_inode;
 306         
 307         set_fs(KERNEL_DS);
 308         if (file->f_op->read(inode, file, (char *) &elf_ex, sizeof(elf_ex)) != sizeof(elf_ex)) {
 309                 sys_close(fd);
 310                 return -EACCES;
 311         }
 312         set_fs(USER_DS);
 313         
 314         if (elf_ex.e_ident[0] != 0x7f ||
 315             strncmp(&elf_ex.e_ident[1], "ELF",3) != 0)
 316                 return -ENOEXEC;
 317         
 318         /* First of all, some simple consistency checks */
 319         if(elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 ||
 320            (elf_ex.e_machine != EM_386 && elf_ex.e_machine != EM_486) ||
 321            (!inode->i_op || !inode->i_op->bmap || 
 322             !inode->i_op->default_file_ops->mmap)){
 323                 return -ENOEXEC;
 324         };
 325         
 326         /* Now read in all of the header information */
 327         
 328         if(sizeof(struct elf_phdr) * elf_ex.e_phnum > PAGE_SIZE) 
 329                 return -ENOEXEC;
 330         
 331         elf_phdata =  (struct elf_phdr *) 
 332                 kmalloc(sizeof(struct elf_phdr) * elf_ex.e_phnum, GFP_KERNEL);
 333         
 334         old_fs = get_fs();
 335         set_fs(get_ds());
 336         retval = read_exec(inode, elf_ex.e_phoff, (char *) elf_phdata,
 337                            sizeof(struct elf_phdr) * elf_ex.e_phnum);
 338         set_fs(old_fs);
 339         
 340         j = 0;
 341         for(i=0; i<elf_ex.e_phnum; i++)
 342                 if((elf_phdata + i)->p_type == PT_LOAD) j++;
 343         
 344         if(j != 1)  {
 345                 kfree(elf_phdata);
 346                 return -ENOEXEC;
 347         };
 348         
 349         while(elf_phdata->p_type != PT_LOAD) elf_phdata++;
 350         
 351         /* Now use mmap to map the library into memory. */
 352         error = do_mmap(file,
 353                         elf_phdata->p_vaddr & 0xfffff000,
 354                         elf_phdata->p_filesz + (elf_phdata->p_vaddr & 0xfff),
 355                         PROT_READ | PROT_WRITE | PROT_EXEC,
 356                         MAP_FIXED | MAP_PRIVATE,
 357                         elf_phdata->p_offset & 0xfffff000);
 358         
 359         sys_close(fd);
 360         if (error != elf_phdata->p_vaddr & 0xfffff000) {
 361                 kfree(elf_phdata);
 362                 return error;
 363         }
 364         len = (elf_phdata->p_filesz + elf_phdata->p_vaddr+ 0xfff) & 0xfffff000;
 365         bss = elf_phdata->p_memsz + elf_phdata->p_vaddr;
 366         if (bss > len)
 367                 zeromap_page_range(len, bss-len, PAGE_COPY);
 368         kfree(elf_phdata);
 369         return 0;
 370 }

/* [previous][next][first][last][top][bottom][index][help] */