]> git.neil.brown.name Git - history.git/commitdiff
Import 1.1.14 1.1.14
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:09:30 +0000 (15:09 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:09:30 +0000 (15:09 -0500)
18 files changed:
Makefile
config.in
drivers/block/mcd.c
drivers/block/sbpcd.c
fs/Makefile
fs/exec.c
fs/proc/net.c
fs/select.c
ibcs/binfmt_coff.c [new file with mode: 0644]
ibcs/binfmt_elf.c [new file with mode: 0644]
include/linux/binfmts.h
include/linux/personality.h [new file with mode: 0644]
include/linux/sched.h
kernel/exit.c
kernel/ksyms.c
kernel/sched.c
kernel/signal.c
net/inet/p8022.c

index 80e02226f91dd9cd66530a34f2d81198671e7164..baa79b8b2b99c7eb45f9a43da606c87cf20c2bfe 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 1
-SUBLEVEL = 13
+SUBLEVEL = 14
 
 all:   Version zImage
 
index b1b38990c61224add8f3cf6899d9f923335f8f20..b3197ba15c5a7ef08626df1c77a7f9da2ab07249 100644 (file)
--- a/config.in
+++ b/config.in
@@ -17,7 +17,9 @@ if [ "$CONFIG_NET" = "y" ]; then
 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 'The IPX protocol' CONFIG_IPX y
 #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 @@ if [ "$CONFIG_SLIP" = "y" ]; then
   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
index 282904a18eb6eb80ce2006bf69370b441b881270..c89aff7c2c525e38bbf408b5f8ec305327e6e85c 100644 (file)
@@ -881,9 +881,9 @@ mcd_init(unsigned long mem_start, unsigned long mem_end)
 
        /* 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);
index 11aa5decfda84bae49cf7e11754b118cf88939a9..4a7cfea2e87cd41b724dcb733c02f6b9609866b5 100644 (file)
 #include <linux/signal.h>
 #endif SBPCD_USE_IRQ
 
-#include <linux/ddi.h>
 #include <linux/major.h> 
 
 #include <asm/system.h>
 #error "SBPCD: \"make config\" again. File system iso9660 is necessary."
 #endif
 
+/*
+ * This may come back some day..
+ */
+#define DDIOCSDBG      0x9000
+
 /*
  * still testing around...
  */
index d008403c1d66da883914a4a2596c07a31f6e9ed1..7d5031b2cf92978f30b793b42b0255293bc92a5e 100644 (file)
@@ -40,13 +40,6 @@ ifdef CONFIG_HPFS_FS
 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:
index dc0517f77ef1a2a9f6cb033dad8d4d08605124e9..8476beba467b9ec51e2971c24f31335e84ffb576 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -53,6 +53,47 @@ asmlinkage int sys_brk(unsigned long);
 
 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 @@ asmlinkage int sys_uselib(const char * library)
        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 @@ void flush_old_exec(struct linux_binprm * bprm)
        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 @@ restart_interp:
        }
 
        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 @@ restart_interp:
                        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 @@ asmlinkage int sys_execve(struct pt_regs regs)
        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 @@ static void set_brk(unsigned long start, unsigned long end)
  * 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 @@ beyond_if:
 }
 
 
-int load_aout_library(int fd)
+static int load_aout_library(int fd)
 {
         struct file * file;
        struct exec ex;
index 66a9186970a1b2afb4c31a9db10b7645c7faf840..cda33a035e017f4c10204fc068e484be75b941ad 100644 (file)
@@ -280,6 +280,8 @@ static int proc_readnet(struct inode * inode, struct file * file,
                 *      the start pointer and we know the length.. 
                 */
 
+               if (length <= 0)
+                       break;
                /*
                 *      Copy the bytes
                 */
index 5cc5ef41b934328c61d1013dc794f3b28975531e..a28e6d8733805d3e8fb100a37e1353684506fdab 100644 (file)
@@ -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 <linux/types.h>
@@ -14,6 +19,7 @@
 #include <linux/stat.h>
 #include <linux/signal.h>
 #include <linux/errno.h>
+#include <linux/personality.h>
 
 #include <asm/segment.h>
 #include <asm/system.h>
@@ -235,7 +241,7 @@ asmlinkage int sys_select( unsigned long *buffer )
        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 --git a/ibcs/binfmt_coff.c b/ibcs/binfmt_coff.c
new file mode 100644 (file)
index 0000000..425a759
--- /dev/null
@@ -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 <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/a.out.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/binfmts.h>
+#include <asm/segment.h>
+#include <linux/string.h>
+#include <linux/fcntl.h>
+#include <linux/ptrace.h>
+#include <linux/coff.h>
+#include <linux/malloc.h>
+
+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, &regs, 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 --git a/ibcs/binfmt_elf.c b/ibcs/binfmt_elf.c
new file mode 100644 (file)
index 0000000..a4fe3bc
--- /dev/null
@@ -0,0 +1,636 @@
+/*
+ * linux/fs/binfmt_elf.c
+ */
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/a.out.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/binfmts.h>
+#include <linux/string.h>
+#include <linux/fcntl.h>
+#include <linux/ptrace.h>
+#include <linux/malloc.h>
+#include <linux/shm.h>
+
+#include <asm/segment.h>
+
+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 <linux/elf.h>
+
+/* 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; i<interp_elf_ex->e_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; i<elf_ex.e_phnum; i++)
+               if((elf_phdata + i)->p_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;
+}
index 908144dc4ab4a394a9c22faad2dd0a9636dd3d2d..b1c72e6b1059b4838af5f1180c64c15b7f77e5b5 100644 (file)
  * 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);
diff --git a/include/linux/personality.h b/include/linux/personality.h
new file mode 100644 (file)
index 0000000..714a5a6
--- /dev/null
@@ -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)
index abb9775457ca7d563c55ae36001a4dce537d2193..0d433dc6350a4dd6021fdba06271bbf9dc21bb92 100644 (file)
@@ -254,10 +254,12 @@ struct task_struct {
 /* 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 @@ struct task_struct {
 /* 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, \
index 24db77a6f8fa6ae9173c6473525a0dfc26a1b507..92133742f1377614b4f23bcbafd006e6e23c7c44 100644 (file)
@@ -282,10 +282,12 @@ int kill_proc(int pid, int sig, int priv)
  * 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) {
index 3c0e4dc00103633e8be5120ab773e421ce7db446..2009e7e658bf8c100c6fd78f032d98868d71d454 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/sys.h>
 #include <linux/utsname.h>
 #include <linux/interrupt.h>
+#include <linux/binfmts.h>
 #ifdef CONFIG_INET
 #include <linux/netdevice.h>
 #endif
@@ -28,20 +29,16 @@ extern char * ftape_big_buffer;
 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 @@ struct {
        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 @@ struct {
        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 @@ struct {
        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 @@ struct {
        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),
index 13fd24f793f8435f79ab2880b0defa14e4d4f290..1890a2e35eb09b76a5097843f2ff59e53930bb03 100644 (file)
@@ -87,6 +87,16 @@ extern void mem_use(void);
 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;
 
index 33aec214b3b933947013760bac2331d85fdfbde6..ab139d168b60ac726077df5abb658f2b1cd70565 100644 (file)
@@ -135,7 +135,9 @@ asmlinkage int sys_signal(int signum, unsigned long handler)
 {
        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;
@@ -154,7 +156,9 @@ asmlinkage int sys_sigaction(int signum, const struct sigaction * action,
 {
        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 @@ static void setup_frame(struct sigaction * sa, unsigned long ** fp, unsigned lon
                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);
index 9ec9ef3ccf9aca124cbaaa5066bbded461782b2d..46ce06980aa480a8a50cd8a850b7fc273435e3ed 100644 (file)
@@ -3,7 +3,6 @@
 #include "datalink.h"
 #include <linux/mm.h>
 #include <linux/in.h>
-#include <linux/ddi.h>
 
 static struct datalink_proto *p8022_list = NULL;