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

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

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