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

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