2007-08-30 13:56:51

by Jiri Kosina

[permalink] [raw]
Subject: [PATCH] i386 and x86_64: randomize brk()

[resending, as discussed last week, thanks]


From: Jiri Kosina <[email protected]>

i386 and x86_64: randomize brk()

This patch randomizes the location of the heap (brk) for i386 and x86_64.
The range is randomized in the range starting at current brk location up
to 0x02000000 offset for both architectures. This, together with
pie-executable-randomization.patch and
pie-executable-randomization-fix.patch, should make the address space
randomization on i386 and x86_64 complete.

Signed-off-by: Jiri Kosina <[email protected]>

diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index 8466471..5817749 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -949,3 +949,15 @@ unsigned long arch_align_stack(unsigned long sp)
sp -= get_random_int() % 8192;
return sp & ~0xf;
}
+
+void arch_randomize_brk(void)
+{
+ unsigned long new_brk, range_start, range_end;
+
+ range_start = current->mm->brk;
+ range_end = range_start + 0x02000000;
+ new_brk = randomize_range(range_start, range_end, 0);
+ if (new_brk)
+ current->mm->brk = current->mm->start_brk = new_brk;
+}
+
diff --git a/arch/x86_64/ia32/ia32_binfmt.c b/arch/x86_64/ia32/ia32_binfmt.c
index dffd2ac..ccc4350 100644
--- a/arch/x86_64/ia32/ia32_binfmt.c
+++ b/arch/x86_64/ia32/ia32_binfmt.c
@@ -262,6 +262,7 @@ static void elf32_init(struct pt_regs *);
#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
#define arch_setup_additional_pages syscall32_setup_pages
extern int syscall32_setup_pages(struct linux_binprm *, int exstack);
+extern void arch_randomize_brk(void);

#include "../../../fs/binfmt_elf.c"

diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c
index 2842f50..5c3953c 100644
--- a/arch/x86_64/kernel/process.c
+++ b/arch/x86_64/kernel/process.c
@@ -902,3 +902,15 @@ unsigned long arch_align_stack(unsigned long sp)
sp -= get_random_int() % 8192;
return sp & ~0xf;
}
+
+void arch_randomize_brk(void)
+{
+ unsigned long new_brk, range_start, range_end;
+
+ range_start = current->mm->brk;
+ range_end = range_start + 0x02000000;
+ new_brk = randomize_range(range_start, range_end, 0);
+ if (new_brk)
+ current->mm->brk = current->mm->start_brk = new_brk;
+}
+
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index d65f1d9..4c92461 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -1073,6 +1073,9 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
current->mm->end_data = end_data;
current->mm->start_stack = bprm->p;

+ if (current->flags & PF_RANDOMIZE)
+ arch_randomize_brk();
+
if (current->personality & MMAP_PAGE_ZERO) {
/* Why this, you ask??? Well SVr4 maps page 0 as read-only,
and some applications "depend" upon this behavior.
diff --git a/include/asm-alpha/elf.h b/include/asm-alpha/elf.h
index 6c2d78f..18210cc 100644
--- a/include/asm-alpha/elf.h
+++ b/include/asm-alpha/elf.h
@@ -163,5 +163,9 @@ extern int alpha_l3_cacheshape;
NEW_AUX_ENT(AT_L3_CACHESHAPE, alpha_l3_cacheshape); \
} while (0)

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif /* __KERNEL__ */
#endif /* __ASM_ALPHA_ELF_H */
diff --git a/include/asm-arm/elf.h b/include/asm-arm/elf.h
index ec1c685..eeeee3f 100644
--- a/include/asm-arm/elf.h
+++ b/include/asm-arm/elf.h
@@ -116,4 +116,8 @@ extern char elf_platform[];

#endif

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif
diff --git a/include/asm-avr32/elf.h b/include/asm-avr32/elf.h
index d334b49..61b7d81 100644
--- a/include/asm-avr32/elf.h
+++ b/include/asm-avr32/elf.h
@@ -107,4 +107,8 @@ typedef struct user_fpu_struct elf_fpregset_t;
#define SET_PERSONALITY(ex, ibcs2) set_personality(PER_LINUX_32BIT)
#endif

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif /* __ASM_AVR32_ELF_H */
diff --git a/include/asm-blackfin/elf.h b/include/asm-blackfin/elf.h
index 5264b55..9223b86 100644
--- a/include/asm-blackfin/elf.h
+++ b/include/asm-blackfin/elf.h
@@ -124,4 +124,8 @@ do { \
#define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX)
#endif

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif
diff --git a/include/asm-cris/elf.h b/include/asm-cris/elf.h
index 96a40c1..10607c7 100644
--- a/include/asm-cris/elf.h
+++ b/include/asm-cris/elf.h
@@ -93,4 +93,8 @@ typedef unsigned long elf_fpregset_t;

#endif /* __KERNEL__ */

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif
diff --git a/include/asm-frv/elf.h b/include/asm-frv/elf.h
index 7df58a3..07df9dd 100644
--- a/include/asm-frv/elf.h
+++ b/include/asm-frv/elf.h
@@ -141,4 +141,8 @@ do { \
#define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX)
#endif

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif
diff --git a/include/asm-h8300/elf.h b/include/asm-h8300/elf.h
index 7ba6a0a..4ee6d1d 100644
--- a/include/asm-h8300/elf.h
+++ b/include/asm-h8300/elf.h
@@ -103,4 +103,8 @@ typedef unsigned long elf_fpregset_t;
#define R_H8_ABS32 65
#define R_H8_ABS32A16 127

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif
diff --git a/include/asm-i386/elf.h b/include/asm-i386/elf.h
index b32df3a..5935d4c 100644
--- a/include/asm-i386/elf.h
+++ b/include/asm-i386/elf.h
@@ -160,4 +160,6 @@ do if (vdso_enabled) { \

#endif

+extern void arch_randomize_brk(void);
+
#endif
diff --git a/include/asm-ia64/elf.h b/include/asm-ia64/elf.h
index 25f9835..3b84b0d 100644
--- a/include/asm-ia64/elf.h
+++ b/include/asm-ia64/elf.h
@@ -249,4 +249,8 @@ do { \

#endif /* __KERNEL__ */

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif /* _ASM_IA64_ELF_H */
diff --git a/include/asm-m32r/elf.h b/include/asm-m32r/elf.h
index bbee8b2..33a5244 100644
--- a/include/asm-m32r/elf.h
+++ b/include/asm-m32r/elf.h
@@ -133,4 +133,8 @@ typedef elf_fpreg_t elf_fpregset_t;
#define SET_PERSONALITY(ex, ibcs2) set_personality(PER_LINUX)
#endif

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif /* _ASM_M32R__ELF_H */
diff --git a/include/asm-m68k/elf.h b/include/asm-m68k/elf.h
index eb63b85..f6ff4fe 100644
--- a/include/asm-m68k/elf.h
+++ b/include/asm-m68k/elf.h
@@ -118,4 +118,8 @@ typedef struct user_m68kfp_struct elf_fpregset_t;
#define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX)
#endif

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif
diff --git a/include/asm-m68knommu/elf.h b/include/asm-m68knommu/elf.h
index 40b1ed6..d73f1d5 100644
--- a/include/asm-m68knommu/elf.h
+++ b/include/asm-m68knommu/elf.h
@@ -109,4 +109,8 @@ typedef struct user_m68kfp_struct elf_fpregset_t;
#define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX)
#endif

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif
diff --git a/include/asm-mips/elf.h b/include/asm-mips/elf.h
index e7d95d4..571cd80 100644
--- a/include/asm-mips/elf.h
+++ b/include/asm-mips/elf.h
@@ -372,4 +372,8 @@ extern int dump_task_fpu(struct task_struct *, elf_fpregset_t *);
#define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2)
#endif

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif /* _ASM_ELF_H */
diff --git a/include/asm-parisc/elf.h b/include/asm-parisc/elf.h
index f628ac7..9807cae 100644
--- a/include/asm-parisc/elf.h
+++ b/include/asm-parisc/elf.h
@@ -344,4 +344,8 @@ struct pt_regs; /* forward declaration... */
#define ELF_HWCAP 0
/* (boot_cpu_data.x86_capability) */

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif
diff --git a/include/asm-powerpc/elf.h b/include/asm-powerpc/elf.h
index de50799..af45d0e 100644
--- a/include/asm-powerpc/elf.h
+++ b/include/asm-powerpc/elf.h
@@ -422,4 +422,8 @@ extern void arch_write_notes(struct file *file);
#define ARCH_HAVE_EXTRA_ELF_NOTES
#endif /* CONFIG_PPC_CELL */

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif /* _ASM_POWERPC_ELF_H */
diff --git a/include/asm-s390/elf.h b/include/asm-s390/elf.h
index 91d0632..0a32ac3 100644
--- a/include/asm-s390/elf.h
+++ b/include/asm-s390/elf.h
@@ -216,4 +216,8 @@ do { \
#endif /* __s390x__ */
#endif

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif
diff --git a/include/asm-sh/elf.h b/include/asm-sh/elf.h
index 43ca244..f055a68 100644
--- a/include/asm-sh/elf.h
+++ b/include/asm-sh/elf.h
@@ -140,4 +140,8 @@ do { \
} while (0)
#endif /* CONFIG_VSYSCALL */

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif /* __ASM_SH_ELF_H */
diff --git a/include/asm-sh64/elf.h b/include/asm-sh64/elf.h
index f994286..5d6dd4b 100644
--- a/include/asm-sh64/elf.h
+++ b/include/asm-sh64/elf.h
@@ -104,4 +104,8 @@ typedef struct user_fpu_struct elf_fpregset_t;
#define SET_PERSONALITY(ex, ibcs2) set_personality(PER_LINUX_32BIT)
#endif

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif /* __ASM_SH64_ELF_H */
diff --git a/include/asm-sparc/elf.h b/include/asm-sparc/elf.h
index aaf6ef4..94b273d 100644
--- a/include/asm-sparc/elf.h
+++ b/include/asm-sparc/elf.h
@@ -168,4 +168,8 @@ do { unsigned long *dest = &(__elf_regs[0]); \

#endif /* __KERNEL__ */

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif /* !(__ASMSPARC_ELF_H) */
diff --git a/include/asm-sparc64/elf.h b/include/asm-sparc64/elf.h
index 303d85e..8afe25f 100644
--- a/include/asm-sparc64/elf.h
+++ b/include/asm-sparc64/elf.h
@@ -190,4 +190,8 @@ do { unsigned long new_flags = current_thread_info()->flags; \
} while (0)
#endif

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif /* !(__ASM_SPARC64_ELF_H) */
diff --git a/include/asm-um/elf-i386.h b/include/asm-um/elf-i386.h
diff --git a/include/asm-um/elf-ppc.h b/include/asm-um/elf-ppc.h
diff --git a/include/asm-um/elf-x86_64.h b/include/asm-um/elf-x86_64.h
index 8a8246d..4b8d4c6 100644
--- a/include/asm-um/elf-x86_64.h
+++ b/include/asm-um/elf-x86_64.h
@@ -81,6 +81,10 @@ extern long elf_aux_hwcap;

#define SET_PERSONALITY(ex, ibcs2) do ; while(0)

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif

/*
diff --git a/include/asm-v850/elf.h b/include/asm-v850/elf.h
index 7db8edf..2e72192 100644
--- a/include/asm-v850/elf.h
+++ b/include/asm-v850/elf.h
@@ -98,4 +98,8 @@ typedef struct user_fpu_struct elf_fpregset_t;
#define SET_PERSONALITY(ex, ibcs2) set_personality(PER_LINUX_32BIT)
#endif

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif /* __V850_ELF_H__ */
diff --git a/include/asm-x86_64/elf.h b/include/asm-x86_64/elf.h
index b4fbe47..5a1adf9 100644
--- a/include/asm-x86_64/elf.h
+++ b/include/asm-x86_64/elf.h
@@ -177,4 +177,6 @@ do if (vdso_enabled) { \

#endif

+extern void arch_randomize_brk(void);
+
#endif
diff --git a/include/asm-xtensa/elf.h b/include/asm-xtensa/elf.h
index 1569b53..10e60bf 100644
--- a/include/asm-xtensa/elf.h
+++ b/include/asm-xtensa/elf.h
@@ -222,5 +222,9 @@ extern void do_save_fpregs (elf_fpregset_t*, struct pt_regs*,
extern int do_restore_fpregs (elf_fpregset_t*, struct pt_regs*,
struct task_struct*);

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif /* __KERNEL__ */
#endif /* _XTENSA_ELF_H */


2007-08-30 14:02:16

by Mike Frysinger

[permalink] [raw]
Subject: Re: [PATCH] i386 and x86_64: randomize brk()

On 8/30/07, Jiri Kosina <[email protected]> wrote:
> From: Jiri Kosina <[email protected]>
>
> i386 and x86_64: randomize brk()
>
> This patch randomizes the location of the heap (brk) for i386 and x86_64.
> The range is randomized in the range starting at current brk location up
> to 0x02000000 offset for both architectures. This, together with
> pie-executable-randomization.patch and
> pie-executable-randomization-fix.patch, should make the address space
> randomization on i386 and x86_64 complete.
>
> Signed-off-by: Jiri Kosina <[email protected]>

does it really make sense to stick stubs into no-mmu ports which
cannot utilize the ELF binfmt ?
-mike

2007-08-30 14:21:25

by Jiri Kosina

[permalink] [raw]
Subject: Re: [PATCH] i386 and x86_64: randomize brk()

On Thu, 30 Aug 2007, Mike Frysinger wrote:

> does it really make sense to stick stubs into no-mmu ports which cannot
> utilize the ELF binfmt ?

Good point, thanks. I have removed the stubs for h8300 and m68knommu.


From: Jiri Kosina <[email protected]>

i386 and x86_64: randomize brk()

This patch randomizes the location of the heap (brk) for i386 and x86_64.
The range is randomized in the range starting at current brk location up
to 0x02000000 offset for both architectures. This, together with
pie-executable-randomization.patch and
pie-executable-randomization-fix.patch, should make the address space
randomization on i386 and x86_64 complete.

Signed-off-by: Jiri Kosina <[email protected]>

diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index 8466471..5817749 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -949,3 +949,15 @@ unsigned long arch_align_stack(unsigned long sp)
sp -= get_random_int() % 8192;
return sp & ~0xf;
}
+
+void arch_randomize_brk(void)
+{
+ unsigned long new_brk, range_start, range_end;
+
+ range_start = current->mm->brk;
+ range_end = range_start + 0x02000000;
+ new_brk = randomize_range(range_start, range_end, 0);
+ if (new_brk)
+ current->mm->brk = current->mm->start_brk = new_brk;
+}
+
diff --git a/arch/x86_64/ia32/ia32_binfmt.c b/arch/x86_64/ia32/ia32_binfmt.c
index dffd2ac..ccc4350 100644
--- a/arch/x86_64/ia32/ia32_binfmt.c
+++ b/arch/x86_64/ia32/ia32_binfmt.c
@@ -262,6 +262,7 @@ static void elf32_init(struct pt_regs *);
#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
#define arch_setup_additional_pages syscall32_setup_pages
extern int syscall32_setup_pages(struct linux_binprm *, int exstack);
+extern void arch_randomize_brk(void);

#include "../../../fs/binfmt_elf.c"

diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c
index 2842f50..5c3953c 100644
--- a/arch/x86_64/kernel/process.c
+++ b/arch/x86_64/kernel/process.c
@@ -902,3 +902,15 @@ unsigned long arch_align_stack(unsigned long sp)
sp -= get_random_int() % 8192;
return sp & ~0xf;
}
+
+void arch_randomize_brk(void)
+{
+ unsigned long new_brk, range_start, range_end;
+
+ range_start = current->mm->brk;
+ range_end = range_start + 0x02000000;
+ new_brk = randomize_range(range_start, range_end, 0);
+ if (new_brk)
+ current->mm->brk = current->mm->start_brk = new_brk;
+}
+
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index d65f1d9..4c92461 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -1073,6 +1073,9 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
current->mm->end_data = end_data;
current->mm->start_stack = bprm->p;

+ if (current->flags & PF_RANDOMIZE)
+ arch_randomize_brk();
+
if (current->personality & MMAP_PAGE_ZERO) {
/* Why this, you ask??? Well SVr4 maps page 0 as read-only,
and some applications "depend" upon this behavior.
diff --git a/include/asm-alpha/elf.h b/include/asm-alpha/elf.h
index 6c2d78f..18210cc 100644
--- a/include/asm-alpha/elf.h
+++ b/include/asm-alpha/elf.h
@@ -163,5 +163,9 @@ extern int alpha_l3_cacheshape;
NEW_AUX_ENT(AT_L3_CACHESHAPE, alpha_l3_cacheshape); \
} while (0)

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif /* __KERNEL__ */
#endif /* __ASM_ALPHA_ELF_H */
diff --git a/include/asm-arm/elf.h b/include/asm-arm/elf.h
index ec1c685..eeeee3f 100644
--- a/include/asm-arm/elf.h
+++ b/include/asm-arm/elf.h
@@ -116,4 +116,8 @@ extern char elf_platform[];

#endif

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif
diff --git a/include/asm-avr32/elf.h b/include/asm-avr32/elf.h
index d334b49..61b7d81 100644
--- a/include/asm-avr32/elf.h
+++ b/include/asm-avr32/elf.h
@@ -107,4 +107,8 @@ typedef struct user_fpu_struct elf_fpregset_t;
#define SET_PERSONALITY(ex, ibcs2) set_personality(PER_LINUX_32BIT)
#endif

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif /* __ASM_AVR32_ELF_H */
diff --git a/include/asm-blackfin/elf.h b/include/asm-blackfin/elf.h
index 5264b55..9223b86 100644
--- a/include/asm-blackfin/elf.h
+++ b/include/asm-blackfin/elf.h
@@ -124,4 +124,8 @@ do { \
#define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX)
#endif

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif
diff --git a/include/asm-cris/elf.h b/include/asm-cris/elf.h
index 96a40c1..10607c7 100644
--- a/include/asm-cris/elf.h
+++ b/include/asm-cris/elf.h
@@ -93,4 +93,8 @@ typedef unsigned long elf_fpregset_t;

#endif /* __KERNEL__ */

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif
diff --git a/include/asm-frv/elf.h b/include/asm-frv/elf.h
index 7df58a3..07df9dd 100644
--- a/include/asm-frv/elf.h
+++ b/include/asm-frv/elf.h
@@ -141,4 +141,8 @@ do { \
#define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX)
#endif

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif
diff --git a/include/asm-i386/elf.h b/include/asm-i386/elf.h
index b32df3a..5935d4c 100644
--- a/include/asm-i386/elf.h
+++ b/include/asm-i386/elf.h
@@ -160,4 +160,6 @@ do if (vdso_enabled) { \

#endif

+extern void arch_randomize_brk(void);
+
#endif
diff --git a/include/asm-ia64/elf.h b/include/asm-ia64/elf.h
index 25f9835..3b84b0d 100644
--- a/include/asm-ia64/elf.h
+++ b/include/asm-ia64/elf.h
@@ -249,4 +249,8 @@ do { \

#endif /* __KERNEL__ */

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif /* _ASM_IA64_ELF_H */
diff --git a/include/asm-m32r/elf.h b/include/asm-m32r/elf.h
index bbee8b2..33a5244 100644
--- a/include/asm-m32r/elf.h
+++ b/include/asm-m32r/elf.h
@@ -133,4 +133,8 @@ typedef elf_fpreg_t elf_fpregset_t;
#define SET_PERSONALITY(ex, ibcs2) set_personality(PER_LINUX)
#endif

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif /* _ASM_M32R__ELF_H */
diff --git a/include/asm-m68k/elf.h b/include/asm-m68k/elf.h
index eb63b85..f6ff4fe 100644
--- a/include/asm-m68k/elf.h
+++ b/include/asm-m68k/elf.h
@@ -118,4 +118,8 @@ typedef struct user_m68kfp_struct elf_fpregset_t;
#define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX)
#endif

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif
diff --git a/include/asm-mips/elf.h b/include/asm-mips/elf.h
index e7d95d4..571cd80 100644
--- a/include/asm-mips/elf.h
+++ b/include/asm-mips/elf.h
@@ -372,4 +372,8 @@ extern int dump_task_fpu(struct task_struct *, elf_fpregset_t *);
#define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2)
#endif

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif /* _ASM_ELF_H */
diff --git a/include/asm-parisc/elf.h b/include/asm-parisc/elf.h
index f628ac7..9807cae 100644
--- a/include/asm-parisc/elf.h
+++ b/include/asm-parisc/elf.h
@@ -344,4 +344,8 @@ struct pt_regs; /* forward declaration... */
#define ELF_HWCAP 0
/* (boot_cpu_data.x86_capability) */

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif
diff --git a/include/asm-powerpc/elf.h b/include/asm-powerpc/elf.h
index de50799..af45d0e 100644
--- a/include/asm-powerpc/elf.h
+++ b/include/asm-powerpc/elf.h
@@ -422,4 +422,8 @@ extern void arch_write_notes(struct file *file);
#define ARCH_HAVE_EXTRA_ELF_NOTES
#endif /* CONFIG_PPC_CELL */

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif /* _ASM_POWERPC_ELF_H */
diff --git a/include/asm-s390/elf.h b/include/asm-s390/elf.h
index 91d0632..0a32ac3 100644
--- a/include/asm-s390/elf.h
+++ b/include/asm-s390/elf.h
@@ -216,4 +216,8 @@ do { \
#endif /* __s390x__ */
#endif

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif
diff --git a/include/asm-sh/elf.h b/include/asm-sh/elf.h
index 43ca244..f055a68 100644
--- a/include/asm-sh/elf.h
+++ b/include/asm-sh/elf.h
@@ -140,4 +140,8 @@ do { \
} while (0)
#endif /* CONFIG_VSYSCALL */

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif /* __ASM_SH_ELF_H */
diff --git a/include/asm-sh64/elf.h b/include/asm-sh64/elf.h
index f994286..5d6dd4b 100644
--- a/include/asm-sh64/elf.h
+++ b/include/asm-sh64/elf.h
@@ -104,4 +104,8 @@ typedef struct user_fpu_struct elf_fpregset_t;
#define SET_PERSONALITY(ex, ibcs2) set_personality(PER_LINUX_32BIT)
#endif

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif /* __ASM_SH64_ELF_H */
diff --git a/include/asm-sparc/elf.h b/include/asm-sparc/elf.h
index aaf6ef4..94b273d 100644
--- a/include/asm-sparc/elf.h
+++ b/include/asm-sparc/elf.h
@@ -168,4 +168,8 @@ do { unsigned long *dest = &(__elf_regs[0]); \

#endif /* __KERNEL__ */

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif /* !(__ASMSPARC_ELF_H) */
diff --git a/include/asm-sparc64/elf.h b/include/asm-sparc64/elf.h
index 303d85e..8afe25f 100644
--- a/include/asm-sparc64/elf.h
+++ b/include/asm-sparc64/elf.h
@@ -190,4 +190,8 @@ do { unsigned long new_flags = current_thread_info()->flags; \
} while (0)
#endif

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif /* !(__ASM_SPARC64_ELF_H) */
diff --git a/include/asm-um/elf-i386.h b/include/asm-um/elf-i386.h
diff --git a/include/asm-um/elf-ppc.h b/include/asm-um/elf-ppc.h
diff --git a/include/asm-um/elf-x86_64.h b/include/asm-um/elf-x86_64.h
index 8a8246d..4b8d4c6 100644
--- a/include/asm-um/elf-x86_64.h
+++ b/include/asm-um/elf-x86_64.h
@@ -81,6 +81,10 @@ extern long elf_aux_hwcap;

#define SET_PERSONALITY(ex, ibcs2) do ; while(0)

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif

/*
diff --git a/include/asm-v850/elf.h b/include/asm-v850/elf.h
index 7db8edf..2e72192 100644
--- a/include/asm-v850/elf.h
+++ b/include/asm-v850/elf.h
@@ -98,4 +98,8 @@ typedef struct user_fpu_struct elf_fpregset_t;
#define SET_PERSONALITY(ex, ibcs2) set_personality(PER_LINUX_32BIT)
#endif

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif /* __V850_ELF_H__ */
diff --git a/include/asm-x86_64/elf.h b/include/asm-x86_64/elf.h
index b4fbe47..5a1adf9 100644
--- a/include/asm-x86_64/elf.h
+++ b/include/asm-x86_64/elf.h
@@ -177,4 +177,6 @@ do if (vdso_enabled) { \

#endif

+extern void arch_randomize_brk(void);
+
#endif
diff --git a/include/asm-xtensa/elf.h b/include/asm-xtensa/elf.h
index 1569b53..10e60bf 100644
--- a/include/asm-xtensa/elf.h
+++ b/include/asm-xtensa/elf.h
@@ -222,5 +222,9 @@ extern void do_save_fpregs (elf_fpregset_t*, struct pt_regs*,
extern int do_restore_fpregs (elf_fpregset_t*, struct pt_regs*,
struct task_struct*);

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif /* __KERNEL__ */
#endif /* _XTENSA_ELF_H */

2007-08-30 14:26:32

by Mike Frysinger

[permalink] [raw]
Subject: Re: [PATCH] i386 and x86_64: randomize brk()

On 8/30/07, Jiri Kosina <[email protected]> wrote:
> On Thu, 30 Aug 2007, Mike Frysinger wrote:
> > does it really make sense to stick stubs into no-mmu ports which cannot
> > utilize the ELF binfmt ?
>
> Good point, thanks. I have removed the stubs for h8300 and m68knommu.

Blackfin too please :)

i think v850 also falls into this category, but i'm not terribly
familiar with it ...
-mike

2007-08-30 15:10:18

by Jiri Kosina

[permalink] [raw]
Subject: Re: [PATCH] i386 and x86_64: randomize brk()

On Thu, 30 Aug 2007, Mike Frysinger wrote:

> Blackfin too please :) i think v850 also falls into this category, but
> i'm not terribly familiar with it ...

Andrew, do you still strongly oppose to having ARCH_HAS_RANDOMIZE_BRK
macro instead please?

Thanks,

--
Jiri Kosina
SUSE Labs

2007-08-30 15:33:20

by Franck Bui-Huu

[permalink] [raw]
Subject: Re: [PATCH] i386 and x86_64: randomize brk()

Jiri Kosina wrote:
> On Thu, 30 Aug 2007, Mike Frysinger wrote:
>
>> Blackfin too please :) i think v850 also falls into this category, but
>> i'm not terribly familiar with it ...
>
> Andrew, do you still strongly oppose to having ARCH_HAS_RANDOMIZE_BRK
> macro instead please?
>

you might want to use a weak function instead ?

void __weak arch_randomize_brk(void)
{
/* nada by default */
}

and overload it only for x86 architectures by now.

BTW, how about minimize the arch specific code by slighly changing its
prototype ?

unsigned long arch_randomize_brk(struct mm_struct *mm)
{
unsigned long range_end = mm->brk + 0x02000000;

return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
}

Franck

2007-08-31 01:05:55

by Andrew Morton

[permalink] [raw]
Subject: Re: [PATCH] i386 and x86_64: randomize brk()

On Thu, 30 Aug 2007 17:10:03 +0200 (CEST) Jiri Kosina <[email protected]> wrote:

> On Thu, 30 Aug 2007, Mike Frysinger wrote:
>
> > Blackfin too please :) i think v850 also falls into this category, but
> > i'm not terribly familiar with it ...
>
> Andrew, do you still strongly oppose to having ARCH_HAS_RANDOMIZE_BRK
> macro instead please?
>

Not strongly, but the general opinion seems to be that ARCH_HAS_FOO is
sucky. It should at least be done in Kconfig rather than in .h, but even
better is just to implement the thing for all architectures.

Please ask checkpatch.pl about you patch, too. It has commonly-occurring
coding mishaps.

2007-08-31 11:56:21

by Jiri Kosina

[permalink] [raw]
Subject: Re: [PATCH] i386 and x86_64: randomize brk()

On Thu, 30 Aug 2007, Andrew Morton wrote:

> Not strongly, but the general opinion seems to be that ARCH_HAS_FOO is
> sucky. It should at least be done in Kconfig rather than in .h, but
> even better is just to implement the thing for all architectures.

Below is an updated patch. checkpatch complains about adding extern into
arch/x86_64/ia32/ia32_binfmt.c, but it's needed to work with this crazy

#include "../../../fs/binfmt_elf.c"

in it.

It also complains about multiple assignments, but I don't seem to see
anything wrong with them here.


From: Jiri Kosina <[email protected]>

i386 and x86_64: randomize brk()

This patch randomizes the location of the heap (brk) for i386 and x86_64.
The range is randomized in the range starting at current brk location up
to 0x02000000 offset for both architectures. This, together with
pie-executable-randomization.patch and
pie-executable-randomization-fix.patch, should make the address space
randomization on i386 and x86_64 complete.

The empty stubs are not added for architectures that don't support ELF
binaries, namely blackfin, h8300, m68knommu and v850.

Signed-off-by: Jiri Kosina <[email protected]>

diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index 8466471..ba8ad15 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -949,3 +949,17 @@ unsigned long arch_align_stack(unsigned long sp)
sp -= get_random_int() % 8192;
return sp & ~0xf;
}
+
+void arch_randomize_brk(void)
+{
+ unsigned long new_brk;
+ unsigned long range_start;
+ unsigned long range_end;
+
+ range_start = current->mm->brk;
+ range_end = range_start + 0x02000000;
+ new_brk = randomize_range(range_start, range_end, 0);
+ if (new_brk)
+ current->mm->brk = current->mm->start_brk = new_brk;
+}
+
diff --git a/arch/x86_64/ia32/ia32_binfmt.c b/arch/x86_64/ia32/ia32_binfmt.c
index dffd2ac..ccc4350 100644
--- a/arch/x86_64/ia32/ia32_binfmt.c
+++ b/arch/x86_64/ia32/ia32_binfmt.c
@@ -262,6 +262,7 @@ static void elf32_init(struct pt_regs *);
#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
#define arch_setup_additional_pages syscall32_setup_pages
extern int syscall32_setup_pages(struct linux_binprm *, int exstack);
+extern void arch_randomize_brk(void);

#include "../../../fs/binfmt_elf.c"

diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c
index 2842f50..fe7203b 100644
--- a/arch/x86_64/kernel/process.c
+++ b/arch/x86_64/kernel/process.c
@@ -902,3 +902,17 @@ unsigned long arch_align_stack(unsigned long sp)
sp -= get_random_int() % 8192;
return sp & ~0xf;
}
+
+void arch_randomize_brk(void)
+{
+ unsigned long new_brk;
+ unsigned long range_start;
+ unsigned long range_end;
+
+ range_start = current->mm->brk;
+ range_end = range_start + 0x02000000;
+ new_brk = randomize_range(range_start, range_end, 0);
+ if (new_brk)
+ current->mm->brk = current->mm->start_brk = new_brk;
+}
+
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index d65f1d9..4c92461 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -1073,6 +1073,9 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
current->mm->end_data = end_data;
current->mm->start_stack = bprm->p;

+ if (current->flags & PF_RANDOMIZE)
+ arch_randomize_brk();
+
if (current->personality & MMAP_PAGE_ZERO) {
/* Why this, you ask??? Well SVr4 maps page 0 as read-only,
and some applications "depend" upon this behavior.
diff --git a/include/asm-alpha/elf.h b/include/asm-alpha/elf.h
index 6c2d78f..18210cc 100644
--- a/include/asm-alpha/elf.h
+++ b/include/asm-alpha/elf.h
@@ -163,5 +163,9 @@ extern int alpha_l3_cacheshape;
NEW_AUX_ENT(AT_L3_CACHESHAPE, alpha_l3_cacheshape); \
} while (0)

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif /* __KERNEL__ */
#endif /* __ASM_ALPHA_ELF_H */
diff --git a/include/asm-arm/elf.h b/include/asm-arm/elf.h
index ec1c685..eeeee3f 100644
--- a/include/asm-arm/elf.h
+++ b/include/asm-arm/elf.h
@@ -116,4 +116,8 @@ extern char elf_platform[];

#endif

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif
diff --git a/include/asm-avr32/elf.h b/include/asm-avr32/elf.h
index d334b49..61b7d81 100644
--- a/include/asm-avr32/elf.h
+++ b/include/asm-avr32/elf.h
@@ -107,4 +107,8 @@ typedef struct user_fpu_struct elf_fpregset_t;
#define SET_PERSONALITY(ex, ibcs2) set_personality(PER_LINUX_32BIT)
#endif

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif /* __ASM_AVR32_ELF_H */
diff --git a/include/asm-cris/elf.h b/include/asm-cris/elf.h
index 96a40c1..10607c7 100644
--- a/include/asm-cris/elf.h
+++ b/include/asm-cris/elf.h
@@ -93,4 +93,8 @@ typedef unsigned long elf_fpregset_t;

#endif /* __KERNEL__ */

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif
diff --git a/include/asm-frv/elf.h b/include/asm-frv/elf.h
index 7df58a3..07df9dd 100644
--- a/include/asm-frv/elf.h
+++ b/include/asm-frv/elf.h
@@ -141,4 +141,8 @@ do { \
#define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX)
#endif

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif
diff --git a/include/asm-i386/elf.h b/include/asm-i386/elf.h
index b32df3a..5935d4c 100644
--- a/include/asm-i386/elf.h
+++ b/include/asm-i386/elf.h
@@ -160,4 +160,6 @@ do if (vdso_enabled) { \

#endif

+extern void arch_randomize_brk(void);
+
#endif
diff --git a/include/asm-ia64/elf.h b/include/asm-ia64/elf.h
index 25f9835..3b84b0d 100644
--- a/include/asm-ia64/elf.h
+++ b/include/asm-ia64/elf.h
@@ -249,4 +249,8 @@ do { \

#endif /* __KERNEL__ */

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif /* _ASM_IA64_ELF_H */
diff --git a/include/asm-m32r/elf.h b/include/asm-m32r/elf.h
index bbee8b2..33a5244 100644
--- a/include/asm-m32r/elf.h
+++ b/include/asm-m32r/elf.h
@@ -133,4 +133,8 @@ typedef elf_fpreg_t elf_fpregset_t;
#define SET_PERSONALITY(ex, ibcs2) set_personality(PER_LINUX)
#endif

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif /* _ASM_M32R__ELF_H */
diff --git a/include/asm-m68k/elf.h b/include/asm-m68k/elf.h
index eb63b85..f6ff4fe 100644
--- a/include/asm-m68k/elf.h
+++ b/include/asm-m68k/elf.h
@@ -118,4 +118,8 @@ typedef struct user_m68kfp_struct elf_fpregset_t;
#define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX)
#endif

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif
diff --git a/include/asm-mips/elf.h b/include/asm-mips/elf.h
index e7d95d4..571cd80 100644
--- a/include/asm-mips/elf.h
+++ b/include/asm-mips/elf.h
@@ -372,4 +372,8 @@ extern int dump_task_fpu(struct task_struct *, elf_fpregset_t *);
#define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2)
#endif

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif /* _ASM_ELF_H */
diff --git a/include/asm-parisc/elf.h b/include/asm-parisc/elf.h
index f628ac7..9807cae 100644
--- a/include/asm-parisc/elf.h
+++ b/include/asm-parisc/elf.h
@@ -344,4 +344,8 @@ struct pt_regs; /* forward declaration... */
#define ELF_HWCAP 0
/* (boot_cpu_data.x86_capability) */

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif
diff --git a/include/asm-powerpc/elf.h b/include/asm-powerpc/elf.h
index de50799..af45d0e 100644
--- a/include/asm-powerpc/elf.h
+++ b/include/asm-powerpc/elf.h
@@ -422,4 +422,8 @@ extern void arch_write_notes(struct file *file);
#define ARCH_HAVE_EXTRA_ELF_NOTES
#endif /* CONFIG_PPC_CELL */

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif /* _ASM_POWERPC_ELF_H */
diff --git a/include/asm-s390/elf.h b/include/asm-s390/elf.h
index 91d0632..0a32ac3 100644
--- a/include/asm-s390/elf.h
+++ b/include/asm-s390/elf.h
@@ -216,4 +216,8 @@ do { \
#endif /* __s390x__ */
#endif

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif
diff --git a/include/asm-sh/elf.h b/include/asm-sh/elf.h
index 43ca244..f055a68 100644
--- a/include/asm-sh/elf.h
+++ b/include/asm-sh/elf.h
@@ -140,4 +140,8 @@ do { \
} while (0)
#endif /* CONFIG_VSYSCALL */

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif /* __ASM_SH_ELF_H */
diff --git a/include/asm-sh64/elf.h b/include/asm-sh64/elf.h
index f994286..5d6dd4b 100644
--- a/include/asm-sh64/elf.h
+++ b/include/asm-sh64/elf.h
@@ -104,4 +104,8 @@ typedef struct user_fpu_struct elf_fpregset_t;
#define SET_PERSONALITY(ex, ibcs2) set_personality(PER_LINUX_32BIT)
#endif

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif /* __ASM_SH64_ELF_H */
diff --git a/include/asm-sparc/elf.h b/include/asm-sparc/elf.h
index aaf6ef4..94b273d 100644
--- a/include/asm-sparc/elf.h
+++ b/include/asm-sparc/elf.h
@@ -168,4 +168,8 @@ do { unsigned long *dest = &(__elf_regs[0]); \

#endif /* __KERNEL__ */

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif /* !(__ASMSPARC_ELF_H) */
diff --git a/include/asm-sparc64/elf.h b/include/asm-sparc64/elf.h
index 303d85e..8afe25f 100644
--- a/include/asm-sparc64/elf.h
+++ b/include/asm-sparc64/elf.h
@@ -190,4 +190,8 @@ do { unsigned long new_flags = current_thread_info()->flags; \
} while (0)
#endif

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif /* !(__ASM_SPARC64_ELF_H) */
diff --git a/include/asm-um/elf-x86_64.h b/include/asm-um/elf-x86_64.h
index 8a8246d..e1d664e 100644
--- a/include/asm-um/elf-x86_64.h
+++ b/include/asm-um/elf-x86_64.h
@@ -81,6 +81,10 @@ extern long elf_aux_hwcap;

#define SET_PERSONALITY(ex, ibcs2) do ; while(0)

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif

/*
diff --git a/include/asm-x86_64/elf.h b/include/asm-x86_64/elf.h
index b4fbe47..5a1adf9 100644
--- a/include/asm-x86_64/elf.h
+++ b/include/asm-x86_64/elf.h
@@ -177,4 +177,6 @@ do if (vdso_enabled) { \

#endif

+extern void arch_randomize_brk(void);
+
#endif
diff --git a/include/asm-xtensa/elf.h b/include/asm-xtensa/elf.h
index 1569b53..10e60bf 100644
--- a/include/asm-xtensa/elf.h
+++ b/include/asm-xtensa/elf.h
@@ -222,5 +222,9 @@ extern void do_save_fpregs (elf_fpregset_t*, struct pt_regs*,
extern int do_restore_fpregs (elf_fpregset_t*, struct pt_regs*,
struct task_struct*);

+static inline void arch_randomize_brk(void)
+{
+}
+
#endif /* __KERNEL__ */
#endif /* _XTENSA_ELF_H */

2007-09-01 20:19:46

by Franck Bui-Huu

[permalink] [raw]
Subject: Re: [PATCH] i386 and x86_64: randomize brk()

Hello Andrew,

Andrew Morton wrote:
> On Thu, 30 Aug 2007 17:10:03 +0200 (CEST) Jiri Kosina <[email protected]> wrote:
>> Andrew, do you still strongly oppose to having ARCH_HAS_RANDOMIZE_BRK
>> macro instead please?
>>
>
> Not strongly, but the general opinion seems to be that ARCH_HAS_FOO is
> sucky. It should at least be done in Kconfig rather than in .h, but even
> better is just to implement the thing for all architectures.
>

Sorry for asking again but the initial poster haven't taken time to
answer to my feedbacks...

What about using a weak function in that case ? It actually gives a
default implementation in _one_ place and can be changed easily from
a nop to something more complex later.

Another point is that the current prototype of arch_randomize_brk()
could be slightly improved IMHO.

The proposed prototype is:

void arch_randomize_brk(void)

and I think it could be:

unsigned long randomize_brk(unsigned long brk)

Because the current code of exec syscall is rather.. hmm "tricky",
_hiding_ "current" global usage inside this function is error prone:
if this function is moved later, its use of "current->mm" could
reference the old mm process and it's hard to notice/fix.

thanks,
Franck

2007-09-02 20:29:24

by Andrew Morton

[permalink] [raw]
Subject: Re: [PATCH] i386 and x86_64: randomize brk()

> On Sat, 01 Sep 2007 22:19:01 +0200 Franck Bui-Huu <[email protected]> wrote:
> Hello Andrew,
>
> Andrew Morton wrote:
> > On Thu, 30 Aug 2007 17:10:03 +0200 (CEST) Jiri Kosina <[email protected]> wrote:
> >> Andrew, do you still strongly oppose to having ARCH_HAS_RANDOMIZE_BRK
> >> macro instead please?
> >>
> >
> > Not strongly, but the general opinion seems to be that ARCH_HAS_FOO is
> > sucky. It should at least be done in Kconfig rather than in .h, but even
> > better is just to implement the thing for all architectures.
> >
>
> Sorry for asking again but the initial poster haven't taken time to
> answer to my feedbacks...
>
> What about using a weak function in that case ? It actually gives a
> default implementation in _one_ place and can be changed easily from
> a nop to something more complex later.

Yeah, weak functions are by far the cleanest way of doing this - they're
most elegant. But they do add the overhead of an empty call/return, so
some thought needs to go into the tradeoff.

> Another point is that the current prototype of arch_randomize_brk()
> could be slightly improved IMHO.
>
> The proposed prototype is:
>
> void arch_randomize_brk(void)
>
> and I think it could be:
>
> unsigned long randomize_brk(unsigned long brk)
>
> Because the current code of exec syscall is rather.. hmm "tricky",
> _hiding_ "current" global usage inside this function is error prone:
> if this function is moved later, its use of "current->mm" could
> reference the old mm process and it's hard to notice/fix.

Could be..

2007-09-03 09:34:19

by Jiri Kosina

[permalink] [raw]
Subject: Re: [PATCH] i386 and x86_64: randomize brk()

On Sun, 2 Sep 2007, Andrew Morton wrote:

> > What about using a weak function in that case ? It actually gives a
> > default implementation in _one_ place and can be changed easily from a
> > nop to something more complex later.
> Yeah, weak functions are by far the cleanest way of doing this - they're
> most elegant. But they do add the overhead of an empty call/return, so
> some thought needs to go into the tradeoff.

Hi,

the problem I am seeing with __weak functions is that as far as I can see,
gcc 4.1.0 optimizes the empty __weak function away with -O2, so it is not
later properly overridden by the other non-weak function, as the callsite
already doesn't have the corresponding call. (when I stick a printk() into
the __weak function, everything works fine - it is not optimized away and
non-weak version of the function gets called).

I persume this is a bug in gcc (4.1.1 doesn't seem to expose this
behavior). I will look at it a little bit more.

Thanks,

--
Jiri Kosina
SUSE Labs

2007-09-03 10:03:17

by Jiri Kosina

[permalink] [raw]
Subject: Re: [PATCH] i386 and x86_64: randomize brk()

On Mon, 3 Sep 2007, Jiri Kosina wrote:

> the problem I am seeing with __weak functions is that as far as I can
> see, gcc 4.1.0 optimizes the empty __weak function away with -O2, so it
> is not later properly overridden by the other non-weak function, as the
> callsite already doesn't have the corresponding call. (when I stick a
> printk() into the __weak function, everything works fine - it is not
> optimized away and non-weak version of the function gets called). I
> persume this is a bug in gcc (4.1.1 doesn't seem to expose this
> behavior). I will look at it a little bit more.

OK, the problem was crappy 4.1.1 gcc on my side (that has been a known bug
and already fixed in later update). Updated patch below, thanks for your
suggestions Franck.


From: Jiri Kosina <[email protected]>

i386 and x86_64: randomize brk()

This patch randomizes the location of the heap (brk) for i386 and x86_64.
The range is randomized in the range starting at current brk location up
to 0x02000000 offset for both architectures. This, together with
pie-executable-randomization.patch and
pie-executable-randomization-fix.patch, should make the address space
randomization on i386 and x86_64 complete.

Signed-off-by: Jiri Kosina <[email protected]>

diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index 8466471..fb3d407 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -949,3 +949,17 @@ unsigned long arch_align_stack(unsigned long sp)
sp -= get_random_int() % 8192;
return sp & ~0xf;
}
+
+void arch_randomize_brk(struct mm_struct *mm)
+{
+ unsigned long new_brk;
+ unsigned long range_start;
+ unsigned long range_end;
+
+ range_start = mm->brk;
+ range_end = range_start + 0x02000000;
+ new_brk = randomize_range(range_start, range_end, 0);
+ if (new_brk)
+ mm->brk = mm->start_brk = new_brk;
+}
+
diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c
index 2842f50..de40057 100644
--- a/arch/x86_64/kernel/process.c
+++ b/arch/x86_64/kernel/process.c
@@ -902,3 +902,17 @@ unsigned long arch_align_stack(unsigned long sp)
sp -= get_random_int() % 8192;
return sp & ~0xf;
}
+
+void arch_randomize_brk(struct mm_struct *mm)
+{
+ unsigned long new_brk;
+ unsigned long range_start;
+ unsigned long range_end;
+
+ range_start = mm->brk;
+ range_end = range_start + 0x02000000;
+ new_brk = randomize_range(range_start, range_end, 0);
+ if (new_brk)
+ mm->brk = mm->start_brk = new_brk;
+}
+
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index d65f1d9..4bf0ca1 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -47,6 +47,9 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs);
static int load_elf_library(struct file *);
static unsigned long elf_map (struct file *, unsigned long, struct elf_phdr *, int, int, unsigned long);

+/* overriden by architectures supporting brk randomization */
+void __weak arch_randomize_brk(struct mm_struct *mm) { }
+
/*
* If we don't support core dumping, then supply a NULL so we
* don't even try.
@@ -1073,6 +1076,9 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
current->mm->end_data = end_data;
current->mm->start_stack = bprm->p;

+ if (current->flags & PF_RANDOMIZE)
+ arch_randomize_brk(current->mm);
+
if (current->personality & MMAP_PAGE_ZERO) {
/* Why this, you ask??? Well SVr4 maps page 0 as read-only,
and some applications "depend" upon this behavior.

2007-09-03 17:38:42

by Franck Bui-Huu

[permalink] [raw]
Subject: Re: [PATCH] i386 and x86_64: randomize brk()

Hi,

Jiri Kosina wrote:
> >

[snip]

> > +/* overriden by architectures supporting brk randomization */
> > +void __weak arch_randomize_brk(struct mm_struct *mm) { }

I was actually suggesting in my last email:

unsigned long randomize_brk(unsigned long brk)

therefore arch specific code don't have to know about implementation
details ie how to retrieve brk values from a mm. And it also matches
the prototype of arch_align_stack().

Franck



2007-09-03 20:44:21

by Jiri Kosina

[permalink] [raw]
Subject: Re: [PATCH] i386 and x86_64: randomize brk()

On Mon, 3 Sep 2007, Franck Bui-Huu wrote:

> > > +/* overriden by architectures supporting brk randomization */
> > > +void __weak arch_randomize_brk(struct mm_struct *mm) { }
> I was actually suggesting in my last email:
> unsigned long randomize_brk(unsigned long brk)
> therefore arch specific code don't have to know about implementation
> details ie how to retrieve brk values from a mm. And it also matches
> the prototype of arch_align_stack().

OK, I personally don't care that much. Andrew, the version as per Franck's
suggestion is below. It should be functionally equivalent to the patch
sent in my previous message in this thread, please consider merging one of
them. Thanks a lot.


From: Jiri Kosina <[email protected]>

i386 and x86_64: randomize brk()

This patch randomizes the location of the heap (brk) for i386 and x86_64.
The range is randomized in the range starting at current brk location up
to 0x02000000 offset for both architectures. This, together with
pie-executable-randomization.patch and
pie-executable-randomization-fix.patch, should make the address space
randomization on i386 and x86_64 complete.

Signed-off-by: Jiri Kosina <[email protected]>

diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index 8466471..8e0624d 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -949,3 +949,17 @@ unsigned long arch_align_stack(unsigned long sp)
sp -= get_random_int() % 8192;
return sp & ~0xf;
}
+
+unsigned long arch_randomize_brk(unsigned long brk)
+{
+ unsigned long new_brk;
+ unsigned long range_end;
+
+ range_end = brk + 0x02000000;
+ new_brk = randomize_range(brk, range_end, 0);
+ if (new_brk)
+ return new_brk;
+ else
+ return brk;
+}
+
diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c
index 2842f50..b20f0eb 100644
--- a/arch/x86_64/kernel/process.c
+++ b/arch/x86_64/kernel/process.c
@@ -902,3 +902,17 @@ unsigned long arch_align_stack(unsigned long sp)
sp -= get_random_int() % 8192;
return sp & ~0xf;
}
+
+unsigned long arch_randomize_brk(unsigned long brk)
+{
+ unsigned long new_brk;
+ unsigned long range_end;
+
+ range_end = brk + 0x02000000;
+ new_brk = randomize_range(brk, range_end, 0);
+ if (new_brk)
+ return new_brk;
+ else
+ return brk;
+}
+
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index d65f1d9..7afec71 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -47,6 +47,9 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs);
static int load_elf_library(struct file *);
static unsigned long elf_map (struct file *, unsigned long, struct elf_phdr *, int, int, unsigned long);

+/* overriden by architectures supporting brk randomization */
+unsigned long __weak arch_randomize_brk(unsigned long brk) { return brk; }
+
/*
* If we don't support core dumping, then supply a NULL so we
* don't even try.
@@ -1073,6 +1076,10 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
current->mm->end_data = end_data;
current->mm->start_stack = bprm->p;

+ if (current->flags & PF_RANDOMIZE)
+ current->mm->brk = current->mm->start_brk =
+ arch_randomize_brk(current->mm->brk);
+
if (current->personality & MMAP_PAGE_ZERO) {
/* Why this, you ask??? Well SVr4 maps page 0 as read-only,
and some applications "depend" upon this behavior.