linux-cvs-patches
[Top] [All Lists]

CVS Update@linux-mips.org: linux

To: linux-cvs-patches@linux-mips.org
Subject: CVS Update@linux-mips.org: linux
From: sjhill@linux-mips.org
Date: Mon, 14 Mar 2005 03:28:23 +0000
Reply-to: linux-mips@linux-mips.org
Sender: linux-cvs-patches-bounce@linux-mips.org
CVSROOT:        /home/cvs
Module name:    linux
Changes by:     sjhill@ftp.linux-mips.org       05/03/14 03:28:17

Modified files:
        arch/mips/kernel: irixelf.c 

Log message:
        Static IRIX binaries are now being detected properly and are using the
        ELF interpreter found in this file.

diff -urN linux/arch/mips/kernel/irixelf.c linux/arch/mips/kernel/irixelf.c
--- linux/arch/mips/kernel/irixelf.c    2005/02/19 16:20:28     1.66
+++ linux/arch/mips/kernel/irixelf.c    2005/03/14 03:28:17     1.67
@@ -31,9 +31,10 @@
 #include <linux/elfcore.h>
 #include <linux/smp_lock.h>
 
-#include <asm/uaccess.h>
 #include <asm/mipsregs.h>
+#include <asm/namei.h>
 #include <asm/prctl.h>
+#include <asm/uaccess.h>
 
 #define DLINFO_ITEMS 12
 
@@ -399,22 +400,16 @@
                return -ENOEXEC;
        }
 
-       /* Only support MIPS ARCH2 or greater IRIX binaries for now. */
-       if(!(ehp->e_flags & EF_MIPS_ARCH) && !(ehp->e_flags & 0x04)) {
-               return -ENOEXEC;
-       }
-
        /* XXX Don't support N32 or 64bit binaries yet because they can
         * XXX and do execute 64 bit instructions and expect all registers
         * XXX to be 64 bit as well.  We need to make the kernel save
         * XXX all registers as 64bits on cpu's capable of this at
         * XXX exception time plus frob the XTLB exception vector.
         */
-       if((ehp->e_flags & EF_MIPS_ABI2)) {
+       if((ehp->e_flags & EF_MIPS_ABI2))
                return -ENOEXEC;
-       }
 
-       return 0; /* It's ok. */
+       return 0;
 }
 
 /*
@@ -422,47 +417,53 @@
  * use interpreters with 'libc.so' in the name, so this function
  * can differentiate between Linux and Irix binaries.
  */
-#define IRIX_INTERP_PREFIX "/usr/gnemul/irix"
-
 static inline int look_for_irix_interpreter(char **name,
                                            struct file **interpreter,
                                            struct elfhdr *interp_elf_ex,
-                                           struct elf_phdr *ihdr,
-                                           struct linux_binprm *bprm)
+                                           struct elf_phdr *epp,
+                                           struct linux_binprm *bprm, int pnum)
 {
+       int i;
        int retval = -EINVAL;
        struct file *file = NULL;
 
-       *name = kmalloc((ihdr->p_filesz + strlen(IRIX_INTERP_PREFIX)),
-                       GFP_KERNEL);
-       if (!*name)
-               return -ENOMEM;
+       *name = NULL;
+       for(i = 0; i < pnum; i++, epp++) {
+               if (epp->p_type != PT_INTERP)
+                       continue;
 
-       strcpy(*name, IRIX_INTERP_PREFIX);
-       retval = kernel_read(bprm->file, ihdr->p_offset, (*name + 16),
-                            ihdr->p_filesz);
-       if (retval < 0)
-               goto out;
+               /* It is illegal to have two interpreters for one executable. */
+               if (*name != NULL)
+                       goto out;
+
+               *name = (char *) kmalloc((epp->p_filesz +
+                                         strlen(IRIX_EMUL)),
+                                        GFP_KERNEL);
+               if (!*name)
+                       return -ENOMEM;
+
+               strcpy(*name, IRIX_EMUL);
+               retval = kernel_read(bprm->file, epp->p_offset, (*name + 16),
+                                    epp->p_filesz);
+               if (retval < 0)
+                       goto out;
+
+               file = open_exec(*name);
+               if (IS_ERR(file)) {
+                       retval = PTR_ERR(file);
+                       goto out;
+               }
+               retval = kernel_read(file, 0, bprm->buf, 128);
+               if (retval < 0)
+                       goto dput_and_out;
 
-       file = open_exec(*name);
-       if (IS_ERR(file)) {
-               retval = PTR_ERR(file);
-               goto out;
+               *interp_elf_ex = *(struct elfhdr *) bprm->buf;
        }
-
-       retval = kernel_read(file, 0, bprm->buf, 128);
-       if (retval < 0)
-               goto dput_and_out;
-
-       *interp_elf_ex = *(struct elfhdr *) bprm->buf;
-
        *interpreter = file;
-
        return 0;
 
 dput_and_out:
        fput(file);
-
 out:
        kfree(*name);
        return retval;
@@ -601,16 +602,26 @@
        elf_ex = *((struct elfhdr *) bprm->buf);
        retval = -ENOEXEC;
 
+       if (verify_binary(&elf_ex, bprm))
+               goto out;
+
        /*
-        * Here until I figure out why NFS filesystems are having
-        * problems with this code. I suspect locking of some sort,
-        * but for now we'll have to disable IRIX support.
+        * Telling -o32 static binaries from Linux and Irix apart from each
+        * other is difficult. There are 2 differences to be noted for static
+        * binaries from the 2 operating systems:
+        *
+        *    1) Irix binaries have their .text section before their .init
+        *       section. Linux binaries are just the opposite.
+        *
+        *    2) Irix binaries usually have <= 12 sections and Linux
+        *       binaries have > 20.
+        *
+        * We will use Method #2 since Method #1 would require us to read in
+        * the section headers which is way too much overhead. This appears
+        * to work for everything we have ran into so far. If anyone has a
+        * better method to tell the binaries apart, I'm listening.
         */
-#if 1
-       goto out;
-#endif
-
-       if (verify_binary(&elf_ex, bprm))
+       if (elf_ex.e_shnum > 20)
                goto out;
 
 #ifdef DEBUG_ELF
@@ -628,7 +639,6 @@
        }
 
        retval = kernel_read(bprm->file, elf_ex.e_phoff, (char *)elf_phdata, 
size);
-
        if (retval < 0)
                goto out_free_ph;
 
@@ -669,7 +679,8 @@
         * which should be the normal ELF binary handler.
         */
        retval = look_for_irix_interpreter(&elf_interpreter, &interpreter,
-                                          &interp_elf_ex, elf_ihdr, bprm);
+                                          &interp_elf_ex, elf_phdata, bprm,
+                                          elf_ex.e_phnum);
        if (retval) {
                retval = -ENOEXEC;
                goto out_free_file;
@@ -827,13 +838,6 @@
           !file->f_op->mmap)
                return -ENOEXEC;
 
-       /*
-        * FIXME: We need to check the SGI_ONLY flag if possible,
-        *        for now we will issue a warning when this occurs
-        *        which should be investigated further.
-        */
-       printk("%s: Check SGI_ONLY flag in this library!\n", __FUNCTION__);
-
        /* Now read in all of the header information. */
        if(sizeof(struct elf_phdr) * elf_ex.e_phnum > PAGE_SIZE)
                return -ENOEXEC;
@@ -1318,7 +1322,7 @@
 
 static int __init init_irix_binfmt(void)
 {
-       int init_inventory(void);
+       extern int init_inventory(void);
        extern asmlinkage unsigned long sys_call_table;
        extern asmlinkage unsigned long sys_call_table_irix5;
 
@@ -1337,7 +1341,9 @@
 
 static void __exit exit_irix_binfmt(void)
 {
-       /* Remove the IRIX ELF loaders. */
+       /*
+        * Remove the Irix ELF loader.
+        */
        unregister_binfmt(&irix_format);
 }
 

<Prev in Thread] Current Thread [Next in Thread>