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

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