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

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