linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] For Segmentation Fault when using large external array
@ 2003-09-29 12:27 srikrish
  2003-09-30  7:03 ` Anton Blanchard
  0 siblings, 1 reply; 2+ messages in thread
From: srikrish @ 2003-09-29 12:27 UTC (permalink / raw)
  To: linux-kernel

When I compile and run an application with a large external array I get a
Segmentation Fault.

<source code of C Application>
int x[3000][3000][30];
int main() {
    return 10;
}

Platform: Linux-2.6.0-test5 on ia-32

Comments: The problem is that we don't reserve the bss region for the app
(via a set_brk/do_brk call) until after we've loaded the loader so they get
mapped to overlapping memory locations. The fix is to move the update to
current->mm.* and the set_brk/do_brk call to before the point we call
load_elf_interp().

Another bug is that the calls to set_brk/do_brk in fs/binfmt_elf.c fail to
check whether the set_brk/do_brk calls succeeded or not, so they implicitly
assume they do.  Fix is to test for failure from the set_brk/do_brk calls.

Here's a patch. This gives a clearer error message. Though I'm not sure id
large external array could be the only trigger for this. I'd appreciate your
comments/suggestions.

Srikrishnan

--- linux-2.6.0-test5/fs/binfmt_elf.c Mon Sep 29 22:29:29 2003
+++ linux-2.6.0-test5-change/fs/binfmt_elf.c Mon Sep 29 22:30:07 2003
@@ -82,13 +82,15 @@
#define BAD_ADDR(x) ((unsigned long)(x) > TASK_SIZE)
-static void set_brk(unsigned long start, unsigned long end)
+static unsigned set_brk(unsigned long start, unsigned long end)
{
+ int retval=0;
start = ELF_PAGEALIGN(start);
end = ELF_PAGEALIGN(end);
if (end > start)
- do_brk(start, end - start);
+ retval = do_brk(start, end - start);
current->mm->start_brk = current->mm->brk = end;
+ return retval;
}
@@ -393,7 +395,7 @@
unsigned long text_data, elf_entry = ~0UL;
char * addr;
loff_t offset;
-
+ int retval;
current->mm->end_code = interp_ex->a_text;
text_data = interp_ex->a_text + interp_ex->a_data;
current->mm->end_data = text_data;
@@ -413,7 +415,9 @@
goto out;
}
- do_brk(0, text_data);
+ retval = do_brk(0, text_data);
+ if(BAD_ADDR(retval))
+ goto out;
if (!interpreter->f_op || !interpreter->f_op->read)
goto out;
if (interpreter->f_op->read(interpreter, addr, text_data, &offset) < 0)
@@ -421,8 +425,10 @@
flush_icache_range((unsigned long)addr,
(unsigned long)addr + text_data);
- do_brk(ELF_PAGESTART(text_data + ELF_MIN_ALIGN - 1),
+ retval = do_brk(ELF_PAGESTART(text_data + ELF_MIN_ALIGN - 1),
interp_ex->a_bss);
+ if(BAD_ADDR(retval))
+ goto out;
elf_entry = interp_ex->a_entry;
out:
@@ -726,7 +732,26 @@
end_code += load_bias;
start_data += load_bias;
end_data += load_bias;
+
+ current->mm->end_code = end_code;
+ current->mm->start_code = start_code;
+ current->mm->start_data = start_data;
+ current->mm->end_data = end_data;
+ current->mm->start_stack = bprm->p;
+
+ /* Calling set_brk effectively mmaps the pages that we need
+ * for the bss and break sections.
+ * We must do this now before we load the interpreter
+ * in case we have a huge bss region.
+ */
+ retval = set_brk(elf_bss, elf_brk);
+ if(retval < 0) {
+ printk(KERN_ERR "unable to map bss section - probably you had declared a
very large external array\n");
+ send_sig(SIGSEGV, current, 0);
+ goto out_free_dentry;
+ }
+ padzero(elf_bss);
if (elf_interpreter) {
if (interpreter_type == INTERPRETER_AOUT)
elf_entry = load_aout_interp(&interp_ex,
@@ -766,19 +791,6 @@
/* N.B. passed_fileno might not be initialized? */
if (interpreter_type == INTERPRETER_AOUT)
current->mm->arg_start += strlen(passed_fileno) + 1;
- current->mm->end_code = end_code;
- current->mm->start_code = start_code;
- current->mm->start_data = start_data;
- current->mm->end_data = end_data;
- current->mm->start_stack = bprm->p;
-
- /* Calling set_brk effectively mmaps the pages that we need
- * for the bss and break sections
- */
- set_brk(elf_bss, elf_brk);
-
- padzero(elf_bss);
-
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.


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH] For Segmentation Fault when using large external array
  2003-09-29 12:27 [PATCH] For Segmentation Fault when using large external array srikrish
@ 2003-09-30  7:03 ` Anton Blanchard
  0 siblings, 0 replies; 2+ messages in thread
From: Anton Blanchard @ 2003-09-30  7:03 UTC (permalink / raw)
  To: srikrish; +Cc: linux-kernel


Hi,

> When I compile and run an application with a large external array I get a
> Segmentation Fault.

...

> Comments: The problem is that we don't reserve the bss region for the app
> (via a set_brk/do_brk call) until after we've loaded the loader so they get
> mapped to overlapping memory locations. The fix is to move the update to
> current->mm.* and the set_brk/do_brk call to before the point we call
> load_elf_interp().

Yes it would be nice if we failed more gracefully here. A number of
people have come to me after hitting this problem, not realising that
its the size of their bss that caused the SEGV.

BTW I didnt look at your patch, unfortunately your mailer destroyed it.

Anton

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2003-09-30  7:04 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-09-29 12:27 [PATCH] For Segmentation Fault when using large external array srikrish
2003-09-30  7:03 ` Anton Blanchard

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).