Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1445182 > unrolled thread

[PULL REQUEST] [PATCH v2 00/10] allow BFLT executables on systems with a MMU

Started byNicolas Pitre <nicolas.pitre@linaro.org>
First post2016-07-18 05:40 +0200
Last post2016-07-19 09:30 +0200
Articles 15 — 3 participants

Back to article view | Back to linux.kernel


Contents

  [PULL REQUEST] [PATCH v2 00/10] allow BFLT executables on systems with a MMU Nicolas Pitre <nicolas.pitre@linaro.org> - 2016-07-18 05:40 +0200
    [PATCH v2 07/10] binfmt_flat: use clear_user() rather than memset() to clear .bss Nicolas Pitre <nicolas.pitre@linaro.org> - 2016-07-18 05:40 +0200
    [PATCH v2 02/10] elf_fdpic_transfer_args_to_stack(): make it generic Nicolas Pitre <nicolas.pitre@linaro.org> - 2016-07-18 05:40 +0200
    [PATCH v2 03/10] binfmt_flat: use generic transfer_args_to_stack() Nicolas Pitre <nicolas.pitre@linaro.org> - 2016-07-18 05:40 +0200
    [PATCH v2 06/10] binfmt_flat: use proper user space accessors with old relocs code Nicolas Pitre <nicolas.pitre@linaro.org> - 2016-07-18 05:40 +0200
    [PATCH v2 01/10] binfmt_flat: assorted cleanups Nicolas Pitre <nicolas.pitre@linaro.org> - 2016-07-18 05:40 +0200
      Re: [PATCH v2 01/10] binfmt_flat: assorted cleanups Greg Ungerer <gerg@linux-m68k.org> - 2016-07-19 07:10 +0200
        Re: [PATCH v2 01/10] binfmt_flat: assorted cleanups Geert Uytterhoeven <geert@linux-m68k.org> - 2016-07-19 08:50 +0200
          Re: [PATCH v2 01/10] binfmt_flat: assorted cleanups Nicolas Pitre <nicolas.pitre@linaro.org> - 2016-07-20 06:20 +0200
            Re: [PATCH v2 01/10] binfmt_flat: assorted cleanups Geert Uytterhoeven <geert@linux-m68k.org> - 2016-07-20 09:00 +0200
              Re: [PATCH v2 01/10] binfmt_flat: assorted cleanups Greg Ungerer <gerg@linux-m68k.org> - 2016-07-20 09:20 +0200
    [PATCH v2 09/10] binfmt_flat: add MMU-specific support Nicolas Pitre <nicolas.pitre@linaro.org> - 2016-07-18 05:50 +0200
    [PATCH v2 04/10] binfmt_flat: clean up create_flat_tables() and stack accesses Nicolas Pitre <nicolas.pitre@linaro.org> - 2016-07-18 05:50 +0200
    [PATCH v2 08/10] binfmt_flat: update libraries' data segment pointer with userspace accessors Nicolas Pitre <nicolas.pitre@linaro.org> - 2016-07-18 05:50 +0200
    Re: [PULL REQUEST] [PATCH v2 00/10] allow BFLT executables on systems  with a MMU Greg Ungerer <gerg@linux-m68k.org> - 2016-07-19 09:30 +0200

#1445182 — [PULL REQUEST] [PATCH v2 00/10] allow BFLT executables on systems with a MMU

FromNicolas Pitre <nicolas.pitre@linaro.org>
Date2016-07-18 05:40 +0200
Subject[PULL REQUEST] [PATCH v2 00/10] allow BFLT executables on systems with a MMU
Message-ID<rW7zs-T6-3@gated-at.bofh.it>
This series provides the necessary changes to allow "flat" executable
binaries meant for no-MMU systems to actually run on systems with a MMU.

This can also be found in the following git repo:

	git://git.linaro.org/people/nicolas.pitre/linux binfmt_flat_with_mmu

*Why?*

Because developing and testing natively on a large system with lots of
RAM makes it so much more convenient to use all the existing profiling
tools and debugging facilities that a kernel with lots of RAM can give.
And incidentally, those systems with lots of RAM all have a MMU.

*Why not use elf_fdpic?*

The flat executable format is simple with very small footprint
overhead, either in the executables themselves or kernel support.
This makes the flat format more suitable than elf_fdpic for very small
single-user-app embedded systems.

And while elf_fdpic binaries can run on MMU systems, flat binaries still
couldn't, which just felt wrong.

So here it is.  The no-MMU support should remain unaffected. Please consider
for pulling.

Tested on ARM only with a busybox build.

Changes since v1:

- Removed SuperH and Xtensa from the Kconfig rule as they fail to build
  due to lack of get/put_unaligned_user().

- Clarified some commit logs a bit.

diffstat:

 arch/arm/include/asm/flat.h  |   5 +-
 arch/m68k/include/asm/flat.h |   5 +-
 fs/Kconfig.binfmt            |   3 +-
 fs/binfmt_elf_fdpic.c        |  38 +---
 fs/binfmt_flat.c             | 372 +++++++++++++++++++++--------------
 fs/exec.c                    |  33 ++++
 include/linux/binfmts.h      |   2 +
 7 files changed, 268 insertions(+), 190 deletions(-)

[toc] | [next] | [standalone]


#1445183 — [PATCH v2 07/10] binfmt_flat: use clear_user() rather than memset() to clear .bss

FromNicolas Pitre <nicolas.pitre@linaro.org>
Date2016-07-18 05:40 +0200
Subject[PATCH v2 07/10] binfmt_flat: use clear_user() rather than memset() to clear .bss
Message-ID<rW7zs-T6-11@gated-at.bofh.it>
In reply to#1445182
This is needed on systems with a MMU.

Signed-off-by: Nicolas Pitre <nico@linaro.org>
---
 fs/binfmt_flat.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index c85f8f1239..e981e66bb5 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -803,10 +803,11 @@ static int load_flat_file(struct linux_binprm * bprm,
 	flush_icache_range(start_code, end_code);
 
 	/* zero the BSS,  BRK and stack areas */
-	memset((void*)(datapos + data_len), 0, bss_len + 
+	if (clear_user((void __user *)(datapos + data_len), bss_len + 
 			(memp + memp_size - stack_len -		/* end brk */
 			libinfo->lib_list[id].start_brk) +	/* start brk */
-			stack_len);
+			stack_len))
+		return -EFAULT;
 
 	return 0;
 err:
-- 
2.7.4

[toc] | [prev] | [next] | [standalone]


#1445184 — [PATCH v2 02/10] elf_fdpic_transfer_args_to_stack(): make it generic

FromNicolas Pitre <nicolas.pitre@linaro.org>
Date2016-07-18 05:40 +0200
Subject[PATCH v2 02/10] elf_fdpic_transfer_args_to_stack(): make it generic
Message-ID<rW7zs-T6-13@gated-at.bofh.it>
In reply to#1445182
This copying of arguments and environment is common to both NOMMU
binary formats we support. Let's make the elf_fdpic version available
to the flat format as well.

While at it, improve the code a bit not to copy below the actual
data area.

Signed-off-by: Nicolas Pitre <nico@linaro.org>
---
 fs/binfmt_elf_fdpic.c   | 38 ++------------------------------------
 fs/exec.c               | 33 +++++++++++++++++++++++++++++++++
 include/linux/binfmts.h |  2 ++
 3 files changed, 37 insertions(+), 36 deletions(-)

diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index 203589311b..464a972e88 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -67,8 +67,6 @@ static int create_elf_fdpic_tables(struct linux_binprm *, struct mm_struct *,
 				   struct elf_fdpic_params *);
 
 #ifndef CONFIG_MMU
-static int elf_fdpic_transfer_args_to_stack(struct linux_binprm *,
-					    unsigned long *);
 static int elf_fdpic_map_file_constdisp_on_uclinux(struct elf_fdpic_params *,
 						   struct file *,
 						   struct mm_struct *);
@@ -515,8 +513,9 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
 	sp = mm->start_stack;
 
 	/* stack the program arguments and environment */
-	if (elf_fdpic_transfer_args_to_stack(bprm, &sp) < 0)
+	if (transfer_args_to_stack(bprm, &sp) < 0)
 		return -EFAULT;
+	sp &= ~15;
 #endif
 
 	/*
@@ -711,39 +710,6 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
 
 /*****************************************************************************/
 /*
- * transfer the program arguments and environment from the holding pages onto
- * the stack
- */
-#ifndef CONFIG_MMU
-static int elf_fdpic_transfer_args_to_stack(struct linux_binprm *bprm,
-					    unsigned long *_sp)
-{
-	unsigned long index, stop, sp;
-	char *src;
-	int ret = 0;
-
-	stop = bprm->p >> PAGE_SHIFT;
-	sp = *_sp;
-
-	for (index = MAX_ARG_PAGES - 1; index >= stop; index--) {
-		src = kmap(bprm->page[index]);
-		sp -= PAGE_SIZE;
-		if (copy_to_user((void *) sp, src, PAGE_SIZE) != 0)
-			ret = -EFAULT;
-		kunmap(bprm->page[index]);
-		if (ret < 0)
-			goto out;
-	}
-
-	*_sp = (*_sp - (MAX_ARG_PAGES * PAGE_SIZE - bprm->p)) & ~15;
-
-out:
-	return ret;
-}
-#endif
-
-/*****************************************************************************/
-/*
  * load the appropriate binary image (executable or interpreter) into memory
  * - we assume no MMU is available
  * - if no other PIC bits are set in params->hdr->e_flags
diff --git a/fs/exec.c b/fs/exec.c
index 887c1c955d..ef0df2f092 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -762,6 +762,39 @@ out_unlock:
 }
 EXPORT_SYMBOL(setup_arg_pages);
 
+#else
+
+/*
+ * Transfer the program arguments and environment from the holding pages
+ * onto the stack. The provided stack pointer is adjusted accordingly.
+ */
+int transfer_args_to_stack(struct linux_binprm *bprm,
+			   unsigned long *sp_location)
+{
+	unsigned long index, stop, sp;
+	int ret = 0;
+
+	stop = bprm->p >> PAGE_SHIFT;
+	sp = *sp_location;
+
+	for (index = MAX_ARG_PAGES - 1; index >= stop; index--) {
+		unsigned int offset = index == stop ? bprm->p & ~PAGE_MASK : 0;
+		char *src = kmap(bprm->page[index]) + offset;
+		sp -= PAGE_SIZE - offset;
+		if (copy_to_user((void *) sp, src, PAGE_SIZE - offset) != 0)
+			ret = -EFAULT;
+		kunmap(bprm->page[index]);
+		if (ret)
+			goto out;
+	}
+
+	*sp_location = sp;
+
+out:
+	return ret;
+}
+EXPORT_SYMBOL(transfer_args_to_stack);
+
 #endif /* CONFIG_MMU */
 
 static struct file *do_open_execat(int fd, struct filename *name, int flags)
diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h
index 314b3caa70..1303b570b1 100644
--- a/include/linux/binfmts.h
+++ b/include/linux/binfmts.h
@@ -113,6 +113,8 @@ extern int suid_dumpable;
 extern int setup_arg_pages(struct linux_binprm * bprm,
 			   unsigned long stack_top,
 			   int executable_stack);
+extern int transfer_args_to_stack(struct linux_binprm *bprm,
+				  unsigned long *sp_location);
 extern int bprm_change_interp(char *interp, struct linux_binprm *bprm);
 extern int copy_strings_kernel(int argc, const char *const *argv,
 			       struct linux_binprm *bprm);
-- 
2.7.4

[toc] | [prev] | [next] | [standalone]


#1445185 — [PATCH v2 03/10] binfmt_flat: use generic transfer_args_to_stack()

FromNicolas Pitre <nicolas.pitre@linaro.org>
Date2016-07-18 05:40 +0200
Subject[PATCH v2 03/10] binfmt_flat: use generic transfer_args_to_stack()
Message-ID<rW7zs-T6-15@gated-at.bofh.it>
In reply to#1445182
This gets rid of the rather ugly, open coded and suboptimal copy code.

Signed-off-by: Nicolas Pitre <nico@linaro.org>
---
 fs/binfmt_flat.c | 22 ++++++++++------------
 1 file changed, 10 insertions(+), 12 deletions(-)

diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index 085059d879..64feb873f0 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -854,10 +854,8 @@ static int load_flat_binary(struct linux_binprm * bprm)
 {
 	struct lib_info libinfo;
 	struct pt_regs *regs = current_pt_regs();
-	unsigned long p = bprm->p;
-	unsigned long stack_len;
+	unsigned long sp, stack_len;
 	unsigned long start_addr;
-	unsigned long *sp;
 	int res;
 	int i, j;
 
@@ -892,15 +890,15 @@ static int load_flat_binary(struct linux_binprm * bprm)
 
 	set_binfmt(&flat_format);
 
-	p = ((current->mm->context.end_brk + stack_len + 3) & ~3) - 4;
-	DBG_FLT("p=%lx\n", p);
+	sp = ((current->mm->context.end_brk + stack_len + 3) & ~3) - 4;
+	DBG_FLT("sp=%lx\n", sp);
 
-	/* copy the arg pages onto the stack, this could be more efficient :-) */
-	for (i = TOP_OF_ARGS - 1; i >= bprm->p; i--)
-		* (char *) --p =
-			((char *) page_address(bprm->page[i/PAGE_SIZE]))[i % PAGE_SIZE];
+	/* copy the arg pages onto the stack */
+	res = transfer_args_to_stack(bprm, &sp);
+	if (res)
+		return res;
 
-	sp = (unsigned long *) create_flat_tables(p, bprm);
+	sp = create_flat_tables(sp, bprm);
 	
 	/* Fake some return addresses to ensure the call chain will
 	 * initialise library in order for us.  We are required to call
@@ -912,14 +910,14 @@ static int load_flat_binary(struct linux_binprm * bprm)
 	for (i = MAX_SHARED_LIBS-1; i>0; i--) {
 		if (libinfo.lib_list[i].loaded) {
 			/* Push previos first to call address */
-			--sp;	put_user(start_addr, sp);
+			--sp;	put_user(start_addr, (unsigned long *)sp);
 			start_addr = libinfo.lib_list[i].entry;
 		}
 	}
 #endif
 	
 	/* Stash our initial stack pointer into the mm structure */
-	current->mm->start_stack = (unsigned long )sp;
+	current->mm->start_stack = sp;
 
 #ifdef FLAT_PLAT_INIT
 	FLAT_PLAT_INIT(regs);
-- 
2.7.4

[toc] | [prev] | [next] | [standalone]


#1445186 — [PATCH v2 06/10] binfmt_flat: use proper user space accessors with old relocs code

FromNicolas Pitre <nicolas.pitre@linaro.org>
Date2016-07-18 05:40 +0200
Subject[PATCH v2 06/10] binfmt_flat: use proper user space accessors with old relocs code
Message-ID<rW7zs-T6-7@gated-at.bofh.it>
In reply to#1445182
Signed-off-by: Nicolas Pitre <nico@linaro.org>
---
 fs/binfmt_flat.c | 28 ++++++++++++++++++----------
 1 file changed, 18 insertions(+), 10 deletions(-)

diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index fc0ee3ed5d..c85f8f1239 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -394,38 +394,41 @@ static void old_reloc(unsigned long rl)
 	static const char *segment[] = { "TEXT", "DATA", "BSS", "*UNKNOWN*" };
 #endif
 	flat_v2_reloc_t	r;
-	unsigned long *ptr;
+	unsigned long __user *ptr;
+	unsigned long val;
 	
 	r.value = rl;
 #if defined(CONFIG_COLDFIRE)
-	ptr = (unsigned long *) (current->mm->start_code + r.reloc.offset);
+	ptr = (unsigned long __user *)(current->mm->start_code + r.reloc.offset);
 #else
-	ptr = (unsigned long *) (current->mm->start_data + r.reloc.offset);
+	ptr = (unsigned long __user *)(current->mm->start_data + r.reloc.offset);
 #endif
+	__get_user(val, ptr);
 
 #ifdef DEBUG
 	printk("Relocation of variable at DATASEG+%x "
 		"(address %p, currently %lx) into segment %s\n",
-		r.reloc.offset, ptr, *ptr, segment[r.reloc.type]);
+		r.reloc.offset, ptr, val, segment[r.reloc.type]);
 #endif
 	
 	switch (r.reloc.type) {
 	case OLD_FLAT_RELOC_TYPE_TEXT:
-		*ptr += current->mm->start_code;
+		val += current->mm->start_code;
 		break;
 	case OLD_FLAT_RELOC_TYPE_DATA:
-		*ptr += current->mm->start_data;
+		val += current->mm->start_data;
 		break;
 	case OLD_FLAT_RELOC_TYPE_BSS:
-		*ptr += current->mm->end_data;
+		val += current->mm->end_data;
 		break;
 	default:
 		printk("BINFMT_FLAT: Unknown relocation type=%x\n", r.reloc.type);
 		break;
 	}
+	__put_user(val, ptr);
 
 #ifdef DEBUG
-	printk("Relocation became %lx\n", *ptr);
+	printk("Relocation became %lx\n", val);
 #endif
 }		
 
@@ -788,8 +791,13 @@ static int load_flat_file(struct linux_binprm * bprm,
 			}
 		}
 	} else {
-		for (i=0; i < relocs; i++)
-			old_reloc(ntohl(reloc[i]));
+		for (i=0; i < relocs; i++) {
+			unsigned long relval;
+			if (get_user(relval, reloc + i))
+				return -EFAULT;
+			relval = ntohl(relval);
+			old_reloc(relval);
+		}
 	}
 	
 	flush_icache_range(start_code, end_code);
-- 
2.7.4

[toc] | [prev] | [next] | [standalone]


#1445187 — [PATCH v2 01/10] binfmt_flat: assorted cleanups

FromNicolas Pitre <nicolas.pitre@linaro.org>
Date2016-07-18 05:40 +0200
Subject[PATCH v2 01/10] binfmt_flat: assorted cleanups
Message-ID<rW7zs-T6-23@gated-at.bofh.it>
In reply to#1445182
Remove excessive casts, do some code grouping, etc.
No functional changes.

Signed-off-by: Nicolas Pitre <nico@linaro.org>
---
 fs/binfmt_flat.c | 118 ++++++++++++++++++++++++++-----------------------------
 1 file changed, 56 insertions(+), 62 deletions(-)

diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index caf9e39bb8..085059d879 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -80,7 +80,7 @@ struct lib_info {
 		unsigned long text_len;			/* Length of text segment */
 		unsigned long entry;			/* Start address for this module */
 		unsigned long build_date;		/* When this one was compiled */
-		short loaded;				/* Has this library been loaded? */
+		bool loaded;				/* Has this library been loaded? */
 	} lib_list[MAX_SHARED_LIBS];
 };
 
@@ -107,7 +107,7 @@ static struct linux_binfmt flat_format = {
 static int flat_core_dump(struct coredump_params *cprm)
 {
 	printk("Process %s:%d received signr %d and should have core dumped\n",
-			current->comm, current->pid, (int) cprm->siginfo->si_signo);
+			current->comm, current->pid, cprm->siginfo->si_signo);
 	return(1);
 }
 
@@ -190,7 +190,7 @@ static int decompress_exec(
 	loff_t fpos;
 	int ret, retval;
 
-	DBG_FLT("decompress_exec(offset=%x,buf=%x,len=%x)\n",(int)offset, (int)dst, (int)len);
+	DBG_FLT("decompress_exec(offset=%lx,buf=%p,len=%lx)\n",offset, dst, len);
 
 	memset(&strm, 0, sizeof(strm));
 	strm.workspace = kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL);
@@ -358,8 +358,8 @@ calc_reloc(unsigned long r, struct lib_info *p, int curid, int internalp)
 	text_len = p->lib_list[id].text_len;
 
 	if (!flat_reloc_valid(r, start_brk - start_data + text_len)) {
-		printk("BINFMT_FLAT: reloc outside program 0x%x (0 - 0x%x/0x%x)",
-		       (int) r,(int)(start_brk-start_data+text_len),(int)text_len);
+		printk("BINFMT_FLAT: reloc outside program 0x%lx (0 - 0x%lx/0x%lx)",
+		       r, start_brk-start_data+text_len, text_len);
 		goto failed;
 	}
 
@@ -383,7 +383,7 @@ failed:
 static void old_reloc(unsigned long rl)
 {
 #ifdef DEBUG
-	char *segment[] = { "TEXT", "DATA", "BSS", "*UNKNOWN*" };
+	static const char *segment[] = { "TEXT", "DATA", "BSS", "*UNKNOWN*" };
 #endif
 	flat_v2_reloc_t	r;
 	unsigned long *ptr;
@@ -397,8 +397,8 @@ static void old_reloc(unsigned long rl)
 
 #ifdef DEBUG
 	printk("Relocation of variable at DATASEG+%x "
-		"(address %p, currently %x) into segment %s\n",
-		r.reloc.offset, ptr, (int)*ptr, segment[r.reloc.type]);
+		"(address %p, currently %lx) into segment %s\n",
+		r.reloc.offset, ptr, *ptr, segment[r.reloc.type]);
 #endif
 	
 	switch (r.reloc.type) {
@@ -417,7 +417,7 @@ static void old_reloc(unsigned long rl)
 	}
 
 #ifdef DEBUG
-	printk("Relocation became %x\n", (int)*ptr);
+	printk("Relocation became %lx\n", *ptr);
 #endif
 }		
 
@@ -427,17 +427,15 @@ static int load_flat_file(struct linux_binprm * bprm,
 		struct lib_info *libinfo, int id, unsigned long *extra_stack)
 {
 	struct flat_hdr * hdr;
-	unsigned long textpos = 0, datapos = 0, result;
-	unsigned long realdatastart = 0;
-	unsigned long text_len, data_len, bss_len, stack_len, flags;
-	unsigned long full_data;
-	unsigned long len, memp = 0;
-	unsigned long memp_size, extra, rlim;
-	unsigned long *reloc = 0, *rp;
+	unsigned long textpos, datapos, realdatastart;
+	unsigned long text_len, data_len, bss_len, stack_len, full_data, flags;
+	unsigned long len, memp, memp_size, extra, rlim;
+	unsigned long *reloc, *rp;
 	struct inode *inode;
-	int i, rev, relocs = 0;
+	int i, rev, relocs;
 	loff_t fpos;
 	unsigned long start_code, end_code;
+	ssize_t result;
 	int ret;
 
 	hdr = ((struct flat_hdr *) bprm->buf);		/* exec-header */
@@ -481,8 +479,8 @@ static int load_flat_file(struct linux_binprm * bprm,
 	
 	/* 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);
+		printk("BINFMT_FLAT: shared libraries are not available before rev 0x%lx\n",
+				FLAT_VERSION);
 		ret = -ENOEXEC;
 		goto err;
 	}
@@ -517,11 +515,9 @@ static int load_flat_file(struct linux_binprm * bprm,
 
 	/* Flush all traces of the currently running executable */
 	if (id == 0) {
-		result = flush_old_exec(bprm);
-		if (result) {
-			ret = result;
+		ret = flush_old_exec(bprm);
+		if (ret)
 			goto err;
-		}
 
 		/* OK, This is the point of no return */
 		set_personality(PER_LINUX_32BIT);
@@ -549,33 +545,33 @@ static int load_flat_file(struct linux_binprm * bprm,
 		textpos = vm_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC,
 				  MAP_PRIVATE|MAP_EXECUTABLE, 0);
 		if (!textpos || IS_ERR_VALUE(textpos)) {
-			if (!textpos)
-				textpos = (unsigned long) -ENOMEM;
-			printk("Unable to mmap process text, errno %d\n", (int)-textpos);
 			ret = textpos;
+			if (!textpos)
+				ret = -ENOMEM;
+			printk("Unable to mmap process text, errno %d\n", ret);
 			goto err;
 		}
 
 		len = data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long);
 		len = PAGE_ALIGN(len);
-		realdatastart = vm_mmap(0, 0, len,
+		realdatastart = vm_mmap(NULL, 0, len,
 			PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0);
 
 		if (realdatastart == 0 || IS_ERR_VALUE(realdatastart)) {
+			ret = realdatastart;
 			if (!realdatastart)
-				realdatastart = (unsigned long) -ENOMEM;
-			printk("Unable to allocate RAM for process data, errno %d\n",
-					(int)-realdatastart);
+				ret = -ENOMEM;
+			printk("Unable to allocate RAM for process data, "
+			       "errno %d\n", ret);
 			vm_munmap(textpos, text_len);
-			ret = realdatastart;
 			goto err;
 		}
 		datapos = ALIGN(realdatastart +
 				MAX_SHARED_LIBS * sizeof(unsigned long),
 				FLAT_DATA_ALIGN);
 
-		DBG_FLT("BINFMT_FLAT: Allocated data+bss+stack (%d bytes): %x\n",
-				(int)(data_len + bss_len + stack_len), (int)datapos);
+		DBG_FLT("BINFMT_FLAT: Allocated data+bss+stack (%ld bytes): %lx\n",
+			data_len + bss_len + stack_len, datapos);
 
 		fpos = ntohl(hdr->data_start);
 #ifdef CONFIG_BINFMT_ZFLAT
@@ -589,29 +585,30 @@ static int load_flat_file(struct linux_binprm * bprm,
 					full_data);
 		}
 		if (IS_ERR_VALUE(result)) {
-			printk("Unable to read data+bss, errno %d\n", (int)-result);
+			ret = result;
+			printk("Unable to read data+bss, errno %d\n", ret);
 			vm_munmap(textpos, text_len);
 			vm_munmap(realdatastart, len);
-			ret = result;
 			goto err;
 		}
 
-		reloc = (unsigned long *) (datapos+(ntohl(hdr->reloc_start)-text_len));
+		reloc = (unsigned long *)
+			(datapos + (ntohl(hdr->reloc_start) - text_len));
 		memp = realdatastart;
 		memp_size = len;
 	} else {
 
 		len = text_len + data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long);
 		len = PAGE_ALIGN(len);
-		textpos = vm_mmap(0, 0, len,
+		textpos = vm_mmap(NULL, 0, len,
 			PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0);
 
 		if (!textpos || IS_ERR_VALUE(textpos)) {
-			if (!textpos)
-				textpos = (unsigned long) -ENOMEM;
-			printk("Unable to allocate RAM for process text/data, errno %d\n",
-					(int)-textpos);
 			ret = textpos;
+			if (!textpos)
+				ret = -ENOMEM;
+			printk("Unable to allocate RAM for process text/data, "
+			       "errno %d\n", ret);
 			goto err;
 		}
 
@@ -652,21 +649,19 @@ static int load_flat_file(struct linux_binprm * bprm,
 						   full_data);
 		}
 		if (IS_ERR_VALUE(result)) {
-			printk("Unable to read code+data+bss, errno %d\n",(int)-result);
+			ret = result;
+			printk("Unable to read code+data+bss, errno %d\n", ret);
 			vm_munmap(textpos, text_len + data_len + extra +
 				MAX_SHARED_LIBS * sizeof(unsigned long));
-			ret = result;
 			goto err;
 		}
 	}
 
-	if (flags & FLAT_FLAG_KTRACE)
-		printk("Mapping is %x, Entry point is %x, data_start is %x\n",
-			(int)textpos, 0x00ffffff&ntohl(hdr->entry), ntohl(hdr->data_start));
-
-	/* The main program needs a little extra setup in the task structure */
 	start_code = textpos + sizeof (struct flat_hdr);
 	end_code = textpos + text_len;
+	text_len -= sizeof(struct flat_hdr); /* the real code len */
+
+	/* The main program needs a little extra setup in the task structure */
 	if (id == 0) {
 		current->mm->start_code = start_code;
 		current->mm->end_code = end_code;
@@ -684,16 +679,14 @@ static int load_flat_file(struct linux_binprm * bprm,
 		current->mm->context.end_brk = memp + memp_size - stack_len;
 	}
 
-	if (flags & FLAT_FLAG_KTRACE)
-		printk("%s %s: TEXT=%x-%x DATA=%x-%x BSS=%x-%x\n",
-			id ? "Lib" : "Load", bprm->filename,
-			(int) start_code, (int) end_code,
-			(int) datapos,
-			(int) (datapos + data_len),
-			(int) (datapos + data_len),
-			(int) (((datapos + data_len + bss_len) + 3) & ~3));
-
-	text_len -= sizeof(struct flat_hdr); /* the real code len */
+	if (flags & FLAT_FLAG_KTRACE) {
+		printk("Mapping is %lx, Entry point is %x, data_start is %x\n",
+		       textpos, 0x00ffffff&ntohl(hdr->entry), ntohl(hdr->data_start));
+		printk("%s %s: TEXT=%lx-%lx DATA=%lx-%lx BSS=%lx-%lx\n",
+		       id ? "Lib" : "Load", bprm->filename,
+		       start_code, end_code, datapos, datapos + data_len,
+		       datapos + data_len, (datapos + data_len + bss_len + 3) & ~3);
+	}
 
 	/* Store the current module values into the global library structure */
 	libinfo->lib_list[id].start_code = start_code;
@@ -869,6 +862,7 @@ static int load_flat_binary(struct linux_binprm * bprm)
 	int i, j;
 
 	memset(&libinfo, 0, sizeof(libinfo));
+
 	/*
 	 * We have to add the size of our arguments to our stack size
 	 * otherwise it's too easy for users to create stack overflows
@@ -899,7 +893,7 @@ static int load_flat_binary(struct linux_binprm * bprm)
 	set_binfmt(&flat_format);
 
 	p = ((current->mm->context.end_brk + stack_len + 3) & ~3) - 4;
-	DBG_FLT("p=%x\n", (int)p);
+	DBG_FLT("p=%lx\n", p);
 
 	/* copy the arg pages onto the stack, this could be more efficient :-) */
 	for (i = TOP_OF_ARGS - 1; i >= bprm->p; i--)
@@ -930,9 +924,9 @@ static int load_flat_binary(struct linux_binprm * bprm)
 #ifdef FLAT_PLAT_INIT
 	FLAT_PLAT_INIT(regs);
 #endif
-	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);
-	
+
+	DBG_FLT("start_thread(regs=0x%p, entry=0x%lx, start_stack=0x%lx)\n",
+		regs, start_addr, current->mm->start_stack);
 	start_thread(regs, start_addr, current->mm->start_stack);
 
 	return 0;
-- 
2.7.4

[toc] | [prev] | [next] | [standalone]


#1446025 — Re: [PATCH v2 01/10] binfmt_flat: assorted cleanups

FromGreg Ungerer <gerg@linux-m68k.org>
Date2016-07-19 07:10 +0200
SubjectRe: [PATCH v2 01/10] binfmt_flat: assorted cleanups
Message-ID<rWvs5-8aD-9@gated-at.bofh.it>
In reply to#1445187
Hi Nicolas,

On 18/07/16 13:31, Nicolas Pitre wrote:
> Remove excessive casts, do some code grouping, etc.
> No functional changes.
> 
> Signed-off-by: Nicolas Pitre <nico@linaro.org>
> ---
>  fs/binfmt_flat.c | 118 ++++++++++++++++++++++++++-----------------------------
>  1 file changed, 56 insertions(+), 62 deletions(-)
> 
> diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
> index caf9e39bb8..085059d879 100644
> --- a/fs/binfmt_flat.c
> +++ b/fs/binfmt_flat.c
> @@ -80,7 +80,7 @@ struct lib_info {
>  		unsigned long text_len;			/* Length of text segment */
>  		unsigned long entry;			/* Start address for this module */
>  		unsigned long build_date;		/* When this one was compiled */
> -		short loaded;				/* Has this library been loaded? */
> +		bool loaded;				/* Has this library been loaded? */
>  	} lib_list[MAX_SHARED_LIBS];
>  };
>  
> @@ -107,7 +107,7 @@ static struct linux_binfmt flat_format = {
>  static int flat_core_dump(struct coredump_params *cprm)
>  {
>  	printk("Process %s:%d received signr %d and should have core dumped\n",
> -			current->comm, current->pid, (int) cprm->siginfo->si_signo);
> +			current->comm, current->pid, cprm->siginfo->si_signo);
>  	return(1);
>  }
>  
> @@ -190,7 +190,7 @@ static int decompress_exec(
>  	loff_t fpos;
>  	int ret, retval;
>  
> -	DBG_FLT("decompress_exec(offset=%x,buf=%x,len=%x)\n",(int)offset, (int)dst, (int)len);
> +	DBG_FLT("decompress_exec(offset=%lx,buf=%p,len=%lx)\n",offset, dst, len);
>  
>  	memset(&strm, 0, sizeof(strm));
>  	strm.workspace = kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL);
> @@ -358,8 +358,8 @@ calc_reloc(unsigned long r, struct lib_info *p, int curid, int internalp)
>  	text_len = p->lib_list[id].text_len;
>  
>  	if (!flat_reloc_valid(r, start_brk - start_data + text_len)) {
> -		printk("BINFMT_FLAT: reloc outside program 0x%x (0 - 0x%x/0x%x)",
> -		       (int) r,(int)(start_brk-start_data+text_len),(int)text_len);
> +		printk("BINFMT_FLAT: reloc outside program 0x%lx (0 - 0x%lx/0x%lx)",
> +		       r, start_brk-start_data+text_len, text_len);

Seeing as you have modified quite a few printk calls is it worth
while annotating them with appropriate KERN_ERR, KERN_INFO, etc?
Just a thought.

Regards
Greg

[toc] | [prev] | [next] | [standalone]


#1446068 — Re: [PATCH v2 01/10] binfmt_flat: assorted cleanups

FromGeert Uytterhoeven <geert@linux-m68k.org>
Date2016-07-19 08:50 +0200
SubjectRe: [PATCH v2 01/10] binfmt_flat: assorted cleanups
Message-ID<rWx0R-BC-23@gated-at.bofh.it>
In reply to#1446025
On Tue, Jul 19, 2016 at 6:52 AM, Greg Ungerer <gerg@linux-m68k.org> wrote:
> Seeing as you have modified quite a few printk calls is it worth
> while annotating them with appropriate KERN_ERR, KERN_INFO, etc?

You mean pr_err(), pr_info(), ... ;-)

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

[toc] | [prev] | [next] | [standalone]


#1446945 — Re: [PATCH v2 01/10] binfmt_flat: assorted cleanups

FromNicolas Pitre <nicolas.pitre@linaro.org>
Date2016-07-20 06:20 +0200
SubjectRe: [PATCH v2 01/10] binfmt_flat: assorted cleanups
Message-ID<rWR9f-4VD-11@gated-at.bofh.it>
In reply to#1446068
On Tue, 19 Jul 2016, Geert Uytterhoeven wrote:

> On Tue, Jul 19, 2016 at 6:52 AM, Greg Ungerer <gerg@linux-m68k.org> wrote:
> > Seeing as you have modified quite a few printk calls is it worth
> > while annotating them with appropriate KERN_ERR, KERN_INFO, etc?
> 
> You mean pr_err(), pr_info(), ... ;-)

Done.  Included in v3.


Nicolas

[toc] | [prev] | [next] | [standalone]


#1447028 — Re: [PATCH v2 01/10] binfmt_flat: assorted cleanups

FromGeert Uytterhoeven <geert@linux-m68k.org>
Date2016-07-20 09:00 +0200
SubjectRe: [PATCH v2 01/10] binfmt_flat: assorted cleanups
Message-ID<rWTE6-6ph-19@gated-at.bofh.it>
In reply to#1446945
Hi Nicolas,

On Wed, Jul 20, 2016 at 6:09 AM, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> On Tue, 19 Jul 2016, Geert Uytterhoeven wrote:
>
>> On Tue, Jul 19, 2016 at 6:52 AM, Greg Ungerer <gerg@linux-m68k.org> wrote:
>> > Seeing as you have modified quite a few printk calls is it worth
>> > while annotating them with appropriate KERN_ERR, KERN_INFO, etc?
>>
>> You mean pr_err(), pr_info(), ... ;-)
>
> Done.  Included in v3.

Really? The only change in v3 is the Reviewed-by?

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

[toc] | [prev] | [next] | [standalone]


#1447037 — Re: [PATCH v2 01/10] binfmt_flat: assorted cleanups

FromGreg Ungerer <gerg@linux-m68k.org>
Date2016-07-20 09:20 +0200
SubjectRe: [PATCH v2 01/10] binfmt_flat: assorted cleanups
Message-ID<rWTXs-6L3-13@gated-at.bofh.it>
In reply to#1447028
Hi Geert,

On 20/07/16 16:54, Geert Uytterhoeven wrote:
> Hi Nicolas,
> 
> On Wed, Jul 20, 2016 at 6:09 AM, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
>> On Tue, 19 Jul 2016, Geert Uytterhoeven wrote:
>>
>>> On Tue, Jul 19, 2016 at 6:52 AM, Greg Ungerer <gerg@linux-m68k.org> wrote:
>>>> Seeing as you have modified quite a few printk calls is it worth
>>>> while annotating them with appropriate KERN_ERR, KERN_INFO, etc?
>>>
>>> You mean pr_err(), pr_info(), ... ;-)
>>
>> Done.  Included in v3.
> 
> Really? The only change in v3 is the Reviewed-by?

Patch 2 in the series now does this:

[PATCH v3 02/12] binfmt_flat: convert printk invocations to their modern form

Regards
Greg


> Gr{oetje,eeting}s,
> 
>                         Geert
> 
> --
> Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
> 
> In personal conversations with technical people, I call myself a hacker. But
> when I'm talking to journalists I just say "programmer" or something like that.
>                                 -- Linus Torvalds
> 

[toc] | [prev] | [next] | [standalone]


#1445188 — [PATCH v2 09/10] binfmt_flat: add MMU-specific support

FromNicolas Pitre <nicolas.pitre@linaro.org>
Date2016-07-18 05:50 +0200
Subject[PATCH v2 09/10] binfmt_flat: add MMU-specific support
Message-ID<rW7J7-X0-1@gated-at.bofh.it>
In reply to#1445182
Not much else to do at this point except for the different stack setups.

SuperH and Xtensa could be added to the allowed list if they implement
__put_user_unaligned() and __get_user_unaligned().

Signed-off-by: Nicolas Pitre <nico@linaro.org>
---
 fs/Kconfig.binfmt |  3 ++-
 fs/binfmt_flat.c  | 16 +++++++++++++---
 2 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/fs/Kconfig.binfmt b/fs/Kconfig.binfmt
index 72c03354c1..4c09d93d95 100644
--- a/fs/Kconfig.binfmt
+++ b/fs/Kconfig.binfmt
@@ -89,7 +89,8 @@ config BINFMT_SCRIPT
 
 config BINFMT_FLAT
 	bool "Kernel support for flat binaries"
-	depends on !MMU && (!FRV || BROKEN)
+	depends on !MMU || ARM || M68K
+	depends on !FRV || BROKEN
 	help
 	  Support uClinux FLAT format binaries.
 
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index 3221ed9d7c..4cb0c4b6ae 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -546,7 +546,7 @@ static int load_flat_file(struct linux_binprm * bprm,
 	 * case,  and then the fully copied to RAM case which lumps
 	 * it all together.
 	 */
-	if ((flags & (FLAT_FLAG_RAM|FLAT_FLAG_GZIP)) == 0) {
+	if (!IS_ENABLED(CONFIG_MMU) && !(flags & (FLAT_FLAG_RAM|FLAT_FLAG_GZIP))) {
 		/*
 		 * this should give us a ROM ptr,  but if it doesn't we don't
 		 * really care
@@ -687,7 +687,9 @@ static int load_flat_file(struct linux_binprm * bprm,
 		 */
 		current->mm->start_brk = datapos + data_len + bss_len;
 		current->mm->brk = (current->mm->start_brk + 3) & ~3;
+#ifndef CONFIG_MMU
 		current->mm->context.end_brk = memp + memp_size - stack_len;
+#endif
 	}
 
 	if (flags & FLAT_FLAG_KTRACE) {
@@ -878,7 +880,7 @@ static int load_flat_binary(struct linux_binprm * bprm)
 {
 	struct lib_info libinfo;
 	struct pt_regs *regs = current_pt_regs();
-	unsigned long stack_len;
+	unsigned long stack_len = 0;
 	unsigned long start_addr;
 	int res;
 	int i, j;
@@ -892,7 +894,9 @@ static int load_flat_binary(struct linux_binprm * bprm)
 	 * pedantic and include space for the argv/envp array as it may have
 	 * a lot of entries.
 	 */
-	stack_len = PAGE_SIZE * MAX_ARG_PAGES - bprm->p;  /* the strings */
+#ifndef CONFIG_MMU
+	stack_len += PAGE_SIZE * MAX_ARG_PAGES - bprm->p; /* the strings */
+#endif
 	stack_len += (bprm->argc + 1) * sizeof(char *);   /* the argv array */
 	stack_len += (bprm->envc + 1) * sizeof(char *);   /* the envp array */
 	stack_len = ALIGN(stack_len, FLAT_STACK_ALIGN);
@@ -920,6 +924,11 @@ static int load_flat_binary(struct linux_binprm * bprm)
 
 	set_binfmt(&flat_format);
 
+#ifdef CONFIG_MMU
+	res = setup_arg_pages(bprm, STACK_TOP, EXSTACK_DEFAULT);
+	if (!res)
+		res = create_flat_tables(bprm, bprm->p);
+#else
 	/* Stash our initial stack pointer into the mm structure */
 	current->mm->start_stack =
 		((current->mm->context.end_brk + stack_len + 3) & ~3) - 4;
@@ -929,6 +938,7 @@ static int load_flat_binary(struct linux_binprm * bprm)
 	res = transfer_args_to_stack(bprm, &current->mm->start_stack);
 	if (!res)
 		res = create_flat_tables(bprm, current->mm->start_stack);
+#endif
 	if (res)
 		return res;
 
-- 
2.7.4

[toc] | [prev] | [next] | [standalone]


#1445189 — [PATCH v2 04/10] binfmt_flat: clean up create_flat_tables() and stack accesses

FromNicolas Pitre <nicolas.pitre@linaro.org>
Date2016-07-18 05:50 +0200
Subject[PATCH v2 04/10] binfmt_flat: clean up create_flat_tables() and stack accesses
Message-ID<rW7J8-X0-3@gated-at.bofh.it>
In reply to#1445182
In addition to better code clarity, this brings proper usage of
user memory accessors everywhere the stack is touched. This is essential
for making this work on MMU systems.

Signed-off-by: Nicolas Pitre <nico@linaro.org>
---
 fs/binfmt_flat.c | 117 ++++++++++++++++++++++++++++++-------------------------
 1 file changed, 63 insertions(+), 54 deletions(-)

diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index 64feb873f0..9538901fe8 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -115,50 +115,58 @@ static int flat_core_dump(struct coredump_params *cprm)
 /*
  * create_flat_tables() parses the env- and arg-strings in new user
  * memory and creates the pointer tables from them, and puts their
- * addresses on the "stack", returning the new stack pointer value.
+ * addresses on the "stack", recording the new stack pointer value.
  */
 
-static unsigned long create_flat_tables(
-	unsigned long pp,
-	struct linux_binprm * bprm)
+static int create_flat_tables(struct linux_binprm * bprm, unsigned long arg_start)
 {
-	unsigned long *argv,*envp;
-	unsigned long * sp;
-	char * p = (char*)pp;
-	int argc = bprm->argc;
-	int envc = bprm->envc;
-	char uninitialized_var(dummy);
-
-	sp = (unsigned long *)p;
-	sp -= (envc + argc + 2) + 1 + (flat_argvp_envp_on_stack() ? 2 : 0);
-	sp = (unsigned long *) ((unsigned long)sp & -FLAT_STACK_ALIGN);
-	argv = sp + 1 + (flat_argvp_envp_on_stack() ? 2 : 0);
-	envp = argv + (argc + 1);
+	char __user *p;
+	unsigned long __user *sp;
+	long i, len;
 
+	p = (char __user *)arg_start;
+	sp = (unsigned long __user *)current->mm->start_stack;
+
+	sp -= bprm->envc + 1;
+	sp -= bprm->argc + 1;
+	sp -= flat_argvp_envp_on_stack() ? 2 : 0;
+	sp -= 1;  /* &argc */
+
+	current->mm->start_stack = (unsigned long)sp & -FLAT_STACK_ALIGN;
+	sp = (unsigned long __user *)current->mm->start_stack;
+
+	__put_user(bprm->argc, sp++);
 	if (flat_argvp_envp_on_stack()) {
-		put_user((unsigned long) envp, sp + 2);
-		put_user((unsigned long) argv, sp + 1);
-	}
-
-	put_user(argc, sp);
-	current->mm->arg_start = (unsigned long) p;
-	while (argc-->0) {
-		put_user((unsigned long) p, argv++);
-		do {
-			get_user(dummy, p); p++;
-		} while (dummy);
-	}
-	put_user((unsigned long) NULL, argv);
-	current->mm->arg_end = current->mm->env_start = (unsigned long) p;
-	while (envc-->0) {
-		put_user((unsigned long)p, envp); envp++;
-		do {
-			get_user(dummy, p); p++;
-		} while (dummy);
-	}
-	put_user((unsigned long) NULL, envp);
-	current->mm->env_end = (unsigned long) p;
-	return (unsigned long)sp;
+		unsigned long argv, envp;
+		argv = (unsigned long)(sp + 2);
+		envp = (unsigned long)(sp + 2 + bprm->argc + 1);
+		__put_user(argv, sp++);
+		__put_user(envp, sp++);
+	}
+
+	current->mm->arg_start = (unsigned long)p;
+	for (i = bprm->argc; i > 0; i--) {
+		__put_user((unsigned long)p, sp++);
+		len = strnlen_user(p, MAX_ARG_STRLEN);
+		if (!len || len > MAX_ARG_STRLEN)
+			return -EINVAL;
+		p += len;
+	}
+	__put_user(0, sp++);
+	current->mm->arg_end = (unsigned long)p;
+
+	current->mm->env_start = (unsigned long) p;
+	for (i = bprm->envc; i > 0; i--) {
+		__put_user((unsigned long)p, sp++);
+		len = strnlen_user(p, MAX_ARG_STRLEN);
+		if (!len || len > MAX_ARG_STRLEN)
+			return -EINVAL;
+		p += len;
+	}
+	__put_user(0, sp++);
+	current->mm->env_end = (unsigned long)p;
+
+	return 0;
 }
 
 /****************************************************************************/
@@ -854,7 +862,7 @@ static int load_flat_binary(struct linux_binprm * bprm)
 {
 	struct lib_info libinfo;
 	struct pt_regs *regs = current_pt_regs();
-	unsigned long sp, stack_len;
+	unsigned long stack_len;
 	unsigned long start_addr;
 	int res;
 	int i, j;
@@ -868,11 +876,10 @@ static int load_flat_binary(struct linux_binprm * bprm)
 	 * pedantic and include space for the argv/envp array as it may have
 	 * a lot of entries.
 	 */
-#define TOP_OF_ARGS (PAGE_SIZE * MAX_ARG_PAGES - sizeof(void *))
-	stack_len = TOP_OF_ARGS - bprm->p;             /* the strings */
-	stack_len += (bprm->argc + 1) * sizeof(char *); /* the argv array */
-	stack_len += (bprm->envc + 1) * sizeof(char *); /* the envp array */
-	stack_len += FLAT_STACK_ALIGN - 1;  /* reserve for upcoming alignment */
+	stack_len = PAGE_SIZE * MAX_ARG_PAGES - bprm->p;  /* the strings */
+	stack_len += (bprm->argc + 1) * sizeof(char *);   /* the argv array */
+	stack_len += (bprm->envc + 1) * sizeof(char *);   /* the envp array */
+	stack_len = ALIGN(stack_len, FLAT_STACK_ALIGN);
 	
 	res = load_flat_file(bprm, &libinfo, 0, &stack_len);
 	if (res < 0)
@@ -890,16 +897,18 @@ static int load_flat_binary(struct linux_binprm * bprm)
 
 	set_binfmt(&flat_format);
 
-	sp = ((current->mm->context.end_brk + stack_len + 3) & ~3) - 4;
-	DBG_FLT("sp=%lx\n", sp);
+	/* Stash our initial stack pointer into the mm structure */
+	current->mm->start_stack =
+		((current->mm->context.end_brk + stack_len + 3) & ~3) - 4;
+	DBG_FLT("sp=%lx\n", current->mm->start_stack);
 
 	/* copy the arg pages onto the stack */
-	res = transfer_args_to_stack(bprm, &sp);
+	res = transfer_args_to_stack(bprm, &current->mm->start_stack);
+	if (!res)
+		res = create_flat_tables(bprm, current->mm->start_stack);
 	if (res)
 		return res;
 
-	sp = create_flat_tables(sp, 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).
@@ -910,14 +919,14 @@ static int load_flat_binary(struct linux_binprm * bprm)
 	for (i = MAX_SHARED_LIBS-1; i>0; i--) {
 		if (libinfo.lib_list[i].loaded) {
 			/* Push previos first to call address */
-			--sp;	put_user(start_addr, (unsigned long *)sp);
+			unsigned long __user *sp;
+			current->mm->start_stack -= sizeof(unsigned long);
+			sp = (unsigned long __user *)current->mm->start_stack;
+			__put_user(start_addr, sp);
 			start_addr = libinfo.lib_list[i].entry;
 		}
 	}
 #endif
-	
-	/* Stash our initial stack pointer into the mm structure */
-	current->mm->start_stack = sp;
 
 #ifdef FLAT_PLAT_INIT
 	FLAT_PLAT_INIT(regs);
-- 
2.7.4

[toc] | [prev] | [next] | [standalone]


#1445190 — [PATCH v2 08/10] binfmt_flat: update libraries' data segment pointer with userspace accessors

FromNicolas Pitre <nicolas.pitre@linaro.org>
Date2016-07-18 05:50 +0200
Subject[PATCH v2 08/10] binfmt_flat: update libraries' data segment pointer with userspace accessors
Message-ID<rW7J8-X0-5@gated-at.bofh.it>
In reply to#1445182
This is needed on systems with a MMU.  This also gets rid of the
strangest C code I've seen lateli i.e. an integer indexed with a
pointer value within square brackets. That really looked backwards.

Signed-off-by: Nicolas Pitre <nico@linaro.org>
---
 fs/binfmt_flat.c | 19 +++++++++++++------
 1 file changed, 13 insertions(+), 6 deletions(-)

diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index e981e66bb5..3221ed9d7c 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -902,12 +902,19 @@ static int load_flat_binary(struct linux_binprm * bprm)
 		return res;
 	
 	/* Update data segment pointers for all libraries */
-	for (i=0; i<MAX_SHARED_LIBS; i++)
-		if (libinfo.lib_list[i].loaded)
-			for (j=0; j<MAX_SHARED_LIBS; j++)
-				(-(j+1))[(unsigned long *)(libinfo.lib_list[i].start_data)] =
-					(libinfo.lib_list[j].loaded)?
-						libinfo.lib_list[j].start_data:UNLOADED_LIB;
+	for (i=0; i<MAX_SHARED_LIBS; i++) {
+		if (!libinfo.lib_list[i].loaded)
+			continue;
+		for (j=0; j<MAX_SHARED_LIBS; j++) {
+			unsigned long val = libinfo.lib_list[j].loaded ?
+				libinfo.lib_list[j].start_data : UNLOADED_LIB;
+			unsigned long __user *p = (unsigned long __user *)
+				libinfo.lib_list[i].start_data;
+			p -= j + 1;
+			if (put_user(val, p))
+				return -EFAULT;
+		}
+	}
 
 	install_exec_creds(bprm);
 
-- 
2.7.4

[toc] | [prev] | [next] | [standalone]


#1446159 — Re: [PULL REQUEST] [PATCH v2 00/10] allow BFLT executables on systems with a MMU

FromGreg Ungerer <gerg@linux-m68k.org>
Date2016-07-19 09:30 +0200
SubjectRe: [PULL REQUEST] [PATCH v2 00/10] allow BFLT executables on systems with a MMU
Message-ID<rWxDA-15B-25@gated-at.bofh.it>
In reply to#1445182
Hi Nicolas,

On 18/07/16 13:31, Nicolas Pitre wrote:
> This series provides the necessary changes to allow "flat" executable
> binaries meant for no-MMU systems to actually run on systems with a MMU.
> 
> This can also be found in the following git repo:
> 
> 	git://git.linaro.org/people/nicolas.pitre/linux binfmt_flat_with_mmu
> 
> *Why?*
> 
> Because developing and testing natively on a large system with lots of
> RAM makes it so much more convenient to use all the existing profiling
> tools and debugging facilities that a kernel with lots of RAM can give.
> And incidentally, those systems with lots of RAM all have a MMU.
> 
> *Why not use elf_fdpic?*
> 
> The flat executable format is simple with very small footprint
> overhead, either in the executables themselves or kernel support.
> This makes the flat format more suitable than elf_fdpic for very small
> single-user-app embedded systems.
> 
> And while elf_fdpic binaries can run on MMU systems, flat binaries still
> couldn't, which just felt wrong.
> 
> So here it is.  The no-MMU support should remain unaffected. Please consider
> for pulling.
> 
> Tested on ARM only with a busybox build.

Tested on m68k (ColdFire specifically) and everything compiles
cleanly and works as before.

I tried running a flat binary on an MMU ColdFire system and
that crashed out with a SIGSEGV. I haven't debugged any further
than that yet.

I had a look over the patches and I didn't see any specific
problems. So from me:

Reviewed-by: Greg Ungerer <gerg@linux-m68k.org>

When I get a minute I'll dig a little into that bflat running
on MMU problem on ColdFire.

Regards
Greg



> Changes since v1:
> 
> - Removed SuperH and Xtensa from the Kconfig rule as they fail to build
>   due to lack of get/put_unaligned_user().
> 
> - Clarified some commit logs a bit.
> 
> diffstat:
> 
>  arch/arm/include/asm/flat.h  |   5 +-
>  arch/m68k/include/asm/flat.h |   5 +-
>  fs/Kconfig.binfmt            |   3 +-
>  fs/binfmt_elf_fdpic.c        |  38 +---
>  fs/binfmt_flat.c             | 372 +++++++++++++++++++++--------------
>  fs/exec.c                    |  33 ++++
>  include/linux/binfmts.h      |   2 +
>  7 files changed, 268 insertions(+), 190 deletions(-)
> 
> 

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web