root/fs/binfmt_elf.c

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

DEFINITIONS

This source file includes following definitions.
  1. padzero
  2. load_elf_binary
  3. 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 
  17 #include <asm/segment.h>
  18 
  19 asmlinkage int sys_exit(int exit_code);
  20 asmlinkage int sys_close(unsigned fd);
  21 asmlinkage int sys_open(const char *, int, int);
  22 asmlinkage int sys_brk(unsigned long);
  23 
  24 #include <linux/elf.h>
  25 
  26 /* We need to explicitly zero any fractional pages
  27    after the data section (i.e. bss).  This would
  28    contain the junk from the file that should not
  29    be in memory */
  30 
  31 static void padzero(int elf_bss){
     /* [previous][next][first][last][top][bottom][index][help] */
  32   unsigned int fpnt, nbyte;
  33   
  34   if(elf_bss & 0xfff) {
  35     
  36     nbyte = (PAGE_SIZE - (elf_bss & 0xfff)) & 0xfff;
  37     if(nbyte){
  38       verify_area(VERIFY_WRITE, (void *) elf_bss, nbyte);
  39       
  40       fpnt = elf_bss;
  41       while(fpnt & 0xfff) put_fs_byte(0, fpnt++);
  42     };
  43   };
  44 }
  45 
  46 /*
  47  * These are the functions used to load ELF style executables and shared
  48  * libraries.  There is no binary dependent code anywhere else.
  49  */
  50 
  51 int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
     /* [previous][next][first][last][top][bottom][index][help] */
  52 {
  53         struct elfhdr elf_ex;
  54         struct file * file;
  55         struct exec ex;
  56         struct inode *interpreter_inode;
  57         int i;
  58         int old_fs;
  59         int error;
  60         struct elf_phdr * elf_ppnt, *elf_phdata;
  61         int elf_exec_fileno;
  62         unsigned int elf_bss, k, elf_brk;
  63         int retval;
  64         char * elf_interpreter;
  65         unsigned int elf_entry;
  66         int status;
  67         unsigned int start_code, end_code, end_data;
  68         unsigned int elf_stack;
  69         char passed_fileno[6];
  70         
  71         status = 0;
  72         elf_ex = *((struct elfhdr *) bprm->buf);          /* exec-header */
  73         
  74         if (elf_ex.e_ident[0] != 0x7f ||
  75             strncmp(&elf_ex.e_ident[1], "ELF",3) != 0)
  76                 return  -ENOEXEC;
  77         
  78         
  79         /* First of all, some simple consistency checks */
  80         if(elf_ex.e_type != ET_EXEC || 
  81            (elf_ex.e_machine != EM_386 && elf_ex.e_machine != EM_486) ||
  82            (!bprm->inode->i_op || !bprm->inode->i_op->default_file_ops ||
  83             !bprm->inode->i_op->default_file_ops->mmap)){
  84                 return -ENOEXEC;
  85         };
  86         
  87         /* Now read in all of the header information */
  88         
  89         elf_phdata = (struct elf_phdr *) kmalloc(elf_ex.e_phentsize * 
  90                                                  elf_ex.e_phnum, GFP_KERNEL);
  91         
  92         old_fs = get_fs();
  93         set_fs(get_ds());
  94         retval = read_exec(bprm->inode, elf_ex.e_phoff, (char *) elf_phdata,
  95                            elf_ex.e_phentsize * elf_ex.e_phnum);
  96         set_fs(old_fs);
  97         if (retval < 0) {
  98                 kfree (elf_phdata);
  99                 return retval;
 100         }
 101         
 102         elf_ppnt = elf_phdata;
 103         
 104         elf_bss = 0;
 105         elf_brk = 0;
 106         
 107         elf_exec_fileno = open_inode(bprm->inode, O_RDONLY);
 108 
 109         if (elf_exec_fileno < 0) {
 110                 kfree (elf_phdata);
 111                 return elf_exec_fileno;
 112         }
 113         
 114         file = current->filp[elf_exec_fileno];
 115         
 116         elf_stack = 0xffffffff;
 117         elf_interpreter = NULL;
 118         start_code = 0;
 119         end_code = 0;
 120         end_data = 0;
 121         
 122         old_fs = get_fs();
 123         set_fs(get_ds());
 124         
 125         for(i=0;i < elf_ex.e_phnum; i++){
 126                 if(elf_ppnt->p_type == PT_INTERP) {
 127                         /* This is the program interpreter used for shared libraries - 
 128                            for now assume that this is an a.out format binary */
 129                         
 130                         elf_interpreter = (char *) kmalloc(elf_ppnt->p_filesz, 
 131                                                            GFP_KERNEL);
 132                         
 133                         retval = read_exec(bprm->inode,elf_ppnt->p_offset,elf_interpreter,
 134                                            elf_ppnt->p_filesz);
 135 #if 0
 136                         printk("Using ELF interpreter %s\n", elf_interpreter);
 137 #endif
 138                         if(retval >= 0)
 139                                 retval = namei(elf_interpreter, &interpreter_inode);
 140                         if(retval >= 0)
 141                                 retval = read_exec(interpreter_inode,0,bprm->buf,128);
 142                         
 143                         if(retval >= 0){
 144                                 ex = *((struct exec *) bprm->buf);              /* exec-header */
 145                                 
 146 #if 0
 147                                 printk("Interpreter: %x %x %x\n",N_MAGIC(ex), ex.a_text,ex.a_data);
 148 #endif
 149                         };
 150                 };
 151                 elf_ppnt++;
 152         };
 153         
 154         set_fs(old_fs);
 155         
 156         /* Some simple consistency checks for the interpreter */
 157         if(elf_interpreter){
 158                 if(retval < 0) {
 159                         kfree(elf_interpreter);
 160                         kfree(elf_phdata);
 161                         return -ELIBACC;
 162                 };
 163                 if((N_MAGIC(ex) != OMAGIC) && (N_MAGIC(ex) != ZMAGIC)) {
 164                         kfree(elf_interpreter);
 165                         kfree(elf_phdata);
 166                         return -ELIBBAD;
 167                 };
 168         }
 169         
 170         /* OK, we are done with that, now set up the arg stuff,
 171            and then start this sucker up */
 172         
 173         if (!bprm->sh_bang) {
 174                 char * passed_p;
 175                 
 176                 sprintf(passed_fileno, "%d", elf_exec_fileno);
 177                 passed_p = passed_fileno;
 178                 
 179                 if(elf_interpreter) {
 180                         bprm->p = copy_strings(1,&passed_p,bprm->page,bprm->p,2);
 181                         bprm->argc++;
 182                 };
 183                 if (!bprm->p) {
 184                         if(elf_interpreter) {
 185                               kfree(elf_interpreter);
 186                         }
 187                         kfree (elf_phdata);
 188                         return -E2BIG;
 189                 }
 190         }
 191         
 192         /* OK, This is the point of no return */
 193         flush_old_exec(bprm);
 194 
 195         current->end_data = 0;
 196         current->end_code = 0;
 197         current->start_mmap = ELF_START_MMAP;
 198         current->mmap = NULL;
 199         elf_entry = (unsigned int) elf_ex.e_entry;
 200         
 201         /* Do this so that we can load the interpreter, if need be.  We will
 202            change some of these later */
 203         current->rss = 0;
 204         bprm->p += change_ldt(0, bprm->page);
 205         current->start_stack = bprm->p;
 206         
 207         /* Now we do a little grungy work by mmaping the ELF image into
 208            the correct location in memory.  At this point, we assume that
 209            the image should be loaded at fixed address, not at a variable
 210            address. */
 211         
 212         old_fs = get_fs();
 213         set_fs(get_ds());
 214         
 215         elf_ppnt = elf_phdata;
 216         for(i=0;i < elf_ex.e_phnum; i++){
 217                 
 218                 if(elf_ppnt->p_type == PT_INTERP) {
 219                         /* Set these up so that we are able to load the interpreter */
 220                         current->brk = ex.a_bss +
 221                                 (current->end_data = ex.a_data +
 222                                  (current->end_code = ex.a_text));
 223                         elf_entry = ex.a_entry;
 224                         
 225                         /* Now load the interpreter into user address space */
 226                         set_fs(old_fs);
 227                         
 228                         if (N_MAGIC(ex) == OMAGIC) {
 229                           do_mmap(NULL, 0, ex.a_text+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                                              ex.a_text+ex.a_data);
 234                                 iput(interpreter_inode);
 235                         } else if (N_MAGIC(ex) == ZMAGIC || N_MAGIC(ex) == QMAGIC) {
 236                           do_mmap(NULL, 0, ex.a_text+ex.a_data,
 237                                   PROT_READ|PROT_WRITE|PROT_EXEC,
 238                                   MAP_FIXED|MAP_PRIVATE, 0);
 239                           retval = read_exec(interpreter_inode,
 240                                              N_TXTOFF(ex) ,
 241                                              (char *) N_TXTADDR(ex),
 242                                              ex.a_text+ex.a_data);
 243                           iput(interpreter_inode);
 244                         } else
 245                                 retval = -1;
 246                         
 247                         old_fs = get_fs();
 248                         set_fs(get_ds());
 249                         
 250                         if(retval >= 0)
 251                           do_mmap(NULL, (ex.a_text + ex.a_data + 0xfff) & 
 252                                   0xfffff000, ex.a_bss,
 253                                   PROT_READ|PROT_WRITE|PROT_EXEC,
 254                                   MAP_FIXED|MAP_PRIVATE, 0);
 255 
 256                         kfree(elf_interpreter);
 257                         
 258                         if(retval < 0) { 
 259                                 kfree(elf_phdata);
 260                                 send_sig(SIGSEGV, current, 0);
 261                                 return 0;
 262                         };
 263                 };
 264                 
 265                 
 266                 if(elf_ppnt->p_type == PT_LOAD) {
 267                         error = do_mmap(file,
 268                                         elf_ppnt->p_vaddr & 0xfffff000,
 269                                         elf_ppnt->p_filesz + (elf_ppnt->p_vaddr & 0xfff),
 270                                         PROT_READ | PROT_WRITE | PROT_EXEC,
 271                                         MAP_FIXED | MAP_PRIVATE,
 272                                         elf_ppnt->p_offset & 0xfffff000);
 273                         
 274 #ifdef LOW_ELF_STACK
 275                         if(elf_ppnt->p_vaddr & 0xfffff000 < elf_stack) 
 276                                 elf_stack = elf_ppnt->p_vaddr & 0xfffff000;
 277 #endif
 278                         
 279                         k = elf_ppnt->p_vaddr;
 280                         if(k > start_code) start_code = k;
 281                         k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
 282                         if(k > elf_bss) elf_bss = k;
 283                         if((elf_ppnt->p_flags | PROT_WRITE) && end_code <  k)
 284                                 end_code = k; 
 285                         if(end_data < k) end_data = k; 
 286                         k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
 287                         if(k > elf_brk) elf_brk = k;                 
 288                         
 289                         if(status == 0xffffffff) {
 290                                 set_fs(old_fs);
 291                                 kfree(elf_phdata);
 292                                 send_sig(SIGSEGV, current, 0);
 293                                 return 0;
 294                         };
 295                 };
 296                 elf_ppnt++;
 297         };
 298         set_fs(old_fs);
 299         
 300         kfree(elf_phdata);
 301         
 302         if(!elf_interpreter) sys_close(elf_exec_fileno);
 303         current->elf_executable = 1;
 304         current->executable = bprm->inode;
 305         bprm->inode->i_count++;
 306 #ifdef LOW_ELF_STACK
 307         current->start_stack = p = elf_stack - 4;
 308 #endif
 309         bprm->p -= MAX_ARG_PAGES*PAGE_SIZE;
 310         bprm->p = (unsigned long) create_tables((char *)bprm->p,bprm->argc,bprm->envc,0);
 311         if(elf_interpreter) current->arg_start += strlen(passed_fileno) + 1;
 312         current->start_brk = current->brk = elf_brk;
 313         current->end_code = end_code;
 314         current->start_code = start_code;
 315         current->end_data = end_data;
 316         current->start_stack = bprm->p;
 317         current->suid = current->euid = bprm->e_uid;
 318         current->sgid = current->egid = bprm->e_gid;
 319 
 320         /* Calling sys_brk effectively mmaps the pages that we need for the bss and break
 321            sections */
 322         current->brk = (elf_bss + 0xfff) & 0xfffff000;
 323         sys_brk((elf_brk + 0xfff) & 0xfffff000);
 324 
 325         padzero(elf_bss);
 326 
 327         regs->eip = elf_entry;          /* eip, magic happens :-) */
 328         regs->esp = bprm->p;                    /* stack pointer */
 329         if (current->flags & PF_PTRACED)
 330                 send_sig(SIGTRAP, current, 0);
 331         return 0;
 332 }
 333 
 334 /* This is really simpleminded and specialized - we are loading an a.out library that is given
 335    an ELF header */
 336 
 337 int load_elf_library(int fd){
     /* [previous][next][first][last][top][bottom][index][help] */
 338         struct file * file;
 339         struct elfhdr elf_ex;
 340         struct elf_phdr *elf_phdata  =  NULL;
 341         struct  inode * inode;
 342         unsigned int len;
 343         int elf_bss;
 344         int old_fs, retval;
 345         unsigned int bss;
 346         int error;
 347         int i,j, k;
 348         
 349         len = 0;
 350         file = current->filp[fd];
 351         inode = file->f_inode;
 352         elf_bss = 0;
 353         
 354         set_fs(KERNEL_DS);
 355         if (file->f_op->read(inode, file, (char *) &elf_ex, sizeof(elf_ex)) != sizeof(elf_ex)) {
 356                 sys_close(fd);
 357                 return -EACCES;
 358         }
 359         set_fs(USER_DS);
 360         
 361         if (elf_ex.e_ident[0] != 0x7f ||
 362             strncmp(&elf_ex.e_ident[1], "ELF",3) != 0)
 363                 return -ENOEXEC;
 364         
 365         /* First of all, some simple consistency checks */
 366         if(elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 ||
 367            (elf_ex.e_machine != EM_386 && elf_ex.e_machine != EM_486) ||
 368            (!inode->i_op || !inode->i_op->bmap || 
 369             !inode->i_op->default_file_ops->mmap)){
 370                 return -ENOEXEC;
 371         };
 372         
 373         /* Now read in all of the header information */
 374         
 375         if(sizeof(struct elf_phdr) * elf_ex.e_phnum > PAGE_SIZE) 
 376                 return -ENOEXEC;
 377         
 378         elf_phdata =  (struct elf_phdr *) 
 379                 kmalloc(sizeof(struct elf_phdr) * elf_ex.e_phnum, GFP_KERNEL);
 380         
 381         old_fs = get_fs();
 382         set_fs(get_ds());
 383         retval = read_exec(inode, elf_ex.e_phoff, (char *) elf_phdata,
 384                            sizeof(struct elf_phdr) * elf_ex.e_phnum);
 385         set_fs(old_fs);
 386         
 387         j = 0;
 388         for(i=0; i<elf_ex.e_phnum; i++)
 389                 if((elf_phdata + i)->p_type == PT_LOAD) j++;
 390         
 391         if(j != 1)  {
 392                 kfree(elf_phdata);
 393                 return -ENOEXEC;
 394         };
 395         
 396         while(elf_phdata->p_type != PT_LOAD) elf_phdata++;
 397         
 398         /* Now use mmap to map the library into memory. */
 399         error = do_mmap(file,
 400                         elf_phdata->p_vaddr & 0xfffff000,
 401                         elf_phdata->p_filesz + (elf_phdata->p_vaddr & 0xfff),
 402                         PROT_READ | PROT_WRITE | PROT_EXEC,
 403                         MAP_FIXED | MAP_PRIVATE,
 404                         elf_phdata->p_offset & 0xfffff000);
 405 
 406         k = elf_phdata->p_vaddr + elf_phdata->p_filesz;
 407         if(k > elf_bss) elf_bss = k;
 408         
 409         sys_close(fd);
 410         if (error != elf_phdata->p_vaddr & 0xfffff000) {
 411                 kfree(elf_phdata);
 412                 return error;
 413         }
 414 
 415         padzero(elf_bss);
 416 
 417         len = (elf_phdata->p_filesz + elf_phdata->p_vaddr+ 0xfff) & 0xfffff000;
 418         bss = elf_phdata->p_memsz + elf_phdata->p_vaddr;
 419         if (bss > len)
 420           do_mmap(NULL, len, bss-len,
 421                   PROT_READ|PROT_WRITE|PROT_EXEC,
 422                   MAP_FIXED|MAP_PRIVATE, 0);
 423         kfree(elf_phdata);
 424         return 0;
 425 }

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