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

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