зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset 5bbf6972b904 (bug 1235982) for landing prematurely a=backout
MozReview-Commit-ID: Fy7NwUoMipw
This commit is contained in:
Родитель
d93e9c00e1
Коммит
6d2e245da8
|
@ -67,11 +67,6 @@ if CONFIG['MOZ_SANDBOX'] and CONFIG['OS_ARCH'] == 'WINNT':
|
|||
'user32.dll',
|
||||
]
|
||||
|
||||
if CONFIG['CC_TYPE'] == "msvc":
|
||||
CFLAGS += ['-guard:cf']
|
||||
CXXFLAGS += ['-guard:cf']
|
||||
LDFLAGS += ['-guard:cf']
|
||||
|
||||
# Control the default heap size.
|
||||
# This is the heap returned by GetProcessHeap().
|
||||
# As we use the CRT heap, the default size is too large and wastes VM.
|
||||
|
|
|
@ -1,74 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include <windows.h>
|
||||
#include <winternl.h>
|
||||
#include <io.h>
|
||||
#include <intrin.h>
|
||||
|
||||
#include <setjmp.h>
|
||||
|
||||
#include "WindowsCFGStatus.h"
|
||||
|
||||
// Inspired by https://github.com/trailofbits/cfg-showcase/blob/master/cfg_icall.cpp
|
||||
|
||||
jmp_buf env;
|
||||
|
||||
#pragma optimize("", off )
|
||||
void not_entry_point() {
|
||||
__nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop();
|
||||
__nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop();
|
||||
__nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop();
|
||||
__nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop();
|
||||
__nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop();
|
||||
__nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop();
|
||||
__nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop();
|
||||
__nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop();
|
||||
__nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop();
|
||||
__nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop();
|
||||
__nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop();
|
||||
__nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop();
|
||||
__nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop();
|
||||
|
||||
longjmp(env, 1);
|
||||
return;
|
||||
}
|
||||
#pragma optimize("", on )
|
||||
|
||||
typedef void (*fn_ptr)();
|
||||
|
||||
/*
|
||||
* Tests for Microsoft's Control Flow Guard compiler security feature.
|
||||
* This function will crash if CFG is enabled, and return false if it is
|
||||
* not enabled.
|
||||
*
|
||||
* CFG protects indirect function calls and ensures they call a valid entry
|
||||
* point. We create a function pointer that calls an invalid entry point.
|
||||
* That invalid entry point is a nop sled.
|
||||
*
|
||||
* Jumping into the nop sled skips the preamble that a function normally
|
||||
* performs, so if we hit the return (ret) we would mess up the stack.
|
||||
* To 'return' from the function safely we jump back to our original
|
||||
* function - no preamble and no return.
|
||||
*
|
||||
* We use setjmp/longjmp because inline asm instructions aren't supported
|
||||
* in x64 by MSVC.
|
||||
*/
|
||||
MFBT_API bool
|
||||
CFG_DisabledOrCrash()
|
||||
{
|
||||
// setjmp returns 0 on the initial call and whatever value is given
|
||||
// to longjmp (here it is 1) when it is jumped back to.
|
||||
int val = setjmp(env);
|
||||
|
||||
if (val == 0) {
|
||||
fn_ptr slide_to_the_left = (fn_ptr)((uintptr_t)(not_entry_point) + 0x20);
|
||||
|
||||
// If CFG is enabled, we're going to crash on the next line
|
||||
slide_to_the_left();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_windowscfgstatus_h
|
||||
#define mozilla_windowscfgstatus_h
|
||||
|
||||
#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
|
||||
|
||||
#include <windows.h>
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Types.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
/**
|
||||
* Tests for Microsoft's Control Flow Guard compiler security feature.
|
||||
* This function will crash if CFG is enabled.
|
||||
* @returns false if CFG is not enabled. Crashes if CFG is enabled.
|
||||
* It will never return true.
|
||||
*/
|
||||
MFBT_API bool CFG_DisabledOrCrash();
|
||||
|
||||
}
|
||||
|
||||
#endif // defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
|
||||
#endif // mozilla_windowscfgstatus_h
|
|
@ -28,12 +28,6 @@ if CONFIG['OS_TARGET'] == 'WINNT':
|
|||
'user32.dll',
|
||||
]
|
||||
|
||||
if CONFIG['CC_TYPE'] == "msvc":
|
||||
CFLAGS += ['-guard:cf']
|
||||
CXXFLAGS += ['-guard:cf']
|
||||
LDFLAGS += ['-guard:cf']
|
||||
|
||||
|
||||
if not CONFIG['JS_STANDALONE']:
|
||||
|
||||
if CONFIG['MOZ_MEMORY'] and (CONFIG['MOZ_SYSTEM_JEMALLOC'] or FORCE_SHARED_LIB):
|
||||
|
@ -51,7 +45,6 @@ if not CONFIG['JS_STANDALONE']:
|
|||
'/memory/build',
|
||||
]
|
||||
SOURCES += [
|
||||
'WindowsCFGStatus.cpp',
|
||||
'WindowsDllBlocklist.cpp',
|
||||
]
|
||||
DISABLE_STL_WRAPPING = True
|
||||
|
@ -63,7 +56,6 @@ if not CONFIG['JS_STANDALONE']:
|
|||
'arm.h',
|
||||
'mips.h',
|
||||
'SSE.h',
|
||||
'WindowsCFGStatus.h',
|
||||
'WindowsDllBlocklist.h',
|
||||
]
|
||||
|
||||
|
|
|
@ -2,6 +2,3 @@
|
|||
|
||||
[browser_checkdllblockliststate.js]
|
||||
skip-if = os != "win"
|
||||
|
||||
[browser_checkcfgstatus.js]
|
||||
skip-if = os != "win"
|
||||
|
|
|
@ -1,104 +0,0 @@
|
|||
"use strict";
|
||||
|
||||
/**
|
||||
* Returns the id of the crash minidump.
|
||||
*
|
||||
* @param subject (nsISupports)
|
||||
* The subject passed through the ipc:content-shutdown
|
||||
* observer notification when a content process crash has
|
||||
* occurred.
|
||||
* @returns {String} The crash dump id.
|
||||
*/
|
||||
function getCrashDumpId(subject) {
|
||||
Assert.ok(subject instanceof Ci.nsIPropertyBag2,
|
||||
"Subject needs to be a nsIPropertyBag2 to clean up properly");
|
||||
|
||||
return subject.getPropertyAsAString("dumpID");
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans up the .dmp and .extra file from a crash.
|
||||
*
|
||||
* @param id {String} The crash dump id.
|
||||
*/
|
||||
function cleanUpMinidump(id) {
|
||||
if (id) {
|
||||
let dir = Services.dirsvc.get("ProfD", Ci.nsIFile);
|
||||
dir.append("minidumps");
|
||||
|
||||
let file = dir.clone();
|
||||
file.append(id + ".dmp");
|
||||
file.remove(true);
|
||||
|
||||
file = dir.clone();
|
||||
file.append(id + ".extra");
|
||||
file.remove(true);
|
||||
}
|
||||
}
|
||||
|
||||
// Calls a function that should crash when CFG is enabled
|
||||
add_task(function* test_cfg_enabled() {
|
||||
// On debug builds, crashing tabs results in much thinking, which
|
||||
// slows down the test and results in intermittent test timeouts,
|
||||
// so we'll pump up the expected timeout for this test.
|
||||
requestLongerTimeout(2);
|
||||
|
||||
if (!gMultiProcessBrowser) {
|
||||
Assert.ok(false, "This test should only be run in multi-process mode.");
|
||||
return;
|
||||
}
|
||||
|
||||
yield BrowserTestUtils.withNewTab({
|
||||
gBrowser,
|
||||
url: "http://example.com",
|
||||
}, function*(browser) {
|
||||
|
||||
// First, sanity check...
|
||||
Assert.ok(browser.isRemoteBrowser,
|
||||
"This browser needs to be remote if this test is going to " +
|
||||
"work properly.");
|
||||
|
||||
let contentProcessGone = TestUtils.topicObserved("ipc:content-shutdown");
|
||||
|
||||
ContentTask.spawn(browser, null, function() {
|
||||
privateNoteIntentionalCrash();
|
||||
|
||||
Cu.import("resource://gre/modules/ctypes.jsm");
|
||||
let mozglue = ctypes.open("mozglue.dll");
|
||||
let CFG_DisabledOrCrash = mozglue.declare("CFG_DisabledOrCrash", ctypes.default_abi, ctypes.bool);
|
||||
CFG_DisabledOrCrash();
|
||||
// ^-- this line should have crashed us. If we get to the next line, no bueno
|
||||
|
||||
Assert.ok(false, "This test should cause a crash when CFG is enabled. If it " +
|
||||
"does not, this false assertion will trigger. It means CFG is not enabled " +
|
||||
"and we have lost compiler hardening features.");
|
||||
});
|
||||
|
||||
// If we don't crash within 5 seconds, give up.
|
||||
let timeout = new Promise(resolve => setTimeout(resolve, 5000, [null]));
|
||||
|
||||
// We crash or timeout
|
||||
let [subject, /* , data */] = yield Promise.race([timeout, contentProcessGone]);
|
||||
|
||||
if (!subject) {
|
||||
// We timed out, or otherwise didn't crash properly
|
||||
Assert.ok(false, "This test should cause a crash when CFG is enabled. We didn't " +
|
||||
"observe a crash. This specific assertion should be redundant to a false assertion " +
|
||||
"immediately prior to it. If it occurs alone, then something strange has occured " +
|
||||
"and CFG status and this test should be investigated.");
|
||||
} else {
|
||||
// We crashed properly, clean up...
|
||||
|
||||
info("Content process is gone!");
|
||||
|
||||
// If we don't clean up the minidump, the harness will complain.
|
||||
let dumpID = getCrashDumpId(subject);
|
||||
|
||||
Assert.ok(dumpID, "There should be a dumpID");
|
||||
if (dumpID) {
|
||||
yield Services.crashmanager.ensureCrashIsPresent(dumpID);
|
||||
cleanUpMinidump(dumpID);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
Загрузка…
Ссылка в новой задаче