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

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