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

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