Closed Bug 943839 Opened 12 years ago Closed 12 years ago

JS_AnchorPtr doesn't, due to compiler optimizations (inlining or removing call without side effects)

Categories

(Core :: JavaScript Engine, defect)

x86
Linux
defect
Not set
critical

Tracking

()

RESOLVED FIXED
mozilla28
Tracking Status
firefox27 --- unaffected
firefox28 --- fixed
firefox-esr24 --- unaffected
b2g18 --- unaffected
b2g-v1.1hd --- unaffected
b2g-v1.2 --- unaffected
b2g-v1.3 --- fixed

People

(Reporter: decoder, Assigned: Waldo)

Details

(Keywords: csectype-uaf, sec-high, testcase, Whiteboard: [qa-])

Attachments

(2 files, 2 obsolete files)

The following testcase shows use-after-free on mozilla-central revision 77b5c6edfe96 (run with --fuzzing-safe): Array(1<<23).join({});
Found by ASan: ==22083==ERROR: AddressSanitizer: heap-use-after-free on address 0xf4e04c90 at pc 0x8acc8ad bp 0xffa55d98 sp 0xffa55d90 READ of size 2 at 0xf4e04c90 thread T0 #0 0x8acc8ac in mozilla::VectorBase<char16_t, 32u, js::ContextAllocPolicy, js::Vector<char16_t, 32u, js::ContextAllocPolicy> >::endNoCheck() js/src/opt32asan/dist/include/mozilla/Vector.h:161 #1 0x8acc8ac in void mozilla::VectorBase<char16_t, 32u, js::ContextAllocPolicy, js::Vector<char16_t, 32u, js::ContextAllocPolicy> >::internalAppend<char16_t>(char16_t const*, unsigned int) js/src/opt32asan/dist/include/mozilla/Vector.h:1000 #2 0x8acc8ac in bool mozilla::VectorBase<char16_t, 32u, js::ContextAllocPolicy, js::Vector<char16_t, 32u, js::ContextAllocPolicy> >::append<char16_t>(char16_t const*, char16_t const*) js/src/opt32asan/dist/include/mozilla/Vector.h:989 #3 0x8acc8ac in bool mozilla::VectorBase<char16_t, 32u, js::ContextAllocPolicy, js::Vector<char16_t, 32u, js::ContextAllocPolicy> >::append<char16_t>(char16_t const*, unsigned int) js/src/opt32asan/dist/include/mozilla/Vector.h:1034 #4 0x8acc8ac in js::StringBuffer::append(char16_t const*, unsigned int) js/src/opt32asan/../vm/StringBuffer.h:49 #5 0x8acc8ac in StringSeparatorOp::operator()(JSContext*, js::StringBuffer&) js/src/opt32asan/../jsarray.cpp:981 #6 0x8acc8ac in _ZL15ArrayJoinKernelILb0E17StringSeparatorOpEbP9JSContextT0_N2JS6HandleIP8JSObjectEEjRN2js12StringBufferE js/src/opt32asan/../jsarray.cpp:1050 #7 0x8acc8ac in _ZL9ArrayJoinILb0EEbP9JSContextRN2JS8CallArgsE js/src/opt32asan/../jsarray.cpp:1123 #8 0x8acc8ac in array_join(JSContext*, unsigned int, JS::Value*) js/src/opt32asan/../jsarray.cpp:1192 #9 0x8e6ead7 in js::CallJSNative(JSContext*, bool (*)(JSContext*, unsigned int, JS::Value*), JS::CallArgs const&) js/src/opt32asan/../jscntxtinlines.h:220 #10 0x8e6ead7 in js::Invoke(JSContext*, JS::CallArgs, js::MaybeConstruct) js/src/opt32asan/../vm/Interpreter.cpp:456 #11 0x8e70023 in js::Invoke(JSContext*, JS::Value const&, JS::Value const&, unsigned int, JS::Value*, JS::MutableHandle<JS::Value>) js/src/opt32asan/../vm/Interpreter.cpp:513 #12 0x84678f7 in js::jit::DoCallFallback(JSContext*, js::jit::BaselineFrame*, js::jit::ICCall_Fallback*, unsigned int, JS::Value*, JS::MutableHandle<JS::Value>) js/src/opt32asan/../jit/BaselineIC.cpp:7986 #13 0xf6213d7c (+0x4d7c) 0xf4e04c90 is located 0 bytes inside of 32-byte region [0xf4e04c90,0xf4e04cb0) freed by thread T0 here: #0 0x8100840 in free /srv/repos/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:64 #1 0x8d0084b in js_free(void*) js/src/opt32asan/dist/include/js/Utility.h:167 #2 0x8d0084b in js::FreeOp::free_(void*) js/src/opt32asan/../vm/Runtime.h:1790 #3 0x8d0084b in JSFlatString::finalize(js::FreeOp*) js/src/opt32asan/../vm/String-inl.h:346 #4 0x8d0084b in JSString::finalize(js::FreeOp*) js/src/opt32asan/../vm/String-inl.h:335 #5 0x8d0084b in bool js::gc::Arena::finalize<JSString>(js::FreeOp*, js::gc::AllocKind, unsigned int) js/src/opt32asan/../jsgc.cpp:475 #6 0x8b45671 in _ZL19FinalizeTypedArenasI8JSStringEbPN2js6FreeOpEPPNS1_2gc11ArenaHeaderERNS4_9ArenaListENS4_9AllocKindERNS1_11SliceBudgetE js/src/opt32asan/../jsgc.cpp:539:25 #7 0x8b45671 in FinalizeArenas(js::FreeOp*, js::gc::ArenaHeader**, js::gc::ArenaList&, js::gc::AllocKind, js::SliceBudget&) js/src/opt32asan/../jsgc.cpp:588 #8 0x8cc6975 in js::gc::ArenaLists::backgroundFinalize(js::FreeOp*, js::gc::ArenaHeader*, bool) js/src/opt32asan/../jsgc.cpp:1535 #9 0x8cc6975 in SweepBackgroundThings(JSRuntime*, bool) js/src/opt32asan/../jsgc.cpp:2355 #10 0x8cc6975 in EndSweepPhase(JSRuntime*, js::JSGCInvocationKind, bool) js/src/opt32asan/../jsgc.cpp:4211 #11 0x8cc6975 in IncrementalCollectSlice(JSRuntime*, long long, JS::gcreason::Reason, js::JSGCInvocationKind) js/src/opt32asan/../jsgc.cpp:4655 #12 0x8cb944f in GCCycle(JSRuntime*, bool, long long, js::JSGCInvocationKind, JS::gcreason::Reason) js/src/opt32asan/../jsgc.cpp:4775 previously allocated by thread T0 here: #0 0x81009c0 in malloc /srv/repos/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:74 #1 0x8f2fe86 in js_malloc(unsigned int) js/src/opt32asan/dist/include/js/Utility.h:144 #2 0x8f2fe86 in js::MallocProvider<js::ThreadSafeContext>::malloc_(unsigned int) js/src/opt32asan/../vm/Runtime.h:590 #3 0x8f2fe86 in js::ContextAllocPolicy::malloc_(unsigned int) js/src/opt32asan/../jscntxt.h:996 #4 0x8f2fe86 in mozilla::VectorBase<char16_t, 32u, js::ContextAllocPolicy, js::Vector<char16_t, 32u, js::ContextAllocPolicy> >::extractRawBuffer() js/src/opt32asan/dist/include/mozilla/Vector.h:1062 #5 0x8f2fe86 in js::StringBuffer::extractWellSized() js/src/opt32asan/../vm/StringBuffer.cpp:21 SUMMARY: AddressSanitizer: heap-use-after-free js/src/opt32asan/dist/include/mozilla/Vector.h:161 mozilla::VectorBase<char16_t, 32u, js::ContextAllocPolicy, js::Vector<char16_t, 32u, js::ContextAllocPolicy> >::endNoCheck() Shadow bytes around the buggy address: 0x3e9c0940: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x3e9c0950: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x3e9c0960: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x3e9c0970: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x3e9c0980: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa =>0x3e9c0990: fa fa[fd]fd fd fd fa fa 00 00 00 fa fa fa fd fd 0x3e9c09a0: fd fa fa fa fd fd fd fa fa fa fd fd fd fd fa fa 0x3e9c09b0: fd fd fd fd fa fa fd fd fd fa fa fa fd fd fd fd 0x3e9c09c0: fa fa 00 00 00 04 fa fa 00 00 00 04 fa fa 00 00 0x3e9c09d0: 00 04 fa fa fd fd fd fd fa fa fd fd fd fa fa fa 0x3e9c09e0: 00 00 04 fa fa fa fd fd fd fa fa fa 00 00 00 04 Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Heap right redzone: fb Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack partial redzone: f4 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 ASan internal: fe ==22083==ABORTING Aborted Marking s-s and sec-critical due to use-after-free.
Might be related to bug 918808, so needinfo'ing myself.
Flags: needinfo?(jdemooij)
Since bug 930625, array_join does this: // Ensure that sepstr stays alive longer than sepchars. JS_AnchorPtr(sepstr); JS_AnchorPtr is defined in jsapi.cpp as: JS_NEVER_INLINE JS_PUBLIC_API(void) JS_AnchorPtr(void *p) { } Now, with unified builds it's possible jsapi.cpp and jsarray.cpp likely end up in the same file, and the compiler is probably smart enough to see through this. According to mxr, this is the only use of JS_AnchorPtr.
Flags: needinfo?(jdemooij) → needinfo?(terrence)
Ehsan, see comment 3, I looked at the code Clang 3.3 emits and it does seem to inline JS_AnchorPtr now. This may explain some of the JS crashes people are seeing with unified builds in other bugs. JS_AnchorPtr is not safe. Terrence, why can't we use an Anchor there?
Flags: needinfo?(ehsan)
I'm sorry, I don't understand what we're talking about here. JS_AnchorPtr is an empty function which is now getting inlined. Why is that a problem? (FWIW I would expect this function to get inlined in PGO builds as well.)
Flags: needinfo?(ehsan)
(In reply to :Ehsan Akhgari (needinfo? me!) from comment #5) > JS_AnchorPtr is an empty function which is now getting inlined. Why is that > a problem? We rely on JS_AnchorPtr(sepstr) to keep sepstr alive for the conservative stack scanner. If we inline JS_AnchorPtr and turn it into a no-op, the compiler has no reason to keep sepstr in a register or on the stack and the conservative scanner can destroy sepstr. This is bad because we still have a pointer to its chars. > (FWIW I would expect this function to get inlined in PGO builds > as well.) True..
WTF?! clang doesn't seem to respect noinline at all! $ cat test.cpp __attribute__((noinline)) int f(); int f() { return 42; } int main() { return f(); } $ clang++ -O3 -S -c -o test.s test.cpp $ cat test.s .section __TEXT,__text,regular,pure_instructions .globl __Z1fv .align 4, 0x90 __Z1fv: ## @_Z1fv .cfi_startproc ## BB#0: pushq %rbp Ltmp2: .cfi_def_cfa_offset 16 Ltmp3: .cfi_offset %rbp, -16 movq %rsp, %rbp Ltmp4: .cfi_def_cfa_register %rbp movl $42, %eax popq %rbp ret .cfi_endproc .globl _main .align 4, 0x90 _main: ## @main .cfi_startproc ## BB#0: pushq %rbp Ltmp7: .cfi_def_cfa_offset 16 Ltmp8: .cfi_offset %rbp, -16 movq %rsp, %rbp Ltmp9: .cfi_def_cfa_register %rbp movl $42, %eax popq %rbp ret .cfi_endproc .subsections_via_symbols
(Filed bug 944460 for the MFBT issue)
Assignee: general → ehsan
Attached patch Patch (v1)Splinter Review
Attachment #8340041 - Flags: review?(jdemooij)
Blocks: 942421
I don't think bug 942421 is the same. My gcc 4.8.2 does respect noinline.
Comment on attachment 8340041 [details] [diff] [review] Patch (v1) Review of attachment 8340041 [details] [diff] [review]: ----------------------------------------------------------------- Seems fine as a stopgap. Once we turn on exact rooting (hopefully soon) and kill the conservative scanner we can remove it. I'm still a bit worried about LTO/PGO though, but that was also a problem before the unified builds. Terrence, what do you think?
Attachment #8340041 - Flags: review?(jdemooij) → review+
Comment on attachment 8340041 [details] [diff] [review] Patch (v1) Review of attachment 8340041 [details] [diff] [review]: ----------------------------------------------------------------- ::: js/src/jsanchor.cpp @@ +11,5 @@ > +#ifdef MOZ_UNIFIED_BUILD > +#error "This file cannot be built in unified mode" > +#endif > + > +JS_NEVER_INLINE JS_PUBLIC_API(void) Note you don't need JS_NEVER_INLINE if this is meant to stay alone in a separate file.
(In reply to Mike Hommey [:glandium] from comment #12) > Comment on attachment 8340041 [details] [diff] [review] > Patch (v1) > > Review of attachment 8340041 [details] [diff] [review]: > ----------------------------------------------------------------- > > ::: js/src/jsanchor.cpp > @@ +11,5 @@ > > +#ifdef MOZ_UNIFIED_BUILD > > +#error "This file cannot be built in unified mode" > > +#endif > > + > > +JS_NEVER_INLINE JS_PUBLIC_API(void) > > Note you don't need JS_NEVER_INLINE if this is meant to stay alone in a > separate file. I'm just moving the code... (Also, do we want to put an asm("") in the body of the function? See bug 944460 comment 7.)
No longer blocks: 942421
FWIW I'm waiting for Terrence to comment here before I land this patch.
With the patch, the function is now: a) public b) alone in a separate source file c) the source file is not unified There is no possible way a call to that function is going to be removed by optimizations. The asm("") would only be useful if the function was kept in the original source file.
(In reply to Mike Hommey [:glandium] from comment #15) > With the patch, the function is now: > a) public > b) alone in a separate source file > c) the source file is not unified > > There is no possible way a call to that function is going to be removed by > optimizations. Technically, that's not true for PGO builds, right?
I agree with comment 16. In fact, I really dislike fixing security bugs by *assuming* the compiler cannot optimize something. Please try to find a way to fix this properly so we don't need to rely on the compiler being dumb.
(In reply to Christian Holler (:decoder) from comment #17) > I agree with comment 16. In fact, I really dislike fixing security bugs by > *assuming* the compiler cannot optimize something. Please try to find a way > to fix this properly so we don't need to rely on the compiler being dumb. Well if you have suggestions on what I can do to make this more robust, I'm all ears. :-)
(In reply to :Ehsan Akhgari (needinfo? me!) from comment #16) > (In reply to Mike Hommey [:glandium] from comment #15) > > With the patch, the function is now: > > a) public > > b) alone in a separate source file > > c) the source file is not unified > > > > There is no possible way a call to that function is going to be removed by > > optimizations. > > Technically, that's not true for PGO builds, right? You can force not to PGO that one file. Put it in sources instead of unified_sources, and add NO_PROFILE_GUIDED_OPTIMIZE = filename to Makefile.in.
Summary: ASan use-after-free through [@ StringSeparatorOp::operator] with large Array → JS_AnchorPtr doesn't, due to compiler optimizations (inlining or removing call without side effects)
Comment on attachment 8340041 [details] [diff] [review] Patch (v1) Review of attachment 8340041 [details] [diff] [review]: ----------------------------------------------------------------- (In reply to Jan de Mooij [:jandem] from comment #4) > Ehsan, see comment 3, I looked at the code Clang 3.3 emits and it does seem > to inline JS_AnchorPtr now. This may explain some of the JS crashes people > are seeing with unified builds in other bugs. > > JS_AnchorPtr is not safe. Terrence, why can't we use an Anchor there? Anchor<JSString*> contains a JSString* on the stack, so the static hazard analysis complains about it. The other option would have been to annotate the analysis to ignore Anchor, but I did not want to add complexity to the analysis for only one case. I think splitting out the file is a fine solution. We should also suppress PGO here with the magic incantation in comment 19.
Attachment #8340041 - Flags: review+
(In reply to Terrence Cole [:terrence] from comment #20) > Anchor<JSString*> contains a JSString* on the stack, so the static hazard > analysis complains about it. So then, basically you're saying we couldn't use JS::Anchor<JSString*> because it's completely broken. Doesn't that imply every place we use it right now is wrong? Why is this the only place that needed JS_AnchorPtr? > The other option would have been to annotate the analysis to ignore > Anchor, but I did not want to add complexity to the analysis for only > one case. Seems more like twenty-odd cases for all the JS::Anchor uses in the tree, to me. Or am I missing something?
(In reply to Jeff Walden [:Waldo] (remove +bmo to email) from comment #21) > (In reply to Terrence Cole [:terrence] from comment #20) > > Anchor<JSString*> contains a JSString* on the stack, so the static hazard > > analysis complains about it. > > So then, basically you're saying we couldn't use JS::Anchor<JSString*> > because it's completely broken. Doesn't that imply every place we use it > right now is wrong? Why is this the only place that needed JS_AnchorPtr? No, it's a bit more complex than that. > > The other option would have been to annotate the analysis to ignore > > Anchor, but I did not want to add complexity to the analysis for only > > one case. > > Seems more like twenty-odd cases for all the JS::Anchor uses in the tree, to > me. Or am I missing something? The analysis is aware of Anchor, but only up to a point. Specifically, it knows that ~Anchor should not count as a use of an anchor. Our typical Anchor use is: build string, construct anchor, use chars, ~Anchor. The case here was a bit different in that we create the string conditionally, but we need the anchor to last beyond the if scope. This gives us the pattern: create anchor, create string, assign anchor, use chars, ~Anchor. It is the assignment-after-gc that is problematic.
Flags: needinfo?(terrence)
It seems like Windows PGO builds are broken with this patch, so I backed it out to test that theory: https://hg.mozilla.org/integration/mozilla-inbound/rev/aa4d8931ec0e https://tbpl.mozilla.org/?tree=Mozilla-Inbound&rev=44f0d31a4530
The log indicates the NO_PROFILE_GUIDED_OPTIMIZE trick didn't have an effect, which is not expected.
(In reply to Mike Hommey [:glandium] from comment #25) > The log indicates the NO_PROFILE_GUIDED_OPTIMIZE trick didn't have an > effect, which is not expected. And this is why: https://mxr.mozilla.org/mozilla-central/source/js/src/Makefile.in#402 This also shows two interesting things: first, that some of the files listed there are not in the tree anymore, and second, that some of the files listed there are unified... Filed bug 945042 to move NO_PROFILE_GUIDED_OPTIMIZE to moz.build.
(In reply to Mike Hommey [:glandium] from comment #26) > (In reply to Mike Hommey [:glandium] from comment #25) > > The log indicates the NO_PROFILE_GUIDED_OPTIMIZE trick didn't have an > > effect, which is not expected. > > And this is why: > https://mxr.mozilla.org/mozilla-central/source/js/src/Makefile.in#402 > > This also shows two interesting things: first, that some of the files listed > there are not in the tree anymore, and second, that some of the files listed > there are unified... > > Filed bug 945042 to move NO_PROFILE_GUIDED_OPTIMIZE to moz.build. Hmm, I'm kind of lost on how that is going to affect my patch here. Do I need to change anything, or should I just wait until bug 945042 lands?
Flags: needinfo?(mh+mozilla)
(In reply to :Ehsan Akhgari (needinfo? me!) from comment #27) > (In reply to Mike Hommey [:glandium] from comment #26) > > (In reply to Mike Hommey [:glandium] from comment #25) > > > The log indicates the NO_PROFILE_GUIDED_OPTIMIZE trick didn't have an > > > effect, which is not expected. > > > > And this is why: > > https://mxr.mozilla.org/mozilla-central/source/js/src/Makefile.in#402 > > > > This also shows two interesting things: first, that some of the files listed > > there are not in the tree anymore, and second, that some of the files listed > > there are unified... > > > > Filed bug 945042 to move NO_PROFILE_GUIDED_OPTIMIZE to moz.build. > > Hmm, I'm kind of lost on how that is going to affect my patch here. Do I > need to change anything, or should I just wait until bug 945042 lands? I'd rather you land first. You need to change the other NO_PROFILE_GUIDED_OPTIMIZEs in js/src/Makefile.in to do += instead of :=.
Flags: needinfo?(mh+mozilla)
(In reply to Terrence Cole [:terrence] from comment #23) > Our typical Anchor use is: build string, construct anchor, use chars, > ~Anchor. The case here was a bit different in that we create the string > conditionally, but we need the anchor to last beyond the if scope. This > gives us the pattern: create anchor, create string, assign anchor, use > chars, ~Anchor. It is the assignment-after-gc that is problematic. Maybe I'm still confused, but why can't you assign to the anchor immediately after sepstr is initialized, in that case, to eliminate the GC-before-assignment issue?
The initialization of sepstr is: sepstr = ToString<CanGC>(cx, args[0]); So that's not really possible.
There's void operator=(const T &t) { hold = t; } in Anchor. Why can't you (just after the failure-exit for the line you quote) have anchor = sepstr.get(); ? (with a JS::Anchor<JSString*> anchor;) before the if?
Attached patch This, to be precise (obsolete) — Splinter Review
Attachment #8341218 - Flags: feedback?(terrence)
Comment on attachment 8340041 [details] [diff] [review] Patch (v1) [Security approval request comment] How easily could an exploit be constructed based on the patch? Not easily at all, and there is no real exploit here. Do comments in the patch, the check-in comment, or tests included in the patch paint a bulls-eye on the security problem? No. Which older supported branches are affected by this flaw? None. If not all supported branches, which bug introduced the flaw? Perhaps bug 941424. It's trunk only. Do you have backports for the affected branches? If not, how different, hard to create, and risky will they be? N/A How likely is this patch to cause regressions; how much testing does it need? Very minimal, but the patch is trivial.
Attachment #8340041 - Flags: sec-approval?
Attached patch Or this? (obsolete) — Splinter Review
Attachment #8341218 - Attachment is obsolete: true
Attachment #8341218 - Flags: feedback?(terrence)
Attachment #8341306 - Flags: feedback?(terrence)
Comment on attachment 8341306 [details] [diff] [review] Or this? Review of attachment 8341306 [details] [diff] [review]: ----------------------------------------------------------------- That's exactly what I was trying to get at, thanks! Might as well include removal of JS_AnchorString while you're at it.
Attachment #8341306 - Flags: feedback?(terrence) → feedback+
Downgrading this to sec-high after discussing with Ehsan. In fact, it should be possible to exploit this because comment 0 provides a way to provoke use-after-free a string that would possibly allow to read memory. But making such an exploit from the patch is surely hard.
Keywords: sec-criticalsec-high
Assignee: ehsan → jwalden+bmo
Attachment #8341306 - Attachment is obsolete: true
Status: NEW → ASSIGNED
Attachment #8341331 - Flags: review?(terrence)
Comment on attachment 8341331 [details] [diff] [review] Once more, with feeling Review of attachment 8341331 [details] [diff] [review]: ----------------------------------------------------------------- Nice! r=me ::: js/public/Anchor.h @@ +99,5 @@ > + > + /* > + * Rooting analysis considers use of operator= to be a use of an anchor. > + * For simplicity, Anchor is treated as if it contained a GC thing, from > + * construction. Thus if we had One space between sentences. @@ +111,5 @@ > + * anchor = str; > + * > + * the last line would be seen as a hazard, because the final = would "use" > + * |anchor| that is a GC thing -- which could have been moved around by the > + * GC. The workaround is to structure your code so that JS::Anchor is Ditto.
Attachment #8341331 - Flags: review?(terrence) → review+
Every sign in this bug is that this was triggered by unified builds, ergo a trunk-only regression, ergo no sec-approval needed. https://hg.mozilla.org/integration/mozilla-inbound/rev/75eedf5dfb51 Will open up in a week or so, or something, to give people time to upgrade in the highly-unlikely event somebody cares to target the infinitesimally small set of people using nightly builds, who don't update quicker than that.
Attachment #8340041 - Flags: sec-approval?
Flags: in-testsuite?
Target Milestone: --- → mozilla28
Status: ASSIGNED → RESOLVED
Closed: 12 years ago
Resolution: --- → FIXED
I don't think this needs QA verification. If anyone thinks that's a mistake please remove the [qa-] whiteboard tag and add the verifyme keyword.
Whiteboard: [qa-]
Group: core-security
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: