Hi folks,

I had this unsubmitted patch in my local filesystem.  It makes Linux
detect ELF32 AMD64 binaries and sets a flag to restrict them to
32-bit address space.

It's not rocket science but can save you some work in case you
haven't implemented this already.

Best regards

-- 
Robert Millan
diff -Nur linux-2.6-2.6.26-libre2.old/arch/x86/kernel/sys_x86_64.c 
linux-2.6-2.6.26-libre2/arch/x86/kernel/sys_x86_64.c
--- linux-2.6-2.6.26-libre2.old/arch/x86/kernel/sys_x86_64.c    2008-07-13 
23:51:29.000000000 +0200
+++ linux-2.6-2.6.26-libre2/arch/x86/kernel/sys_x86_64.c        2009-05-29 
22:57:41.000000000 +0200
@@ -48,7 +48,7 @@
 static void find_start_end(unsigned long flags, unsigned long *begin,
                           unsigned long *end)
 {
-       if (!test_thread_flag(TIF_IA32) && (flags & MAP_32BIT)) {
+       if ((!test_thread_flag(TIF_IA32) && (flags & MAP_32BIT)) || 
test_thread_flag(TIF_AMD32)) {
                unsigned long new_begin;
                /* This is usually used needed to map code in small
                   model, so it needs to be in the first 31bit. Limit
@@ -94,7 +94,7 @@
                    (!vma || addr + len <= vma->vm_start))
                        return addr;
        }
-       if (((flags & MAP_32BIT) || test_thread_flag(TIF_IA32))
+       if (((flags & MAP_32BIT) || test_thread_flag(TIF_IA32) || 
test_thread_flag(TIF_AMD32))
            && len <= mm->cached_hole_size) {
                mm->cached_hole_size = 0;
                mm->free_area_cache = begin;
@@ -150,8 +150,8 @@
        if (flags & MAP_FIXED)
                return addr;
 
-       /* for MAP_32BIT mappings we force the legact mmap base */
-       if (!test_thread_flag(TIF_IA32) && (flags & MAP_32BIT))
+       /* for MAP_32BIT mappings we force the legacy mmap base */
+       if ((!test_thread_flag(TIF_IA32) && (flags & MAP_32BIT)) || 
test_thread_flag(TIF_AMD32))
                goto bottomup;
 
        /* requesting a specific address */
@@ -232,5 +232,7 @@
        up_read(&uts_sem);
        if (personality(current->personality) == PER_LINUX32) 
                err |= copy_to_user(&name->machine, "i686", 5);                 
+       else if (test_thread_flag(TIF_AMD32))
+               err |= copy_to_user(&name->machine, "amd32", 6);
        return err ? -EFAULT : 0;
 }
diff -Nur linux-2.6-2.6.26-libre2.old/arch/x86/mm/mmap.c 
linux-2.6-2.6.26-libre2/arch/x86/mm/mmap.c
--- linux-2.6-2.6.26-libre2.old/arch/x86/mm/mmap.c      2008-07-13 
23:51:29.000000000 +0200
+++ linux-2.6-2.6.26-libre2/arch/x86/mm/mmap.c  2009-05-26 14:30:53.000000000 
+0200
@@ -53,6 +53,15 @@
        return 0;
 }
 
+static int mmap_is_32bit(void)
+{
+       if (mmap_is_ia32 ())
+               return 1;
+       if (test_thread_flag(TIF_AMD32))
+               return 1;
+       return 0;
+}
+
 static int mmap_is_legacy(void)
 {
        if (current->personality & ADDR_COMPAT_LAYOUT)
@@ -73,7 +82,7 @@
        * 28 bits of randomness in 64bit mmaps, 40 address space bits
        */
        if (current->flags & PF_RANDOMIZE) {
-               if (mmap_is_ia32())
+               if (mmap_is_32bit())
                        rnd = (long)get_random_int() % (1<<8);
                else
                        rnd = (long)(get_random_int() % (1<<28));
diff -Nur linux-2.6-2.6.26-libre2.old/fs/binfmt_elf_amd32.c 
linux-2.6-2.6.26-libre2/fs/binfmt_elf_amd32.c
--- linux-2.6-2.6.26-libre2.old/fs/binfmt_elf_amd32.c   1970-01-01 
01:00:00.000000000 +0100
+++ linux-2.6-2.6.26-libre2/fs/binfmt_elf_amd32.c       2009-05-26 
14:26:24.000000000 +0200
@@ -0,0 +1,46 @@
+/*
+ *  Support for loading AMD32 binaries
+ *  Copyright (C) 2009  Robert Millan
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/elfcore-compat.h>
+
+#undef ELF_CLASS
+#define        ELF_CLASS       ELFCLASS32
+
+#undef elfhdr
+#define elfhdr         elf32_hdr
+#undef elf_phdr
+#define elf_phdr       elf32_phdr
+#undef elf_note
+#define elf_note       elf32_note
+#undef elf_addr_t
+#define elf_addr_t     Elf32_Addr
+
+#undef ELF_PLATFORM
+#define        ELF_PLATFORM    ("amd32")
+
+#undef elf_check_arch
+#define        elf_check_arch(x)       ((x)->e_machine == EM_X86_64 && 
(x)->e_ident[EI_CLASS] == ELFCLASS32)
+
+#undef SET_PERSONALITY
+#define SET_PERSONALITY(ex, ibcs2)     do { set_personality_64bit(); 
set_thread_flag(TIF_AMD32); current->personality |= force_personality32; } 
while (0)
+
+/* Use the generic 32-bit definition from asm/elf.h */
+#undef ELF_ET_DYN_BASE
+#define        ELF_ET_DYN_BASE         COMPAT_ELF_ET_DYN_BASE
+
+#include "binfmt_elf.c"
diff -Nur linux-2.6-2.6.26-libre2.old/fs/Kconfig.binfmt 
linux-2.6-2.6.26-libre2/fs/Kconfig.binfmt
--- linux-2.6-2.6.26-libre2.old/fs/Kconfig.binfmt       2008-07-13 
23:51:29.000000000 +0200
+++ linux-2.6-2.6.26-libre2/fs/Kconfig.binfmt   2009-05-25 00:26:10.000000000 
+0200
@@ -23,6 +23,13 @@
          ld.so (check the file <file:Documentation/Changes> for location and
          latest version).
 
+config BINFMT_ELF_AMD32
+       bool "Kernel support for AMD32 binaries"
+       depends on X86_64
+       default y
+       help
+         Support for ELF32 binaries on AMD x86-64.
+
 config COMPAT_BINFMT_ELF
        bool
        depends on COMPAT && MMU
diff -Nur linux-2.6-2.6.26-libre2.old/fs/Makefile 
linux-2.6-2.6.26-libre2/fs/Makefile
--- linux-2.6-2.6.26-libre2.old/fs/Makefile     2008-07-13 23:51:29.000000000 
+0200
+++ linux-2.6-2.6.26-libre2/fs/Makefile 2009-05-25 00:24:37.000000000 +0200
@@ -39,6 +39,7 @@
 obj-y                          += binfmt_script.o
 
 obj-$(CONFIG_BINFMT_ELF)       += binfmt_elf.o
+obj-$(CONFIG_BINFMT_ELF_AMD32) += binfmt_elf_amd32.o
 obj-$(CONFIG_COMPAT_BINFMT_ELF)        += compat_binfmt_elf.o
 obj-$(CONFIG_BINFMT_ELF_FDPIC) += binfmt_elf_fdpic.o
 obj-$(CONFIG_BINFMT_SOM)       += binfmt_som.o
diff -Nur linux-2.6-2.6.26-libre2.old/include/asm-x86/elf.h 
linux-2.6-2.6.26-libre2/include/asm-x86/elf.h
--- linux-2.6-2.6.26-libre2.old/include/asm-x86/elf.h   2008-07-13 
23:51:29.000000000 +0200
+++ linux-2.6-2.6.26-libre2/include/asm-x86/elf.h       2009-05-26 
14:03:51.000000000 +0200
@@ -298,7 +298,7 @@
 #define VDSO_HIGH_BASE         0xffffe000U /* CONFIG_COMPAT_VDSO address */
 
 /* 1GB for 64bit, 8MB for 32bit */
-#define STACK_RND_MASK (test_thread_flag(TIF_IA32) ? 0x7ff : 0x3fffff)
+#define STACK_RND_MASK ((test_thread_flag(TIF_IA32) || 
test_thread_flag(TIF_AMD32)) ? 0x7ff : 0x3fffff)
 
 #define ARCH_DLINFO                                                    \
 do {                                                                   \
diff -Nur linux-2.6-2.6.26-libre2.old/include/asm-x86/processor.h 
linux-2.6-2.6.26-libre2/include/asm-x86/processor.h
--- linux-2.6-2.6.26-libre2.old/include/asm-x86/processor.h     2008-07-13 
23:51:29.000000000 +0200
+++ linux-2.6-2.6.26-libre2/include/asm-x86/processor.h 2009-05-26 
14:06:49.000000000 +0200
@@ -881,9 +881,9 @@
 #define IA32_PAGE_OFFSET       ((current->personality & ADDR_LIMIT_3GB) ? \
                                        0xc0000000 : 0xFFFFe000)
 
-#define TASK_SIZE              (test_thread_flag(TIF_IA32) ? \
+#define TASK_SIZE              ((test_thread_flag(TIF_IA32) || 
test_thread_flag(TIF_AMD32)) ? \
                                        IA32_PAGE_OFFSET : TASK_SIZE64)
-#define TASK_SIZE_OF(child)    ((test_tsk_thread_flag(child, TIF_IA32)) ? \
+#define TASK_SIZE_OF(child)    ((test_tsk_thread_flag(child, TIF_IA32) || 
test_tsk_thread_flag(child, TIF_AMD32)) ? \
                                        IA32_PAGE_OFFSET : TASK_SIZE64)
 
 #define STACK_TOP              TASK_SIZE
diff -Nur linux-2.6-2.6.26-libre2.old/include/asm-x86/thread_info_64.h 
linux-2.6-2.6.26-libre2/include/asm-x86/thread_info_64.h
--- linux-2.6-2.6.26-libre2.old/include/asm-x86/thread_info_64.h        
2008-07-13 23:51:29.000000000 +0200
+++ linux-2.6-2.6.26-libre2/include/asm-x86/thread_info_64.h    2009-05-26 
14:28:33.000000000 +0200
@@ -111,8 +111,8 @@
 #define TIF_SECCOMP            8       /* secure computing */
 #define TIF_MCE_NOTIFY         10      /* notify userspace of an MCE */
 #define TIF_HRTICK_RESCHED     11      /* reprogram hrtick timer */
-/* 16 free */
-#define TIF_IA32               17      /* 32bit process */
+#define TIF_AMD32              16      /* 32bit AMD process */
+#define TIF_IA32               17      /* 32bit Intel process */
 #define TIF_FORK               18      /* ret_from_fork */
 #define TIF_ABI_PENDING                19
 #define TIF_MEMDIE             20
@@ -134,6 +134,7 @@
 #define _TIF_SECCOMP           (1 << TIF_SECCOMP)
 #define _TIF_MCE_NOTIFY                (1 << TIF_MCE_NOTIFY)
 #define _TIF_HRTICK_RESCHED    (1 << TIF_HRTICK_RESCHED)
+#define _TIF_AMD32             (1 << TIF_AMD32)
 #define _TIF_IA32              (1 << TIF_IA32)
 #define _TIF_FORK              (1 << TIF_FORK)
 #define _TIF_ABI_PENDING       (1 << TIF_ABI_PENDING)

Reply via email to