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

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