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

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