root/fs/binfmt_elf.c

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

DEFINITIONS

This source file includes following definitions.
  1. padzero
  2. create_elf_tables
  3. load_elf_interp
  4. load_aout_interp
  5. load_elf_binary
  6. load_elf_library
  7. init_module
  8. cleanup_module

   1 /*
   2  * linux/fs/binfmt_elf.c
   3  *
   4  * These are the functions used to load ELF format executables as used
   5  * on SVr4 machines.  Information on the format may be found in the book
   6  * "UNIX SYSTEM V RELEASE 4 Programmers Guide: Ansi C and Programming Support
   7  * Tools".
   8  *
   9  * Copyright 1993, 1994: Eric Youngdale (ericy@cais.com).
  10  */
  11 
  12 #ifdef MODULE
  13 #include <linux/module.h>
  14 #include <linux/version.h>
  15 #else
  16 #define MOD_INC_USE_COUNT
  17 #define MOD_DEC_USE_COUNT
  18 #endif
  19 
  20 #include <linux/fs.h>
  21 #include <linux/sched.h>
  22 #include <linux/mm.h>
  23 #include <linux/mman.h>
  24 #include <linux/a.out.h>
  25 #include <linux/errno.h>
  26 #include <linux/signal.h>
  27 #include <linux/binfmts.h>
  28 #include <linux/string.h>
  29 #include <linux/fcntl.h>
  30 #include <linux/ptrace.h>
  31 #include <linux/malloc.h>
  32 #include <linux/shm.h>
  33 #include <linux/personality.h>
  34 
  35 #include <asm/segment.h>
  36 #include <asm/pgtable.h>
  37 
  38 #include <linux/config.h>
  39 
  40 #include <linux/unistd.h>
  41 typedef int (*sysfun_p)(int, ...);
  42 extern sysfun_p sys_call_table[];
  43 #define SYS(name)       (sys_call_table[__NR_##name])
  44 
  45 #define DLINFO_ITEMS 8
  46 
  47 #include <linux/elf.h>
  48 
  49 static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs);
  50 static int load_elf_library(int fd);
  51 
  52 struct linux_binfmt elf_format = {
  53 #ifndef MODULE
  54         NULL, NULL, load_elf_binary, load_elf_library, NULL
  55 #else
  56         NULL, &mod_use_count_, load_elf_binary, load_elf_library, NULL
  57 #endif
  58 };
  59 
  60 /* We need to explicitly zero any fractional pages
  61    after the data section (i.e. bss).  This would
  62    contain the junk from the file that should not
  63    be in memory */
  64 
  65 
  66 static void padzero(unsigned long elf_bss)
     /* [previous][next][first][last][top][bottom][index][help] */
  67 {
  68         unsigned long nbyte;
  69         char * fpnt;
  70   
  71         nbyte = elf_bss & (PAGE_SIZE-1);
  72         if (nbyte) {
  73                 nbyte = PAGE_SIZE - nbyte;
  74                 verify_area(VERIFY_WRITE, (void *) elf_bss, nbyte);
  75                 fpnt = (char *) elf_bss;
  76                 do {
  77                         put_user(0, fpnt++);
  78                 } while (--nbyte);
  79         }
  80 }
  81 
  82 unsigned long * create_elf_tables(char * p,int argc,int envc,struct elfhdr * exec, unsigned int load_addr, unsigned int interp_load_addr, int ibcs)
     /* [previous][next][first][last][top][bottom][index][help] */
  83 {
  84         unsigned long *argv,*envp, *dlinfo;
  85         unsigned long * sp;
  86         struct vm_area_struct *mpnt;
  87 
  88         mpnt = (struct vm_area_struct *)kmalloc(sizeof(*mpnt), GFP_KERNEL);
  89         if (mpnt) {
  90                 mpnt->vm_task = current;
  91                 mpnt->vm_start = PAGE_MASK & (unsigned long) p;
  92                 mpnt->vm_end = TASK_SIZE;
  93                 mpnt->vm_page_prot = PAGE_COPY;
  94 #ifdef VM_STACK_FLAGS
  95                 mpnt->vm_flags = VM_STACK_FLAGS;
  96                 mpnt->vm_pte = 0;
  97 #else
  98 #  ifdef VM_GROWSDOWN
  99                 mpnt->vm_flags = VM_GROWSDOWN;
 100 #  endif
 101 #endif
 102                 mpnt->vm_inode = NULL;
 103                 mpnt->vm_offset = 0;
 104                 mpnt->vm_ops = NULL;
 105                 insert_vm_struct(current, mpnt);
 106 #ifndef VM_GROWSDOWN
 107                 current->mm->stk_vma = mpnt;
 108 #endif
 109 
 110         }
 111         sp = (unsigned long *) (0xfffffffc & (unsigned long) p);
 112         if(exec) sp -= DLINFO_ITEMS*2;
 113         dlinfo = sp;
 114         sp -= envc+1;
 115         envp = sp;
 116         sp -= argc+1;
 117         argv = sp;
 118         if (!ibcs) {
 119                 put_user(envp,--sp);
 120                 put_user(argv,--sp);
 121         }
 122 
 123         /* The constant numbers (0-9) that we are writing here are
 124            described in the header file sys/auxv.h on at least
 125            some versions of SVr4 */
 126         if(exec) { /* Put this here for an ELF program interpreter */
 127           struct elf_phdr * eppnt;
 128           eppnt = (struct elf_phdr *) exec->e_phoff;
 129           put_user(3,dlinfo++); put_user(load_addr + exec->e_phoff,dlinfo++);
 130           put_user(4,dlinfo++); put_user(sizeof(struct elf_phdr),dlinfo++);
 131           put_user(5,dlinfo++); put_user(exec->e_phnum,dlinfo++);
 132           put_user(9,dlinfo++); put_user((unsigned long) exec->e_entry,dlinfo++);
 133           put_user(7,dlinfo++); put_user(interp_load_addr,dlinfo++);
 134           put_user(8,dlinfo++); put_user(0,dlinfo++);
 135           put_user(6,dlinfo++); put_user(PAGE_SIZE,dlinfo++);
 136           put_user(0,dlinfo++); put_user(0,dlinfo++);
 137         }
 138 
 139         put_user((unsigned long)argc,--sp);
 140         current->mm->arg_start = (unsigned long) p;
 141         while (argc-->0) {
 142                 put_user(p,argv++);
 143                 while (get_user(p++)) /* nothing */ ;
 144         }
 145         put_user(0,argv);
 146         current->mm->arg_end = current->mm->env_start = (unsigned long) p;
 147         while (envc-->0) {
 148                 put_user(p,envp++);
 149                 while (get_user(p++)) /* nothing */ ;
 150         }
 151         put_user(0,envp);
 152         current->mm->env_end = (unsigned long) p;
 153         return sp;
 154 }
 155 
 156 
 157 /* This is much more generalized than the library routine read function,
 158    so we keep this separate.  Technically the library read function
 159    is only provided so that we can read a.out libraries that have
 160    an ELF header */
 161 
 162 static unsigned int load_elf_interp(struct elfhdr * interp_elf_ex,
     /* [previous][next][first][last][top][bottom][index][help] */
 163                              struct inode * interpreter_inode, unsigned int *interp_load_addr)
 164 {
 165         struct file * file;
 166         struct elf_phdr *elf_phdata  =  NULL;
 167         struct elf_phdr *eppnt;
 168         unsigned int len;
 169         unsigned int load_addr;
 170         int elf_exec_fileno;
 171         int elf_bss;
 172         int retval;
 173         unsigned int last_bss;
 174         int error;
 175         int i, k;
 176         
 177         elf_bss = 0;
 178         last_bss = 0;
 179         error = load_addr = 0;
 180         
 181         /* First of all, some simple consistency checks */
 182         if((interp_elf_ex->e_type != ET_EXEC && 
 183             interp_elf_ex->e_type != ET_DYN) || 
 184            (interp_elf_ex->e_machine != EM_386 && interp_elf_ex->e_machine != EM_486) ||
 185            (!interpreter_inode->i_op ||
 186             !interpreter_inode->i_op->default_file_ops->mmap)){
 187                 return 0xffffffff;
 188         }
 189         
 190         /* Now read in all of the header information */
 191         
 192         if(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > PAGE_SIZE) 
 193             return 0xffffffff;
 194         
 195         elf_phdata =  (struct elf_phdr *) 
 196                 kmalloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum, GFP_KERNEL);
 197         if(!elf_phdata) return 0xffffffff;
 198         
 199         retval = read_exec(interpreter_inode, interp_elf_ex->e_phoff, (char *) elf_phdata,
 200                            sizeof(struct elf_phdr) * interp_elf_ex->e_phnum, 1);
 201         
 202         elf_exec_fileno = open_inode(interpreter_inode, O_RDONLY);
 203         if (elf_exec_fileno < 0) return 0xffffffff;
 204         file = current->files->fd[elf_exec_fileno];
 205 
 206         eppnt = elf_phdata;
 207         for(i=0; i<interp_elf_ex->e_phnum; i++, eppnt++)
 208           if(eppnt->p_type == PT_LOAD) {
 209             int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
 210             int elf_prot = 0;
 211             unsigned long vaddr = 0;
 212             if (eppnt->p_flags & PF_R) elf_prot =  PROT_READ;
 213             if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
 214             if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
 215             if (interp_elf_ex->e_type == ET_EXEC) {
 216                 elf_type |= MAP_FIXED;
 217                 vaddr = eppnt->p_vaddr;
 218             }
 219             
 220             error = do_mmap(file, 
 221                             vaddr & 0xfffff000,
 222                             eppnt->p_filesz + (vaddr & 0xfff),
 223                             elf_prot,
 224                             elf_type,
 225                             eppnt->p_offset & 0xfffff000);
 226             
 227             if(error < 0 && error > -1024) break;  /* Real error */
 228 
 229             if(!load_addr && interp_elf_ex->e_type == ET_DYN)
 230               load_addr = error;
 231 
 232             /*
 233              * Find the end of the file  mapping for this phdr, and keep
 234              * track of the largest address we see for this.
 235              */
 236             k = load_addr + eppnt->p_vaddr + eppnt->p_filesz;
 237             if(k > elf_bss) elf_bss = k;
 238 
 239             /*
 240              * Do the same thing for the memory mapping - between
 241              * elf_bss and last_bss is the bss section.
 242              */
 243             k = load_addr + eppnt->p_memsz + eppnt->p_vaddr;
 244             if(k > last_bss) last_bss = k;
 245           }
 246         
 247         /* Now use mmap to map the library into memory. */
 248 
 249         SYS(close)(elf_exec_fileno);
 250         if(error < 0 && error > -1024) {
 251                 kfree(elf_phdata);
 252                 return 0xffffffff;
 253         }
 254 
 255         /*
 256          * Now fill out the bss section.  First pad the last page up
 257          * to the page boundary, and then perform a mmap to make sure
 258          * that there are zeromapped pages up to and including the last
 259          * bss page.
 260          */
 261         padzero(elf_bss);
 262         len = (elf_bss + 0xfff) & 0xfffff000; /* What we have mapped so far */
 263 
 264         /* Map the last of the bss segment */
 265         if (last_bss > len)
 266           do_mmap(NULL, len, last_bss-len,
 267                   PROT_READ|PROT_WRITE|PROT_EXEC,
 268                   MAP_FIXED|MAP_PRIVATE, 0);
 269         kfree(elf_phdata);
 270 
 271         *interp_load_addr = load_addr;
 272         return ((unsigned int) interp_elf_ex->e_entry) + load_addr;
 273 }
 274 
 275 static unsigned int load_aout_interp(struct exec * interp_ex,
     /* [previous][next][first][last][top][bottom][index][help] */
 276                              struct inode * interpreter_inode)
 277 {
 278   int retval;
 279   unsigned int elf_entry;
 280   
 281   current->mm->brk = interp_ex->a_bss +
 282     (current->mm->end_data = interp_ex->a_data +
 283      (current->mm->end_code = interp_ex->a_text));
 284   elf_entry = interp_ex->a_entry;
 285   
 286   
 287   if (N_MAGIC(*interp_ex) == OMAGIC) {
 288     do_mmap(NULL, 0, interp_ex->a_text+interp_ex->a_data,
 289             PROT_READ|PROT_WRITE|PROT_EXEC,
 290             MAP_FIXED|MAP_PRIVATE, 0);
 291     retval = read_exec(interpreter_inode, 32, (char *) 0, 
 292                        interp_ex->a_text+interp_ex->a_data, 0);
 293   } else if (N_MAGIC(*interp_ex) == ZMAGIC || N_MAGIC(*interp_ex) == QMAGIC) {
 294     do_mmap(NULL, 0, interp_ex->a_text+interp_ex->a_data,
 295             PROT_READ|PROT_WRITE|PROT_EXEC,
 296             MAP_FIXED|MAP_PRIVATE, 0);
 297     retval = read_exec(interpreter_inode,
 298                        N_TXTOFF(*interp_ex) ,
 299                        (char *) N_TXTADDR(*interp_ex),
 300                        interp_ex->a_text+interp_ex->a_data, 0);
 301   } else
 302     retval = -1;
 303   
 304   if(retval >= 0)
 305     do_mmap(NULL, (interp_ex->a_text + interp_ex->a_data + 0xfff) & 
 306             0xfffff000, interp_ex->a_bss,
 307             PROT_READ|PROT_WRITE|PROT_EXEC,
 308             MAP_FIXED|MAP_PRIVATE, 0);
 309   if(retval < 0) return 0xffffffff;
 310   return elf_entry;
 311 }
 312 
 313 /*
 314  * These are the functions used to load ELF style executables and shared
 315  * libraries.  There is no binary dependent code anywhere else.
 316  */
 317 
 318 #define INTERPRETER_NONE 0
 319 #define INTERPRETER_AOUT 1
 320 #define INTERPRETER_ELF 2
 321 
 322 
 323 static int
 324 load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 325 {
 326         struct elfhdr elf_ex;
 327         struct elfhdr interp_elf_ex;
 328         struct file * file;
 329         struct exec interp_ex;
 330         struct inode *interpreter_inode;
 331         unsigned int load_addr;
 332         unsigned int interpreter_type = INTERPRETER_NONE;
 333         unsigned char ibcs2_interpreter;
 334         int i;
 335         int old_fs;
 336         int error;
 337         struct elf_phdr * elf_ppnt, *elf_phdata;
 338         int elf_exec_fileno;
 339         unsigned int elf_bss, k, elf_brk;
 340         int retval;
 341         char * elf_interpreter;
 342         unsigned int elf_entry, interp_load_addr = 0;
 343         int status;
 344         unsigned int start_code, end_code, end_data;
 345         unsigned int elf_stack;
 346         char passed_fileno[6];
 347         
 348         MOD_INC_USE_COUNT;
 349 
 350         ibcs2_interpreter = 0;
 351         status = 0;
 352         load_addr = 0;
 353         elf_ex = *((struct elfhdr *) bprm->buf);          /* exec-header */
 354         
 355         if (elf_ex.e_ident[0] != 0x7f ||
 356             strncmp(&elf_ex.e_ident[1], "ELF",3) != 0) {
 357                 MOD_DEC_USE_COUNT;
 358                 return  -ENOEXEC;
 359         }
 360         
 361         
 362         /* First of all, some simple consistency checks */
 363         if(elf_ex.e_type != ET_EXEC || 
 364            (elf_ex.e_machine != EM_386 && elf_ex.e_machine != EM_486) ||
 365            (!bprm->inode->i_op || !bprm->inode->i_op->default_file_ops ||
 366             !bprm->inode->i_op->default_file_ops->mmap)){
 367                 MOD_DEC_USE_COUNT;
 368                 return -ENOEXEC;
 369         }
 370         
 371         /* Now read in all of the header information */
 372         
 373         elf_phdata = (struct elf_phdr *) kmalloc(elf_ex.e_phentsize * 
 374                                                  elf_ex.e_phnum, GFP_KERNEL);
 375         
 376         retval = read_exec(bprm->inode, elf_ex.e_phoff, (char *) elf_phdata,
 377                            elf_ex.e_phentsize * elf_ex.e_phnum, 1);
 378         if (retval < 0) {
 379                 kfree (elf_phdata);
 380                 MOD_DEC_USE_COUNT;
 381                 return retval;
 382         }
 383         
 384         elf_ppnt = elf_phdata;
 385         
 386         elf_bss = 0;
 387         elf_brk = 0;
 388         
 389         elf_exec_fileno = open_inode(bprm->inode, O_RDONLY);
 390 
 391         if (elf_exec_fileno < 0) {
 392                 kfree (elf_phdata);
 393                 MOD_DEC_USE_COUNT;
 394                 return elf_exec_fileno;
 395         }
 396         
 397         file = current->files->fd[elf_exec_fileno];
 398         
 399         elf_stack = 0xffffffff;
 400         elf_interpreter = NULL;
 401         start_code = 0;
 402         end_code = 0;
 403         end_data = 0;
 404         
 405         for(i=0;i < elf_ex.e_phnum; i++){
 406                 if(elf_ppnt->p_type == PT_INTERP) {
 407                         /* This is the program interpreter used for shared libraries - 
 408                            for now assume that this is an a.out format binary */
 409                         
 410                         elf_interpreter = (char *) kmalloc(elf_ppnt->p_filesz, 
 411                                                            GFP_KERNEL);
 412                         
 413                         retval = read_exec(bprm->inode,elf_ppnt->p_offset,elf_interpreter,
 414                                            elf_ppnt->p_filesz, 1);
 415                         /* If the program interpreter is one of these two,
 416                            then assume an iBCS2 image. Otherwise assume
 417                            a native linux image. */
 418                         if (strcmp(elf_interpreter,"/usr/lib/libc.so.1") == 0 ||
 419                             strcmp(elf_interpreter,"/usr/lib/ld.so.1") == 0)
 420                           ibcs2_interpreter = 1;
 421 #if 0
 422                         printk("Using ELF interpreter %s\n", elf_interpreter);
 423 #endif
 424                         if(retval >= 0) {
 425                                 old_fs = get_fs(); /* This could probably be optimized */
 426                                 set_fs(get_ds());
 427                                 retval = namei(elf_interpreter, &interpreter_inode);
 428                                 set_fs(old_fs);
 429                         }
 430 
 431                         if(retval >= 0)
 432                                 retval = read_exec(interpreter_inode,0,bprm->buf,128, 1);
 433                         
 434                         if(retval >= 0) {
 435                                 interp_ex = *((struct exec *) bprm->buf);               /* exec-header */
 436                                 interp_elf_ex = *((struct elfhdr *) bprm->buf);   /* exec-header */
 437                                 
 438                         }
 439                         if(retval < 0) {
 440                                 kfree (elf_phdata);
 441                                 kfree(elf_interpreter);
 442                                 MOD_DEC_USE_COUNT;
 443                                 return retval;
 444                         }
 445                 }
 446                 elf_ppnt++;
 447         }
 448         
 449         /* Some simple consistency checks for the interpreter */
 450         if(elf_interpreter){
 451                 interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT;
 452                 if(retval < 0) {
 453                         kfree(elf_interpreter);
 454                         kfree(elf_phdata);
 455                         MOD_DEC_USE_COUNT;
 456                         return -ELIBACC;
 457                 }
 458                 /* Now figure out which format our binary is */
 459                 if((N_MAGIC(interp_ex) != OMAGIC) && 
 460                    (N_MAGIC(interp_ex) != ZMAGIC) &&
 461                    (N_MAGIC(interp_ex) != QMAGIC)) 
 462                   interpreter_type = INTERPRETER_ELF;
 463 
 464                 if (interp_elf_ex.e_ident[0] != 0x7f ||
 465                     strncmp(&interp_elf_ex.e_ident[1], "ELF",3) != 0)
 466                   interpreter_type &= ~INTERPRETER_ELF;
 467 
 468                 if(!interpreter_type)
 469                   {
 470                     kfree(elf_interpreter);
 471                     kfree(elf_phdata);
 472                     MOD_DEC_USE_COUNT;
 473                     return -ELIBBAD;
 474                   }
 475         }
 476         
 477         /* OK, we are done with that, now set up the arg stuff,
 478            and then start this sucker up */
 479         
 480         if (!bprm->sh_bang) {
 481                 char * passed_p;
 482                 
 483                 if(interpreter_type == INTERPRETER_AOUT) {
 484                   sprintf(passed_fileno, "%d", elf_exec_fileno);
 485                   passed_p = passed_fileno;
 486                 
 487                   if(elf_interpreter) {
 488                     bprm->p = copy_strings(1,&passed_p,bprm->page,bprm->p,2);
 489                     bprm->argc++;
 490                   }
 491                 }
 492                 if (!bprm->p) {
 493                         if(elf_interpreter) {
 494                               kfree(elf_interpreter);
 495                         }
 496                         kfree (elf_phdata);
 497                         MOD_DEC_USE_COUNT;
 498                         return -E2BIG;
 499                 }
 500         }
 501         
 502         /* OK, This is the point of no return */
 503         flush_old_exec(bprm);
 504 
 505         current->mm->end_data = 0;
 506         current->mm->end_code = 0;
 507         current->mm->start_mmap = ELF_START_MMAP;
 508         current->mm->mmap = NULL;
 509         elf_entry = (unsigned int) elf_ex.e_entry;
 510         
 511         /* Do this so that we can load the interpreter, if need be.  We will
 512            change some of these later */
 513         current->mm->rss = 0;
 514         bprm->p += setup_arg_pages(0, bprm->page);
 515         current->mm->start_stack = bprm->p;
 516         
 517         /* Now we do a little grungy work by mmaping the ELF image into
 518            the correct location in memory.  At this point, we assume that
 519            the image should be loaded at fixed address, not at a variable
 520            address. */
 521         
 522         old_fs = get_fs();
 523         set_fs(get_ds());
 524         
 525         elf_ppnt = elf_phdata;
 526         for(i=0;i < elf_ex.e_phnum; i++){
 527                 
 528                 if(elf_ppnt->p_type == PT_INTERP) {
 529                         /* Set these up so that we are able to load the interpreter */
 530                   /* Now load the interpreter into user address space */
 531                   set_fs(old_fs);
 532 
 533                   if(interpreter_type & 1) elf_entry = 
 534                     load_aout_interp(&interp_ex, interpreter_inode);
 535 
 536                   if(interpreter_type & 2) elf_entry = 
 537                     load_elf_interp(&interp_elf_ex, interpreter_inode, &interp_load_addr);
 538 
 539                   old_fs = get_fs();
 540                   set_fs(get_ds());
 541 
 542                   iput(interpreter_inode);
 543                   kfree(elf_interpreter);
 544                         
 545                   if(elf_entry == 0xffffffff) { 
 546                     printk("Unable to load interpreter\n");
 547                     kfree(elf_phdata);
 548                     send_sig(SIGSEGV, current, 0);
 549                     MOD_DEC_USE_COUNT;
 550                     return 0;
 551                   }
 552                 }
 553                 
 554                 
 555                 if(elf_ppnt->p_type == PT_LOAD) {
 556                         int elf_prot = (elf_ppnt->p_flags & PF_R) ? PROT_READ : 0;
 557                         if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
 558                         if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
 559                         error = do_mmap(file,
 560                                         elf_ppnt->p_vaddr & 0xfffff000,
 561                                         elf_ppnt->p_filesz + (elf_ppnt->p_vaddr & 0xfff),
 562                                         elf_prot,
 563                                         MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
 564                                         elf_ppnt->p_offset & 0xfffff000);
 565                         
 566 #ifdef LOW_ELF_STACK
 567                         if(elf_ppnt->p_vaddr & 0xfffff000 < elf_stack) 
 568                                 elf_stack = elf_ppnt->p_vaddr & 0xfffff000;
 569 #endif
 570                         
 571                         if(!load_addr) 
 572                           load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset;
 573                         k = elf_ppnt->p_vaddr;
 574                         if(k > start_code) start_code = k;
 575                         k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
 576                         if(k > elf_bss) elf_bss = k;
 577                         if((elf_ppnt->p_flags | PROT_WRITE) && end_code <  k)
 578                                 end_code = k; 
 579                         if(end_data < k) end_data = k; 
 580                         k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
 581                         if(k > elf_brk) elf_brk = k;                 
 582                       }
 583                 elf_ppnt++;
 584         }
 585         set_fs(old_fs);
 586         
 587         kfree(elf_phdata);
 588         
 589         if(interpreter_type != INTERPRETER_AOUT) SYS(close)(elf_exec_fileno);
 590         current->personality = (ibcs2_interpreter ? PER_SVR4 : PER_LINUX);
 591 
 592         if (current->exec_domain && current->exec_domain->use_count)
 593                 (*current->exec_domain->use_count)--;
 594         if (current->binfmt && current->binfmt->use_count)
 595                 (*current->binfmt->use_count)--;
 596         current->exec_domain = lookup_exec_domain(current->personality);
 597         current->binfmt = &elf_format;
 598         if (current->exec_domain && current->exec_domain->use_count)
 599                 (*current->exec_domain->use_count)++;
 600         if (current->binfmt && current->binfmt->use_count)
 601                 (*current->binfmt->use_count)++;
 602 
 603 #ifndef VM_STACK_FLAGS
 604         current->executable = bprm->inode;
 605         bprm->inode->i_count++;
 606 #endif
 607 #ifdef LOW_ELF_STACK
 608         current->start_stack = p = elf_stack - 4;
 609 #endif
 610         bprm->p -= MAX_ARG_PAGES*PAGE_SIZE;
 611         bprm->p = (unsigned long) 
 612           create_elf_tables((char *)bprm->p,
 613                         bprm->argc,
 614                         bprm->envc,
 615                         (interpreter_type == INTERPRETER_ELF ? &elf_ex : NULL),
 616                         load_addr,
 617                         interp_load_addr,
 618                         (interpreter_type == INTERPRETER_AOUT ? 0 : 1));
 619         if(interpreter_type == INTERPRETER_AOUT)
 620           current->mm->arg_start += strlen(passed_fileno) + 1;
 621         current->mm->start_brk = current->mm->brk = elf_brk;
 622         current->mm->end_code = end_code;
 623         current->mm->start_code = start_code;
 624         current->mm->end_data = end_data;
 625         current->mm->start_stack = bprm->p;
 626         current->suid = current->euid = current->fsuid = bprm->e_uid;
 627         current->sgid = current->egid = current->fsgid = bprm->e_gid;
 628 
 629         /* Calling sys_brk effectively mmaps the pages that we need for the bss and break
 630            sections */
 631         current->mm->brk = (elf_bss + 0xfff) & 0xfffff000;
 632         SYS(brk)((elf_brk + 0xfff) & 0xfffff000);
 633 
 634         padzero(elf_bss);
 635 
 636 #if 0
 637         printk("(start_brk) %x\n" , current->mm->start_brk);
 638         printk("(end_code) %x\n" , current->mm->end_code);
 639         printk("(start_code) %x\n" , current->mm->start_code);
 640         printk("(end_data) %x\n" , current->mm->end_data);
 641         printk("(start_stack) %x\n" , current->mm->start_stack);
 642         printk("(brk) %x\n" , current->mm->brk);
 643 #endif
 644 
 645         if( current->personality == PER_SVR4 )
 646         {
 647                 /* Why this, you ask???  Well SVr4 maps page 0 as read-only,
 648                    and some applications "depend" upon this behavior.
 649                    Since we do not have the power to recompile these, we
 650                    emulate the SVr4 behavior.  Sigh.  */
 651                 error = do_mmap(NULL, 0, 4096, PROT_READ | PROT_EXEC,
 652                                 MAP_FIXED | MAP_PRIVATE, 0);
 653         }
 654 
 655         start_thread(regs, elf_entry, bprm->p);
 656         if (current->flags & PF_PTRACED)
 657                 send_sig(SIGTRAP, current, 0);
 658         MOD_DEC_USE_COUNT;
 659         return 0;
 660 }
 661 
 662 /* This is really simpleminded and specialized - we are loading an
 663    a.out library that is given an ELF header. */
 664 
 665 static int
 666 load_elf_library(int fd){
     /* [previous][next][first][last][top][bottom][index][help] */
 667         struct file * file;
 668         struct elfhdr elf_ex;
 669         struct elf_phdr *elf_phdata  =  NULL;
 670         struct  inode * inode;
 671         unsigned int len;
 672         int elf_bss;
 673         int retval;
 674         unsigned int bss;
 675         int error;
 676         int i,j, k;
 677 
 678         MOD_INC_USE_COUNT;
 679         len = 0;
 680         file = current->files->fd[fd];
 681         inode = file->f_inode;
 682         elf_bss = 0;
 683         
 684         set_fs(KERNEL_DS);
 685         if (file->f_op->read(inode, file, (char *) &elf_ex, sizeof(elf_ex)) != sizeof(elf_ex)) {
 686                 SYS(close)(fd);
 687                 MOD_DEC_USE_COUNT;
 688                 return -EACCES;
 689         }
 690         set_fs(USER_DS);
 691         
 692         if (elf_ex.e_ident[0] != 0x7f ||
 693             strncmp(&elf_ex.e_ident[1], "ELF",3) != 0) {
 694                 MOD_DEC_USE_COUNT;
 695                 return -ENOEXEC;
 696         }
 697         
 698         /* First of all, some simple consistency checks */
 699         if(elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 ||
 700            (elf_ex.e_machine != EM_386 && elf_ex.e_machine != EM_486) ||
 701            (!inode->i_op || !inode->i_op->default_file_ops->mmap)){
 702                 MOD_DEC_USE_COUNT;
 703                 return -ENOEXEC;
 704         }
 705         
 706         /* Now read in all of the header information */
 707         
 708         if(sizeof(struct elf_phdr) * elf_ex.e_phnum > PAGE_SIZE) {
 709                 MOD_DEC_USE_COUNT;
 710                 return -ENOEXEC;
 711         }
 712         
 713         elf_phdata =  (struct elf_phdr *) 
 714                 kmalloc(sizeof(struct elf_phdr) * elf_ex.e_phnum, GFP_KERNEL);
 715         
 716         retval = read_exec(inode, elf_ex.e_phoff, (char *) elf_phdata,
 717                            sizeof(struct elf_phdr) * elf_ex.e_phnum, 1);
 718         
 719         j = 0;
 720         for(i=0; i<elf_ex.e_phnum; i++)
 721                 if((elf_phdata + i)->p_type == PT_LOAD) j++;
 722         
 723         if(j != 1)  {
 724                 kfree(elf_phdata);
 725                 MOD_DEC_USE_COUNT;
 726                 return -ENOEXEC;
 727         }
 728         
 729         while(elf_phdata->p_type != PT_LOAD) elf_phdata++;
 730         
 731         /* Now use mmap to map the library into memory. */
 732         error = do_mmap(file,
 733                         elf_phdata->p_vaddr & 0xfffff000,
 734                         elf_phdata->p_filesz + (elf_phdata->p_vaddr & 0xfff),
 735                         PROT_READ | PROT_WRITE | PROT_EXEC,
 736                         MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
 737                         elf_phdata->p_offset & 0xfffff000);
 738 
 739         k = elf_phdata->p_vaddr + elf_phdata->p_filesz;
 740         if(k > elf_bss) elf_bss = k;
 741         
 742         SYS(close)(fd);
 743         if (error != (elf_phdata->p_vaddr & 0xfffff000)) {
 744                 kfree(elf_phdata);
 745                 MOD_DEC_USE_COUNT;
 746                 return error;
 747         }
 748 
 749         padzero(elf_bss);
 750 
 751         len = (elf_phdata->p_filesz + elf_phdata->p_vaddr+ 0xfff) & 0xfffff000;
 752         bss = elf_phdata->p_memsz + elf_phdata->p_vaddr;
 753         if (bss > len)
 754           do_mmap(NULL, len, bss-len,
 755                   PROT_READ|PROT_WRITE|PROT_EXEC,
 756                   MAP_FIXED|MAP_PRIVATE, 0);
 757         kfree(elf_phdata);
 758         MOD_DEC_USE_COUNT;
 759         return 0;
 760 }
 761 
 762 #ifdef MODULE
 763 char kernel_version[] = UTS_RELEASE;
 764 
 765 int init_module(void) {
     /* [previous][next][first][last][top][bottom][index][help] */
 766         /* Install the COFF, ELF and XOUT loaders.
 767          * N.B. We *rely* on the table being the right size with the
 768          * right number of free slots...
 769          */
 770         register_binfmt(&elf_format);
 771         return 0;
 772 }
 773 
 774 void cleanup_module( void) {
     /* [previous][next][first][last][top][bottom][index][help] */
 775         
 776         if (MOD_IN_USE)
 777                 printk(KERN_INFO "iBCS: module is in use, remove delayed\n");
 778 
 779         /* Remove the COFF and ELF loaders. */
 780         unregister_binfmt(&elf_format);
 781 }
 782 #endif

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