📄 binfmt_coff.c
字号:
* THIS IS THE POINT OF NO RETURN. THE NEW PROCESS WILL TRAP OUT SHOULD * SOMETHING FAIL IN THE LOAD SEQUENCE FROM THIS POINT ONWARD. */ if (status >= 0) { long text_scnptr = COFF_LONG (text_sect->s_scnptr); long text_size = COFF_LONG (text_sect->s_size); long text_vaddr = COFF_LONG (text_sect->s_vaddr); long data_scnptr; long data_size; long data_vaddr; long bss_size; long bss_vaddr;/* * Generate the proper values for the data fields */ if (data_sect != NULL) { data_scnptr = COFF_LONG (data_sect->s_scnptr); data_size = COFF_LONG (data_sect->s_size); data_vaddr = COFF_LONG (data_sect->s_vaddr); } else { data_scnptr = 0; data_size = 0; data_vaddr = 0; }/* * Generate the proper values for the bss fields */ if (bss_sect != NULL) { bss_size = COFF_LONG (bss_sect->s_size); bss_vaddr = COFF_LONG (bss_sect->s_vaddr); } else { bss_size = 0; bss_vaddr = 0; }/* * Flush the executable from memory. At this point the executable is * committed to being defined or a segmentation violation will occur. */ if (lib_ok) {#ifdef COFF_DEBUG printk ("flushing executable\n");#endif flush_old_exec (bprm);/* * Define the initial locations for the various items in the new process */ current->mmap = NULL; current->rss = 0;/* * Construct the parameter and environment string table entries. */ bprm->p += change_ldt (0, bprm->page); bprm->p -= MAX_ARG_PAGES*PAGE_SIZE; bprm->p = (unsigned long) create_tables ((char *) bprm->p, bprm->argc, bprm->envc, 1);/* * Do the end processing once the stack has been constructed */ current->start_code = text_vaddr & PAGE_MASK; current->end_code = text_vaddr + text_size; current->end_data = data_vaddr + data_size; current->start_brk = current->brk = bss_vaddr + bss_size; current->suid = current->euid = bprm->e_uid; current->sgid = current->egid = bprm->e_gid; current->executable = bprm->inode; /* Store inode for file */ ++bprm->inode->i_count; /* Count the open inode */ regs->eip = start_addr; /* Current EIP register */ regs->esp = current->start_stack = bprm->p; }/* * Map the text pages */#ifdef COFF_DEBUG printk (".text: vaddr = %d, size = %d, scnptr = %d\n", text_vaddr, text_size, text_scnptr);#endif status = do_mmap (fp, text_vaddr & PAGE_MASK, text_size + (text_vaddr & ~PAGE_MASK), PROT_READ | PROT_EXEC, MAP_FIXED | MAP_SHARED, text_scnptr & PAGE_MASK); status = (status == (text_vaddr & PAGE_MASK)) ? 0 : -ENOEXEC;/* * Map the data pages */ if (status >= 0 && data_size != 0) {#ifdef COFF_DEBUG printk (".data: vaddr = %d, size = %d, scnptr = %d\n", data_vaddr, data_size, data_scnptr);#endif status = do_mmap (fp, data_vaddr & PAGE_MASK, data_size + (data_vaddr & ~PAGE_MASK), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, data_scnptr & PAGE_MASK); status = (status == (data_vaddr & PAGE_MASK)) ? 0 : -ENOEXEC; }/* * Construct the bss data for the process. The bss ranges from the * end of the data (which may not be on a page boundry) to the end * of the bss section. Allocate any necessary pages for the data. */ if (status >= 0 && bss_size != 0) {#ifdef COFF_DEBUG printk (".bss: vaddr = %d, size = %d\n", bss_vaddr, bss_size);#endif zeromap_page_range (PAGE_ALIGN (bss_vaddr), PAGE_ALIGN (bss_size), PAGE_COPY); status = clear_memory (bss_vaddr, bss_size); }/* * Load any shared library for the executable. */ if (status >= 0 && lib_ok && lib_count != 0) { int nIndex; COFF_SCNHDR *sect_ptr = sect_bufr;/* * Find the library sections. (There should be atleast one. It was counted * earlier.) This will evenutally recurse to our code and load the shared * library with our own procedures. */ for (nIndex = 0; nIndex < sections; ++nIndex) { long int sect_flags = COFF_LONG (sect_ptr->s_flags); if (sect_flags == COFF_STYP_LIB) { status = preload_library (bprm, sect_ptr, fp); if (status != 0) break; } sect_ptr = (COFF_SCNHDR *) &((char *) sect_ptr) [COFF_SCNHSZ]; } }/* * Generate any needed trap for this process. If an error occured then * generate a segmentation violation. If the process is being debugged * then generate the load trap. (Note: If this is a library load then * do not generate the trap here. Pass the error to the caller who * will do it for the process in the outer lay of this procedure call.) */ if (lib_ok) { if (status < 0) send_sig (SIGSEGV, current, 0); /* Generate the error trap */ else { if (current->flags & PF_PTRACED) send_sig (SIGTRAP, current, 0); } status = 0; /* We are committed. It can't fail */ } }/* * Do any cleanup processing */ if (fd >= 0) sys_close (fd); /* Close unused code file */ if (sect_bufr != NULL) kfree (sect_bufr); /* Release section list buffer *//* * Return the completion status. */#ifdef COFF_DEBUG printk ("binfmt_coff: result = %d\n", status);#endif return (status);}/* * This procedure will load the library listed in the file name given * as the paramter. The result will be non-zero should something fail * to load. */static intpreload_this_library (struct linux_binprm *exe_bprm, char *lib_name){ int status; int old_fs = get_fs();/* * If debugging then print "we have arrived" */#ifdef COFF_DEBUG printk ("%s loading shared library %s\n", exe_bprm->filename, lib_name);#endif/* * Change the FS register to the proper kernel address space and attempt * to load the library. The library name is allocated from the kernel * pool. */ set_fs (get_ds ()); status = sys_uselib (lib_name); set_fs (old_fs);/* * Return the success/failure to the caller. */ return (status);}/* * This procedure is called to load a library section. The various * libraries are loaded from the list given in the section data. */static intpreload_library (struct linux_binprm *exe_bprm, COFF_SCNHDR * sect, struct file *fp){ int status = 0; /* Completion status */ long nbytes; /* Count of bytes in the header area *//* * Fetch the size of the section. There must be enough room for atleast * one entry. */ nbytes = COFF_LONG (sect->s_size); if (nbytes < COFF_SLIBSZ) { status = -ENOEXEC;#ifdef COFF_DEBUG printk ("library section too small\n");#endif }/* * Allocate a buffer to hold the section data */ else { COFF_SLIBHD *phdr; char *buffer = (char *) kmalloc (nbytes, GFP_KERNEL); if (0 == buffer) { status = -ENOEXEC;#ifdef COFF_DEBUG printk ("kmalloc failed\n");#endif } else { int old_fs = get_fs ();/* * Read the section data from the disk file. */ set_fs (get_ds ()); /* Make it point to the proper location */ status = read_exec (exe_bprm->inode, /* INODE for file */ COFF_LONG (sect->s_scnptr), /* Disk location */ buffer, /* Buffer for read */ nbytes); /* Byte count reqd. */ set_fs (old_fs); /* Restore the selector *//* * Check the result. The value returned is the byte count actaully read. */ if (status >= 0 && status != nbytes) {#ifdef COFF_DEBUG printk ("read of lib section was short\n");#endif status = -ENOEXEC; } }/* * At this point, go through the list of libraries in the data area. */ phdr = (COFF_SLIBHD *) buffer; while (status >= 0 && nbytes > COFF_SLIBSZ) { int entry_size = COFF_LONG (phdr->sl_entsz) * sizeof (long); int header_size = COFF_LONG (phdr->sl_pathndx) * sizeof (long);/* * Validate the sizes of the various items. I don't trust the linker!! */ if ((unsigned) header_size >= (unsigned) nbytes || entry_size <= 0 || (unsigned) entry_size <= (unsigned) header_size) { status = -ENOEXEC;#ifdef COFF_DEBUG printk ("header count is invalid\n");#endif }/* * Load the library. Stop the load process on the first error. */ else { status = preload_this_library (exe_bprm, &((char *) phdr)[header_size]);#ifdef COFF_DEBUG printk ("preload_this_library result = %d\n", status);#endif }/* * Point to the next library in the section data. */ nbytes -= entry_size; phdr = (COFF_SLIBHD *) &((char *) phdr)[entry_size]; }/* * Release the space for the library list. */ if (buffer != NULL) kfree (buffer); }/* * Return the resulting status to the caller. */ return (status);}/* * This procedure is called by the main load sequence. It will load * the executable and prepare it for execution. It provides the additional * parameters used by the recursive coff loader and tells the loader that * this is the main executable. How simple it is . . . . */intload_coff_binary (struct linux_binprm *bprm, struct pt_regs *regs){ return (load_object (bprm, regs, 1));}/* * Load the image for any shared library. * * This is called when we need to load a library based upon a file name. */intload_coff_library (int fd){ struct linux_binprm *bprm; /* Parameters for the load operation */ int status; /* Status of the request *//* * Read the first portion of the file. */ bprm = (struct linux_binprm *) kmalloc (sizeof (struct linux_binprm), GFP_KERNEL); if (0 == bprm) {#ifdef COFF_DEBUG printk ("kmalloc failed\n");#endif status = -ENOEXEC; } else { struct file *file; /* Pointer to the file table */ struct pt_regs regs; /* Register work area */ int old_fs = get_fs (); /* Previous FS register value */ memset (bprm, '\0', sizeof (struct linux_binprm)); file = current->filp[fd]; bprm->inode = file->f_inode; /* The only item _really_ needed */ bprm->filename = ""; /* Make it a legal string *//* * Read the section list from the disk file. */ set_fs (get_ds ()); /* Make it point to the proper location */ status = read_exec (bprm->inode, /* INODE for file */ 0L, /* Offset in the file */ bprm->buf, /* Buffer for read */ sizeof (bprm->buf)); /* Size of the buffer */ set_fs (old_fs); /* Restore the selector *//* * Try to load the library. */ status = load_object (bprm, ®s, 0);/* * Release the work buffer and return the result. */ kfree (bprm); /* Release the buffer area */ }/* * Return the result of the load operation */ return (status);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -