root/arch/i386/ibcs/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

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

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