[PATCH 4/4] Blackfin: binfmt patch to enhance stacking checking

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi all,

 This is a patch to enable stacks in L1 scratchpad memory for flat
binaries. A small area of L1 scratchpad memory is reserved to hold
task-specific information, in particular the stack pointer limit. This
will be used by an upcoming gcc patch to implement stack checking in a
way that's compatible with both flat and ELF. When task switching,
this area is swapped out to the thread_info structure.
 As a future enhancement, we can add code to libpthread and/or the
kernel to update this information for clone()d tasks; then we'll have
stack checking for threaded applications as well.
Another enhancement will be to let the compiler track the maximum
stack usage by using the second field in the L1 info structure.

Signed-off-by:  Luke Yang <[email protected]>

fs/binfmt_elf_fdpic.c       |    7 +-
fs/binfmt_flat.c            |  150 ++++++++++++++++++++++++++------------------
include/asm-arm/mmu.h       |    1
include/asm-frv/mmu.h       |    1
include/asm-h8300/mmu.h     |    1
include/asm-m32r/mmu.h      |    1
include/asm-m68knommu/mmu.h |    1
include/asm-sh/mmu.h        |    1
include/asm-v850/mmu.h      |    1
include/linux/flat.h        |   13 ++-
10 files changed, 112 insertions(+), 65 deletions(-)


diff -urN linux-2.6.18.patch2/fs/binfmt_elf_fdpic.c
linux-2.6.18.patch3/fs/binfmt_elf_fdpic.c
--- linux-2.6.18.patch2/fs/binfmt_elf_fdpic.c	2006-09-21
09:37:18.000000000 +0800
+++ linux-2.6.18.patch3/fs/binfmt_elf_fdpic.c	2006-09-21
11:17:49.000000000 +0800
@@ -170,7 +170,7 @@
{
	struct elf_fdpic_params exec_params, interp_params;
	struct elf_phdr *phdr;
-	unsigned long stack_size, entryaddr;
+	unsigned long stack_size, entryaddr, requested_stack_size;
#ifndef CONFIG_MMU
	unsigned long fullsize;
#endif
@@ -361,6 +361,7 @@
	 * - the stack starts at the top and works down
	 */
	stack_size = (stack_size + PAGE_SIZE - 1) & PAGE_MASK;
+	requested_stack_size = stack_size;
	if (stack_size < PAGE_SIZE * 2)
		stack_size = PAGE_SIZE * 2;

@@ -388,6 +389,8 @@
	current->mm->context.end_brk = current->mm->start_brk;
	current->mm->context.end_brk +=
		(stack_size > PAGE_SIZE) ? (stack_size - PAGE_SIZE) : 0;
+	current->mm->context.stack_start =
+		current->mm->start_brk + stack_size - requested_stack_size;
	current->mm->start_stack = current->mm->start_brk + stack_size;
#endif

@@ -959,6 +962,8 @@
}
#endif

+extern void *safe_dma_memcpy(void *, const void *, size_t);
+
/*****************************************************************************/
/*
 * map a binary by direct mmap() of the individual PT_LOAD segments
diff -urN linux-2.6.18.patch2/fs/binfmt_flat.c
linux-2.6.18.patch3/fs/binfmt_flat.c
--- linux-2.6.18.patch2/fs/binfmt_flat.c	2006-09-21 09:37:18.000000000 +0800
+++ linux-2.6.18.patch3/fs/binfmt_flat.c	2006-09-21 09:52:02.000000000 +0800
@@ -16,6 +16,7 @@
 */

#include <linux/module.h>
+#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mm.h>
@@ -35,13 +36,13 @@
#include <linux/personality.h>
#include <linux/init.h>
#include <linux/flat.h>
-#include <linux/syscalls.h>

#include <asm/byteorder.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/unaligned.h>
#include <asm/cacheflush.h>
+#include <asm/mmu_context.h>

/****************************************************************************/

@@ -77,6 +78,8 @@
static int load_flat_binary(struct linux_binprm *, struct pt_regs * regs);
static int flat_core_dump(long signr, struct pt_regs * regs, struct
file *file);

+extern void dump_thread(struct pt_regs *, struct user *);
+
static struct linux_binfmt flat_format = {
	.module		= THIS_MODULE,
	.load_binary	= load_flat_binary,
@@ -413,7 +416,9 @@
/****************************************************************************/

static int load_flat_file(struct linux_binprm * bprm,
-		struct lib_info *libinfo, int id, unsigned long *extra_stack)
+			  struct lib_info *libinfo, int id,
+			  unsigned long *extra_stack,
+			  unsigned long *stack_base)
{
	struct flat_hdr * hdr;
	unsigned long textpos = 0, datapos = 0, result;
@@ -426,7 +431,6 @@
	int i, rev, relocs = 0;
	loff_t fpos;
	unsigned long start_code, end_code;
-	int ret;

	hdr = ((struct flat_hdr *) bprm->buf);		/* exec-header */
	inode = bprm->file->f_dentry->d_inode;
@@ -451,25 +455,24 @@
		 */
		if (strncmp(hdr->magic, "#!", 2))
			printk("BINFMT_FLAT: bad header magic\n");
-		ret = -ENOEXEC;
-		goto err;
+		return -ENOEXEC;
	}
-
+#ifdef DEBUG
+	flags |= FLAT_FLAG_KTRACE;
+#endif
	if (flags & FLAT_FLAG_KTRACE)
		printk("BINFMT_FLAT: Loading file: %s\n", bprm->filename);

	if (rev != FLAT_VERSION && rev != OLD_FLAT_VERSION) {
		printk("BINFMT_FLAT: bad flat file version 0x%x (supported 0x%x and
0x%x)\n", rev, FLAT_VERSION, OLD_FLAT_VERSION);
-		ret = -ENOEXEC;
-		goto err;
+		return -ENOEXEC;
	}
-	
+
	/* Don't allow old format executables to use shared libraries */
	if (rev == OLD_FLAT_VERSION && id != 0) {
		printk("BINFMT_FLAT: shared libraries are not available before rev 0x%x\n",
				(int) FLAT_VERSION);
-		ret = -ENOEXEC;
-		goto err;
+		return -ENOEXEC;
	}

	/*
@@ -482,8 +485,7 @@
#ifndef CONFIG_BINFMT_ZFLAT
	if (flags & (FLAT_FLAG_GZIP|FLAT_FLAG_GZDATA)) {
		printk("Support for ZFLAT executables is not enabled.\n");
-		ret = -ENOEXEC;
-		goto err;
+		return -ENOEXEC;
	}
#endif

@@ -495,18 +497,27 @@
	rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur;
	if (rlim >= RLIM_INFINITY)
		rlim = ~0;
-	if (data_len + bss_len > rlim) {
-		ret = -ENOMEM;
-		goto err;
+	if (data_len + bss_len > rlim)
+		return -ENOMEM;
+
+	if (flags & FLAT_FLAG_L1STK) {
+		if (stack_base == 0) {
+			printk ("BINFMT_FLAT: requesting L1 stack for shared library\n");
+			return -ENOEXEC;
+		}
+		stack_len = alloc_l1stack(stack_len, stack_base);
+		if (stack_len == 0) {
+			printk("BINFMT_FLAT: stack size with arguments exceeds scratchpad
memory\n");
+			return -ENOMEM;
+		}
+		*extra_stack = stack_len;
	}

	/* Flush all traces of the currently running executable */
	if (id == 0) {
		result = flush_old_exec(bprm);
-		if (result) {
-			ret = result;
-			goto err;
-		}
+		if (result)
+			goto out_fail;

		/* OK, This is the point of no return */
		set_personality(PER_LINUX_32BIT);
@@ -536,14 +547,17 @@
			if (!textpos)
				textpos = (unsigned long) -ENOMEM;
			printk("Unable to mmap process text, errno %d\n", (int)-textpos);
-			ret = textpos;
-			goto err;
+			result = textpos;
+			goto out_fail;
		}

		down_write(&current->mm->mmap_sem);
		realdatastart = do_mmap(0, 0, data_len + extra +
				MAX_SHARED_LIBS * sizeof(unsigned long),
				PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0);
+		do_mremap(realdatastart, data_len + extra +
+			  MAX_SHARED_LIBS * sizeof(unsigned long),
+			  ksize((void *)realdatastart), 0, 0);
		up_write(&current->mm->mmap_sem);

		if (realdatastart == 0 || realdatastart >= (unsigned long)-4096) {
@@ -552,8 +566,8 @@
			printk("Unable to allocate RAM for process data, errno %d\n",
					(int)-datapos);
			do_munmap(current->mm, textpos, text_len);
-			ret = realdatastart;
-			goto err;
+			result = realdatastart;
+			goto out_fail;
		}
		datapos = realdatastart + MAX_SHARED_LIBS * sizeof(unsigned long);

@@ -575,8 +589,7 @@
			printk("Unable to read data+bss, errno %d\n", (int)-result);
			do_munmap(current->mm, textpos, text_len);
			do_munmap(current->mm, realdatastart, data_len + extra);
-			ret = result;
-			goto err;
+			goto out_fail;
		}

		reloc = (unsigned long *) (datapos+(ntohl(hdr->reloc_start)-text_len));
@@ -588,15 +601,19 @@
		textpos = do_mmap(0, 0, text_len + data_len + extra +
					MAX_SHARED_LIBS * sizeof(unsigned long),
				PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0);
-		up_write(&current->mm->mmap_sem);
		if (!textpos  || textpos >= (unsigned long) -4096) {
+			up_write(&current->mm->mmap_sem);
			if (!textpos)
				textpos = (unsigned long) -ENOMEM;
			printk("Unable to allocate RAM for process text/data, errno %d\n",
					(int)-textpos);
-			ret = textpos;
-			goto err;
+			result = textpos;
+			goto out_fail;
		}
+		do_mremap(textpos, text_len + data_len + extra +
+			  MAX_SHARED_LIBS * sizeof(unsigned long),
+			  ksize((void *)textpos), 0, 0);
+		up_write(&current->mm->mmap_sem);

		realdatastart = textpos + ntohl(hdr->data_start);
		datapos = realdatastart + MAX_SHARED_LIBS * sizeof(unsigned long);
@@ -640,8 +657,7 @@
			printk("Unable to read code+data+bss, errno %d\n",(int)-result);
			do_munmap(current->mm, textpos, text_len + data_len + extra +
				MAX_SHARED_LIBS * sizeof(unsigned long));
-			ret = result;
-			goto err;
+			goto out_fail;
		}
	}

@@ -665,6 +681,7 @@
		current->mm->start_brk = datapos + data_len + bss_len;
		current->mm->brk = (current->mm->start_brk + 3) & ~3;
		current->mm->context.end_brk = memp + ksize((void *) memp) - stack_len;
+		current->mm->context.stack_start = current->mm->context.end_brk;
	}

	if (flags & FLAT_FLAG_KTRACE)
@@ -686,7 +703,7 @@
	libinfo->lib_list[id].loaded = 1;
	libinfo->lib_list[id].entry = (0x00ffffff & ntohl(hdr->entry)) + textpos;
	libinfo->lib_list[id].build_date = ntohl(hdr->build_date);
-	
+
	/*
	 * We just load the allocations into some temporary memory to
	 * help simplify all this mumbo jumbo
@@ -705,8 +722,8 @@
			if (*rp) {
				addr = calc_reloc(*rp, libinfo, id, 0);
				if (addr == RELOC_FAILED) {
-					ret = -ENOEXEC;
-					goto err;
+					result = -ENOEXEC;
+					goto out_fail;
				}
				*rp = addr;
			}
@@ -725,6 +742,7 @@
	 * __start to address 4 so that is okay).
	 */
	if (rev > OLD_FLAT_VERSION) {
+		unsigned long persistent = 0;
		for (i=0; i < relocs; i++) {
			unsigned long addr, relval;

@@ -732,16 +750,20 @@
			   relocated (of course, the address has to be
			   relocated first).  */
			relval = ntohl(reloc[i]);
+			if (flat_set_persistent (relval, &persistent))
+				continue;
			addr = flat_get_relocate_addr(relval);
			rp = (unsigned long *) calc_reloc(addr, libinfo, id, 1);
			if (rp == (unsigned long *)RELOC_FAILED) {
-				ret = -ENOEXEC;
-				goto err;
+				result = -ENOEXEC;
+				goto out_fail;
			}

			/* Get the pointer's value.  */
-			addr = flat_get_addr_from_rp(rp, relval, flags);
-			if (addr != 0) {
+			addr = flat_get_addr_from_rp(rp, relval, flags, &persistent);
+			if (addr == 0)
+				continue;
+			if (! flat_addr_absolute (relval)) {
				/*
				 * Do the relocation.  PIC relocs in the data section are
				 * already in target order
@@ -750,30 +772,31 @@
					addr = ntohl(addr);
				addr = calc_reloc(addr, libinfo, id, 0);
				if (addr == RELOC_FAILED) {
-					ret = -ENOEXEC;
-					goto err;
+					result = -ENOEXEC;
+					goto out_fail;
				}
-
-				/* Write back the relocated pointer.  */
-				flat_put_addr_at_rp(rp, addr, relval);
			}
+			/* Write back the relocated pointer.  */
+			flat_put_addr_at_rp(rp, addr, relval);
		}
	} else {
		for (i=0; i < relocs; i++)
			old_reloc(ntohl(reloc[i]));
	}
-	
+
	flush_icache_range(start_code, end_code);

	/* zero the BSS,  BRK and stack areas */
-	memset((void*)(datapos + data_len), 0, bss_len +
+	memset((void*)(datapos + data_len), 0, bss_len +
			(memp + ksize((void *) memp) - stack_len -	/* end brk */
			libinfo->lib_list[id].start_brk) +		/* start brk */
			stack_len);

	return 0;
-err:
-	return ret;
+ out_fail:
+	if (flags & FLAT_FLAG_L1STK)
+		free_l1stack();
+	return result;
}


@@ -804,7 +827,7 @@
	res = prepare_binprm(&bprm);

	if (res <= (unsigned long)-4096)
-		res = load_flat_file(&bprm, libs, id, NULL);
+		res = load_flat_file(&bprm, libs, id, NULL, NULL);
	if (bprm.file) {
		allow_write_access(bprm.file);
		fput(bprm.file);
@@ -827,6 +850,7 @@
	unsigned long p = bprm->p;
	unsigned long stack_len;
	unsigned long start_addr;
+	unsigned long l1stack_base, ramstack_top;
	unsigned long *sp;
	int res;
	int i, j;
@@ -844,11 +868,11 @@
	stack_len += (bprm->argc + 1) * sizeof(char *); /* the argv array */
	stack_len += (bprm->envc + 1) * sizeof(char *); /* the envp array */

-	
-	res = load_flat_file(bprm, &libinfo, 0, &stack_len);
+	l1stack_base = 0;
+	res = load_flat_file(bprm, &libinfo, 0, &stack_len, &l1stack_base);
	if (res > (unsigned long)-4096)
		return res;
-	
+
	/* Update data segment pointers for all libraries */
	for (i=0; i<MAX_SHARED_LIBS; i++)
		if (libinfo.lib_list[i].loaded)
@@ -863,6 +887,7 @@
	set_binfmt(&flat_format);

	p = ((current->mm->context.end_brk + stack_len + 3) & ~3) - 4;
+	ramstack_top = p;
	DBG_FLT("p=%x\n", (int)p);

	/* copy the arg pages onto the stack, this could be more efficient :-) */
@@ -871,7 +896,7 @@
			((char *) page_address(bprm->page[i/PAGE_SIZE]))[i % PAGE_SIZE];

	sp = (unsigned long *) create_flat_tables(p, bprm);
-	
+
	/* Fake some return addresses to ensure the call chain will
	 * initialise library in order for us.  We are required to call
	 * lib 1 first, then 2, ... and finally the main program (id 0).
@@ -887,15 +912,24 @@
		}
	}
#endif
-	
+
	/* Stash our initial stack pointer into the mm structure */
	current->mm->start_stack = (unsigned long )sp;

-	
-	DBG_FLT("start_thread(regs=0x%x, entry=0x%x, start_stack=0x%x)\n",
-		(int)regs, (int)start_addr, (int)current->mm->start_stack);
-	
-	start_thread(regs, start_addr, current->mm->start_stack);
+	if (l1stack_base) {
+		/* Find L1 stack pointer corresponding to the current bottom
+		   of the stack in normal RAM.  */
+		l1stack_base += stack_len - (ramstack_top - (unsigned long)sp);
+		if (!activate_l1stack(current->mm, ramstack_top - stack_len))
+			l1stack_base = 0;
+	}
+
+	DBG_FLT("start_thread(regs=0x%x, entry=0x%x, start_stack=0x%x,
l1stk=0x%x, len 0x%x)\n",
+		(int)regs, (int)start_addr, (int)current->mm->start_stack, l1stack_base,
+		stack_len);
+
+	start_thread(regs, start_addr,
+		     l1stack_base ? l1stack_base : current->mm->start_stack);

	if (current->ptrace & PT_PTRACED)
		send_sig(SIGTRAP, current, 0);
diff -urN linux-2.6.18.patch2/include/asm-arm/mmu.h
linux-2.6.18.patch3/include/asm-arm/mmu.h
--- linux-2.6.18.patch2/include/asm-arm/mmu.h	2006-09-21
09:37:24.000000000 +0800
+++ linux-2.6.18.patch3/include/asm-arm/mmu.h	2006-09-21
09:52:02.000000000 +0800
@@ -26,6 +26,7 @@
typedef struct {
	struct vm_list_struct	*vmlist;
	unsigned long		end_brk;
+	unsigned long		stack_start;
} mm_context_t;

#endif
diff -urN linux-2.6.18.patch2/include/asm-frv/mmu.h
linux-2.6.18.patch3/include/asm-frv/mmu.h
--- linux-2.6.18.patch2/include/asm-frv/mmu.h	2006-09-21
09:37:25.000000000 +0800
+++ linux-2.6.18.patch3/include/asm-frv/mmu.h	2006-09-21
09:52:02.000000000 +0800
@@ -24,6 +24,7 @@
#else
	struct vm_list_struct	*vmlist;
	unsigned long		end_brk;
+	unsigned long		stack_start;

#endif

diff -urN linux-2.6.18.patch2/include/asm-h8300/mmu.h
linux-2.6.18.patch3/include/asm-h8300/mmu.h
--- linux-2.6.18.patch2/include/asm-h8300/mmu.h	2006-09-21
09:37:26.000000000 +0800
+++ linux-2.6.18.patch3/include/asm-h8300/mmu.h	2006-09-21
09:52:02.000000000 +0800
@@ -6,6 +6,7 @@
typedef struct {
	struct vm_list_struct	*vmlist;
	unsigned long		end_brk;
+	unsigned long		stack_start;
} mm_context_t;

#endif
diff -urN linux-2.6.18.patch2/include/asm-m32r/mmu.h
linux-2.6.18.patch3/include/asm-m32r/mmu.h
--- linux-2.6.18.patch2/include/asm-m32r/mmu.h	2006-09-21
09:37:26.000000000 +0800
+++ linux-2.6.18.patch3/include/asm-m32r/mmu.h	2006-09-21
09:52:02.000000000 +0800
@@ -6,6 +6,7 @@
typedef struct {
	struct vm_list_struct	*vmlist;
	unsigned long		end_brk;
+	unsigned long		stack_start;
} mm_context_t;
#else

diff -urN linux-2.6.18.patch2/include/asm-m68knommu/mmu.h
linux-2.6.18.patch3/include/asm-m68knommu/mmu.h
--- linux-2.6.18.patch2/include/asm-m68knommu/mmu.h	2006-09-21
09:37:26.000000000 +0800
+++ linux-2.6.18.patch3/include/asm-m68knommu/mmu.h	2006-09-21
09:52:02.000000000 +0800
@@ -6,6 +6,7 @@
typedef struct {
	struct vm_list_struct	*vmlist;
	unsigned long		end_brk;
+	unsigned long		stack_start;
} mm_context_t;

#endif /* __M68KNOMMU_MMU_H */
diff -urN linux-2.6.18.patch2/include/asm-sh/mmu.h
linux-2.6.18.patch3/include/asm-sh/mmu.h
--- linux-2.6.18.patch2/include/asm-sh/mmu.h	2006-09-21 09:37:26.000000000 +0800
+++ linux-2.6.18.patch3/include/asm-sh/mmu.h	2006-09-21 09:52:02.000000000 +0800
@@ -17,6 +17,7 @@
typedef struct {
	struct mm_tblock_struct tblock;
	unsigned long		end_brk;
+	unsigned long		stack_start;
} mm_context_t;

#else
diff -urN linux-2.6.18.patch2/include/asm-v850/mmu.h
linux-2.6.18.patch3/include/asm-v850/mmu.h
--- linux-2.6.18.patch2/include/asm-v850/mmu.h	2006-09-21
09:37:27.000000000 +0800
+++ linux-2.6.18.patch3/include/asm-v850/mmu.h	2006-09-21
09:52:02.000000000 +0800
@@ -6,6 +6,7 @@
typedef struct {
	struct vm_list_struct	*vmlist;
	unsigned long		end_brk;
+	unsigned long		stack_start;
} mm_context_t;

#endif /* __V850_MMU_H__ */
diff -urN linux-2.6.18.patch2/include/linux/flat.h
linux-2.6.18.patch3/include/linux/flat.h
--- linux-2.6.18.patch2/include/linux/flat.h	2006-09-21 09:37:27.000000000 +0800
+++ linux-2.6.18.patch3/include/linux/flat.h	2006-09-21 09:52:02.000000000 +0800
@@ -10,6 +10,13 @@
#ifndef _LINUX_FLAT_H
#define _LINUX_FLAT_H

+#define FLAT_FLAG_RAM    0x0001 /* load program entirely into RAM */
+#define FLAT_FLAG_GOTPIC 0x0002 /* program is PIC with GOT */
+#define FLAT_FLAG_GZIP   0x0004 /* all but the header is compressed */
+#define FLAT_FLAG_GZDATA 0x0008 /* only data/relocs are compressed (for XIP) */
+#define FLAT_FLAG_KTRACE 0x0010 /* output useful kernel trace for debugging */
+#define FLAT_FLAG_L1STK  0x0020 /* use a 4k stack in L1 scratch memory.  */
+
#ifdef __KERNEL__
#include <asm/flat.h>
#endif
@@ -50,12 +57,6 @@
	unsigned long filler[5];    /* Reservered, set to zero */
};

-#define FLAT_FLAG_RAM    0x0001 /* load program entirely into RAM */
-#define FLAT_FLAG_GOTPIC 0x0002 /* program is PIC with GOT */
-#define FLAT_FLAG_GZIP   0x0004 /* all but the header is compressed */
-#define FLAT_FLAG_GZDATA 0x0008 /* only data/relocs are compressed (for XIP) */
-#define FLAT_FLAG_KTRACE 0x0010 /* output useful kernel trace for debugging */
-

#ifdef __KERNEL__ /* so systems without linux headers can compile the apps */
/*

--
Best regards,
Luke Yang
[email protected]
diff -urN linux-2.6.18.patch2/fs/binfmt_elf_fdpic.c linux-2.6.18.patch3/fs/binfmt_elf_fdpic.c
--- linux-2.6.18.patch2/fs/binfmt_elf_fdpic.c	2006-09-21 09:37:18.000000000 +0800
+++ linux-2.6.18.patch3/fs/binfmt_elf_fdpic.c	2006-09-21 11:17:49.000000000 +0800
@@ -170,7 +170,7 @@
 {
 	struct elf_fdpic_params exec_params, interp_params;
 	struct elf_phdr *phdr;
-	unsigned long stack_size, entryaddr;
+	unsigned long stack_size, entryaddr, requested_stack_size;
 #ifndef CONFIG_MMU
 	unsigned long fullsize;
 #endif
@@ -361,6 +361,7 @@
 	 * - the stack starts at the top and works down
 	 */
 	stack_size = (stack_size + PAGE_SIZE - 1) & PAGE_MASK;
+	requested_stack_size = stack_size;
 	if (stack_size < PAGE_SIZE * 2)
 		stack_size = PAGE_SIZE * 2;
 
@@ -388,6 +389,8 @@
 	current->mm->context.end_brk = current->mm->start_brk;
 	current->mm->context.end_brk +=
 		(stack_size > PAGE_SIZE) ? (stack_size - PAGE_SIZE) : 0;
+	current->mm->context.stack_start =
+		current->mm->start_brk + stack_size - requested_stack_size;
 	current->mm->start_stack = current->mm->start_brk + stack_size;
 #endif
 
@@ -959,6 +962,8 @@
 }
 #endif
 
+extern void *safe_dma_memcpy(void *, const void *, size_t);
+
 /*****************************************************************************/
 /*
  * map a binary by direct mmap() of the individual PT_LOAD segments
diff -urN linux-2.6.18.patch2/fs/binfmt_flat.c linux-2.6.18.patch3/fs/binfmt_flat.c
--- linux-2.6.18.patch2/fs/binfmt_flat.c	2006-09-21 09:37:18.000000000 +0800
+++ linux-2.6.18.patch3/fs/binfmt_flat.c	2006-09-21 09:52:02.000000000 +0800
@@ -16,6 +16,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
@@ -35,13 +36,13 @@
 #include <linux/personality.h>
 #include <linux/init.h>
 #include <linux/flat.h>
-#include <linux/syscalls.h>
 
 #include <asm/byteorder.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/unaligned.h>
 #include <asm/cacheflush.h>
+#include <asm/mmu_context.h>
 
 /****************************************************************************/
 
@@ -77,6 +78,8 @@
 static int load_flat_binary(struct linux_binprm *, struct pt_regs * regs);
 static int flat_core_dump(long signr, struct pt_regs * regs, struct file *file);
 
+extern void dump_thread(struct pt_regs *, struct user *);
+
 static struct linux_binfmt flat_format = {
 	.module		= THIS_MODULE,
 	.load_binary	= load_flat_binary,
@@ -413,7 +416,9 @@
 /****************************************************************************/
 
 static int load_flat_file(struct linux_binprm * bprm,
-		struct lib_info *libinfo, int id, unsigned long *extra_stack)
+			  struct lib_info *libinfo, int id,
+			  unsigned long *extra_stack,
+			  unsigned long *stack_base)
 {
 	struct flat_hdr * hdr;
 	unsigned long textpos = 0, datapos = 0, result;
@@ -426,7 +431,6 @@
 	int i, rev, relocs = 0;
 	loff_t fpos;
 	unsigned long start_code, end_code;
-	int ret;
 
 	hdr = ((struct flat_hdr *) bprm->buf);		/* exec-header */
 	inode = bprm->file->f_dentry->d_inode;
@@ -451,25 +455,24 @@
 		 */
 		if (strncmp(hdr->magic, "#!", 2))
 			printk("BINFMT_FLAT: bad header magic\n");
-		ret = -ENOEXEC;
-		goto err;
+		return -ENOEXEC;
 	}
-
+#ifdef DEBUG
+	flags |= FLAT_FLAG_KTRACE;
+#endif
 	if (flags & FLAT_FLAG_KTRACE)
 		printk("BINFMT_FLAT: Loading file: %s\n", bprm->filename);
 
 	if (rev != FLAT_VERSION && rev != OLD_FLAT_VERSION) {
 		printk("BINFMT_FLAT: bad flat file version 0x%x (supported 0x%x and 0x%x)\n", rev, FLAT_VERSION, OLD_FLAT_VERSION);
-		ret = -ENOEXEC;
-		goto err;
+		return -ENOEXEC;
 	}
-	
+
 	/* Don't allow old format executables to use shared libraries */
 	if (rev == OLD_FLAT_VERSION && id != 0) {
 		printk("BINFMT_FLAT: shared libraries are not available before rev 0x%x\n",
 				(int) FLAT_VERSION);
-		ret = -ENOEXEC;
-		goto err;
+		return -ENOEXEC;
 	}
 
 	/*
@@ -482,8 +485,7 @@
 #ifndef CONFIG_BINFMT_ZFLAT
 	if (flags & (FLAT_FLAG_GZIP|FLAT_FLAG_GZDATA)) {
 		printk("Support for ZFLAT executables is not enabled.\n");
-		ret = -ENOEXEC;
-		goto err;
+		return -ENOEXEC;
 	}
 #endif
 
@@ -495,18 +497,27 @@
 	rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur;
 	if (rlim >= RLIM_INFINITY)
 		rlim = ~0;
-	if (data_len + bss_len > rlim) {
-		ret = -ENOMEM;
-		goto err;
+	if (data_len + bss_len > rlim)
+		return -ENOMEM;
+
+	if (flags & FLAT_FLAG_L1STK) {
+		if (stack_base == 0) {
+			printk ("BINFMT_FLAT: requesting L1 stack for shared library\n");
+			return -ENOEXEC;
+		}
+		stack_len = alloc_l1stack(stack_len, stack_base);
+		if (stack_len == 0) {
+			printk("BINFMT_FLAT: stack size with arguments exceeds scratchpad memory\n");
+			return -ENOMEM;
+		}
+		*extra_stack = stack_len;
 	}
 
 	/* Flush all traces of the currently running executable */
 	if (id == 0) {
 		result = flush_old_exec(bprm);
-		if (result) {
-			ret = result;
-			goto err;
-		}
+		if (result)
+			goto out_fail;
 
 		/* OK, This is the point of no return */
 		set_personality(PER_LINUX_32BIT);
@@ -536,14 +547,17 @@
 			if (!textpos)
 				textpos = (unsigned long) -ENOMEM;
 			printk("Unable to mmap process text, errno %d\n", (int)-textpos);
-			ret = textpos;
-			goto err;
+			result = textpos;
+			goto out_fail;
 		}
 
 		down_write(&current->mm->mmap_sem);
 		realdatastart = do_mmap(0, 0, data_len + extra +
 				MAX_SHARED_LIBS * sizeof(unsigned long),
 				PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0);
+		do_mremap(realdatastart, data_len + extra +
+			  MAX_SHARED_LIBS * sizeof(unsigned long),
+			  ksize((void *)realdatastart), 0, 0);
 		up_write(&current->mm->mmap_sem);
 
 		if (realdatastart == 0 || realdatastart >= (unsigned long)-4096) {
@@ -552,8 +566,8 @@
 			printk("Unable to allocate RAM for process data, errno %d\n",
 					(int)-datapos);
 			do_munmap(current->mm, textpos, text_len);
-			ret = realdatastart;
-			goto err;
+			result = realdatastart;
+			goto out_fail;
 		}
 		datapos = realdatastart + MAX_SHARED_LIBS * sizeof(unsigned long);
 
@@ -575,8 +589,7 @@
 			printk("Unable to read data+bss, errno %d\n", (int)-result);
 			do_munmap(current->mm, textpos, text_len);
 			do_munmap(current->mm, realdatastart, data_len + extra);
-			ret = result;
-			goto err;
+			goto out_fail;
 		}
 
 		reloc = (unsigned long *) (datapos+(ntohl(hdr->reloc_start)-text_len));
@@ -588,15 +601,19 @@
 		textpos = do_mmap(0, 0, text_len + data_len + extra +
 					MAX_SHARED_LIBS * sizeof(unsigned long),
 				PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0);
-		up_write(&current->mm->mmap_sem);
 		if (!textpos  || textpos >= (unsigned long) -4096) {
+			up_write(&current->mm->mmap_sem);
 			if (!textpos)
 				textpos = (unsigned long) -ENOMEM;
 			printk("Unable to allocate RAM for process text/data, errno %d\n",
 					(int)-textpos);
-			ret = textpos;
-			goto err;
+			result = textpos;
+			goto out_fail;
 		}
+		do_mremap(textpos, text_len + data_len + extra +
+			  MAX_SHARED_LIBS * sizeof(unsigned long),
+			  ksize((void *)textpos), 0, 0);
+		up_write(&current->mm->mmap_sem);
 
 		realdatastart = textpos + ntohl(hdr->data_start);
 		datapos = realdatastart + MAX_SHARED_LIBS * sizeof(unsigned long);
@@ -640,8 +657,7 @@
 			printk("Unable to read code+data+bss, errno %d\n",(int)-result);
 			do_munmap(current->mm, textpos, text_len + data_len + extra +
 				MAX_SHARED_LIBS * sizeof(unsigned long));
-			ret = result;
-			goto err;
+			goto out_fail;
 		}
 	}
 
@@ -665,6 +681,7 @@
 		current->mm->start_brk = datapos + data_len + bss_len;
 		current->mm->brk = (current->mm->start_brk + 3) & ~3;
 		current->mm->context.end_brk = memp + ksize((void *) memp) - stack_len;
+		current->mm->context.stack_start = current->mm->context.end_brk;
 	}
 
 	if (flags & FLAT_FLAG_KTRACE)
@@ -686,7 +703,7 @@
 	libinfo->lib_list[id].loaded = 1;
 	libinfo->lib_list[id].entry = (0x00ffffff & ntohl(hdr->entry)) + textpos;
 	libinfo->lib_list[id].build_date = ntohl(hdr->build_date);
-	
+
 	/*
 	 * We just load the allocations into some temporary memory to
 	 * help simplify all this mumbo jumbo
@@ -705,8 +722,8 @@
 			if (*rp) {
 				addr = calc_reloc(*rp, libinfo, id, 0);
 				if (addr == RELOC_FAILED) {
-					ret = -ENOEXEC;
-					goto err;
+					result = -ENOEXEC;
+					goto out_fail;
 				}
 				*rp = addr;
 			}
@@ -725,6 +742,7 @@
 	 * __start to address 4 so that is okay).
 	 */
 	if (rev > OLD_FLAT_VERSION) {
+		unsigned long persistent = 0;
 		for (i=0; i < relocs; i++) {
 			unsigned long addr, relval;
 
@@ -732,16 +750,20 @@
 			   relocated (of course, the address has to be
 			   relocated first).  */
 			relval = ntohl(reloc[i]);
+			if (flat_set_persistent (relval, &persistent))
+				continue;
 			addr = flat_get_relocate_addr(relval);
 			rp = (unsigned long *) calc_reloc(addr, libinfo, id, 1);
 			if (rp == (unsigned long *)RELOC_FAILED) {
-				ret = -ENOEXEC;
-				goto err;
+				result = -ENOEXEC;
+				goto out_fail;
 			}
 
 			/* Get the pointer's value.  */
-			addr = flat_get_addr_from_rp(rp, relval, flags);
-			if (addr != 0) {
+			addr = flat_get_addr_from_rp(rp, relval, flags, &persistent);
+			if (addr == 0)
+				continue;
+			if (! flat_addr_absolute (relval)) {
 				/*
 				 * Do the relocation.  PIC relocs in the data section are
 				 * already in target order
@@ -750,30 +772,31 @@
 					addr = ntohl(addr);
 				addr = calc_reloc(addr, libinfo, id, 0);
 				if (addr == RELOC_FAILED) {
-					ret = -ENOEXEC;
-					goto err;
+					result = -ENOEXEC;
+					goto out_fail;
 				}
-
-				/* Write back the relocated pointer.  */
-				flat_put_addr_at_rp(rp, addr, relval);
 			}
+			/* Write back the relocated pointer.  */
+			flat_put_addr_at_rp(rp, addr, relval);
 		}
 	} else {
 		for (i=0; i < relocs; i++)
 			old_reloc(ntohl(reloc[i]));
 	}
-	
+
 	flush_icache_range(start_code, end_code);
 
 	/* zero the BSS,  BRK and stack areas */
-	memset((void*)(datapos + data_len), 0, bss_len + 
+	memset((void*)(datapos + data_len), 0, bss_len +
 			(memp + ksize((void *) memp) - stack_len -	/* end brk */
 			libinfo->lib_list[id].start_brk) +		/* start brk */
 			stack_len);
 
 	return 0;
-err:
-	return ret;
+ out_fail:
+	if (flags & FLAT_FLAG_L1STK)
+		free_l1stack();
+	return result;
 }
 
 
@@ -804,7 +827,7 @@
 	res = prepare_binprm(&bprm);
 
 	if (res <= (unsigned long)-4096)
-		res = load_flat_file(&bprm, libs, id, NULL);
+		res = load_flat_file(&bprm, libs, id, NULL, NULL);
 	if (bprm.file) {
 		allow_write_access(bprm.file);
 		fput(bprm.file);
@@ -827,6 +850,7 @@
 	unsigned long p = bprm->p;
 	unsigned long stack_len;
 	unsigned long start_addr;
+	unsigned long l1stack_base, ramstack_top;
 	unsigned long *sp;
 	int res;
 	int i, j;
@@ -844,11 +868,11 @@
 	stack_len += (bprm->argc + 1) * sizeof(char *); /* the argv array */
 	stack_len += (bprm->envc + 1) * sizeof(char *); /* the envp array */
 
-	
-	res = load_flat_file(bprm, &libinfo, 0, &stack_len);
+	l1stack_base = 0;
+	res = load_flat_file(bprm, &libinfo, 0, &stack_len, &l1stack_base);
 	if (res > (unsigned long)-4096)
 		return res;
-	
+
 	/* Update data segment pointers for all libraries */
 	for (i=0; i<MAX_SHARED_LIBS; i++)
 		if (libinfo.lib_list[i].loaded)
@@ -863,6 +887,7 @@
 	set_binfmt(&flat_format);
 
 	p = ((current->mm->context.end_brk + stack_len + 3) & ~3) - 4;
+	ramstack_top = p;
 	DBG_FLT("p=%x\n", (int)p);
 
 	/* copy the arg pages onto the stack, this could be more efficient :-) */
@@ -871,7 +896,7 @@
 			((char *) page_address(bprm->page[i/PAGE_SIZE]))[i % PAGE_SIZE];
 
 	sp = (unsigned long *) create_flat_tables(p, bprm);
-	
+
 	/* Fake some return addresses to ensure the call chain will
 	 * initialise library in order for us.  We are required to call
 	 * lib 1 first, then 2, ... and finally the main program (id 0).
@@ -887,15 +912,24 @@
 		}
 	}
 #endif
-	
+
 	/* Stash our initial stack pointer into the mm structure */
 	current->mm->start_stack = (unsigned long )sp;
 
-	
-	DBG_FLT("start_thread(regs=0x%x, entry=0x%x, start_stack=0x%x)\n",
-		(int)regs, (int)start_addr, (int)current->mm->start_stack);
-	
-	start_thread(regs, start_addr, current->mm->start_stack);
+	if (l1stack_base) {
+		/* Find L1 stack pointer corresponding to the current bottom
+		   of the stack in normal RAM.  */
+		l1stack_base += stack_len - (ramstack_top - (unsigned long)sp);
+		if (!activate_l1stack(current->mm, ramstack_top - stack_len))
+			l1stack_base = 0;
+	}
+
+	DBG_FLT("start_thread(regs=0x%x, entry=0x%x, start_stack=0x%x, l1stk=0x%x, len 0x%x)\n",
+		(int)regs, (int)start_addr, (int)current->mm->start_stack, l1stack_base,
+		stack_len);
+
+	start_thread(regs, start_addr,
+		     l1stack_base ? l1stack_base : current->mm->start_stack);
 
 	if (current->ptrace & PT_PTRACED)
 		send_sig(SIGTRAP, current, 0);
diff -urN linux-2.6.18.patch2/include/asm-arm/mmu.h linux-2.6.18.patch3/include/asm-arm/mmu.h
--- linux-2.6.18.patch2/include/asm-arm/mmu.h	2006-09-21 09:37:24.000000000 +0800
+++ linux-2.6.18.patch3/include/asm-arm/mmu.h	2006-09-21 09:52:02.000000000 +0800
@@ -26,6 +26,7 @@
 typedef struct {
 	struct vm_list_struct	*vmlist;
 	unsigned long		end_brk;
+	unsigned long		stack_start;
 } mm_context_t;
 
 #endif
diff -urN linux-2.6.18.patch2/include/asm-frv/mmu.h linux-2.6.18.patch3/include/asm-frv/mmu.h
--- linux-2.6.18.patch2/include/asm-frv/mmu.h	2006-09-21 09:37:25.000000000 +0800
+++ linux-2.6.18.patch3/include/asm-frv/mmu.h	2006-09-21 09:52:02.000000000 +0800
@@ -24,6 +24,7 @@
 #else
 	struct vm_list_struct	*vmlist;
 	unsigned long		end_brk;
+	unsigned long		stack_start;
 
 #endif
 
diff -urN linux-2.6.18.patch2/include/asm-h8300/mmu.h linux-2.6.18.patch3/include/asm-h8300/mmu.h
--- linux-2.6.18.patch2/include/asm-h8300/mmu.h	2006-09-21 09:37:26.000000000 +0800
+++ linux-2.6.18.patch3/include/asm-h8300/mmu.h	2006-09-21 09:52:02.000000000 +0800
@@ -6,6 +6,7 @@
 typedef struct {
 	struct vm_list_struct	*vmlist;
 	unsigned long		end_brk;
+	unsigned long		stack_start;
 } mm_context_t;
 
 #endif
diff -urN linux-2.6.18.patch2/include/asm-m32r/mmu.h linux-2.6.18.patch3/include/asm-m32r/mmu.h
--- linux-2.6.18.patch2/include/asm-m32r/mmu.h	2006-09-21 09:37:26.000000000 +0800
+++ linux-2.6.18.patch3/include/asm-m32r/mmu.h	2006-09-21 09:52:02.000000000 +0800
@@ -6,6 +6,7 @@
 typedef struct {
 	struct vm_list_struct	*vmlist;
 	unsigned long		end_brk;
+	unsigned long		stack_start;
 } mm_context_t;
 #else
 
diff -urN linux-2.6.18.patch2/include/asm-m68knommu/mmu.h linux-2.6.18.patch3/include/asm-m68knommu/mmu.h
--- linux-2.6.18.patch2/include/asm-m68knommu/mmu.h	2006-09-21 09:37:26.000000000 +0800
+++ linux-2.6.18.patch3/include/asm-m68knommu/mmu.h	2006-09-21 09:52:02.000000000 +0800
@@ -6,6 +6,7 @@
 typedef struct {
 	struct vm_list_struct	*vmlist;
 	unsigned long		end_brk;
+	unsigned long		stack_start;
 } mm_context_t;
 
 #endif /* __M68KNOMMU_MMU_H */
diff -urN linux-2.6.18.patch2/include/asm-sh/mmu.h linux-2.6.18.patch3/include/asm-sh/mmu.h
--- linux-2.6.18.patch2/include/asm-sh/mmu.h	2006-09-21 09:37:26.000000000 +0800
+++ linux-2.6.18.patch3/include/asm-sh/mmu.h	2006-09-21 09:52:02.000000000 +0800
@@ -17,6 +17,7 @@
 typedef struct {
 	struct mm_tblock_struct tblock;
 	unsigned long		end_brk;
+	unsigned long		stack_start;
 } mm_context_t;
 
 #else
diff -urN linux-2.6.18.patch2/include/asm-v850/mmu.h linux-2.6.18.patch3/include/asm-v850/mmu.h
--- linux-2.6.18.patch2/include/asm-v850/mmu.h	2006-09-21 09:37:27.000000000 +0800
+++ linux-2.6.18.patch3/include/asm-v850/mmu.h	2006-09-21 09:52:02.000000000 +0800
@@ -6,6 +6,7 @@
 typedef struct {
 	struct vm_list_struct	*vmlist;
 	unsigned long		end_brk;
+	unsigned long		stack_start;
 } mm_context_t;
 
 #endif /* __V850_MMU_H__ */
diff -urN linux-2.6.18.patch2/include/linux/flat.h linux-2.6.18.patch3/include/linux/flat.h
--- linux-2.6.18.patch2/include/linux/flat.h	2006-09-21 09:37:27.000000000 +0800
+++ linux-2.6.18.patch3/include/linux/flat.h	2006-09-21 09:52:02.000000000 +0800
@@ -10,6 +10,13 @@
 #ifndef _LINUX_FLAT_H
 #define _LINUX_FLAT_H
 
+#define FLAT_FLAG_RAM    0x0001 /* load program entirely into RAM */
+#define FLAT_FLAG_GOTPIC 0x0002 /* program is PIC with GOT */
+#define FLAT_FLAG_GZIP   0x0004 /* all but the header is compressed */
+#define FLAT_FLAG_GZDATA 0x0008 /* only data/relocs are compressed (for XIP) */
+#define FLAT_FLAG_KTRACE 0x0010 /* output useful kernel trace for debugging */
+#define FLAT_FLAG_L1STK  0x0020 /* use a 4k stack in L1 scratch memory.  */
+
 #ifdef __KERNEL__
 #include <asm/flat.h>
 #endif
@@ -50,12 +57,6 @@
 	unsigned long filler[5];    /* Reservered, set to zero */
 };
 
-#define FLAT_FLAG_RAM    0x0001 /* load program entirely into RAM */
-#define FLAT_FLAG_GOTPIC 0x0002 /* program is PIC with GOT */
-#define FLAT_FLAG_GZIP   0x0004 /* all but the header is compressed */
-#define FLAT_FLAG_GZDATA 0x0008 /* only data/relocs are compressed (for XIP) */
-#define FLAT_FLAG_KTRACE 0x0010 /* output useful kernel trace for debugging */
-
 
 #ifdef __KERNEL__ /* so systems without linux headers can compile the apps */
 /*

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux