diff -u --recursive --new-file v1.1.13/linux/Makefile linux/Makefile --- v1.1.13/linux/Makefile Tue May 24 00:34:45 1994 +++ linux/Makefile Mon May 23 23:42:47 1994 @@ -1,6 +1,6 @@ VERSION = 1 PATCHLEVEL = 1 -SUBLEVEL = 13 +SUBLEVEL = 14 all: Version zImage diff -u --recursive --new-file v1.1.13/linux/config.in linux/config.in --- v1.1.13/linux/config.in Tue May 24 00:34:45 1994 +++ linux/config.in Tue May 24 00:58:23 1994 @@ -17,7 +17,9 @@ comment 'Networking options' bool 'TCP/IP networking' CONFIG_INET y if [ "$CONFIG_INET" "=" "y" ]; then +bool 'IP forwarding/gatewaying' CONFIG_IP_FORWARD n comment '(it is safe to leave these untouched)' +bool 'PC/TCP compatibility mode' CONFIG_INET_PCTCP n bool 'Reverse ARP' CONFIG_INET_RARP n bool 'Assume subnets are local' CONFIG_INET_SNARL y bool 'Disable NAGLE algorithm (normally enabled)' CONFIG_TCP_NAGLE_OFF n @@ -26,11 +28,6 @@ #bool 'Amateur Radio AX.25 Level 2' CONFIG_AX25 n fi -comment 'Program binary formats' - -bool 'Elf executables' CONFIG_BINFMT_ELF y -bool 'COFF executables' CONFIG_BINFMT_COFF y - comment 'SCSI support' bool 'SCSI support?' CONFIG_SCSI n @@ -78,7 +75,7 @@ bool ' CSLIP compressed headers' SL_COMPRESSED y # bool ' SLIP debugging on' SL_DUMP y fi -#bool 'PPP (point-to-point) support' CONFIG_PPP n +bool 'PPP (point-to-point) support' CONFIG_PPP n bool 'Load balancing support (very experimental)' CONFIG_SLAVE_BALANCING n bool 'PLIP (parallel port) support' CONFIG_PLIP n bool 'NE2000/NE1000 support' CONFIG_NE2000 n diff -u --recursive --new-file v1.1.13/linux/drivers/block/mcd.c linux/drivers/block/mcd.c --- v1.1.13/linux/drivers/block/mcd.c Wed Apr 6 11:18:19 1994 +++ linux/drivers/block/mcd.c Mon May 23 21:52:32 1994 @@ -881,9 +881,9 @@ /* don't get the IRQ until we know for sure the drive is there */ - if (irqaction(MCD_INTR_NR, &mcd_sigaction)) + if (irqaction(mcd_irq, &mcd_sigaction)) { - printk("mcd: Unable to get IRQ%d for Mitsumi CD-ROM\n", MCD_INTR_NR); + printk("mcd: Unable to get IRQ%d for Mitsumi CD-ROM\n", mcd_irq); return mem_start; } snarf_region(mcd_port, 4); diff -u --recursive --new-file v1.1.13/linux/drivers/block/sbpcd.c linux/drivers/block/sbpcd.c --- v1.1.13/linux/drivers/block/sbpcd.c Wed Apr 27 09:46:06 1994 +++ linux/drivers/block/sbpcd.c Mon May 23 22:50:22 1994 @@ -123,7 +123,6 @@ #include #endif SBPCD_USE_IRQ -#include #include #include @@ -141,6 +140,11 @@ #ifndef CONFIG_ISO9660_FS #error "SBPCD: \"make config\" again. File system iso9660 is necessary." #endif + +/* + * This may come back some day.. + */ +#define DDIOCSDBG 0x9000 /* * still testing around... diff -u --recursive --new-file v1.1.13/linux/fs/Makefile linux/fs/Makefile --- v1.1.13/linux/fs/Makefile Tue Dec 21 12:30:23 1993 +++ linux/fs/Makefile Mon May 23 22:56:31 1994 @@ -40,13 +40,6 @@ FS_SUBDIRS := $(FS_SUBDIRS) hpfs endif -ifdef CONFIG_BINFMT_ELF -BINFMTS := $(BINFMTS) binfmt_elf.o -endif -ifdef CONFIG_BINFMT_COFF -BINFMTS := $(BINFMTS) binfmt_coff.o -endif - .c.s: $(CC) $(CFLAGS) -S $< .c.o: Only in v1.1.13/linux/fs: binfmt_coff.c Only in v1.1.13/linux/fs: binfmt_elf.c diff -u --recursive --new-file v1.1.13/linux/fs/exec.c linux/fs/exec.c --- v1.1.13/linux/fs/exec.c Sat May 7 14:54:05 1994 +++ linux/fs/exec.c Tue May 24 00:20:59 1994 @@ -53,6 +53,47 @@ extern void shm_exit (void); +static int load_aout_binary(struct linux_binprm *, struct pt_regs * regs); +static int load_aout_library(int fd); + +/* + * Here are the actual binaries that will be accepted: + * add more with "register_binfmt()".. + */ +static struct linux_binfmt aout_format = { NULL, load_aout_binary, load_aout_library }; +static struct linux_binfmt *formats = &aout_format; + +int register_binfmt(struct linux_binfmt * fmt) +{ + struct linux_binfmt ** tmp = &formats; + + if (!fmt) + return -EINVAL; + if (fmt->next) + return -EBUSY; + while (*tmp) { + if (fmt == *tmp) + return -EBUSY; + tmp = &(*tmp)->next; + } + *tmp = fmt; + return 0; +} + +int unregister_binfmt(struct linux_binfmt * fmt) +{ + struct linux_binfmt ** tmp = &formats; + + while (*tmp) { + if (fmt == *tmp) { + *tmp = fmt->next; + return 0; + } + tmp = &(*tmp)->next; + } + return -EINVAL; +} + int open_inode(struct inode * inode, int mode) { int error, fd; @@ -247,14 +288,14 @@ file = current->files->fd[fd]; retval = -ENOEXEC; if (file && file->f_inode && file->f_op && file->f_op->read) { - fmt = formats; - do { + for (fmt = formats ; fmt ; fmt = fmt->next) { int (*fn)(int) = fmt->load_shlib; if (!fn) break; retval = fn(fd); - fmt++; - } while (retval == -ENOEXEC); + if (retval != -ENOEXEC) + break; + } } sys_close(fd); return retval; @@ -530,13 +571,13 @@ if (last_task_used_math == current) last_task_used_math = NULL; current->used_math = 0; - current->elf_executable = 0; + current->personality = 0; } /* * sys_execve() executes a new program. */ -static int do_execve(char * filename, char ** argv, char ** envp, struct pt_regs * regs) +int do_execve(char * filename, char ** argv, char ** envp, struct pt_regs * regs) { struct linux_binprm bprm; struct linux_binfmt * fmt; @@ -684,8 +725,7 @@ } bprm.sh_bang = sh_bang; - fmt = formats; - do { + for (fmt = formats ; fmt ; fmt = fmt->next) { int (*fn)(struct linux_binprm *, struct pt_regs *) = fmt->load_binary; if (!fn) break; @@ -695,8 +735,9 @@ current->did_exec = 1; return 0; } - fmt++; - } while (retval == -ENOEXEC); + if (retval != -ENOEXEC) + break; + } exec_error2: iput(bprm.inode); exec_error1: @@ -721,39 +762,6 @@ return error; } -/* - * These are the prototypes for the functions in the dispatch table, as - * well as the dispatch table itself. - */ - -extern int load_aout_binary(struct linux_binprm *, - struct pt_regs * regs); -extern int load_aout_library(int fd); - -#ifdef CONFIG_BINFMT_ELF -extern int load_elf_binary(struct linux_binprm *, - struct pt_regs * regs); -extern int load_elf_library(int fd); -#endif - -#ifdef CONFIG_BINFMT_COFF -extern int load_coff_binary(struct linux_binprm *, - struct pt_regs * regs); -extern int load_coff_library(int fd); -#endif - -/* Here are the actual binaries that will be accepted */ -struct linux_binfmt formats[] = { - {load_aout_binary, load_aout_library}, -#ifdef CONFIG_BINFMT_ELF - {load_elf_binary, load_elf_library}, -#endif -#ifdef CONFIG_BINFMT_COFF - {load_coff_binary, load_coff_library}, -#endif - {NULL, NULL} -}; - static void set_brk(unsigned long start, unsigned long end) { start = PAGE_ALIGN(start); @@ -770,7 +778,7 @@ * libraries. There is no binary dependent code anywhere else. */ -int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) +static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) { struct exec ex; struct file * file; @@ -868,7 +876,7 @@ } -int load_aout_library(int fd) +static int load_aout_library(int fd) { struct file * file; struct exec ex; diff -u --recursive --new-file v1.1.13/linux/fs/proc/net.c linux/fs/proc/net.c --- v1.1.13/linux/fs/proc/net.c Tue May 24 00:34:54 1994 +++ linux/fs/proc/net.c Mon May 23 21:41:47 1994 @@ -280,6 +280,8 @@ * the start pointer and we know the length.. */ + if (length <= 0) + break; /* * Copy the bytes */ diff -u --recursive --new-file v1.1.13/linux/fs/select.c linux/fs/select.c --- v1.1.13/linux/fs/select.c Sat May 7 14:54:11 1994 +++ linux/fs/select.c Mon May 23 23:45:34 1994 @@ -3,6 +3,11 @@ * * Created for Linux based loosely upon Mathius Lattner's minix * patches by Peter MacDonald. Heavily edited by Linus. + * + * 4 February 1994 + * COFF/ELF binary emulation. If the process has the STICKY_TIMEOUTS + * flag set in its personality we do *not* modify the given timeout + * parameter to reflect time remaining. */ #include @@ -14,6 +19,7 @@ #include #include #include +#include #include #include @@ -235,7 +241,7 @@ else timeout = 0; current->timeout = 0; - if (tvp) { + if (tvp && !(current->personality & STICKY_TIMEOUTS)) { put_fs_long(timeout/HZ, (unsigned long *) &tvp->tv_sec); timeout %= HZ; timeout *= (1000000/HZ); diff -u --recursive --new-file v1.1.13/linux/ibcs/binfmt_coff.c linux/ibcs/binfmt_coff.c --- v1.1.13/linux/ibcs/binfmt_coff.c Thu Jan 1 02:00:00 1970 +++ linux/ibcs/binfmt_coff.c Tue May 24 00:27:49 1994 @@ -0,0 +1,784 @@ +/* + * These are the functions used to load COFF IBSC style executables. + * Information on COFF format may be obtained in either the Intel Binary + * Compatibility Specification 2 or O'Rilley's book on COFF. The shared + * libraries are defined only the in the Intel book. + * + * This file is based upon code written by Eric Youndale for the ELF object + * file format. + * + * Author: Al Longyear (longyear@sii.com) + * + * Latest Revision: + * 3 Feburary 1994 + * Al Longyear (longyear@sii.com) + * Cleared first page of bss section using put_fs_byte. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +asmlinkage int sys_exit (int exit_code); +asmlinkage int sys_close (unsigned fd); +asmlinkage int sys_open (const char *, int, int); +asmlinkage int sys_uselib(const char * library); + +static int preload_library (struct linux_binprm *exe_bprm, + COFF_SCNHDR * sect, + struct file *fp); + +static int load_object (struct linux_binprm *bprm, + struct pt_regs *regs, + int lib_ok); + +/* + * Small procedure to test for the proper file alignment. + */ + +static inline int +is_properly_aligned (COFF_SCNHDR *sect) +{ + long scnptr = COFF_LONG (sect->s_scnptr); + long vaddr = COFF_LONG (sect->s_vaddr); +/* + * Print the section information if needed + */ + +#ifdef COFF_DEBUG + printk ("%s, scnptr = %d, vaddr = %d\n", + sect->s_name, + scnptr, vaddr); +#endif + +/* + * Return the error code if the section is not properly aligned. + */ + +#ifdef COFF_DEBUG + if (((vaddr - scnptr) & ~PAGE_MASK) != 0) + printk ("bad alignment in %s\n", sect->s_name); +#endif + return ((((vaddr - scnptr) & ~PAGE_MASK) != 0) ? -ENOEXEC : 0); +} + +/* + * Clear the bytes in the last page of data. + */ + +static +int clear_memory (unsigned long addr, unsigned long size) +{ + int status; + + size = (PAGE_SIZE - (addr & ~PAGE_MASK)) & ~PAGE_MASK; + if (size == 0) + status = 0; + else { + +#ifdef COFF_DEBUG + printk ("un-initialized storage in last page %d\n", size); +#endif + + status = verify_area (VERIFY_WRITE, + (void *) addr, size); +#ifdef COFF_DEBUG + printk ("result from verify_area = %d\n", status); +#endif + + if (status >= 0) + while (size-- != 0) + put_fs_byte (0, addr++); + } + return status; +} + +/* + * Helper function to process the load operation. + */ + +static int +load_object (struct linux_binprm * bprm, struct pt_regs *regs, int lib_ok) +{ + COFF_FILHDR *coff_hdr = (COFF_FILHDR *) bprm->buf; /* COFF Header */ + COFF_SCNHDR *sect_bufr; /* Pointer to section table */ + COFF_SCNHDR *text_sect; /* Pointer to the text section */ + COFF_SCNHDR *data_sect; /* Pointer to the data section */ + COFF_SCNHDR *bss_sect; /* Pointer to the bss section */ + int text_count; /* Number of text sections */ + int data_count; /* Number of data sections */ + int bss_count; /* Number of bss sections */ + int lib_count; /* Number of lib sections */ + unsigned int start_addr = 0;/* Starting location for program */ + int status = 0; /* Result status register */ + int fd = -1; /* Open file descriptor */ + struct file *fp = NULL; /* Pointer to the file at "fd" */ + short int sections = 0; /* Number of sections in the file */ + short int aout_size = 0; /* Size of the a.out header area */ + short int flags; /* Flag bits from the COFF header */ + +#ifdef COFF_DEBUG + printk ("binfmt_coff entry: %s\n", bprm->filename); +#endif + +/* + * Validate the magic value for the object file. + */ + do { + if (COFF_I386BADMAG (*coff_hdr)) { +#ifdef COFF_DEBUG + printk ("bad filehdr magic\n"); +#endif + status = -ENOEXEC; + break; + } +/* + * The object file should have 32 BIT little endian format. Do not allow + * it to have the 16 bit object file flag set as Linux is not able to run + * on the 80286/80186/8086. + */ + flags = COFF_SHORT (coff_hdr->f_flags); + if ((flags & (COFF_F_AR32WR | COFF_F_AR16WR)) != COFF_F_AR32WR) { +#ifdef COFF_DEBUG + printk ("invalid f_flags bits\n"); +#endif + status = -ENOEXEC; + break; + } +/* + * Extract the header information which we need. + */ + sections = COFF_SHORT (coff_hdr->f_nscns); /* Number of sections */ + aout_size = COFF_SHORT (coff_hdr->f_opthdr); /* Size of opt. headr */ +/* + * If the file is not executable then reject the exectution. This means + * that there must not be external references. + */ + if ((flags & COFF_F_EXEC) == 0) { +#ifdef COFF_DEBUG + printk ("not executable bit\n"); +#endif + status = -ENOEXEC; + break; + } +/* + * There must be atleast one section. + */ + if (sections == 0) { +#ifdef COFF_DEBUG + printk ("no sections\n"); +#endif + status = -ENOEXEC; + break; + } +/* + * Do some additional consistency checks. + * The system requires mapping for this loader. If you try + * to use a file system with no mapping, the format is not valid. + */ + if (!bprm->inode->i_op || + !bprm->inode->i_op->default_file_ops->mmap) { +#ifdef COFF_DEBUG + printk ("no mmap in fs\n"); +#endif + status = -ENOEXEC; + } + } + while (0); +/* + * Allocate a buffer to hold the entire coff section list. + */ + if (status >= 0) { + int nbytes = sections * COFF_SCNHSZ; + + sect_bufr = (COFF_SCNHDR *) kmalloc (nbytes, GFP_KERNEL); + if (0 == sect_bufr) { +#ifdef COFF_DEBUG + printk ("kmalloc failed\n"); +#endif + status = -ENOEXEC; + } +/* + * Read the section list from the disk file. + */ + else { + int old_fs = get_fs (); + set_fs (get_ds ()); /* Make it point to the proper location */ + status = read_exec (bprm->inode, /* INODE for file */ + aout_size + COFF_FILHSZ, /* Offset in the file */ + (char *) sect_bufr, /* Buffer for read */ + nbytes); /* Byte count reqd. */ + set_fs (old_fs); /* Restore the selector */ +#ifdef COFF_DEBUG + if (status < 0) + printk ("read aout hdr, status = %d\n", status); +#endif + } + } + else + sect_bufr = NULL; /* Errors do not have a section buffer */ +/* + * Count the number of sections for the required types and store the location + * of the last section for the three primary types. + */ + text_count = 0; + data_count = 0; + bss_count = 0; + lib_count = 0; + + text_sect = NULL; + data_sect = NULL; + bss_sect = NULL; +/* + * Loop through the sections and find the various types + */ + if (status >= 0) { + int nIndex; + COFF_SCNHDR *sect_ptr = sect_bufr; + + for (nIndex = 0; nIndex < sections; ++nIndex) { + long int sect_flags = COFF_LONG (sect_ptr->s_flags); + + switch (sect_flags) { + case COFF_STYP_TEXT: + text_sect = sect_ptr; + ++text_count; + status = is_properly_aligned (sect_ptr); + break; + + case COFF_STYP_DATA: + data_sect = sect_ptr; + ++data_count; + status = is_properly_aligned (sect_ptr); + break; + + case COFF_STYP_BSS: + bss_sect = sect_ptr; + ++bss_count; + break; + + case COFF_STYP_LIB: +#ifdef COFF_DEBUG + printk (".lib section found\n"); +#endif + ++lib_count; + break; + + default: + break; + } + sect_ptr = (COFF_SCNHDR *) & ((char *) sect_ptr)[COFF_SCNHSZ]; + } +/* + * Ensure that there are the required sections. There must be one text + * sections and one each of the data and bss sections for an executable. + * A library may or may not have a data / bss section. + */ + if (text_count != 1) { + status = -ENOEXEC; +#ifdef COFF_DEBUG + printk ("no text sections\n"); +#endif + } + else { + if (lib_ok) { + if (data_count != 1 || bss_count != 1) { + status = -ENOEXEC; +#ifdef COFF_DEBUG + printk ("no .data nor .bss sections\n"); +#endif + } + } + } + } +/* + * If there is no additional header then assume the file starts at + * the first byte of the text section. This may not be the proper place, + * so the best solution is to include the optional header. A shared library + * __MUST__ have an optional header to indicate that it is a shared library. + */ + if (status >= 0) { + if (aout_size == 0) { + if (!lib_ok) { + status = -ENOEXEC; +#ifdef COFF_DEBUG + printk ("no header in library\n"); +#endif + } + start_addr = COFF_LONG (text_sect->s_vaddr); + } +/* + * There is some header. Ensure that it is sufficient. + */ + else { + if (aout_size < COFF_AOUTSZ) { + status = -ENOEXEC; +#ifdef COFF_DEBUG + printk ("header too small\n"); +#endif + } + else { + COFF_AOUTHDR *aout_hdr = /* Pointer to a.out header */ + (COFF_AOUTHDR *) & ((char *) coff_hdr)[COFF_FILHSZ]; + short int aout_magic = COFF_SHORT (aout_hdr->magic); /* id */ +/* + * Validate the magic number in the a.out header. If it is valid then + * update the starting symbol location. Do not accept these file formats + * when loading a shared library. + */ + switch (aout_magic) { + case COFF_OMAGIC: + case COFF_ZMAGIC: + case COFF_STMAGIC: + if (!lib_ok) { + status = -ENOEXEC; +#ifdef COFF_DEBUG + printk ("wrong a.out header magic\n"); +#endif + } + start_addr = (unsigned int) COFF_LONG (aout_hdr->entry); + break; +/* + * Magic value for a shared library. This is valid only when loading a + * shared library. (There is no need for a start_addr. It won't be used.) + */ + case COFF_SHMAGIC: + if (lib_ok) { +#ifdef COFF_DEBUG + printk ("wrong a.out header magic\n"); +#endif + status = -ENOEXEC; + } + break; + + default: +#ifdef COFF_DEBUG + printk ("wrong a.out header magic\n"); +#endif + status = -ENOEXEC; + break; + } + } + } + } +/* + * Fetch a file pointer to the executable. + */ + if (status >= 0) { + fd = open_inode (bprm->inode, O_RDONLY); + if (fd < 0) { +#ifdef COFF_DEBUG + printk ("can not open inode, result = %d\n", fd); +#endif + status = fd; + } + else + fp = current->files->fd[fd]; + } + else + fd = -1; /* Invalidate the open file descriptor */ +/* + * Generate the proper values for the text fields + * + * 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->mm->mmap = NULL; + current->mm->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->mm->start_code = text_vaddr & PAGE_MASK; + current->mm->end_code = text_vaddr + text_size; + current->mm->end_data = data_vaddr + data_size; + current->mm->start_brk = + current->mm->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->mm->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 int +preload_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 int +preload_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 . . . . + */ + +int +load_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. + */ + +int +load_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->files->fd[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); +} diff -u --recursive --new-file v1.1.13/linux/ibcs/binfmt_elf.c linux/ibcs/binfmt_elf.c --- v1.1.13/linux/ibcs/binfmt_elf.c Thu Jan 1 02:00:00 1970 +++ linux/ibcs/binfmt_elf.c Tue May 24 00:27:49 1994 @@ -0,0 +1,636 @@ +/* + * linux/fs/binfmt_elf.c + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +asmlinkage int sys_exit(int exit_code); +asmlinkage int sys_close(unsigned fd); +asmlinkage int sys_open(const char *, int, int); +asmlinkage int sys_brk(unsigned long); + +#define DLINFO_ITEMS 8 + +#include + +/* We need to explicitly zero any fractional pages + after the data section (i.e. bss). This would + contain the junk from the file that should not + be in memory */ + +static void padzero(int elf_bss){ + unsigned int fpnt, nbyte; + + if(elf_bss & 0xfff) { + + nbyte = (PAGE_SIZE - (elf_bss & 0xfff)) & 0xfff; + if(nbyte){ + verify_area(VERIFY_WRITE, (void *) elf_bss, nbyte); + + fpnt = elf_bss; + while(fpnt & 0xfff) put_fs_byte(0, fpnt++); + }; + }; +} + +unsigned long * create_elf_tables(char * p,int argc,int envc,struct elfhdr * exec, unsigned int load_addr, int ibcs) +{ + unsigned long *argv,*envp, *dlinfo; + unsigned long * sp; + struct vm_area_struct *mpnt; + + mpnt = (struct vm_area_struct *)kmalloc(sizeof(*mpnt), GFP_KERNEL); + if (mpnt) { + mpnt->vm_task = current; + mpnt->vm_start = PAGE_MASK & (unsigned long) p; + mpnt->vm_end = TASK_SIZE; + mpnt->vm_page_prot = PAGE_PRIVATE|PAGE_DIRTY; + mpnt->vm_share = NULL; + mpnt->vm_inode = NULL; + mpnt->vm_offset = 0; + mpnt->vm_ops = NULL; + insert_vm_struct(current, mpnt); + current->mm->stk_vma = mpnt; + } + sp = (unsigned long *) (0xfffffffc & (unsigned long) p); + if(exec) sp -= DLINFO_ITEMS*2; + dlinfo = sp; + sp -= envc+1; + envp = sp; + sp -= argc+1; + argv = sp; + if (!ibcs) { + put_fs_long((unsigned long)envp,--sp); + put_fs_long((unsigned long)argv,--sp); + } + + /* The constant numbers (0-9) that we are writing here are + described in the header file sys/auxv.h on at least + some versions of SVr4 */ + if(exec) { /* Put this here for an ELF program interpreter */ + struct elf_phdr * eppnt; + eppnt = (struct elf_phdr *) exec->e_phoff; + put_fs_long(3,dlinfo++); put_fs_long(load_addr + exec->e_phoff,dlinfo++); + put_fs_long(4,dlinfo++); put_fs_long(sizeof(struct elf_phdr),dlinfo++); + put_fs_long(5,dlinfo++); put_fs_long(exec->e_phnum,dlinfo++); + put_fs_long(9,dlinfo++); put_fs_long((unsigned long) exec->e_entry,dlinfo++); + put_fs_long(7,dlinfo++); put_fs_long(SHM_RANGE_START,dlinfo++); + put_fs_long(8,dlinfo++); put_fs_long(0,dlinfo++); + put_fs_long(6,dlinfo++); put_fs_long(PAGE_SIZE,dlinfo++); + put_fs_long(0,dlinfo++); put_fs_long(0,dlinfo++); + }; + + put_fs_long((unsigned long)argc,--sp); + current->mm->arg_start = (unsigned long) p; + while (argc-->0) { + put_fs_long((unsigned long) p,argv++); + while (get_fs_byte(p++)) /* nothing */ ; + } + put_fs_long(0,argv); + current->mm->arg_end = current->mm->env_start = (unsigned long) p; + while (envc-->0) { + put_fs_long((unsigned long) p,envp++); + while (get_fs_byte(p++)) /* nothing */ ; + } + put_fs_long(0,envp); + current->mm->env_end = (unsigned long) p; + return sp; +} + + +/* This is much more generalized than the library routine read function, + so we keep this separate. Techincally the library read function + is only provided so that we can read a.out libraries that have + an ELF header */ + +static unsigned int load_elf_interp(struct elfhdr * interp_elf_ex, + struct inode * interpreter_inode) +{ + struct file * file; + struct elf_phdr *elf_phdata = NULL; + struct elf_phdr *eppnt; + unsigned int len; + unsigned int load_addr; + int elf_exec_fileno; + int elf_bss; + int old_fs, retval; + unsigned int last_bss; + int error; + int i, k; + + elf_bss = 0; + last_bss = 0; + error = load_addr = 0; + + /* First of all, some simple consistency checks */ + if((interp_elf_ex->e_type != ET_EXEC && + interp_elf_ex->e_type != ET_DYN) || + (interp_elf_ex->e_machine != EM_386 && interp_elf_ex->e_machine != EM_486) || + (!interpreter_inode->i_op || !interpreter_inode->i_op->bmap || + !interpreter_inode->i_op->default_file_ops->mmap)){ + return 0xffffffff; + }; + + /* Now read in all of the header information */ + + if(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > PAGE_SIZE) + return 0xffffffff; + + elf_phdata = (struct elf_phdr *) + kmalloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum, GFP_KERNEL); + if(!elf_phdata) return 0xffffffff; + + old_fs = get_fs(); + set_fs(get_ds()); + retval = read_exec(interpreter_inode, interp_elf_ex->e_phoff, (char *) elf_phdata, + sizeof(struct elf_phdr) * interp_elf_ex->e_phnum); + set_fs(old_fs); + + elf_exec_fileno = open_inode(interpreter_inode, O_RDONLY); + if (elf_exec_fileno < 0) return 0xffffffff; + file = current->files->fd[elf_exec_fileno]; + + eppnt = elf_phdata; + for(i=0; ie_phnum; i++, eppnt++) + if(eppnt->p_type == PT_LOAD) { + error = do_mmap(file, + eppnt->p_vaddr & 0xfffff000, + eppnt->p_filesz + (eppnt->p_vaddr & 0xfff), + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | (interp_elf_ex->e_type == ET_EXEC ? MAP_FIXED : 0), + eppnt->p_offset & 0xfffff000); + + if(!load_addr && interp_elf_ex->e_type == ET_DYN) + load_addr = error; + k = load_addr + eppnt->p_vaddr + eppnt->p_filesz; + if(k > elf_bss) elf_bss = k; + if(error < 0 && error > -1024) break; /* Real error */ + k = load_addr + eppnt->p_memsz + eppnt->p_vaddr; + if(k > last_bss) last_bss = k; + } + + /* Now use mmap to map the library into memory. */ + + + sys_close(elf_exec_fileno); + if(error < 0 && error > -1024) { + kfree(elf_phdata); + return 0xffffffff; + } + + padzero(elf_bss); + len = (elf_bss + 0xfff) & 0xfffff000; /* What we have mapped so far */ + + /* Map the last of the bss segment */ + if (last_bss > len) + do_mmap(NULL, len, last_bss-len, + PROT_READ|PROT_WRITE|PROT_EXEC, + MAP_FIXED|MAP_PRIVATE, 0); + kfree(elf_phdata); + + return ((unsigned int) interp_elf_ex->e_entry) + load_addr; +} + +static unsigned int load_aout_interp(struct exec * interp_ex, + struct inode * interpreter_inode) +{ + int retval; + unsigned int elf_entry; + + current->mm->brk = interp_ex->a_bss + + (current->mm->end_data = interp_ex->a_data + + (current->mm->end_code = interp_ex->a_text)); + elf_entry = interp_ex->a_entry; + + + if (N_MAGIC(*interp_ex) == OMAGIC) { + do_mmap(NULL, 0, interp_ex->a_text+interp_ex->a_data, + PROT_READ|PROT_WRITE|PROT_EXEC, + MAP_FIXED|MAP_PRIVATE, 0); + retval = read_exec(interpreter_inode, 32, (char *) 0, + interp_ex->a_text+interp_ex->a_data); + } else if (N_MAGIC(*interp_ex) == ZMAGIC || N_MAGIC(*interp_ex) == QMAGIC) { + do_mmap(NULL, 0, interp_ex->a_text+interp_ex->a_data, + PROT_READ|PROT_WRITE|PROT_EXEC, + MAP_FIXED|MAP_PRIVATE, 0); + retval = read_exec(interpreter_inode, + N_TXTOFF(*interp_ex) , + (char *) N_TXTADDR(*interp_ex), + interp_ex->a_text+interp_ex->a_data); + } else + retval = -1; + + if(retval >= 0) + do_mmap(NULL, (interp_ex->a_text + interp_ex->a_data + 0xfff) & + 0xfffff000, interp_ex->a_bss, + PROT_READ|PROT_WRITE|PROT_EXEC, + MAP_FIXED|MAP_PRIVATE, 0); + if(retval < 0) return 0xffffffff; + return elf_entry; +} + +/* + * These are the functions used to load ELF style executables and shared + * libraries. There is no binary dependent code anywhere else. + */ + +#define INTERPRETER_NONE 0 +#define INTERPRETER_AOUT 1 +#define INTERPRETER_ELF 2 + +int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) +{ + struct elfhdr elf_ex; + struct elfhdr interp_elf_ex; + struct file * file; + struct exec interp_ex; + struct inode *interpreter_inode; + unsigned int load_addr; + unsigned int interpreter_type = INTERPRETER_NONE; + int i; + int old_fs; + int error; + struct elf_phdr * elf_ppnt, *elf_phdata; + int elf_exec_fileno; + unsigned int elf_bss, k, elf_brk; + int retval; + char * elf_interpreter; + unsigned int elf_entry; + int status; + unsigned int start_code, end_code, end_data; + unsigned int elf_stack; + char passed_fileno[6]; + + status = 0; + load_addr = 0; + elf_ex = *((struct elfhdr *) bprm->buf); /* exec-header */ + + if (elf_ex.e_ident[0] != 0x7f || + strncmp(&elf_ex.e_ident[1], "ELF",3) != 0) + return -ENOEXEC; + + + /* First of all, some simple consistency checks */ + if(elf_ex.e_type != ET_EXEC || + (elf_ex.e_machine != EM_386 && elf_ex.e_machine != EM_486) || + (!bprm->inode->i_op || !bprm->inode->i_op->default_file_ops || + !bprm->inode->i_op->default_file_ops->mmap)){ + return -ENOEXEC; + }; + + /* Now read in all of the header information */ + + elf_phdata = (struct elf_phdr *) kmalloc(elf_ex.e_phentsize * + elf_ex.e_phnum, GFP_KERNEL); + + old_fs = get_fs(); + set_fs(get_ds()); + retval = read_exec(bprm->inode, elf_ex.e_phoff, (char *) elf_phdata, + elf_ex.e_phentsize * elf_ex.e_phnum); + set_fs(old_fs); + if (retval < 0) { + kfree (elf_phdata); + return retval; + } + + elf_ppnt = elf_phdata; + + elf_bss = 0; + elf_brk = 0; + + elf_exec_fileno = open_inode(bprm->inode, O_RDONLY); + + if (elf_exec_fileno < 0) { + kfree (elf_phdata); + return elf_exec_fileno; + } + + file = current->files->fd[elf_exec_fileno]; + + elf_stack = 0xffffffff; + elf_interpreter = NULL; + start_code = 0; + end_code = 0; + end_data = 0; + + old_fs = get_fs(); + set_fs(get_ds()); + + for(i=0;i < elf_ex.e_phnum; i++){ + if(elf_ppnt->p_type == PT_INTERP) { + /* This is the program interpreter used for shared libraries - + for now assume that this is an a.out format binary */ + + elf_interpreter = (char *) kmalloc(elf_ppnt->p_filesz, + GFP_KERNEL); + + retval = read_exec(bprm->inode,elf_ppnt->p_offset,elf_interpreter, + elf_ppnt->p_filesz); +#if 0 + printk("Using ELF interpreter %s\n", elf_interpreter); +#endif + if(retval >= 0) + retval = namei(elf_interpreter, &interpreter_inode); + if(retval >= 0) + retval = read_exec(interpreter_inode,0,bprm->buf,128); + + if(retval >= 0){ + interp_ex = *((struct exec *) bprm->buf); /* exec-header */ + interp_elf_ex = *((struct elfhdr *) bprm->buf); /* exec-header */ + + }; + if(retval < 0) { + kfree (elf_phdata); + kfree(elf_interpreter); + return retval; + }; + }; + elf_ppnt++; + }; + + set_fs(old_fs); + + /* Some simple consistency checks for the interpreter */ + if(elf_interpreter){ + interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT; + if(retval < 0) { + kfree(elf_interpreter); + kfree(elf_phdata); + return -ELIBACC; + }; + /* Now figure out which format our binary is */ + if((N_MAGIC(interp_ex) != OMAGIC) && + (N_MAGIC(interp_ex) != ZMAGIC) && + (N_MAGIC(interp_ex) != QMAGIC)) + interpreter_type = INTERPRETER_ELF; + + if (interp_elf_ex.e_ident[0] != 0x7f || + strncmp(&interp_elf_ex.e_ident[1], "ELF",3) != 0) + interpreter_type &= ~INTERPRETER_ELF; + + if(!interpreter_type) + { + kfree(elf_interpreter); + kfree(elf_phdata); + return -ELIBBAD; + }; + } + + /* OK, we are done with that, now set up the arg stuff, + and then start this sucker up */ + + if (!bprm->sh_bang) { + char * passed_p; + + if(interpreter_type == INTERPRETER_AOUT) { + sprintf(passed_fileno, "%d", elf_exec_fileno); + passed_p = passed_fileno; + + if(elf_interpreter) { + bprm->p = copy_strings(1,&passed_p,bprm->page,bprm->p,2); + bprm->argc++; + }; + }; + if (!bprm->p) { + if(elf_interpreter) { + kfree(elf_interpreter); + } + kfree (elf_phdata); + return -E2BIG; + } + } + + /* OK, This is the point of no return */ + flush_old_exec(bprm); + + current->mm->end_data = 0; + current->mm->end_code = 0; + current->mm->start_mmap = ELF_START_MMAP; + current->mm->mmap = NULL; + elf_entry = (unsigned int) elf_ex.e_entry; + + /* Do this so that we can load the interpreter, if need be. We will + change some of these later */ + current->mm->rss = 0; + bprm->p += change_ldt(0, bprm->page); + current->mm->start_stack = bprm->p; + + /* Now we do a little grungy work by mmaping the ELF image into + the correct location in memory. At this point, we assume that + the image should be loaded at fixed address, not at a variable + address. */ + + old_fs = get_fs(); + set_fs(get_ds()); + + elf_ppnt = elf_phdata; + for(i=0;i < elf_ex.e_phnum; i++){ + + if(elf_ppnt->p_type == PT_INTERP) { + /* Set these up so that we are able to load the interpreter */ + /* Now load the interpreter into user address space */ + set_fs(old_fs); + + if(interpreter_type & 1) elf_entry = + load_aout_interp(&interp_ex, interpreter_inode); + + if(interpreter_type & 2) elf_entry = + load_elf_interp(&interp_elf_ex, interpreter_inode); + + old_fs = get_fs(); + set_fs(get_ds()); + + iput(interpreter_inode); + kfree(elf_interpreter); + + if(elf_entry == 0xffffffff) { + printk("Unable to load interpreter\n"); + kfree(elf_phdata); + send_sig(SIGSEGV, current, 0); + return 0; + }; + }; + + + if(elf_ppnt->p_type == PT_LOAD) { + error = do_mmap(file, + elf_ppnt->p_vaddr & 0xfffff000, + elf_ppnt->p_filesz + (elf_ppnt->p_vaddr & 0xfff), + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_FIXED | MAP_PRIVATE, + elf_ppnt->p_offset & 0xfffff000); + +#ifdef LOW_ELF_STACK + if(elf_ppnt->p_vaddr & 0xfffff000 < elf_stack) + elf_stack = elf_ppnt->p_vaddr & 0xfffff000; +#endif + + if(!load_addr) + load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset; + k = elf_ppnt->p_vaddr; + if(k > start_code) start_code = k; + k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz; + if(k > elf_bss) elf_bss = k; + if((elf_ppnt->p_flags | PROT_WRITE) && end_code < k) + end_code = k; + if(end_data < k) end_data = k; + k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz; + if(k > elf_brk) elf_brk = k; + }; + elf_ppnt++; + }; + set_fs(old_fs); + + kfree(elf_phdata); + + if(!elf_interpreter) sys_close(elf_exec_fileno); + current->elf_executable = 1; + current->executable = bprm->inode; + bprm->inode->i_count++; +#ifdef LOW_ELF_STACK + current->start_stack = p = elf_stack - 4; +#endif + bprm->p -= MAX_ARG_PAGES*PAGE_SIZE; + bprm->p = (unsigned long) + create_elf_tables((char *)bprm->p, + bprm->argc, + bprm->envc, + (interpreter_type == INTERPRETER_ELF ? &elf_ex : NULL), + load_addr, + (interpreter_type == INTERPRETER_AOUT ? 0 : 1)); + if(interpreter_type == INTERPRETER_AOUT) + current->mm->arg_start += strlen(passed_fileno) + 1; + current->mm->start_brk = current->mm->brk = elf_brk; + current->mm->end_code = end_code; + current->mm->start_code = start_code; + current->mm->end_data = end_data; + current->mm->start_stack = bprm->p; + current->suid = current->euid = bprm->e_uid; + current->sgid = current->egid = bprm->e_gid; + + /* Calling sys_brk effectively mmaps the pages that we need for the bss and break + sections */ + current->mm->brk = (elf_bss + 0xfff) & 0xfffff000; + sys_brk((elf_brk + 0xfff) & 0xfffff000); + + padzero(elf_bss); + + /* Why this, you ask??? Well SVr4 maps page 0 as read-only, + and some applications "depend" upon this behavior. + Since we do not have the power to recompile these, we + emulate the SVr4 behavior. Sigh. */ + error = do_mmap(NULL, 0, 4096, PROT_READ | PROT_EXEC, + MAP_FIXED | MAP_PRIVATE, 0); + + regs->eip = elf_entry; /* eip, magic happens :-) */ + regs->esp = bprm->p; /* stack pointer */ + if (current->flags & PF_PTRACED) + send_sig(SIGTRAP, current, 0); + return 0; +} + +/* This is really simpleminded and specialized - we are loading an + a.out library that is given an ELF header. */ + +int load_elf_library(int fd){ + struct file * file; + struct elfhdr elf_ex; + struct elf_phdr *elf_phdata = NULL; + struct inode * inode; + unsigned int len; + int elf_bss; + int old_fs, retval; + unsigned int bss; + int error; + int i,j, k; + + len = 0; + file = current->files->fd[fd]; + inode = file->f_inode; + elf_bss = 0; + + set_fs(KERNEL_DS); + if (file->f_op->read(inode, file, (char *) &elf_ex, sizeof(elf_ex)) != sizeof(elf_ex)) { + sys_close(fd); + return -EACCES; + } + set_fs(USER_DS); + + if (elf_ex.e_ident[0] != 0x7f || + strncmp(&elf_ex.e_ident[1], "ELF",3) != 0) + return -ENOEXEC; + + /* First of all, some simple consistency checks */ + if(elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 || + (elf_ex.e_machine != EM_386 && elf_ex.e_machine != EM_486) || + (!inode->i_op || !inode->i_op->bmap || + !inode->i_op->default_file_ops->mmap)){ + return -ENOEXEC; + }; + + /* Now read in all of the header information */ + + if(sizeof(struct elf_phdr) * elf_ex.e_phnum > PAGE_SIZE) + return -ENOEXEC; + + elf_phdata = (struct elf_phdr *) + kmalloc(sizeof(struct elf_phdr) * elf_ex.e_phnum, GFP_KERNEL); + + old_fs = get_fs(); + set_fs(get_ds()); + retval = read_exec(inode, elf_ex.e_phoff, (char *) elf_phdata, + sizeof(struct elf_phdr) * elf_ex.e_phnum); + set_fs(old_fs); + + j = 0; + for(i=0; ip_type == PT_LOAD) j++; + + if(j != 1) { + kfree(elf_phdata); + return -ENOEXEC; + }; + + while(elf_phdata->p_type != PT_LOAD) elf_phdata++; + + /* Now use mmap to map the library into memory. */ + error = do_mmap(file, + elf_phdata->p_vaddr & 0xfffff000, + elf_phdata->p_filesz + (elf_phdata->p_vaddr & 0xfff), + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_FIXED | MAP_PRIVATE, + elf_phdata->p_offset & 0xfffff000); + + k = elf_phdata->p_vaddr + elf_phdata->p_filesz; + if(k > elf_bss) elf_bss = k; + + sys_close(fd); + if (error != elf_phdata->p_vaddr & 0xfffff000) { + kfree(elf_phdata); + return error; + } + + padzero(elf_bss); + + len = (elf_phdata->p_filesz + elf_phdata->p_vaddr+ 0xfff) & 0xfffff000; + bss = elf_phdata->p_memsz + elf_phdata->p_vaddr; + if (bss > len) + do_mmap(NULL, len, bss-len, + PROT_READ|PROT_WRITE|PROT_EXEC, + MAP_FIXED|MAP_PRIVATE, 0); + kfree(elf_phdata); + return 0; +} diff -u --recursive --new-file v1.1.13/linux/include/linux/binfmts.h linux/include/linux/binfmts.h --- v1.1.13/linux/include/linux/binfmts.h Tue Dec 21 12:30:23 1993 +++ linux/include/linux/binfmts.h Tue May 24 00:16:26 1994 @@ -14,25 +14,28 @@ * This structure is used to hold the arguments that are used when loading binaries. */ struct linux_binprm{ - char buf[128]; - unsigned long page[MAX_ARG_PAGES]; - unsigned long p; - int sh_bang; - struct inode * inode; - int e_uid, e_gid; - int argc, envc; - char * filename; /* Name of binary */ + char buf[128]; + unsigned long page[MAX_ARG_PAGES]; + unsigned long p; + int sh_bang; + struct inode * inode; + int e_uid, e_gid; + int argc, envc; + char * filename; /* Name of binary */ }; -/* This structure defines the functions that are used to load the binary formats that - * linux accepts. */ - -struct linux_binfmt{ - int (*load_binary)(struct linux_binprm *, struct pt_regs * regs); - int (*load_shlib)(int fd); +/* + * This structure defines the functions that are used to load the binary formats that + * linux accepts. + */ +struct linux_binfmt { + struct linux_binfmt * next; + int (*load_binary)(struct linux_binprm *, struct pt_regs * regs); + int (*load_shlib)(int fd); }; -extern struct linux_binfmt formats[]; +extern int register_binfmt(struct linux_binfmt *); +extern int unregister_binfmt(struct linux_binfmt *); extern int read_exec(struct inode *inode, unsigned long offset, char * addr, unsigned long count); Only in v1.1.13/linux/include/linux: ddi.h diff -u --recursive --new-file v1.1.13/linux/include/linux/personality.h linux/include/linux/personality.h --- v1.1.13/linux/include/linux/personality.h Thu Jan 1 02:00:00 1970 +++ linux/include/linux/personality.h Mon May 23 23:45:34 1994 @@ -0,0 +1,12 @@ +/* Flags for bug emulation. These occupy the top three bytes. */ +#define STICKY_TIMEOUTS 0x8000000 +#define WHOLE_SECONDS 0x4000000 + +/* Personality types. These go in the low byte. */ +#define PER_MASK (0x00ff) +#define PER_LINUX (0x0000) +#define PER_SVR4 (0x0001 | STICKY_TIMEOUTS) +#define PER_SVR3 (0x0002 | STICKY_TIMEOUTS) +#define PER_SCOSVR3 (0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS) +#define PER_WYSEV386 (0x0004 | STICKY_TIMEOUTS) +#define PER_ISCR4 (0x0005 | STICKY_TIMEOUTS) diff -u --recursive --new-file v1.1.13/linux/include/linux/sched.h linux/include/linux/sched.h --- v1.1.13/linux/include/linux/sched.h Tue May 24 00:34:56 1994 +++ linux/include/linux/sched.h Mon May 23 23:45:34 1994 @@ -254,10 +254,12 @@ /* various fields */ struct task_struct *next_task, *prev_task; struct sigaction sigaction[32]; + unsigned long * signal_map; + unsigned long * signal_invmap; unsigned long saved_kernel_stack; unsigned long kernel_stack_page; int exit_code, exit_signal; - int elf_executable:1; + unsigned long personality; int dumpable:1; int did_exec:1; int pid,pgrp,session,leader; @@ -323,7 +325,7 @@ /* state etc */ { 0,15,15,0,0,0,0, \ /* debugregs */ { 0, }, \ /* schedlink */ &init_task,&init_task, \ -/* signals */ {{ 0, },}, \ +/* signals */ {{ 0, },}, ident_map, ident_map, \ /* stack */ 0,(unsigned long) &init_kernel_stack, \ /* ec,brk... */ 0,0,0,0,0, \ /* pid etc.. */ 0,0,0,0, \ diff -u --recursive --new-file v1.1.13/linux/kernel/exit.c linux/kernel/exit.c --- v1.1.13/linux/kernel/exit.c Tue May 24 00:34:58 1994 +++ linux/kernel/exit.c Mon May 23 23:28:20 1994 @@ -282,10 +282,12 @@ * POSIX specifies that kill(-1,sig) is unspecified, but what we have * is probably wrong. Should make it like BSD or SYSV. */ -asmlinkage int sys_kill(int pid,int sig) +asmlinkage int sys_kill(int pid, unsigned int sig) { int err, retval = 0, count = 0; + if (sig > 32) + return -EINVAL; if (!pid) return(kill_pg(current->pgrp,sig,0)); if (pid == -1) { diff -u --recursive --new-file v1.1.13/linux/kernel/ksyms.c linux/kernel/ksyms.c --- v1.1.13/linux/kernel/ksyms.c Tue May 24 00:34:58 1994 +++ linux/kernel/ksyms.c Tue May 24 00:31:36 1994 @@ -15,6 +15,7 @@ #include #include #include +#include #ifdef CONFIG_INET #include #endif @@ -28,20 +29,16 @@ extern void (*do_floppy)(void); #endif -#ifdef CONFIG_BINFMT_IBCS extern int do_execve(char * filename, char ** argv, char ** envp, struct pt_regs * regs); extern void flush_old_exec(struct linux_binprm * bprm); extern int open_inode(struct inode * inode, int mode); extern int read_exec(struct inode *inode, unsigned long offset, char * addr, unsigned long count); - -extern void check_pending(int signum); extern int do_signal(unsigned long oldmask, struct pt_regs * regs); -extern int (*ibcs_invmapsig)(int); extern void (* iABI_hook)(struct pt_regs * regs); -#endif + #ifdef CONFIG_INET extern int register_netdev(struct device *); extern void unregister_netdev(struct device *); @@ -67,6 +64,8 @@ X(__verify_write), X(do_mmap), X(do_munmap), + X(insert_vm_struct), + X(zeromap_page_range), /* internal kernel memory management */ X(__get_free_pages), @@ -94,6 +93,10 @@ X(register_filesystem), X(unregister_filesystem), + /* executable format registration */ + X(register_binfmt), + X(unregister_binfmt), + /* interrupt handling */ X(request_irq), X(free_irq), @@ -115,24 +118,8 @@ X(system_utsname), X(sys_call_table), -#ifdef CONFIG_FTAPE - /* The next labels are needed for ftape driver. */ - X(ftape_big_buffer), - X(do_floppy), -#endif - -#ifdef CONFIG_BINFMT_IBCS -/* - * The following are needed if iBCS support is modular rather than - * compiled in. - */ - /* Emulator hooks. */ - X(iABI_hook), - X(ibcs_invmapsig), - /* Signal interfaces */ X(do_signal), - X(check_pending), X(send_sig), /* Program loader interfaces */ @@ -141,16 +128,17 @@ X(create_tables), X(do_execve), X(flush_old_exec), - X(formats), - X(insert_vm_struct), X(open_inode), X(read_exec), - X(zeromap_page_range), /* Miscellaneous access points */ X(si_meminfo), -#endif +#ifdef CONFIG_FTAPE + /* The next labels are needed for ftape driver. */ + X(ftape_big_buffer), + X(do_floppy), +#endif #ifdef CONFIG_INET /* support for loadable net drivers */ X(register_netdev), diff -u --recursive --new-file v1.1.13/linux/kernel/sched.c linux/kernel/sched.c --- v1.1.13/linux/kernel/sched.c Tue May 24 00:34:58 1994 +++ linux/kernel/sched.c Mon May 23 22:28:57 1994 @@ -87,6 +87,16 @@ extern int timer_interrupt(void); asmlinkage int system_call(void); +/* + * signal mapping: this is the default identity mapping used for normal + * linux binaries (it's both the reverse and the normal map, of course) + */ +static unsigned long ident_map[33] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 +}; + static unsigned long init_kernel_stack[1024] = { STACK_MAGIC, }; struct task_struct init_task = INIT_TASK; diff -u --recursive --new-file v1.1.13/linux/kernel/signal.c linux/kernel/signal.c --- v1.1.13/linux/kernel/signal.c Mon Apr 25 10:04:36 1994 +++ linux/kernel/signal.c Mon May 23 23:29:03 1994 @@ -135,8 +135,10 @@ { struct sigaction tmp; - if (signum<1 || signum>32 || signum==SIGKILL || signum==SIGSTOP) + if (signum<1 || signum>32) return -EINVAL; + if (signum==SIGKILL || signum==SIGSTOP) + return -EINVAL; if (handler >= TASK_SIZE) return -EFAULT; tmp.sa_handler = (void (*)(int)) handler; @@ -154,7 +156,9 @@ { struct sigaction new_sa, *p; - if (signum<1 || signum>32 || signum==SIGKILL || signum==SIGSTOP) + if (signum<1 || signum>32) + return -EINVAL; + if (signum==SIGKILL || signum==SIGSTOP) return -EINVAL; p = signum - 1 + current->sigaction; if (action) { @@ -242,7 +246,7 @@ do_exit(SIGSEGV); /* set up the "normal" stack seen by the signal handler (iBCS2) */ put_fs_long(__CODE,frame); - put_fs_long(signr, frame+1); + put_fs_long(current->signal_invmap[signr], frame+1); put_fs_long(regs->gs, frame+2); put_fs_long(regs->fs, frame+3); put_fs_long(regs->es, frame+4); Only in v1.1.13/linux/net: Space.c Only in v1.1.13/linux/net: ddi.c Only in v1.1.13/linux/net/inet: dev.h Only in v1.1.13/linux/net/inet: inet.h Only in v1.1.13/linux/net/inet: loopback.c diff -u --recursive --new-file v1.1.13/linux/net/inet/p8022.c linux/net/inet/p8022.c --- v1.1.13/linux/net/inet/p8022.c Tue May 24 00:35:02 1994 +++ linux/net/inet/p8022.c Mon May 23 23:10:33 1994 @@ -3,7 +3,6 @@ #include "datalink.h" #include #include -#include static struct datalink_proto *p8022_list = NULL; Only in v1.1.13/linux/net/inet: skbuff.h