root/ibcs/binfmt_coff.c

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

DEFINITIONS

This source file includes following definitions.
  1. is_properly_aligned
  2. clear_memory
  3. load_object
  4. preload_this_library
  5. preload_library
  6. load_coff_binary
  7. load_coff_library

   1 /*
   2  * These are the functions used to load COFF IBSC style executables.
   3  * Information on COFF format may be obtained in either the Intel Binary
   4  * Compatibility Specification 2 or O'Rilley's book on COFF. The shared
   5  * libraries are defined only the in the Intel book.
   6  *
   7  * This file is based upon code written by Eric Youndale for the ELF object
   8  * file format.
   9  *
  10  * Author: Al Longyear (longyear@sii.com)
  11  *
  12  * Latest Revision:
  13  *    3 Feburary 1994
  14  *      Al Longyear (longyear@sii.com)
  15  *      Cleared first page of bss section using put_fs_byte.
  16  */
  17 
  18 #include <linux/fs.h>
  19 #include <linux/sched.h>
  20 #include <linux/mm.h>
  21 #include <linux/mman.h>
  22 #include <linux/a.out.h>
  23 #include <linux/errno.h>
  24 #include <linux/signal.h>
  25 #include <linux/binfmts.h>
  26 #include <asm/segment.h>
  27 #include <linux/string.h>
  28 #include <linux/fcntl.h>
  29 #include <linux/ptrace.h>
  30 #include <linux/coff.h>
  31 #include <linux/malloc.h>
  32 
  33 asmlinkage int sys_exit (int exit_code);
  34 asmlinkage int sys_close (unsigned fd);
  35 asmlinkage int sys_open (const char *, int, int);
  36 asmlinkage int sys_uselib(const char * library);
  37 
  38 static int preload_library (struct linux_binprm *exe_bprm,
  39                             COFF_SCNHDR * sect,
  40                             struct file *fp);
  41 
  42 static int load_object (struct linux_binprm *bprm,
  43                         struct pt_regs *regs,
  44                         int lib_ok);
  45 
  46 /*
  47  *  Small procedure to test for the proper file alignment.
  48  */
  49 
  50 static inline int
  51 is_properly_aligned (COFF_SCNHDR *sect)
     /* [previous][next][first][last][top][bottom][index][help] */
  52 {
  53     long scnptr = COFF_LONG (sect->s_scnptr);
  54     long vaddr  = COFF_LONG (sect->s_vaddr);
  55 /*
  56  *  Print the section information if needed
  57  */
  58 
  59 #ifdef COFF_DEBUG
  60     printk ("%s, scnptr = %d, vaddr = %d\n",
  61             sect->s_name,
  62             scnptr, vaddr);
  63 #endif
  64 
  65 /*
  66  *  Return the error code if the section is not properly aligned.
  67  */
  68 
  69 #ifdef COFF_DEBUG
  70     if (((vaddr - scnptr) & ~PAGE_MASK) != 0)
  71         printk ("bad alignment in %s\n", sect->s_name);
  72 #endif
  73     return ((((vaddr - scnptr) & ~PAGE_MASK) != 0) ? -ENOEXEC : 0);
  74 }
  75 
  76 /*
  77  *    Clear the bytes in the last page of data.
  78  */
  79 
  80 static
  81 int clear_memory (unsigned long addr, unsigned long size)
     /* [previous][next][first][last][top][bottom][index][help] */
  82 {
  83     int status;
  84 
  85     size = (PAGE_SIZE - (addr & ~PAGE_MASK)) & ~PAGE_MASK;
  86     if (size == 0)
  87         status = 0;
  88     else {
  89       
  90 #ifdef COFF_DEBUG
  91         printk ("un-initialized storage in last page %d\n", size);
  92 #endif
  93 
  94         status = verify_area (VERIFY_WRITE,
  95                               (void *) addr, size);
  96 #ifdef COFF_DEBUG
  97         printk ("result from verify_area = %d\n", status);
  98 #endif
  99 
 100         if (status >= 0)
 101             while (size-- != 0)
 102                 put_fs_byte (0, addr++);
 103     }
 104     return status;
 105 }
 106 
 107 /*
 108  *  Helper function to process the load operation.
 109  */
 110 
 111 static int
 112 load_object (struct linux_binprm * bprm, struct pt_regs *regs, int lib_ok)
     /* [previous][next][first][last][top][bottom][index][help] */
 113 {
 114     COFF_FILHDR  *coff_hdr = (COFF_FILHDR *) bprm->buf; /* COFF Header */
 115     COFF_SCNHDR  *sect_bufr;    /* Pointer to section table            */
 116     COFF_SCNHDR  *text_sect;    /* Pointer to the text section         */
 117     COFF_SCNHDR  *data_sect;    /* Pointer to the data section         */
 118     COFF_SCNHDR  *bss_sect;     /* Pointer to the bss section          */
 119     int text_count;             /* Number of text sections             */
 120     int data_count;             /* Number of data sections             */
 121     int bss_count;              /* Number of bss sections              */
 122     int lib_count;              /* Number of lib sections              */
 123     unsigned int start_addr = 0;/* Starting location for program       */
 124     int status = 0;             /* Result status register              */
 125     int fd = -1;                /* Open file descriptor                */
 126     struct file *fp     = NULL; /* Pointer to the file at "fd"         */
 127     short int sections  = 0;    /* Number of sections in the file      */
 128     short int aout_size = 0;    /* Size of the a.out header area       */
 129     short int flags;            /* Flag bits from the COFF header      */
 130 
 131 #ifdef COFF_DEBUG
 132     printk ("binfmt_coff entry: %s\n", bprm->filename);
 133 #endif
 134 
 135 /*
 136  *  Validate the magic value for the object file.
 137  */
 138     do {
 139         if (COFF_I386BADMAG (*coff_hdr)) {
 140 #ifdef COFF_DEBUG
 141             printk ("bad filehdr magic\n");
 142 #endif
 143             status = -ENOEXEC;
 144             break;
 145         }
 146 /*
 147  *  The object file should have 32 BIT little endian format. Do not allow
 148  *  it to have the 16 bit object file flag set as Linux is not able to run
 149  *  on the 80286/80186/8086.
 150  */
 151         flags = COFF_SHORT (coff_hdr->f_flags);
 152         if ((flags & (COFF_F_AR32WR | COFF_F_AR16WR)) != COFF_F_AR32WR) {
 153 #ifdef COFF_DEBUG
 154             printk ("invalid f_flags bits\n");
 155 #endif
 156             status = -ENOEXEC;
 157             break;
 158         }
 159 /*
 160  *  Extract the header information which we need.
 161  */
 162         sections  = COFF_SHORT (coff_hdr->f_nscns);   /* Number of sections */
 163         aout_size = COFF_SHORT (coff_hdr->f_opthdr);  /* Size of opt. headr */
 164 /*
 165  *  If the file is not executable then reject the exectution. This means
 166  *  that there must not be external references.
 167  */
 168         if ((flags & COFF_F_EXEC) == 0) {
 169 #ifdef COFF_DEBUG
 170             printk ("not executable bit\n");
 171 #endif
 172             status = -ENOEXEC;
 173             break;
 174         }
 175 /*
 176  *  There must be atleast one section.
 177  */
 178         if (sections == 0) {
 179 #ifdef COFF_DEBUG
 180             printk ("no sections\n");
 181 #endif
 182             status = -ENOEXEC;
 183             break;
 184         }
 185 /*
 186  *  Do some additional consistency checks.
 187  *  The system requires mapping for this loader. If you try
 188  *  to use a file system with no mapping, the format is not valid.
 189  */
 190         if (!bprm->inode->i_op ||
 191             !bprm->inode->i_op->default_file_ops->mmap) {
 192 #ifdef COFF_DEBUG
 193             printk ("no mmap in fs\n");
 194 #endif
 195             status = -ENOEXEC;
 196         }
 197     }
 198     while (0);
 199 /*
 200  *  Allocate a buffer to hold the entire coff section list.
 201  */
 202     if (status >= 0) {
 203         int nbytes = sections * COFF_SCNHSZ;
 204 
 205         sect_bufr = (COFF_SCNHDR *) kmalloc (nbytes, GFP_KERNEL);
 206         if (0 == sect_bufr) {
 207 #ifdef COFF_DEBUG
 208             printk ("kmalloc failed\n");
 209 #endif
 210             status = -ENOEXEC;
 211         }
 212 /*
 213  *  Read the section list from the disk file.
 214  */
 215         else {
 216              int old_fs = get_fs ();
 217              set_fs (get_ds ());  /* Make it point to the proper location    */
 218              status = read_exec (bprm->inode,        /* INODE for file       */
 219                             aout_size + COFF_FILHSZ, /* Offset in the file   */
 220                             (char *) sect_bufr,      /* Buffer for read      */
 221                             nbytes);                 /* Byte count reqd.     */
 222              set_fs (old_fs);                        /* Restore the selector */
 223 #ifdef COFF_DEBUG
 224              if (status < 0)
 225                 printk ("read aout hdr, status = %d\n", status);
 226 #endif
 227          }
 228     }
 229     else
 230         sect_bufr = NULL;       /* Errors do not have a section buffer */
 231 /*
 232  *  Count the number of sections for the required types and store the location
 233  *  of the last section for the three primary types.
 234  */
 235     text_count = 0;
 236     data_count = 0;
 237     bss_count  = 0;
 238     lib_count  = 0;
 239 
 240     text_sect = NULL;
 241     data_sect = NULL;
 242     bss_sect  = NULL;
 243 /*
 244  *  Loop through the sections and find the various types
 245  */
 246     if (status >= 0) {
 247         int nIndex;
 248         COFF_SCNHDR *sect_ptr = sect_bufr;
 249 
 250         for (nIndex = 0; nIndex < sections; ++nIndex) {
 251             long int sect_flags = COFF_LONG (sect_ptr->s_flags);
 252 
 253             switch (sect_flags) {
 254             case COFF_STYP_TEXT:
 255                 text_sect = sect_ptr;
 256                 ++text_count;
 257                 status = is_properly_aligned (sect_ptr);
 258                 break;
 259 
 260             case COFF_STYP_DATA:
 261                 data_sect = sect_ptr;
 262                 ++data_count;
 263                 status = is_properly_aligned (sect_ptr);
 264                 break;
 265 
 266             case COFF_STYP_BSS:
 267                 bss_sect = sect_ptr;
 268                 ++bss_count;
 269                 break;
 270 
 271             case COFF_STYP_LIB:
 272 #ifdef COFF_DEBUG
 273                 printk (".lib section found\n");
 274 #endif
 275                 ++lib_count;
 276                 break;
 277 
 278             default:
 279                 break;
 280             }
 281             sect_ptr = (COFF_SCNHDR *) & ((char *) sect_ptr)[COFF_SCNHSZ];
 282         }
 283 /*
 284  *  Ensure that there are the required sections. There must be one text
 285  *  sections and one each of the data and bss sections for an executable.
 286  *  A library may or may not have a data / bss section.
 287  */
 288         if (text_count != 1) {
 289             status = -ENOEXEC;
 290 #ifdef COFF_DEBUG
 291             printk ("no text sections\n");
 292 #endif
 293         }
 294         else {
 295             if (lib_ok) {
 296                 if (data_count != 1 || bss_count != 1) {
 297                     status = -ENOEXEC;
 298 #ifdef COFF_DEBUG
 299                     printk ("no .data nor .bss sections\n");
 300 #endif
 301                 }
 302             }
 303         }
 304     }
 305 /*
 306  *  If there is no additional header then assume the file starts at
 307  *  the first byte of the text section. This may not be the proper place,
 308  *  so the best solution is to include the optional header. A shared library
 309  *  __MUST__ have an optional header to indicate that it is a shared library.
 310  */
 311     if (status >= 0) {
 312         if (aout_size == 0) {
 313             if (!lib_ok) {
 314                 status = -ENOEXEC;
 315 #ifdef COFF_DEBUG
 316                 printk ("no header in library\n");
 317 #endif
 318             }
 319             start_addr = COFF_LONG (text_sect->s_vaddr);
 320         }
 321 /*
 322  *  There is some header. Ensure that it is sufficient.
 323  */
 324         else {
 325             if (aout_size < COFF_AOUTSZ) {
 326                 status = -ENOEXEC;
 327 #ifdef COFF_DEBUG
 328                 printk ("header too small\n");
 329 #endif
 330             }
 331             else {
 332                 COFF_AOUTHDR *aout_hdr =        /* Pointer to a.out header */
 333                 (COFF_AOUTHDR *) & ((char *) coff_hdr)[COFF_FILHSZ];
 334                 short int aout_magic = COFF_SHORT (aout_hdr->magic); /* id */
 335 /*
 336  *  Validate the magic number in the a.out header. If it is valid then
 337  *  update the starting symbol location. Do not accept these file formats
 338  *  when loading a shared library.
 339  */
 340                 switch (aout_magic) {
 341                 case COFF_OMAGIC:
 342                 case COFF_ZMAGIC:
 343                 case COFF_STMAGIC:
 344                     if (!lib_ok) {
 345                         status = -ENOEXEC;
 346 #ifdef COFF_DEBUG
 347                         printk ("wrong a.out header magic\n");
 348 #endif
 349                     }
 350                     start_addr = (unsigned int) COFF_LONG (aout_hdr->entry);
 351                     break;
 352 /*
 353  *  Magic value for a shared library. This is valid only when loading a
 354  *  shared library. (There is no need for a start_addr. It won't be used.)
 355  */
 356                 case COFF_SHMAGIC:
 357                     if (lib_ok) {
 358 #ifdef COFF_DEBUG
 359                         printk ("wrong a.out header magic\n");
 360 #endif
 361                         status = -ENOEXEC;
 362                     }
 363                     break;
 364 
 365                 default:
 366 #ifdef COFF_DEBUG
 367                     printk ("wrong a.out header magic\n");
 368 #endif
 369                     status = -ENOEXEC;
 370                     break;
 371                 }
 372             }
 373         }
 374     }
 375 /*
 376  *  Fetch a file pointer to the executable.
 377  */
 378     if (status >= 0) {
 379         fd = open_inode (bprm->inode, O_RDONLY);
 380         if (fd < 0) {
 381 #ifdef COFF_DEBUG
 382             printk ("can not open inode, result = %d\n", fd);
 383 #endif
 384             status = fd;
 385         }
 386         else
 387             fp = current->files->fd[fd];
 388     }
 389     else
 390         fd = -1;                /* Invalidate the open file descriptor */
 391 /*
 392  *  Generate the proper values for the text fields
 393  *
 394  *  THIS IS THE POINT OF NO RETURN. THE NEW PROCESS WILL TRAP OUT SHOULD
 395  *  SOMETHING FAIL IN THE LOAD SEQUENCE FROM THIS POINT ONWARD.
 396  */
 397     if (status >= 0) {
 398         long text_scnptr = COFF_LONG (text_sect->s_scnptr);
 399         long text_size   = COFF_LONG (text_sect->s_size);
 400         long text_vaddr  = COFF_LONG (text_sect->s_vaddr);
 401 
 402         long data_scnptr;
 403         long data_size;
 404         long data_vaddr;
 405 
 406         long bss_size;
 407         long bss_vaddr;
 408 /*
 409  *  Generate the proper values for the data fields
 410  */
 411         if (data_sect != NULL) {
 412             data_scnptr = COFF_LONG (data_sect->s_scnptr);
 413             data_size   = COFF_LONG (data_sect->s_size);
 414             data_vaddr  = COFF_LONG (data_sect->s_vaddr);
 415         }
 416         else {
 417             data_scnptr = 0;
 418             data_size   = 0;
 419             data_vaddr  = 0;
 420         }
 421 /*
 422  *  Generate the proper values for the bss fields
 423  */
 424         if (bss_sect != NULL) {
 425             bss_size  = COFF_LONG (bss_sect->s_size);
 426             bss_vaddr = COFF_LONG (bss_sect->s_vaddr);
 427         }
 428         else {
 429             bss_size  = 0;
 430             bss_vaddr = 0;
 431         }
 432 /*
 433  *  Flush the executable from memory. At this point the executable is
 434  *  committed to being defined or a segmentation violation will occur.
 435  */
 436         if (lib_ok) {
 437 #ifdef COFF_DEBUG
 438             printk ("flushing executable\n");
 439 #endif
 440             flush_old_exec (bprm);
 441 /*
 442  *  Define the initial locations for the various items in the new process
 443  */
 444             current->mm->mmap        = NULL;
 445             current->mm->rss         = 0;
 446 /*
 447  *  Construct the parameter and environment string table entries.
 448  */
 449             bprm->p += change_ldt (0, bprm->page);
 450             bprm->p -= MAX_ARG_PAGES*PAGE_SIZE;
 451             bprm->p  = (unsigned long) create_tables ((char *) bprm->p,
 452                                                       bprm->argc,
 453                                                       bprm->envc,
 454                                                       1);
 455 /*
 456  *  Do the end processing once the stack has been constructed
 457  */
 458             current->mm->start_code  = text_vaddr & PAGE_MASK;
 459             current->mm->end_code    = text_vaddr + text_size;
 460             current->mm->end_data    = data_vaddr + data_size;
 461             current->mm->start_brk   =
 462             current->mm->brk         = bss_vaddr + bss_size;
 463             current->suid            =
 464             current->euid            = bprm->e_uid;
 465             current->sgid            =
 466             current->egid            = bprm->e_gid;
 467             current->executable      = bprm->inode; /* Store inode for file  */
 468             ++bprm->inode->i_count;             /* Count the open inode  */
 469             regs->eip                = start_addr;  /* Current EIP register  */
 470             regs->esp                =
 471             current->mm->start_stack = bprm->p;
 472         }
 473 /*
 474  *   Map the text pages
 475  */
 476 
 477 #ifdef COFF_DEBUG
 478         printk (".text: vaddr = %d, size = %d, scnptr = %d\n",
 479                  text_vaddr,
 480                  text_size,
 481                  text_scnptr);
 482 #endif
 483         status = do_mmap (fp,
 484                           text_vaddr & PAGE_MASK,
 485                           text_size + (text_vaddr & ~PAGE_MASK),
 486                           PROT_READ | PROT_EXEC,
 487                           MAP_FIXED | MAP_SHARED,
 488                           text_scnptr & PAGE_MASK);
 489 
 490         status = (status == (text_vaddr & PAGE_MASK)) ? 0 : -ENOEXEC;
 491 /*
 492  *   Map the data pages
 493  */
 494         if (status >= 0 && data_size != 0) {
 495 #ifdef COFF_DEBUG
 496             printk (".data: vaddr = %d, size = %d, scnptr = %d\n",
 497                      data_vaddr,
 498                      data_size,
 499                      data_scnptr);
 500 #endif
 501             status = do_mmap (fp,
 502                               data_vaddr & PAGE_MASK,
 503                               data_size + (data_vaddr & ~PAGE_MASK),
 504                               PROT_READ | PROT_WRITE | PROT_EXEC,
 505                               MAP_FIXED | MAP_PRIVATE,
 506                               data_scnptr & PAGE_MASK);
 507 
 508             status = (status == (data_vaddr & PAGE_MASK)) ? 0 : -ENOEXEC;
 509         }
 510 /*
 511  *   Construct the bss data for the process. The bss ranges from the
 512  *   end of the data (which may not be on a page boundry) to the end
 513  *   of the bss section. Allocate any necessary pages for the data.
 514  */
 515         if (status >= 0 && bss_size != 0) {
 516 #ifdef COFF_DEBUG
 517             printk (".bss: vaddr = %d, size = %d\n",
 518                      bss_vaddr,
 519                      bss_size);
 520 #endif
 521             zeromap_page_range (PAGE_ALIGN (bss_vaddr),
 522                                 PAGE_ALIGN (bss_size),
 523                                 PAGE_COPY);
 524 
 525             status = clear_memory (bss_vaddr, bss_size);
 526         }
 527 /*
 528  *  Load any shared library for the executable.
 529  */
 530         if (status >= 0 && lib_ok && lib_count != 0) {
 531             int nIndex;
 532             COFF_SCNHDR *sect_ptr = sect_bufr;
 533 /*
 534  *  Find the library sections. (There should be atleast one. It was counted
 535  *  earlier.) This will evenutally recurse to our code and load the shared
 536  *  library with our own procedures.
 537  */
 538             for (nIndex = 0; nIndex < sections; ++nIndex) {
 539                 long int sect_flags = COFF_LONG (sect_ptr->s_flags);
 540                 if (sect_flags == COFF_STYP_LIB) {
 541                     status = preload_library (bprm, sect_ptr, fp);
 542                     if (status != 0)
 543                         break;
 544                 }
 545             sect_ptr = (COFF_SCNHDR *) &((char *) sect_ptr) [COFF_SCNHSZ];
 546             }
 547         }
 548 /*
 549  *   Generate any needed trap for this process. If an error occured then
 550  *   generate a segmentation violation. If the process is being debugged
 551  *   then generate the load trap. (Note: If this is a library load then
 552  *   do not generate the trap here. Pass the error to the caller who
 553  *   will do it for the process in the outer lay of this procedure call.)
 554  */
 555         if (lib_ok) {
 556             if (status < 0)
 557                 send_sig (SIGSEGV, current, 0); /* Generate the error trap  */
 558             else {
 559                 if (current->flags & PF_PTRACED)
 560                     send_sig (SIGTRAP, current, 0);
 561             }
 562             status = 0;         /* We are committed. It can't fail */
 563         }
 564     }
 565 /*
 566  *  Do any cleanup processing
 567  */
 568     if (fd >= 0)
 569         sys_close (fd);         /* Close unused code file      */
 570 
 571     if (sect_bufr != NULL)
 572         kfree (sect_bufr);      /* Release section list buffer */
 573 /*
 574  *  Return the completion status.
 575  */
 576 #ifdef COFF_DEBUG
 577     printk ("binfmt_coff: result = %d\n", status);
 578 #endif
 579     return (status);
 580 }
 581 
 582 /*
 583  *  This procedure will load the library listed in the file name given
 584  *  as the paramter. The result will be non-zero should something fail
 585  *  to load.
 586  */
 587 
 588 static int
 589 preload_this_library (struct linux_binprm *exe_bprm, char *lib_name)
     /* [previous][next][first][last][top][bottom][index][help] */
 590 {
 591     int   status;
 592     int   old_fs = get_fs();
 593 /*
 594  *  If debugging then print "we have arrived"
 595  */
 596 #ifdef COFF_DEBUG
 597     printk ("%s loading shared library %s\n",
 598             exe_bprm->filename,
 599             lib_name);
 600 #endif
 601 /*
 602  *  Change the FS register to the proper kernel address space and attempt
 603  *  to load the library. The library name is allocated from the kernel
 604  *  pool.
 605  */
 606     set_fs (get_ds ());
 607     status = sys_uselib (lib_name);
 608     set_fs (old_fs);
 609 /*
 610  *  Return the success/failure to the caller.
 611  */
 612     return (status);
 613 }
 614 
 615 /*
 616  *  This procedure is called to load a library section. The various
 617  *  libraries are loaded from the list given in the section data.
 618  */
 619 
 620 static int
 621 preload_library (struct linux_binprm *exe_bprm,
     /* [previous][next][first][last][top][bottom][index][help] */
 622                  COFF_SCNHDR * sect, struct file *fp)
 623 {
 624     int status = 0;             /* Completion status                  */
 625     long nbytes;                /* Count of bytes in the header area  */
 626 /*
 627  *  Fetch the size of the section. There must be enough room for atleast
 628  *  one entry.
 629  */
 630     nbytes = COFF_LONG (sect->s_size);
 631     if (nbytes < COFF_SLIBSZ) {
 632         status = -ENOEXEC;
 633 #ifdef COFF_DEBUG
 634         printk ("library section too small\n");
 635 #endif
 636     }
 637 /*
 638  *  Allocate a buffer to hold the section data
 639  */
 640     else {
 641         COFF_SLIBHD *phdr;
 642         char *buffer = (char *) kmalloc (nbytes, GFP_KERNEL);
 643 
 644         if (0 == buffer) {
 645             status = -ENOEXEC;
 646 #ifdef COFF_DEBUG
 647             printk ("kmalloc failed\n");
 648 #endif
 649         }
 650         else {
 651             int old_fs   = get_fs ();
 652 /*
 653  *  Read the section data from the disk file.
 654  */
 655             set_fs (get_ds ());   /* Make it point to the proper location    */
 656             status = read_exec (exe_bprm->inode,     /* INODE for file       */
 657                             COFF_LONG (sect->s_scnptr), /* Disk location     */
 658                             buffer,                     /* Buffer for read   */
 659                             nbytes);                    /* Byte count reqd.  */
 660             set_fs (old_fs);                         /* Restore the selector */
 661 /*
 662  *  Check the result. The value returned is the byte count actaully read.
 663  */
 664             if (status >= 0 && status != nbytes) {
 665 #ifdef COFF_DEBUG
 666                 printk ("read of lib section was short\n");
 667 #endif
 668                 status = -ENOEXEC;
 669             }
 670         }
 671 /*
 672  *  At this point, go through the list of libraries in the data area.
 673  */
 674         phdr = (COFF_SLIBHD *) buffer;
 675         while (status >= 0 && nbytes > COFF_SLIBSZ) {
 676             int entry_size  = COFF_LONG (phdr->sl_entsz)   * sizeof (long);
 677             int header_size = COFF_LONG (phdr->sl_pathndx) * sizeof (long);
 678 /*
 679  *  Validate the sizes of the various items. I don't trust the linker!!
 680  */
 681             if ((unsigned) header_size >= (unsigned) nbytes ||
 682                 entry_size <= 0 ||
 683                 (unsigned) entry_size <= (unsigned) header_size) {
 684                 status = -ENOEXEC;
 685 #ifdef COFF_DEBUG
 686                 printk ("header count is invalid\n");
 687 #endif
 688             }
 689 /*
 690  *  Load the library. Stop the load process on the first error.
 691  */
 692             else {
 693                 status = preload_this_library (exe_bprm,
 694                                                &((char *) phdr)[header_size]);
 695 #ifdef COFF_DEBUG
 696                 printk ("preload_this_library result = %d\n", status);
 697 #endif
 698             }
 699 /*
 700  *  Point to the next library in the section data.
 701  */
 702             nbytes -= entry_size;
 703             phdr = (COFF_SLIBHD *) &((char *) phdr)[entry_size];
 704         }
 705 /*
 706  *  Release the space for the library list.
 707  */
 708         if (buffer != NULL)
 709             kfree (buffer);
 710     }
 711 /*
 712  *  Return the resulting status to the caller.
 713  */
 714     return (status);
 715 }
 716 
 717 /*
 718  *  This procedure is called by the main load sequence. It will load
 719  *  the executable and prepare it for execution. It provides the additional
 720  *  parameters used by the recursive coff loader and tells the loader that
 721  *  this is the main executable. How simple it is . . . .
 722  */
 723 
 724 int
 725 load_coff_binary (struct linux_binprm *bprm, struct pt_regs *regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 726 {
 727     return (load_object (bprm, regs, 1));
 728 }
 729 
 730 /*
 731  *   Load the image for any shared library.
 732  *
 733  *   This is called when we need to load a library based upon a file name.
 734  */
 735 
 736 int
 737 load_coff_library (int fd)
     /* [previous][next][first][last][top][bottom][index][help] */
 738 {
 739     struct linux_binprm *bprm;  /* Parameters for the load operation   */
 740     int    status;              /* Status of the request               */
 741 /*
 742  *  Read the first portion of the file.
 743  */
 744     bprm = (struct linux_binprm *) kmalloc (sizeof (struct linux_binprm),
 745                                             GFP_KERNEL);
 746     if (0 == bprm) {
 747 #ifdef COFF_DEBUG
 748         printk ("kmalloc failed\n");
 749 #endif
 750         status = -ENOEXEC;
 751     }
 752     else {
 753         struct file         *file;  /* Pointer to the file table           */
 754         struct pt_regs       regs;  /* Register work area                  */
 755         int old_fs = get_fs ();     /* Previous FS register value          */
 756 
 757         memset (bprm, '\0', sizeof (struct linux_binprm));
 758 
 759         file           = current->files->fd[fd];
 760         bprm->inode    = file->f_inode;   /* The only item _really_ needed */
 761         bprm->filename = "";              /* Make it a legal string        */
 762 /*
 763  *  Read the section list from the disk file.
 764  */
 765         set_fs (get_ds ());   /* Make it point to the proper location    */
 766         status = read_exec (bprm->inode,         /* INODE for file       */
 767                             0L,                  /* Offset in the file   */
 768                             bprm->buf,           /* Buffer for read      */
 769                             sizeof (bprm->buf)); /* Size of the buffer   */
 770         set_fs (old_fs);                         /* Restore the selector */
 771 /*
 772  *  Try to load the library.
 773  */
 774         status = load_object (bprm, &regs, 0);
 775 /*
 776  *  Release the work buffer and return the result.
 777  */
 778         kfree (bprm);                 /* Release the buffer area */
 779     }
 780 /*
 781  *  Return the result of the load operation
 782  */
 783     return (status);
 784 }

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