Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

flat: fix data sections alignment

The flat loader uses an architecture's flat_stack_align() to align the
stack but assumes word-alignment is enough for the data sections.

However, on the Xtensa S6000 we have registers up to 128bit width
which can be used from userspace and therefor need userspace stack and
data-section alignment of at least this size.

This patch drops flat_stack_align() and uses the same alignment that
is required for slab caches, ARCH_SLAB_MINALIGN, or wordsize if it's
not defined by the architecture.

It also fixes m32r which was obviously kaput, aligning an
uninitialized stack entry instead of the stack pointer.

[akpm@linux-foundation.org: coding-style fixes]
Signed-off-by: Oskar Schirmer <os@emlix.com>
Cc: David Howells <dhowells@redhat.com>
Cc: Russell King <rmk@arm.linux.org.uk>
Cc: Bryan Wu <cooloney@kernel.org>
Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Acked-by: Paul Mundt <lethal@linux-sh.org>
Cc: Greg Ungerer <gerg@uclinux.org>
Signed-off-by: Johannes Weiner <jw@emlix.com>
Acked-by: Mike Frysinger <vapier.adi@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Oskar Schirmer and committed by
Linus Torvalds
c3dc5bec ba944719

+31 -23
-3
arch/arm/include/asm/flat.h
··· 5 5 #ifndef __ARM_FLAT_H__ 6 6 #define __ARM_FLAT_H__ 7 7 8 - /* An odd number of words will be pushed after this alignment, so 9 - deliberately misalign the value. */ 10 - #define flat_stack_align(sp) sp = (void *)(((unsigned long)(sp) - 4) | 4) 11 8 #define flat_argvp_envp_on_stack() 1 12 9 #define flat_old_ram_flag(flags) (flags) 13 10 #define flat_reloc_valid(reloc, size) ((reloc) <= (size))
-1
arch/blackfin/include/asm/flat.h
··· 10 10 11 11 #include <asm/unaligned.h> 12 12 13 - #define flat_stack_align(sp) /* nothing needed */ 14 13 #define flat_argvp_envp_on_stack() 0 15 14 #define flat_old_ram_flag(flags) (flags) 16 15
-1
arch/h8300/include/asm/flat.h
··· 5 5 #ifndef __H8300_FLAT_H__ 6 6 #define __H8300_FLAT_H__ 7 7 8 - #define flat_stack_align(sp) /* nothing needed */ 9 8 #define flat_argvp_envp_on_stack() 1 10 9 #define flat_old_ram_flag(flags) 1 11 10 #define flat_reloc_valid(reloc, size) ((reloc) <= (size))
-1
arch/m32r/include/asm/flat.h
··· 12 12 #ifndef __ASM_M32R_FLAT_H 13 13 #define __ASM_M32R_FLAT_H 14 14 15 - #define flat_stack_align(sp) (*sp += (*sp & 3 ? (4 - (*sp & 3)): 0)) 16 15 #define flat_argvp_envp_on_stack() 0 17 16 #define flat_old_ram_flag(flags) (flags) 18 17 #define flat_set_persistent(relval, p) 0
-1
arch/m68k/include/asm/flat.h
··· 5 5 #ifndef __M68KNOMMU_FLAT_H__ 6 6 #define __M68KNOMMU_FLAT_H__ 7 7 8 - #define flat_stack_align(sp) /* nothing needed */ 9 8 #define flat_argvp_envp_on_stack() 1 10 9 #define flat_old_ram_flag(flags) (flags) 11 10 #define flat_reloc_valid(reloc, size) ((reloc) <= (size))
-1
arch/sh/include/asm/flat.h
··· 12 12 #ifndef __ASM_SH_FLAT_H 13 13 #define __ASM_SH_FLAT_H 14 14 15 - #define flat_stack_align(sp) /* nothing needed */ 16 15 #define flat_argvp_envp_on_stack() 0 17 16 #define flat_old_ram_flag(flags) (flags) 18 17 #define flat_reloc_valid(reloc, size) ((reloc) <= (size))
+31 -15
fs/binfmt_flat.c
··· 41 41 #include <asm/uaccess.h> 42 42 #include <asm/unaligned.h> 43 43 #include <asm/cacheflush.h> 44 + #include <asm/page.h> 44 45 45 46 /****************************************************************************/ 46 47 ··· 53 52 #define DBG_FLT(a...) printk(a) 54 53 #else 55 54 #define DBG_FLT(a...) 55 + #endif 56 + 57 + /* 58 + * User data (stack, data section and bss) needs to be aligned 59 + * for the same reasons as SLAB memory is, and to the same amount. 60 + * Avoid duplicating architecture specific code by using the same 61 + * macro as with SLAB allocation: 62 + */ 63 + #ifdef ARCH_SLAB_MINALIGN 64 + #define FLAT_DATA_ALIGN (ARCH_SLAB_MINALIGN) 65 + #else 66 + #define FLAT_DATA_ALIGN (sizeof(void *)) 56 67 #endif 57 68 58 69 #define RELOC_FAILED 0xff00ff01 /* Relocation incorrect somewhere */ ··· 127 114 int envc = bprm->envc; 128 115 char uninitialized_var(dummy); 129 116 130 - sp = (unsigned long *) ((-(unsigned long)sizeof(char *))&(unsigned long) p); 117 + sp = (unsigned long *)p; 118 + sp -= (envc + argc + 2) + 1 + (flat_argvp_envp_on_stack() ? 2 : 0); 119 + sp = (unsigned long *) ((unsigned long)sp & -FLAT_DATA_ALIGN); 120 + argv = sp + 1 + (flat_argvp_envp_on_stack() ? 2 : 0); 121 + envp = argv + (argc + 1); 131 122 132 - sp -= envc+1; 133 - envp = sp; 134 - sp -= argc+1; 135 - argv = sp; 136 - 137 - flat_stack_align(sp); 138 123 if (flat_argvp_envp_on_stack()) { 139 - --sp; put_user((unsigned long) envp, sp); 140 - --sp; put_user((unsigned long) argv, sp); 124 + put_user((unsigned long) envp, sp + 2); 125 + put_user((unsigned long) argv, sp + 1); 141 126 } 142 127 143 - put_user(argc,--sp); 128 + put_user(argc, sp); 144 129 current->mm->arg_start = (unsigned long) p; 145 130 while (argc-->0) { 146 131 put_user((unsigned long) p, argv++); ··· 569 558 ret = realdatastart; 570 559 goto err; 571 560 } 572 - datapos = realdatastart + MAX_SHARED_LIBS * sizeof(unsigned long); 561 + datapos = ALIGN(realdatastart + 562 + MAX_SHARED_LIBS * sizeof(unsigned long), 563 + FLAT_DATA_ALIGN); 573 564 574 565 DBG_FLT("BINFMT_FLAT: Allocated data+bss+stack (%d bytes): %x\n", 575 566 (int)(data_len + bss_len + stack_len), (int)datapos); ··· 617 604 } 618 605 619 606 realdatastart = textpos + ntohl(hdr->data_start); 620 - datapos = realdatastart + MAX_SHARED_LIBS * sizeof(unsigned long); 621 - reloc = (unsigned long *) (textpos + ntohl(hdr->reloc_start) + 622 - MAX_SHARED_LIBS * sizeof(unsigned long)); 607 + datapos = ALIGN(realdatastart + 608 + MAX_SHARED_LIBS * sizeof(unsigned long), 609 + FLAT_DATA_ALIGN); 610 + 611 + reloc = (unsigned long *) 612 + (datapos + (ntohl(hdr->reloc_start) - text_len)); 623 613 memp = textpos; 624 614 memp_size = len; 625 615 #ifdef CONFIG_BINFMT_ZFLAT ··· 870 854 stack_len = TOP_OF_ARGS - bprm->p; /* the strings */ 871 855 stack_len += (bprm->argc + 1) * sizeof(char *); /* the argv array */ 872 856 stack_len += (bprm->envc + 1) * sizeof(char *); /* the envp array */ 873 - 857 + stack_len += FLAT_DATA_ALIGN - 1; /* reserve for upcoming alignment */ 874 858 875 859 res = load_flat_file(bprm, &libinfo, 0, &stack_len); 876 860 if (res > (unsigned long)-4096)