Closed Bug 399293 Opened 17 years ago Closed 11 years ago

Segfaults in the Javascript engine causes crashes with PaX enabled

Categories

(Core :: JavaScript Engine, defect)

1.9.1 Branch
x86
Linux
defect
Not set
critical

Tracking

()

RESOLVED WORKSFORME

People

(Reporter: linkfanel, Unassigned)

References

()

Details

(Keywords: crash, Whiteboard: [needs retesting on Linux with PaX])

User-Agent:       Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.8.1.7) Gecko/20070914 Iceweasel/2.0.0.7 (Debian-2.0.0.7-2)
Build Identifier: Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.8.1.7) Gecko/20070914 Iceweasel/2.0.0.7 (Debian-2.0.0.7-2)

PaX is enabled on my system, and browsing some web pages using javascript crashes firefox. Straces show that these pages trigger lots of segmentation faults and SIGSEGV signals, that are apparently caught and gracefully handled. Unfortunately, PaX also detects execution attempts in anonymous memory and thus terminates the process. Disabling javascript prevents the problem from happening: no segfault shows up in the straces, nothing abnormal is detected by PaX. Disabling PaX also solves the problem, and though segfaults still happen the pages seem to be rendered normally.

Some problematic pages:
 - http://subscribe.free.fr/login/
 - latest version of Yahoo!'s AJAX-based webmail

Reproducible: Always

Steps to Reproduce:
1. Launch Firefox on a PaX-enabled system
2. Load one of the pages mentionned above
Actual Results:  
Firefox is killed by PaX.

Expected Results:  
Page loads nicely.

I'm running Linux 2.6.22.6-grsec patched with a pre-release version of GRsec (http://www.grsecurity.net/~spender/). Non-executable pages protection ("s" flag in my case) needs to be disabled on the firefox executable to prevent the crash. The problem is still present in safe mode.
Salut Pierre,

the problem is not in firefox but in the Adobe flash plugin that apparently generates code at runtime (i looked at the assembly and i don't see why that code had to be runtime generated though). in any case, you don't have to disable non-exec pages altogether, it's enough to allow runtime code generation, that is, disable the MPROTECT PaX feature on the firefox binary (the one also reported in the PaX logs), it's enough to get your example pages to work here (at least they do proper code generation into executable pages).
I am positive that at the time I submitted the bug, firefox would still crash with only MPROTECT disabled. I just tried again with Debian's version 2.0.0.11-1. It still crashes, but now indeed disabling MPROTECT is sufficient to prevent it, so it looks better now.
PaX is http://en.wikipedia.org/wiki/PaX
Whiteboard: [needs retesting on Linux with PaX]
Using:

Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.9.1.5) Gecko/20091123 Iceweasel/3.5.5 (like Firefox/3.5.5; Debian-3.5.5-1)

and Adobe Flash Player version 9.0.246.0

I still get bunches of segfaults with the flash plugin enabled. They don't make firefox crash... they seem harmless, but hmm. They go away if I disable flash.

Also, disabling MPROTECT is now mandatory to start firefox without crashing, even with flash *and* javascript disabled.
not sure what you're doing but FF 3.5.x works fine with MPROTECT by default, only the javascript JIT and flash make its removal necessary. can you perhaps debug the crashes you're seeing to determine what exactly fails?
Right, it works fine in safe mode... I works fine too if I disable my language pack (French Language Pack 3.5.660 for the record). That's kind of lame :/

...
[pid  7983] open("/usr/lib/iceweasel/extensions/langpack-fr@firefox.mozilla.org/chrome/fr.jar", O_RDONLY|O_LARGEFILE) = 43
[pid  7983] lseek(43, 92389, SEEK_SET)  = 92389
[pid  7983] read(43, "PK\3\4\n\0\0\0\0\0k{b;\272\5\"r@\0\0\0@\0\0\0\31\0\34\0", 30) = 30
[pid  7983] lseek(43, 92472, SEEK_SET)  = 92472
[pid  7983] read(43, "<!ENTITY restoreNaturalOrder.lab"..., 64) = 64
[pid  7983] close(43)                   = 0
[pid  7983] gettimeofday({1259963142, 931427}, NULL) = 0
[pid  7983] gettimeofday({1259963142, 935619}, NULL) = 0
[pid  7983] gettimeofday({1259963142, 935681}, NULL) = 0
[pid  7983] gettimeofday({1259963142, 935716}, NULL) = 0
[pid  7983] gettimeofday({1259963142, 945054}, NULL) = 0
[pid  7983] mprotect(0x54e34000, 4096, PROT_READ|PROT_WRITE|PROT_EXEC) = -1 EACCES (Permission denied)
[pid  7983] rt_sigprocmask(SIG_UNBLOCK, [ABRT], NULL, 8) = 0
[pid  7983] tgkill(7983, 7983, SIGABRT) = 0
[pid  7983] --- SIGABRT (Aborted) @ 0 (0) ---
...
can you find out who did the original allocation at 0x54e34000 (or whatever it is when re-randomized)? the point is, here i don't see any such requests, so it may not be FF's doing, but some plugin or library, i don't know, but would be important to determine.
Well disregard what I said about the language pack. The crash just doesn't always occur, maybe it's related to a race condition or something. I couldn't reproduce it in safe mode, but I did with no plugin, extension or whatever enabled. The only invariant that I could find in straces is that xpconnect.xpt is opened after mmap-ing the faulty address. An example:

[pid  9378] mmap2(NULL, 4096, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x57300000
[pid  9378] mmap2(NULL, 8192, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x5528f000
[pid  9378] mmap2(NULL, 4096, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x54cae000
[pid  9378] mmap2(NULL, 8192, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x54cac000
[pid  9378] open("/dev/urandom", O_RDONLY) = 21
[pid  9378] read(21, "\212\35\317\10", 4) = 4
[pid  9378] gettimeofday({1259969079, 465932}, NULL) = 0
[pid  9378] stat64("/usr/lib/iceweasel/xulrunner/components/xpconnect.xpt", {st_mode=S_IFREG|0644, st_size=7934, ...}) = 0
[pid  9378] open("/usr/lib/iceweasel/xulrunner/components/xpconnect.xpt", O_RDONLY|O_LARGEFILE) = 22
[pid  9378] read(22, "XPCOM\nTypeLib\r\n\32\1\2\0,\0\0\36\376\0\0\0\"\0\0\4\361"..., 7934) = 7934
[pid  9378] close(22)                   = 0

... long later...

[pid  9378] mprotect(0x5528f000, 4096, PROT_READ|PROT_WRITE|PROT_EXEC) = -1 EACCES (Permission denied)

Does it make sense to call mprotect() with the same protection?

How could I find who does that allocation?
ok, so there're a bunch of rwx mappings, that's already bad enough, the later mprotect is just collateral damage here ;). probably there's another mprotect in-between that reduces access rights, that's why it wants to increase them later.

in any case, what you should find out is the backtrace when these rwx mmap requests occur. i'm afraid that'll need a gdb session and some (conditional?) breakpoints, but i don't know gdb that well to tell you the exact commands unfortunately.
um, PaX Team: welcome to mozilla.org, we have this tool called MXR which helps answer such questions:

http://mxr.mozilla.org/mozilla-central/ident?i=mprotect

mprotect is used by our nanojit vm:

147   int retval = mprotect((maddr_ptr)beginPage, (unsigned int)sizePaged, flags);
148   AvmAssert(retval == 0);

And it assumes you wouldn't prevent us from using it.

Please note that the concept of "disabling" javascript is not quite the same thing as "disabling all javascript from ever running in our process". Our application has a lot of javascript code, without it, there'd be no user interface. Disabling JavaScript only disables web page scripts, not javascript.

Reporter: please don't file bugs about "javascript engine" in the "shell integration" component just because some system service (PaX) is breaking things. The end result is that the wrong eyeballs will see your bug for two months.
Assignee: nobody → general
Component: Shell Integration → JavaScript Engine
Keywords: crash
Product: Firefox → Core
QA Contact: shell.integration → general
Version: unspecified → 1.9.1 Branch
Assuming this works now. Please file a new bug if it's still a problem.
Status: UNCONFIRMED → RESOLVED
Closed: 11 years ago
Resolution: --- → WORKSFORME
You need to log in before you can comment on or make changes to this bug.