From a8a933a51f46ee794ab7216015eb88a0ba61556b Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Sun, 28 Jan 2018 08:41:36 +0100 Subject: [PATCH 1/8] Bug 1425559 - Implement nsIThreadManager::spinEventLoopUntilOrShutdown, r=smaug Currently nsIThreadManager::spinEventLoopUntil doesn't monitor the shutting down. Firefox shutting down can be blocked by a 'broken' use of nsIThreadManager::spinEventLoopUntil. nsIThreadManager::spinEventLoopUntilOrShutdown should be used instead. --- layout/build/nsLayoutStatics.cpp | 3 + xpcom/threads/moz.build | 1 + xpcom/threads/nsIThreadManager.idl | 9 +++ xpcom/threads/nsThreadManager.cpp | 121 +++++++++++++++++++++++++++++ xpcom/threads/nsThreadManager.h | 6 ++ 5 files changed, 140 insertions(+) diff --git a/layout/build/nsLayoutStatics.cpp b/layout/build/nsLayoutStatics.cpp index 7ead72fc3430..5ba429e23ff0 100644 --- a/layout/build/nsLayoutStatics.cpp +++ b/layout/build/nsLayoutStatics.cpp @@ -122,6 +122,7 @@ #include "mozilla/dom/U2FTokenManager.h" #include "mozilla/dom/PointerEventHandler.h" #include "nsHostObjectProtocolHandler.h" +#include "nsThreadManager.h" using namespace mozilla; using namespace mozilla::net; @@ -321,6 +322,8 @@ nsLayoutStatics::Initialize() mozilla::dom::DOMPrefs::Initialize(); } + nsThreadManager::InitializeShutdownObserver(); + return NS_OK; } diff --git a/xpcom/threads/moz.build b/xpcom/threads/moz.build index 0f77f3339180..1953c5affcd9 100644 --- a/xpcom/threads/moz.build +++ b/xpcom/threads/moz.build @@ -31,6 +31,7 @@ EXPORTS += [ 'nsProcess.h', 'nsProxyRelease.h', 'nsThread.h', + 'nsThreadManager.h', 'nsThreadUtils.h', ] diff --git a/xpcom/threads/nsIThreadManager.idl b/xpcom/threads/nsIThreadManager.idl index 1e3479234213..8f68f1f71a4f 100644 --- a/xpcom/threads/nsIThreadManager.idl +++ b/xpcom/threads/nsIThreadManager.idl @@ -120,6 +120,15 @@ interface nsIThreadManager : nsISupports */ void spinEventLoopUntil(in nsINestedEventLoopCondition condition); + /** + * Similar to the previous method, but the spinning of the event loop + * terminates when the shutting down starts. + * + * C++ code should not use this function, instead preferring + * mozilla::SpinEventLoopUntil. + */ + void spinEventLoopUntilOrShutdown(in nsINestedEventLoopCondition condition); + /** * Spin the current thread's event loop until there are no more pending * events. This could be done with spinEventLoopUntil, but that would diff --git a/xpcom/threads/nsThreadManager.cpp b/xpcom/threads/nsThreadManager.cpp index b461c4b61c6c..40271aaa8b99 100644 --- a/xpcom/threads/nsThreadManager.cpp +++ b/xpcom/threads/nsThreadManager.cpp @@ -14,10 +14,12 @@ #include "LabeledEventQueue.h" #include "MainThreadQueue.h" #include "mozilla/AbstractThread.h" +#include "mozilla/ClearOnShutdown.h" #include "mozilla/EventQueue.h" #include "mozilla/Preferences.h" #include "mozilla/Scheduler.h" #include "mozilla/SystemGroup.h" +#include "mozilla/StaticPtr.h" #include "mozilla/ThreadEventQueue.h" #include "mozilla/ThreadLocal.h" #include "PrioritizedEventQueue.h" @@ -103,6 +105,83 @@ NS_IMPL_CLASSINFO(nsThreadManager, nullptr, NS_IMPL_QUERY_INTERFACE_CI(nsThreadManager, nsIThreadManager) NS_IMPL_CI_INTERFACE_GETTER(nsThreadManager, nsIThreadManager) +namespace { + +// Simple observer to monitor the beginning of the shutdown. +class ShutdownObserveHelper final : public nsIObserver + , public nsSupportsWeakReference +{ +public: + NS_DECL_ISUPPORTS + + static nsresult + Create(ShutdownObserveHelper** aObserver) + { + MOZ_ASSERT(aObserver); + + RefPtr observer = new ShutdownObserveHelper(); + + nsCOMPtr obs = mozilla::services::GetObserverService(); + if (NS_WARN_IF(!obs)) { + return NS_ERROR_FAILURE; + } + + nsresult rv = obs->AddObserver(observer, NS_XPCOM_SHUTDOWN_OBSERVER_ID, true); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + rv = obs->AddObserver(observer, "content-child-will-shutdown", true); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + observer.forget(aObserver); + return NS_OK; + } + + NS_IMETHOD + Observe(nsISupports* aSubject, const char* aTopic, + const char16_t* aData) override + { + if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) || + !strcmp(aTopic, "content-child-will-shutdown")) { + mShuttingDown = true; + return NS_OK; + } + + return NS_OK; + } + + bool + ShuttingDown() const + { + return mShuttingDown; + } + +private: + explicit ShutdownObserveHelper() + : mShuttingDown(false) + {} + + ~ShutdownObserveHelper() = default; + + bool mShuttingDown; +}; + +NS_INTERFACE_MAP_BEGIN(ShutdownObserveHelper) + NS_INTERFACE_MAP_ENTRY(nsIObserver) + NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIObserver) +NS_INTERFACE_MAP_END + +NS_IMPL_ADDREF(ShutdownObserveHelper) +NS_IMPL_RELEASE(ShutdownObserveHelper) + +StaticRefPtr gShutdownObserveHelper; + +} // anonymous + //----------------------------------------------------------------------------- /*static*/ nsThreadManager& @@ -112,6 +191,21 @@ nsThreadManager::get() return sInstance; } +/* static */ void +nsThreadManager::InitializeShutdownObserver() +{ + MOZ_ASSERT(!gShutdownObserveHelper); + + RefPtr observer; + nsresult rv = ShutdownObserveHelper::Create(getter_AddRefs(observer)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return; + } + + gShutdownObserveHelper = observer; + ClearOnShutdown(&gShutdownObserveHelper); +} + nsresult nsThreadManager::Init() { @@ -424,11 +518,38 @@ nsThreadManager::GetCurrentThread(nsIThread** aResult) NS_IMETHODIMP nsThreadManager::SpinEventLoopUntil(nsINestedEventLoopCondition* aCondition) +{ + return SpinEventLoopUntilInternal(aCondition, false); +} + +NS_IMETHODIMP +nsThreadManager::SpinEventLoopUntilOrShutdown(nsINestedEventLoopCondition* aCondition) +{ + return SpinEventLoopUntilInternal(aCondition, true); +} + +nsresult +nsThreadManager::SpinEventLoopUntilInternal(nsINestedEventLoopCondition* aCondition, + bool aCheckingShutdown) { nsCOMPtr condition(aCondition); nsresult rv = NS_OK; + // Nothing to do if already shutting down. Note that gShutdownObserveHelper is + // nullified on shutdown. + if (aCheckingShutdown && + (!gShutdownObserveHelper || gShutdownObserveHelper->ShuttingDown())) { + return NS_OK; + } + if (!mozilla::SpinEventLoopUntil([&]() -> bool { + // Shutting down is started. + if (aCheckingShutdown && + (!gShutdownObserveHelper || + gShutdownObserveHelper->ShuttingDown())) { + return true; + } + bool isDone = false; rv = condition->IsDone(&isDone); // JS failure should be unusual, but we need to stop and propagate diff --git a/xpcom/threads/nsThreadManager.h b/xpcom/threads/nsThreadManager.h index a1ac70e57045..2518616143f9 100644 --- a/xpcom/threads/nsThreadManager.h +++ b/xpcom/threads/nsThreadManager.h @@ -22,6 +22,8 @@ public: static nsThreadManager& get(); + static void InitializeShutdownObserver(); + nsresult Init(); // Shutdown all threads. This function should only be called on the main @@ -75,6 +77,10 @@ private: { } + nsresult + SpinEventLoopUntilInternal(nsINestedEventLoopCondition* aCondition, + bool aCheckingShutdown); + nsRefPtrHashtable, nsThread> mThreadsByPRThread; unsigned mCurThreadIndex; // thread-local-storage index RefPtr mMainThread; From 3eea0de148697b31a8eee0bc09ecce542cc287ce Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Sun, 28 Jan 2018 08:41:36 +0100 Subject: [PATCH 2/8] Bug 1425559 - "content-child-will-shutdown" notification when the content process starts the shutting down, r=smaug --- dom/ipc/ContentChild.cpp | 20 ++++++++++++++++---- dom/ipc/ContentChild.h | 2 ++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index c863d4dcec2e..6021f8ff2bbe 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -2936,6 +2936,19 @@ ContentChild::ForceKillTimerCallback(nsITimer* aTimer, void* aClosure) mozilla::ipc::IPCResult ContentChild::RecvShutdown() +{ + nsCOMPtr os = services::GetObserverService(); + if (os) { + os->NotifyObservers(static_cast(this), + "content-child-will-shutdown", nullptr); + } + + ShutdownInternal(); + return IPC_OK(); +} + +void +ContentChild::ShutdownInternal() { // If we receive the shutdown message from within a nested event loop, we want // to wait for that event loop to finish. Otherwise we could prematurely @@ -2956,9 +2969,10 @@ ContentChild::RecvShutdown() // then. MessageLoop::current()->PostDelayedTask( NewRunnableMethod( - "dom::ContentChild::RecvShutdown", this, &ContentChild::RecvShutdown), + "dom::ContentChild::RecvShutdown", this, + &ContentChild::ShutdownInternal), 100); - return IPC_OK(); + return; } mShuttingDown = true; @@ -3005,8 +3019,6 @@ ContentChild::RecvShutdown() CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("IPCShutdownState"), sent ? NS_LITERAL_CSTRING("SendFinishShutdown (sent)") : NS_LITERAL_CSTRING("SendFinishShutdown (failed)")); - - return IPC_OK(); } PBrowserOrId diff --git a/dom/ipc/ContentChild.h b/dom/ipc/ContentChild.h index 086ed3daa529..077231050c67 100644 --- a/dom/ipc/ContentChild.h +++ b/dom/ipc/ContentChild.h @@ -727,6 +727,8 @@ private: static void ForceKillTimerCallback(nsITimer* aTimer, void* aClosure); void StartForceKillTimer(); + void ShutdownInternal(); + virtual void ActorDestroy(ActorDestroyReason why) override; virtual void ProcessingError(Result aCode, const char* aReason) override; From 2ced31c722fc305446282608c809accb00e9ece0 Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Sun, 28 Jan 2018 08:41:36 +0100 Subject: [PATCH 3/8] Bug 1425559 - nsPrompter must use nsIThreadManager::spinEventLoopUntilOrShutdown, r=smaug --- .../webdriver/tests/execute_async_script/user_prompts.py.ini | 3 --- .../meta/webdriver/tests/execute_script/user_prompts.py.ini | 3 --- toolkit/components/prompts/src/nsPrompter.js | 2 +- 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/testing/web-platform/meta/webdriver/tests/execute_async_script/user_prompts.py.ini b/testing/web-platform/meta/webdriver/tests/execute_async_script/user_prompts.py.ini index cb3c3895c4ad..f0d5001858cc 100644 --- a/testing/web-platform/meta/webdriver/tests/execute_async_script/user_prompts.py.ini +++ b/testing/web-platform/meta/webdriver/tests/execute_async_script/user_prompts.py.ini @@ -1,7 +1,4 @@ [user_prompts.py] - expected: - if debug: TIMEOUT # https://bugzilla.mozilla.org/show_bug.cgi?id=1425559 - [test_handle_prompt_accept] expected: FAIL diff --git a/testing/web-platform/meta/webdriver/tests/execute_script/user_prompts.py.ini b/testing/web-platform/meta/webdriver/tests/execute_script/user_prompts.py.ini index cb3c3895c4ad..f0d5001858cc 100644 --- a/testing/web-platform/meta/webdriver/tests/execute_script/user_prompts.py.ini +++ b/testing/web-platform/meta/webdriver/tests/execute_script/user_prompts.py.ini @@ -1,7 +1,4 @@ [user_prompts.py] - expected: - if debug: TIMEOUT # https://bugzilla.mozilla.org/show_bug.cgi?id=1425559 - [test_handle_prompt_accept] expected: FAIL diff --git a/toolkit/components/prompts/src/nsPrompter.js b/toolkit/components/prompts/src/nsPrompter.js index abc94586d905..12412485af71 100644 --- a/toolkit/components/prompts/src/nsPrompter.js +++ b/toolkit/components/prompts/src/nsPrompter.js @@ -507,7 +507,7 @@ function openRemotePrompt(domWin, args, tabPrompt) { messageManager.sendAsyncMessage("Prompt:Open", args, {}); - Services.tm.spinEventLoopUntil(() => closed); + Services.tm.spinEventLoopUntilOrShutdown(() => closed); } function ModalPrompter(domWin) { From dfb28054d05c200403c3660e9de328735e13a4e6 Mon Sep 17 00:00:00 2001 From: Tooru Fujisawa Date: Mon, 29 Jan 2018 19:15:11 +0900 Subject: [PATCH 4/8] Bug 1430979 - Wait for focus event in addition to FormReady event in formautofill tests. r=MattN --- .../browser/browser_editCreditCardDialog.js | 44 +++++++++---------- .../browser/browser_manageAddressesDialog.js | 20 ++++----- .../browser_manageCreditCardsDialog.js | 24 +++++----- .../formautofill/test/browser/head.js | 24 +++++----- 4 files changed, 51 insertions(+), 61 deletions(-) diff --git a/browser/extensions/formautofill/test/browser/browser_editCreditCardDialog.js b/browser/extensions/formautofill/test/browser/browser_editCreditCardDialog.js index 1e1c2f6340b1..e8f9380e0a8f 100644 --- a/browser/extensions/formautofill/test/browser/browser_editCreditCardDialog.js +++ b/browser/extensions/formautofill/test/browser/browser_editCreditCardDialog.js @@ -5,33 +5,33 @@ add_task(async function test_cancelEditCreditCardDialog() { await new Promise(resolve => { let win = window.openDialog(EDIT_CREDIT_CARD_DIALOG_URL); - win.addEventListener("load", () => { + waitForFocus(() => { win.addEventListener("unload", () => { ok(true, "Edit credit card dialog is closed"); resolve(); }, {once: true}); win.document.querySelector("#cancel").click(); - }, {once: true}); + }, win); }); }); add_task(async function test_cancelEditCreditCardDialogWithESC() { await new Promise(resolve => { let win = window.openDialog(EDIT_CREDIT_CARD_DIALOG_URL); - win.addEventListener("load", () => { + waitForFocus(() => { win.addEventListener("unload", () => { ok(true, "Edit credit card dialog is closed with ESC key"); resolve(); }, {once: true}); EventUtils.synthesizeKey("VK_ESCAPE", {}, win); - }, {once: true}); + }, win); }); }); add_task(async function test_saveCreditCard() { await new Promise(resolve => { let win = window.openDialog(EDIT_CREDIT_CARD_DIALOG_URL); - win.addEventListener("load", () => { + waitForFocus(() => { win.addEventListener("unload", () => { ok(true, "Edit credit card dialog is closed"); resolve(); @@ -48,7 +48,7 @@ add_task(async function test_saveCreditCard() { EventUtils.synthesizeKey("VK_TAB", {}, win); info("saving credit card"); EventUtils.synthesizeKey("VK_RETURN", {}, win); - }, {once: true}); + }, win); }); let creditCards = await getCreditCards(); @@ -65,7 +65,7 @@ add_task(async function test_saveCreditCard() { add_task(async function test_saveCreditCardWithMaxYear() { await new Promise(resolve => { let win = window.openDialog(EDIT_CREDIT_CARD_DIALOG_URL); - win.addEventListener("load", () => { + waitForFocus(() => { win.addEventListener("unload", () => { ok(true, "Edit credit card dialog is closed"); resolve(); @@ -82,7 +82,7 @@ add_task(async function test_saveCreditCardWithMaxYear() { EventUtils.synthesizeKey("VK_TAB", {}, win); info("saving credit card"); EventUtils.synthesizeKey("VK_RETURN", {}, win); - }, {once: true}); + }, win); }); let creditCards = await getCreditCards(); @@ -100,20 +100,16 @@ add_task(async function test_saveCreditCardWithMaxYear() { add_task(async function test_editCreditCard() { let creditCards = await getCreditCards(); is(creditCards.length, 1, "only one credit card is in storage"); - await new Promise(resolve => { - let win = window.openDialog(EDIT_CREDIT_CARD_DIALOG_URL, null, null, creditCards[0]); - win.addEventListener("FormReady", () => { - win.addEventListener("unload", () => { - ok(true, "Edit credit card dialog is closed"); - resolve(); - }, {once: true}); - EventUtils.synthesizeKey("VK_TAB", {}, win); - EventUtils.synthesizeKey("VK_TAB", {}, win); - EventUtils.synthesizeKey("VK_RIGHT", {}, win); - EventUtils.synthesizeKey("test", {}, win); - win.document.querySelector("#save").click(); - }, {once: true}); - }); + let win = window.openDialog(EDIT_CREDIT_CARD_DIALOG_URL, null, null, creditCards[0]); + await waitForFocusAndFormReady(win); + let unloadPromise = BrowserTestUtils.waitForEvent(win, "unload"); + EventUtils.synthesizeKey("VK_TAB", {}, win); + EventUtils.synthesizeKey("VK_TAB", {}, win); + EventUtils.synthesizeKey("VK_RIGHT", {}, win); + EventUtils.synthesizeKey("test", {}, win); + win.document.querySelector("#save").click(); + await unloadPromise; + ok(true, "Edit credit card dialog is closed"); creditCards = await getCreditCards(); is(creditCards.length, 1, "only one credit card is in storage"); @@ -127,7 +123,7 @@ add_task(async function test_editCreditCard() { add_task(async function test_addInvalidCreditCard() { await new Promise(resolve => { let win = window.openDialog(EDIT_CREDIT_CARD_DIALOG_URL); - win.addEventListener("load", () => { + waitForFocus(() => { const unloadHandler = () => ok(false, "Edit credit card dialog shouldn't be closed"); win.addEventListener("unload", unloadHandler); @@ -142,7 +138,7 @@ add_task(async function test_addInvalidCreditCard() { win.close(); resolve(); }, 500); - }, {once: true}); + }, win); }); let creditCards = await getCreditCards(); diff --git a/browser/extensions/formautofill/test/browser/browser_manageAddressesDialog.js b/browser/extensions/formautofill/test/browser/browser_manageAddressesDialog.js index ef2e109f6560..4ba982ec83dc 100644 --- a/browser/extensions/formautofill/test/browser/browser_manageAddressesDialog.js +++ b/browser/extensions/formautofill/test/browser/browser_manageAddressesDialog.js @@ -26,16 +26,12 @@ add_task(async function test_manageAddressesInitialState() { }); add_task(async function test_cancelManageAddressDialogWithESC() { - await new Promise(resolve => { - let win = window.openDialog(MANAGE_ADDRESSES_DIALOG_URL); - win.addEventListener("FormReady", () => { - win.addEventListener("unload", () => { - ok(true, "Manage addresses dialog is closed with ESC key"); - resolve(); - }, {once: true}); - EventUtils.synthesizeKey("VK_ESCAPE", {}, win); - }, {once: true}); - }); + let win = window.openDialog(MANAGE_ADDRESSES_DIALOG_URL); + await waitForFocusAndFormReady(win); + let unloadPromise = BrowserTestUtils.waitForEvent(win, "unload"); + EventUtils.synthesizeKey("VK_ESCAPE", {}, win); + await unloadPromise; + ok(true, "Manage addresses dialog is closed with ESC key"); }); add_task(async function test_removingSingleAndMultipleAddresses() { @@ -44,7 +40,7 @@ add_task(async function test_removingSingleAndMultipleAddresses() { await saveAddress(TEST_ADDRESS_3); let win = window.openDialog(MANAGE_ADDRESSES_DIALOG_URL, null, DIALOG_SIZE); - await BrowserTestUtils.waitForEvent(win, "FormReady"); + await waitForFocusAndFormReady(win); let selRecords = win.document.querySelector(TEST_SELECTORS.selRecords); let btnRemove = win.document.querySelector(TEST_SELECTORS.btnRemove); @@ -73,7 +69,7 @@ add_task(async function test_removingSingleAndMultipleAddresses() { add_task(async function test_addressesDialogWatchesStorageChanges() { let win = window.openDialog(MANAGE_ADDRESSES_DIALOG_URL, null, DIALOG_SIZE); - await BrowserTestUtils.waitForEvent(win, "FormReady"); + await waitForFocusAndFormReady(win); let selRecords = win.document.querySelector(TEST_SELECTORS.selRecords); diff --git a/browser/extensions/formautofill/test/browser/browser_manageCreditCardsDialog.js b/browser/extensions/formautofill/test/browser/browser_manageCreditCardsDialog.js index 4f9e0e027ea0..1f756c57e602 100644 --- a/browser/extensions/formautofill/test/browser/browser_manageCreditCardsDialog.js +++ b/browser/extensions/formautofill/test/browser/browser_manageCreditCardsDialog.js @@ -29,16 +29,12 @@ add_task(async function test_manageCreditCardsInitialState() { }); add_task(async function test_cancelManageCreditCardsDialogWithESC() { - await new Promise(resolve => { - let win = window.openDialog(MANAGE_CREDIT_CARDS_DIALOG_URL); - win.addEventListener("FormReady", () => { - win.addEventListener("unload", () => { - ok(true, "Manage credit cards dialog is closed with ESC key"); - resolve(); - }, {once: true}); - EventUtils.synthesizeKey("VK_ESCAPE", {}, win); - }, {once: true}); - }); + let win = window.openDialog(MANAGE_CREDIT_CARDS_DIALOG_URL); + await waitForFocusAndFormReady(win); + let unloadPromise = BrowserTestUtils.waitForEvent(win, "unload"); + EventUtils.synthesizeKey("VK_ESCAPE", {}, win); + await unloadPromise; + ok(true, "Manage credit cards dialog is closed with ESC key"); }); add_task(async function test_removingSingleAndMultipleCreditCards() { @@ -47,7 +43,7 @@ add_task(async function test_removingSingleAndMultipleCreditCards() { await saveCreditCard(TEST_CREDIT_CARD_3); let win = window.openDialog(MANAGE_CREDIT_CARDS_DIALOG_URL, null, DIALOG_SIZE); - await BrowserTestUtils.waitForEvent(win, "FormReady"); + await waitForFocusAndFormReady(win); let selRecords = win.document.querySelector(TEST_SELECTORS.selRecords); let btnRemove = win.document.querySelector(TEST_SELECTORS.btnRemove); @@ -79,7 +75,7 @@ add_task(async function test_removingSingleAndMultipleCreditCards() { add_task(async function test_creditCardsDialogWatchesStorageChanges() { let win = window.openDialog(MANAGE_CREDIT_CARDS_DIALOG_URL, null, DIALOG_SIZE); - await BrowserTestUtils.waitForEvent(win, "FormReady"); + await waitForFocusAndFormReady(win); let selRecords = win.document.querySelector(TEST_SELECTORS.selRecords); @@ -99,7 +95,7 @@ add_task(async function test_showCreditCards() { await saveCreditCard(TEST_CREDIT_CARD_3); let win = window.openDialog(MANAGE_CREDIT_CARDS_DIALOG_URL, null, DIALOG_SIZE); - await BrowserTestUtils.waitForEvent(win, "FormReady"); + await waitForFocusAndFormReady(win); let selRecords = win.document.querySelector(TEST_SELECTORS.selRecords); let btnShowHideCreditCards = win.document.querySelector(TEST_SELECTORS.btnShowHideCreditCards); @@ -148,7 +144,7 @@ add_task(async function test_hasMasterPassword() { LoginTestUtils.masterPassword.enable(); let win = window.openDialog(MANAGE_CREDIT_CARDS_DIALOG_URL, null, DIALOG_SIZE); - await BrowserTestUtils.waitForEvent(win, "FormReady"); + await waitForFocusAndFormReady(win); let selRecords = win.document.querySelector(TEST_SELECTORS.selRecords); let btnRemove = win.document.querySelector(TEST_SELECTORS.btnRemove); diff --git a/browser/extensions/formautofill/test/browser/head.js b/browser/extensions/formautofill/test/browser/head.js index 08650f39b57e..95de18d5ba69 100644 --- a/browser/extensions/formautofill/test/browser/head.js +++ b/browser/extensions/formautofill/test/browser/head.js @@ -329,17 +329,19 @@ async function removeAllRecords() { } } -function testDialog(url, testFn, arg) { - return new Promise(resolve => { - let win = window.openDialog(url, null, null, arg); - win.addEventListener("FormReady", () => { - win.addEventListener("unload", () => { - ok(true, "Dialog is closed"); - resolve(); - }, {once: true}); - testFn(win); - }, {once: true}); - }); +async function waitForFocusAndFormReady(win) { + return Promise.all([ + new Promise(resolve => waitForFocus(resolve, win)), + BrowserTestUtils.waitForEvent(win, "FormReady"), + ]); +} + +async function testDialog(url, testFn, arg) { + let win = window.openDialog(url, null, null, arg); + await waitForFocusAndFormReady(win); + let unloadPromise = BrowserTestUtils.waitForEvent(win, "unload"); + testFn(win); + return unloadPromise; } registerCleanupFunction(removeAllRecords); From 227ed4308385954c76001149a894758afa1586ea Mon Sep 17 00:00:00 2001 From: Franziskus Kiefer Date: Mon, 29 Jan 2018 12:28:20 +0100 Subject: [PATCH 5/8] Bug 1432177 - land NSS 1b20549e1075 UPGRADE_NSS_RELEASE, r=me --- security/nss/TAG-INFO | 2 +- .../abi-check/expected-report-libssl3.so.txt | 10 +- .../nss/automation/buildbot-slave/build.sh | 9 +- security/nss/automation/saw/poly1305-hacl.saw | 38 ++ security/nss/automation/saw/poly1305.cry | 336 ++++++++++++++++++ security/nss/automation/saw/poly1305.saw | 47 +++ .../automation/taskcluster/docker/setup.sh | 22 +- .../taskcluster/graph/src/extend.js | 45 ++- .../taskcluster/graph/src/try_syntax.js | 2 +- .../taskcluster/scripts/check_abi.sh | 172 +++++++++ .../taskcluster/scripts/run_scan_build.sh | 2 +- security/nss/coreconf/coreconf.dep | 1 + .../nss/gtests/ssl_gtest/libssl_internals.c | 4 - .../nss/gtests/ssl_gtest/libssl_internals.h | 1 - .../nss/gtests/ssl_gtest/ssl_0rtt_unittest.cc | 9 +- .../ssl_gtest/ssl_resumption_unittest.cc | 21 ++ security/nss/gtests/ssl_gtest/tls_agent.cc | 6 + security/nss/gtests/ssl_gtest/tls_agent.h | 5 + security/nss/gtests/ssl_gtest/tls_connect.cc | 1 - security/nss/gtests/ssl_gtest/tls_connect.h | 2 + security/nss/lib/freebl/Makefile | 7 +- security/nss/lib/freebl/lowhash_vector.c | 75 ++-- security/nss/lib/freebl/stubs.c | 8 +- security/nss/lib/ssl/ssl3con.c | 5 +- security/nss/lib/ssl/ssl3exthandle.c | 2 +- security/nss/lib/ssl/sslexp.h | 8 + security/nss/lib/ssl/sslimpl.h | 4 +- security/nss/lib/ssl/sslnonce.c | 66 ++-- security/nss/lib/ssl/sslsock.c | 70 ++-- security/nss/lib/ssl/tls13con.c | 4 +- security/nss/tests/interop/interop.sh | 7 +- 31 files changed, 835 insertions(+), 156 deletions(-) create mode 100644 security/nss/automation/saw/poly1305-hacl.saw create mode 100644 security/nss/automation/saw/poly1305.cry create mode 100644 security/nss/automation/saw/poly1305.saw create mode 100755 security/nss/automation/taskcluster/scripts/check_abi.sh diff --git a/security/nss/TAG-INFO b/security/nss/TAG-INFO index f8c4be828bfa..f9b5f7597341 100644 --- a/security/nss/TAG-INFO +++ b/security/nss/TAG-INFO @@ -1 +1 @@ -10f7e0179b18 +1b20549e1075 diff --git a/security/nss/automation/abi-check/expected-report-libssl3.so.txt b/security/nss/automation/abi-check/expected-report-libssl3.so.txt index a9bd7348a37d..366591b84bd9 100644 --- a/security/nss/automation/abi-check/expected-report-libssl3.so.txt +++ b/security/nss/automation/abi-check/expected-report-libssl3.so.txt @@ -1,15 +1,15 @@ -Functions changes summary: 0 Removed, 1 Changed (2 filtered out), 0 Added function -Variables changes summary: 0 Removed, 0 Changed, 0 Added variable 1 function with some indirect sub-type change: - [C]'function SECStatus SSL_GetChannelInfo(SSLChannelInfo*, PRUintn)' at sslinfo.c:12:1 has some indirect sub-type changes: - parameter 1 of type 'SSLChannelInfo*' has sub-type changes: + [C]'function SECStatus SSL_GetChannelInfo(PRFileDesc*, SSLChannelInfo*, PRUintn)' at sslinfo.c:12:1 has some indirect sub-type changes: + parameter 2 of type 'SSLChannelInfo*' has sub-type changes: in pointed to type 'typedef SSLChannelInfo' at sslt.h:318:1: underlying type 'struct SSLChannelInfoStr' at sslt.h:259:1 changed: + type size hasn't changed 1 data member change: type of 'SSLSignatureScheme SSLChannelInfoStr::signatureScheme' changed: - underlying type 'enum __anonymous_enum__' changed: + underlying type 'enum __anonymous_enum__' at sslt.h:115:1 changed: + type size hasn't changed 3 enumerator deletions: '__anonymous_enum__::ssl_sig_rsa_pss_sha256' value '2052' '__anonymous_enum__::ssl_sig_rsa_pss_sha384' value '2053' diff --git a/security/nss/automation/buildbot-slave/build.sh b/security/nss/automation/buildbot-slave/build.sh index 99054293f7f4..00e749672dc5 100755 --- a/security/nss/automation/buildbot-slave/build.sh +++ b/security/nss/automation/buildbot-slave/build.sh @@ -212,7 +212,7 @@ test_nss() RET=$? print_log "######## details of detected failures (if any) ########" - grep -B50 FAILED ${OUTPUTFILE} + grep -B50 -w FAILED ${OUTPUTFILE} [ $? -eq 1 ] || RET=1 print_result "NSS - tests - ${BITS} bits - ${OPT}" ${RET} 0 @@ -268,8 +268,13 @@ check_abi() fi abidiff --hd1 $PREVDIST/public/ --hd2 $NEWDIST/public \ $PREVDIST/*/lib/$SO $NEWDIST/*/lib/$SO \ - > ${HGDIR}/nss/automation/abi-check/new-report-$SO.txt + > ${HGDIR}/nss/automation/abi-check/new-report-temp$SO.txt RET=$? + cat ${HGDIR}/nss/automation/abi-check/new-report-temp$SO.txt \ + | grep -v "^Functions changes summary:" \ + | grep -v "^Variables changes summary:" \ + > ${HGDIR}/nss/automation/abi-check/new-report-$SO.txt + rm -f ${HGDIR}/nss/automation/abi-check/new-report-temp$SO.txt ABIDIFF_ERROR=$((($RET & 0x01) != 0)) ABIDIFF_USAGE_ERROR=$((($RET & 0x02) != 0)) ABIDIFF_ABI_CHANGE=$((($RET & 0x04) != 0)) diff --git a/security/nss/automation/saw/poly1305-hacl.saw b/security/nss/automation/saw/poly1305-hacl.saw new file mode 100644 index 000000000000..a4dfff6d925c --- /dev/null +++ b/security/nss/automation/saw/poly1305-hacl.saw @@ -0,0 +1,38 @@ +// 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/. + +import "poly1305.cry" as poly1305; + +print "Proving Poly1305 spec..."; +prove_print abc {{ poly1305::allTestsPass }}; + +print "Loading LLVM bitcode..."; +m <- llvm_load_module "../../../dist/Debug/lib/libfreeblpriv3.so.bc"; + +let SpecPoly1305 n = do { + llvm_ptr "output" (llvm_array 16 (llvm_int 8)); + output <- llvm_var "*output" (llvm_array 16 (llvm_int 8)); + + llvm_ptr "input" (llvm_array n (llvm_int 8)); + input <- llvm_var "*input" (llvm_array n (llvm_int 8)); + + llvm_var "len1" (llvm_int 64); + llvm_ptr "k1" (llvm_array 32 (llvm_int 8)); + k1 <- llvm_var "*k1" (llvm_array 32 (llvm_int 8)); + + llvm_assert_eq "*input" {{ zero : [n][8] }}; + llvm_assert_eq "len1" {{ `n : [64] }}; + + llvm_assert_eq "*k1" {{ zero : [32][8] }}; + + let res = {{ poly1305::Poly1305 input (take`{16} k1) (drop`{16} k1) }}; + llvm_ensure_eq "*output" {{ res }}; + + llvm_verify_tactic abc; +}; + +print "Proving equality for a single block..."; +// This is currently disabled as it takes way too long. We need to help Z3 +// prove this before we can enable it on Taskcluster. +//time (llvm_verify m "Hacl_Poly1305_64_crypto_onetimeauth" [] (SpecPoly1305 16)); diff --git a/security/nss/automation/saw/poly1305.cry b/security/nss/automation/saw/poly1305.cry new file mode 100644 index 000000000000..6321a4f190ae --- /dev/null +++ b/security/nss/automation/saw/poly1305.cry @@ -0,0 +1,336 @@ +/* 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/. */ + +/* This file provides a spec of the Poly1305 one-time authenticator. + * See for details. */ + +module poly1305 where + +P : [136] +P = 2^^130 - 5 + +Poly1305 : {n} (fin n) => [n][8] -> [16][8] -> [16][8] -> [16][8] +Poly1305 msg r s = reverse (groupBy (drop ((rounds ! 0) + s'))) + where + rounds = [zero] # [ Poly1305_block acc r' b | b <- blocks | acc <- rounds ] + r' = zero # (Poly1305_clamp (join (reverse r))) + s' = zero # (join (reverse s)) + blocks = Poly1305_split msg + +private + // 0x0f - for r[3], r[7], r[11], r[15] + // 0xfc - for r[4], r[8], r[12] + Poly1305_clamp r = r && 0x0ffffffc0ffffffc0ffffffc0fffffff + + // Poly1305_block : ((acc + msg) * r) % P + Poly1305_block : [136] -> [136] -> [136] -> [136] + Poly1305_block acc r msg = drop (prod % (zero # P)) + where + acc' : [137] + // Add the current block to the accumulator. + acc' = (zero # acc) + (zero # msg) + prod : [273] + // Multiply the new accumulator value by r. + prod = ((zero : [137]) # r) * ((zero : [136]) # acc') + + Poly1305_split : {n, nb, nf} (fin n, nf == n / 16, nb == (n + 15) / 16) => [n][8] -> [nb][136] + Poly1305_split msg = take ((h1 : [nf][136]) # h2) + where + // Split all full 16-byte blocks and append 0x01, then convert to LE. + h1 = [ join (reverse (b # [0x01])) | b <- groupBy`{16} (take msg)] + // Pad the remaining bytes (if any) and convert to LE. + h2 = [join (reverse ((drop`{nf * 16} msg) # [0x01] # zero))] + +/* -------------------------------------------------------------------------- */ +/* -- Tests ----------------------------------------------------------------- */ + +private + // https://tools.ietf.org/html/rfc7539#section-2.5.2 + rval1 = [0x85, 0xd6, 0xbe, 0x78, 0x57, 0x55, 0x6d, 0x33, + 0x7f, 0x44, 0x52, 0xfe, 0x42, 0xd5, 0x06, 0xa8] + sval1 = [0x01, 0x03, 0x80, 0x8a, 0xfb, 0x0d, 0xb2, 0xfd, + 0x4a, 0xbf, 0xf6, 0xaf, 0x41, 0x49, 0xf5, 0x1b] + text1 = [0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x67, 0x72, + 0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x46, 0x6f, + 0x72, 0x75, 0x6d, 0x20, 0x52, 0x65, 0x73, 0x65, + 0x61, 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6f, + 0x75, 0x70] + + rfctest01 = Poly1305 text1 rval1 sval1 + == [0xa8, 0x06, 0x1d, 0xc1, 0x30, 0x51, 0x36, 0xc6, + 0xc2, 0x2b, 0x8b, 0xaf, 0x0c, 0x01, 0x27, 0xa9] + + // https://tools.ietf.org/html/rfc7539#appendix-A.3 + // Test Vector #1 + rval2 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + sval2 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + text2 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + + rfctest02 = Poly1305 text2 rval2 sval2 + == [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + + // https://tools.ietf.org/html/rfc7539#appendix-A.3 + // Test Vector #2 + rval3 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + sval3 = [0x36, 0xe5, 0xf6, 0xb5, 0xc5, 0xe0, 0x60, 0x70, + 0xf0, 0xef, 0xca, 0x96, 0x22, 0x7a, 0x86, 0x3e] + text3 = [0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d, + 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74, + 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45, + 0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e, + 0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61, + 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72, + 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66, + 0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46, + 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, + 0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x20, + 0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61, + 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73, + 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, + 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69, + 0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, + 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49, + 0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69, + 0x76, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20, + 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72, + 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49, + 0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, + 0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, + 0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, + 0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, + 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45, + 0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20, + 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20, + 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20, + 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6c, 0x65, 0x63, + 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63, + 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61, + 0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e, + 0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f, + 0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c, + 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61, + 0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f] + + rfctest03 = Poly1305 text3 rval3 sval3 + == [0x36, 0xe5, 0xf6, 0xb5, 0xc5, 0xe0, 0x60, 0x70, + 0xf0, 0xef, 0xca, 0x96, 0x22, 0x7a, 0x86, 0x3e] + + // https://tools.ietf.org/html/rfc7539#appendix-A.3 + // Test Vector #3 + rval4 = [0x36, 0xe5, 0xf6, 0xb5, 0xc5, 0xe0, 0x60, 0x70, + 0xf0, 0xef, 0xca, 0x96, 0x22, 0x7a, 0x86, 0x3e] + sval4 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + text4 = [0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d, + 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74, + 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45, + 0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e, + 0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61, + 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72, + 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66, + 0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46, + 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, + 0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x20, + 0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61, + 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73, + 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, + 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69, + 0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, + 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49, + 0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69, + 0x76, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20, + 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72, + 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49, + 0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, + 0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, + 0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, + 0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, + 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45, + 0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20, + 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20, + 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20, + 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6c, 0x65, 0x63, + 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63, + 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61, + 0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e, + 0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f, + 0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c, + 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61, + 0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f] + + rfctest04 = Poly1305 text4 rval4 sval4 + == [0xf3, 0x47, 0x7e, 0x7c, 0xd9, 0x54, 0x17, 0xaf, + 0x89, 0xa6, 0xb8, 0x79, 0x4c, 0x31, 0x0c, 0xf0] + + // https://tools.ietf.org/html/rfc7539#appendix-A.3 + // Test Vector #4 + rval5 = [0x1c, 0x92, 0x40, 0xa5, 0xeb, 0x55, 0xd3, 0x8a, + 0xf3, 0x33, 0x88, 0x86, 0x04, 0xf6, 0xb5, 0xf0] + sval5 = [0x47, 0x39, 0x17, 0xc1, 0x40, 0x2b, 0x80, 0x09, + 0x9d, 0xca, 0x5c, 0xbc, 0x20, 0x70, 0x75, 0xc0] + text5 = [0x27, 0x54, 0x77, 0x61, 0x73, 0x20, 0x62, 0x72, + 0x69, 0x6c, 0x6c, 0x69, 0x67, 0x2c, 0x20, 0x61, + 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, + 0x6c, 0x69, 0x74, 0x68, 0x79, 0x20, 0x74, 0x6f, + 0x76, 0x65, 0x73, 0x0a, 0x44, 0x69, 0x64, 0x20, + 0x67, 0x79, 0x72, 0x65, 0x20, 0x61, 0x6e, 0x64, + 0x20, 0x67, 0x69, 0x6d, 0x62, 0x6c, 0x65, 0x20, + 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, + 0x61, 0x62, 0x65, 0x3a, 0x0a, 0x41, 0x6c, 0x6c, + 0x20, 0x6d, 0x69, 0x6d, 0x73, 0x79, 0x20, 0x77, + 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x62, 0x6f, 0x72, 0x6f, 0x67, 0x6f, 0x76, 0x65, + 0x73, 0x2c, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x6d, 0x65, 0x20, + 0x72, 0x61, 0x74, 0x68, 0x73, 0x20, 0x6f, 0x75, + 0x74, 0x67, 0x72, 0x61, 0x62, 0x65, 0x2e] + + rfctest05 = Poly1305 text5 rval5 sval5 + == [0x45, 0x41, 0x66, 0x9a, 0x7e, 0xaa, 0xee, 0x61, + 0xe7, 0x08, 0xdc, 0x7c, 0xbc, 0xc5, 0xeb, 0x62] + + // https://tools.ietf.org/html/rfc7539#appendix-A.3 + // Test Vector #5 + rval6 = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + sval6 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + text6 = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff] + + rfctest06 = Poly1305 text6 rval6 sval6 + == [0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + + // https://tools.ietf.org/html/rfc7539#appendix-A.3 + // Test Vector #6 + rval7 = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + sval7 = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff] + text7 = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + + rfctest07 = Poly1305 text7 rval7 sval7 + == [0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + + // https://tools.ietf.org/html/rfc7539#appendix-A.3 + // Test Vector #7 + rval8 = [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + sval8 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + text8 = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + + rfctest08 = Poly1305 text8 rval8 sval8 + == [0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + + // https://tools.ietf.org/html/rfc7539#appendix-A.3 + // Test Vector #8 + rval9 = [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + sval9 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + text9 = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xfb, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, + 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01] + + rfctest09 = Poly1305 text9 rval9 sval9 + == [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + + // https://tools.ietf.org/html/rfc7539#appendix-A.3 + // Test Vector #9 + rval10 = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + sval10 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + text10 = [0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff] + + rfctest10 = Poly1305 text10 rval10 sval10 + == [0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff] + + // https://tools.ietf.org/html/rfc7539#appendix-A.3 + // Test Vector #10 + rval11 = [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + sval11 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + text11 = [0xe3, 0x35, 0x94, 0xd7, 0x50, 0x5e, 0x43, 0xb9, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x33, 0x94, 0xd7, 0x50, 0x5e, 0x43, 0x79, 0xcd, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + + rfctest11 = Poly1305 text11 rval11 sval11 + == [0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + + // https://tools.ietf.org/html/rfc7539#appendix-A.3 + // Test Vector #11 + rval12 = [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + sval12 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + text12 = [0xe3, 0x35, 0x94, 0xd7, 0x50, 0x5e, 0x43, 0xb9, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x33, 0x94, 0xd7, 0x50, 0x5e, 0x43, 0x79, 0xcd, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + + rfctest12 = Poly1305 text12 rval12 sval12 + == [0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + +property allTestsPass = + ([ // Full RFC test vectors + rfctest01, rfctest02, rfctest03, rfctest04, + rfctest05, rfctest06, rfctest07, rfctest08, + rfctest09, rfctest10, rfctest11, rfctest12 + ] : [_]Bit) == ~zero // All test bits should equal one diff --git a/security/nss/automation/saw/poly1305.saw b/security/nss/automation/saw/poly1305.saw new file mode 100644 index 000000000000..44be1e3e0c44 --- /dev/null +++ b/security/nss/automation/saw/poly1305.saw @@ -0,0 +1,47 @@ +// 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/. + +import "poly1305.cry" as poly1305; + +print "Proving Poly1305 spec..."; +prove_print abc {{ poly1305::allTestsPass }}; + +print "Loading LLVM bitcode..."; +m <- llvm_load_module "../../../dist/Debug/lib/libfreeblpriv3.so.bc"; + +let SpecPoly1305 n = do { + llvm_ptr "out" (llvm_array 16 (llvm_int 8)); + out <- llvm_var "*out" (llvm_array 16 (llvm_int 8)); + + llvm_ptr "ad" (llvm_array 16 (llvm_int 8)); + ad <- llvm_var "*ad" (llvm_array 16 (llvm_int 8)); + + adLen <- llvm_var "adLen" (llvm_int 32); + + llvm_ptr "ciphertext" (llvm_array n (llvm_int 8)); + ciphertext <- llvm_var "*ciphertext" (llvm_array n (llvm_int 8)); + + ciphertextLen <- llvm_var "ciphertextLen" (llvm_int 32); + + llvm_ptr "key" (llvm_array 32 (llvm_int 8)); + key <- llvm_var "*key" (llvm_array 32 (llvm_int 8)); + + llvm_assert_eq "*ad" {{ zero : [16][8] }}; + llvm_assert_eq "adLen" {{ 16 : [32] }}; + + llvm_assert_eq "*ciphertext" {{ zero : [n][8] }}; + llvm_assert_eq "ciphertextLen" {{ `n : [32] }}; + + llvm_assert_eq "*key" {{ zero : [32][8] }}; + + let res = {{ poly1305::Poly1305 (ad # ciphertext # [16, 0, 0, 0, 0, 0, 0, 0] # [`n, 0, 0, 0, 0, 0, 0, 0]) (take`{16} key) (drop`{16} key) }}; + llvm_ensure_eq "*out" {{ res }}; + + llvm_verify_tactic abc; +}; + +print "Proving equality for a single block..."; +// This is currently disabled as it takes way too long. We need to help Z3 +// prove this before we can enable it on Taskcluster. +//time (llvm_verify m "Poly1305Do" [] (SpecPoly1305 16)); diff --git a/security/nss/automation/taskcluster/docker/setup.sh b/security/nss/automation/taskcluster/docker/setup.sh index 01f9c413a570..7b90b2e69cba 100644 --- a/security/nss/automation/taskcluster/docker/setup.sh +++ b/security/nss/automation/taskcluster/docker/setup.sh @@ -12,6 +12,7 @@ apt-get install -y --no-install-recommends apt-utils apt_packages=() apt_packages+=('build-essential') apt_packages+=('ca-certificates') +apt_packages+=('clang-5.0') apt_packages+=('curl') apt_packages+=('npm') apt_packages+=('git') @@ -47,16 +48,17 @@ echo "deb http://ppa.launchpad.net/ubuntu-toolchain-r/test/ubuntu xenial main" > apt-get -y update apt-get install -y --no-install-recommends ${apt_packages[@]} -# Download clang. -curl -LO https://releases.llvm.org/4.0.0/clang+llvm-4.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz -curl -LO https://releases.llvm.org/4.0.0/clang+llvm-4.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz.sig -# Verify the signature. -gpg --keyserver pool.sks-keyservers.net --recv-keys B6C8F98282B944E3B0D5C2530FC3042E345AD05D -gpg --verify *.tar.xz.sig -# Install into /usr/local/. -tar xJvf *.tar.xz -C /usr/local --strip-components=1 -# Cleanup. -rm *.tar.xz* +# Latest version of abigail-tools +apt-get install -y libxml2-dev autoconf libelf-dev libdw-dev libtool +git clone git://sourceware.org/git/libabigail.git +cd ./libabigail +autoreconf -fi +./configure --prefix=/usr --disable-static --disable-apidoc --disable-manual +make +make install +cd .. +apt-get remove -y libxml2-dev autoconf libtool +rm -rf libabigail # Install latest Rust (stable). su worker -c "curl https://sh.rustup.rs -sSf | sh -s -- -y" diff --git a/security/nss/automation/taskcluster/graph/src/extend.js b/security/nss/automation/taskcluster/graph/src/extend.js index 666d90d99049..f6e7b9b75039 100644 --- a/security/nss/automation/taskcluster/graph/src/extend.js +++ b/security/nss/automation/taskcluster/graph/src/extend.js @@ -192,8 +192,8 @@ export default async function main() { UBSAN_OPTIONS: "print_stacktrace=1", NSS_DISABLE_ARENA_FREE_LIST: "1", NSS_DISABLE_UNLOAD: "1", - CC: "clang", - CCC: "clang++", + CC: "clang-5.0", + CCC: "clang++-5.0", }, platform: "linux64", collection: "asan", @@ -423,12 +423,12 @@ async function scheduleLinux(name, base, args = "") { // Extra builds. let extra_base = merge({group: "Builds"}, build_base); queue.scheduleTask(merge(extra_base, { - name: `${name} w/ clang-4.0`, + name: `${name} w/ clang-5.0`, env: { - CC: "clang", - CCC: "clang++", + CC: "clang-5.0", + CCC: "clang++-5.0", }, - symbol: "clang-4.0" + symbol: "clang-5.0" })); queue.scheduleTask(merge(extra_base, { @@ -951,6 +951,18 @@ async function scheduleTools() { kind: "test" }; + //ABI check task + queue.scheduleTask(merge(base, { + symbol: "abi", + name: "abi", + image: LINUX_IMAGE, + command: [ + "/bin/bash", + "-c", + "bin/checkout.sh && nss/automation/taskcluster/scripts/check_abi.sh" + ], + })); + queue.scheduleTask(merge(base, { symbol: "clang-format-3.9", name: "clang-format-3.9", @@ -963,13 +975,13 @@ async function scheduleTools() { })); queue.scheduleTask(merge(base, { - symbol: "scan-build-4.0", - name: "scan-build-4.0", + symbol: "scan-build-5.0", + name: "scan-build-5.0", image: LINUX_IMAGE, env: { USE_64: "1", - CC: "clang", - CCC: "clang++", + CC: "clang-5.0", + CCC: "clang++-5.0", }, artifacts: { public: { @@ -1047,5 +1059,18 @@ async function scheduleTools() { ] })); + queue.scheduleTask(merge(base, { + parent: task_saw, + symbol: "Poly1305", + group: "SAW", + name: "poly1305.saw", + image: SAW_IMAGE, + command: [ + "/bin/bash", + "-c", + "bin/checkout.sh && nss/automation/taskcluster/scripts/run_saw.sh poly1305" + ] + })); + return queue.submit(); } diff --git a/security/nss/automation/taskcluster/graph/src/try_syntax.js b/security/nss/automation/taskcluster/graph/src/try_syntax.js index 4a721be394bf..1c06dde1337c 100644 --- a/security/nss/automation/taskcluster/graph/src/try_syntax.js +++ b/security/nss/automation/taskcluster/graph/src/try_syntax.js @@ -51,7 +51,7 @@ function parseOptions(opts) { } // Parse tools. - let allTools = ["clang-format", "scan-build", "hacl", "saw"]; + let allTools = ["clang-format", "scan-build", "hacl", "saw", "abi"]; let tools = intersect(opts.tools.split(/\s*,\s*/), allTools); // If the given value is "all" run all tools. diff --git a/security/nss/automation/taskcluster/scripts/check_abi.sh b/security/nss/automation/taskcluster/scripts/check_abi.sh new file mode 100755 index 000000000000..dbc1a476fde2 --- /dev/null +++ b/security/nss/automation/taskcluster/scripts/check_abi.sh @@ -0,0 +1,172 @@ +#! /bin/bash + +set_env() +{ + cd /home/worker + HGDIR=/home/worker + OUTPUTDIR=$(pwd)$(echo "/output") + DATE=$(date "+TB [%Y-%m-%d %H:%M:%S]") + + if [ ! -d "${OUTPUTDIR}" ]; then + echo "Creating output dir" + mkdir "${OUTPUTDIR}" + fi + + if [ ! -d "nspr" ]; then + for i in 0 2 5; do + sleep $i + hg clone -r "default" "https://hg.mozilla.org/projects/nspr" "${HGDIR}/nspr" && break + rm -rf nspr + done + fi + + cd nss + ./build.sh -v -c + cd .. +} + +check_abi() +{ + set_env + set +e #reverses set -e from build.sh to allow possible hg clone failures + if [[ "$1" != --nobuild ]]; then # Start nobuild block + + echo "######## NSS ABI CHECK ########" + echo "######## creating temporary HG clones ########" + + rm -rf ${HGDIR}/baseline + mkdir ${HGDIR}/baseline + BASE_NSS=`cat ${HGDIR}/nss/automation/abi-check/previous-nss-release` #Reads the version number of the last release from the respective file + NSS_CLONE_RESULT=0 + for i in 0 2 5; do + sleep $i + hg clone -u "${BASE_NSS}" "https://hg.mozilla.org/projects/nss" "${HGDIR}/baseline/nss" + if [ $? -eq 0 ]; then + NSS_CLONE_RESULT=0 + break + fi + rm -rf "${HGDIR}/baseline/nss" + NSS_CLONE_RESULT=1 + done + if [ ${NSS_CLONE_RESULT} -ne 0 ]; then + echo "invalid tag in automation/abi-check/previous-nss-release" + return 1 + fi + + BASE_NSPR=NSPR_$(head -1 ${HGDIR}/baseline/nss/automation/release/nspr-version.txt | cut -d . -f 1-2 | tr . _)_BRANCH + hg clone -u "${BASE_NSPR}" "https://hg.mozilla.org/projects/nspr" "${HGDIR}/baseline/nspr" + NSPR_CLONE_RESULT=$? + + if [ ${NSPR_CLONE_RESULT} -ne 0 ]; then + rm -rf "${HGDIR}/baseline/nspr" + for i in 0 2 5; do + sleep $i + hg clone -u "default" "https://hg.mozilla.org/projects/nspr" "${HGDIR}/baseline/nspr" && break + rm -rf "${HGDIR}/baseline/nspr" + done + echo "Nonexisting tag ${BASE_NSPR} derived from ${BASE_NSS} automation/release/nspr-version.txt" + echo "Using default branch instead." + fi + + echo "######## building baseline NSPR/NSS ########" + echo "${HGDIR}/baseline/nss/build.sh" + cd ${HGDIR}/baseline/nss + ./build.sh -v -c + cd ${HGDIR} + else # Else nobuild block + echo "######## using existing baseline NSPR/NSS build ########" + fi # End nobuild block + + set +e #reverses set -e from build.sh to allow abidiff failures + + echo "######## Starting abidiff procedure ########" + abi_diff +} + +#Slightly modified from builbot-slave/build.sh +abi_diff() +{ + ABI_PROBLEM_FOUND=0 + ABI_REPORT=${OUTPUTDIR}/abi-diff.txt + rm -f ${ABI_REPORT} + PREVDIST=${HGDIR}/baseline/dist + NEWDIST=${HGDIR}/dist + ALL_SOs="libfreebl3.so libfreeblpriv3.so libnspr4.so libnss3.so libnssckbi.so libnssdbm3.so libnsssysinit.so libnssutil3.so libplc4.so libplds4.so libsmime3.so libsoftokn3.so libssl3.so" + for SO in ${ALL_SOs}; do + if [ ! -f ${HGDIR}/nss/automation/abi-check/expected-report-$SO.txt ]; then + touch ${HGDIR}/nss/automation/abi-check/expected-report-$SO.txt + fi + abidiff --hd1 $PREVDIST/public/ --hd2 $NEWDIST/public \ + $PREVDIST/*/lib/$SO $NEWDIST/*/lib/$SO \ + > ${HGDIR}/nss/automation/abi-check/new-report-temp$SO.txt + RET=$? + cat ${HGDIR}/nss/automation/abi-check/new-report-temp$SO.txt \ + | grep -v "^Functions changes summary:" \ + | grep -v "^Variables changes summary:" \ + > ${HGDIR}/nss/automation/abi-check/new-report-$SO.txt + rm -f ${HGDIR}/nss/automation/abi-check/new-report-temp$SO.txt + + ABIDIFF_ERROR=$((($RET & 0x01) != 0)) + ABIDIFF_USAGE_ERROR=$((($RET & 0x02) != 0)) + ABIDIFF_ABI_CHANGE=$((($RET & 0x04) != 0)) + ABIDIFF_ABI_INCOMPATIBLE_CHANGE=$((($RET & 0x08) != 0)) + ABIDIFF_UNKNOWN_BIT_SET=$((($RET & 0xf0) != 0)) + + # If abidiff reports an error, or a usage error, or if it sets a result + # bit value this script doesn't know yet about, we'll report failure. + # For ABI changes, we don't yet report an error. We'll compare the + # result report with our whitelist. This allows us to silence changes + # that we're already aware of and have been declared acceptable. + + REPORT_RET_AS_FAILURE=0 + if [ $ABIDIFF_ERROR -ne 0 ]; then + echo "abidiff reported ABIDIFF_ERROR." + REPORT_RET_AS_FAILURE=1 + fi + if [ $ABIDIFF_USAGE_ERROR -ne 0 ]; then + echo "abidiff reported ABIDIFF_USAGE_ERROR." + REPORT_RET_AS_FAILURE=1 + fi + if [ $ABIDIFF_UNKNOWN_BIT_SET -ne 0 ]; then + echo "abidiff reported ABIDIFF_UNKNOWN_BIT_SET." + REPORT_RET_AS_FAILURE=1 + fi + + if [ $ABIDIFF_ABI_CHANGE -ne 0 ]; then + echo "Ignoring abidiff result ABI_CHANGE, instead we'll check for non-whitelisted differences." + fi + if [ $ABIDIFF_ABI_INCOMPATIBLE_CHANGE -ne 0 ]; then + echo "Ignoring abidiff result ABIDIFF_ABI_INCOMPATIBLE_CHANGE, instead we'll check for non-whitelisted differences." + fi + + if [ $REPORT_RET_AS_FAILURE -ne 0 ]; then + ABI_PROBLEM_FOUND=1 + echo "abidiff {$PREVDIST , $NEWDIST} for $SO FAILED with result $RET, or failed writing to ${HGDIR}/nss/automation/abi-check/new-report-$SO.txt" + fi + if [ ! -f ${HGDIR}/nss/automation/abi-check/expected-report-$SO.txt ]; then + ABI_PROBLEM_FOUND=1 + echo "FAILED to access report file: ${HGDIR}/nss/automation/abi-check/expected-report-$SO.txt" + fi + + diff -wB -u ${HGDIR}/nss/automation/abi-check/expected-report-$SO.txt \ + ${HGDIR}/nss/automation/abi-check/new-report-$SO.txt >> ${ABI_REPORT} + if [ ! -f ${ABI_REPORT} ]; then + ABI_PROBLEM_FOUND=1 + echo "FAILED to compare exepcted and new report: ${HGDIR}/nss/automation/abi-check/new-report-$SO.txt" + fi + done + + if [ -s ${ABI_REPORT} ]; then + echo "FAILED: there are new unexpected ABI changes" + cat ${ABI_REPORT} + return 1 + elif [ $ABI_PROBLEM_FOUND -ne 0 ]; then + echo "FAILED: failure executing the ABI checks" + cat ${ABI_REPORT} + return 1 + fi + + return 0 +} + +check_abi $1 diff --git a/security/nss/automation/taskcluster/scripts/run_scan_build.sh b/security/nss/automation/taskcluster/scripts/run_scan_build.sh index 4024c226e9e8..014530b42b98 100755 --- a/security/nss/automation/taskcluster/scripts/run_scan_build.sh +++ b/security/nss/automation/taskcluster/scripts/run_scan_build.sh @@ -34,7 +34,7 @@ for i in "${!scan[@]}"; do done # run scan-build (only building affected directories) -scan-build -o /home/worker/artifacts --use-cc=$CC --use-c++=$CCC make nss_build_all && cd .. +scan-build-5.0 -o /home/worker/artifacts --use-cc=$CC --use-c++=$CCC make nss_build_all && cd .. # print errors we found set +v +x diff --git a/security/nss/coreconf/coreconf.dep b/security/nss/coreconf/coreconf.dep index 5182f75552c8..590d1bfaeee3 100644 --- a/security/nss/coreconf/coreconf.dep +++ b/security/nss/coreconf/coreconf.dep @@ -10,3 +10,4 @@ */ #error "Do not include this header file." + diff --git a/security/nss/gtests/ssl_gtest/libssl_internals.c b/security/nss/gtests/ssl_gtest/libssl_internals.c index 887d852786be..17b4ffe49a50 100644 --- a/security/nss/gtests/ssl_gtest/libssl_internals.c +++ b/security/nss/gtests/ssl_gtest/libssl_internals.c @@ -332,10 +332,6 @@ void SSLInt_SetTicketLifetime(uint32_t lifetime) { ssl_ticket_lifetime = lifetime; } -void SSLInt_SetMaxEarlyDataSize(uint32_t size) { - ssl_max_early_data_size = size; -} - SECStatus SSLInt_SetSocketMaxEarlyDataSize(PRFileDesc *fd, uint32_t size) { sslSocket *ss; diff --git a/security/nss/gtests/ssl_gtest/libssl_internals.h b/security/nss/gtests/ssl_gtest/libssl_internals.h index 95d4afdaf9a9..3efb362c2742 100644 --- a/security/nss/gtests/ssl_gtest/libssl_internals.h +++ b/security/nss/gtests/ssl_gtest/libssl_internals.h @@ -50,7 +50,6 @@ PK11SymKey *SSLInt_CipherSpecToKey(const ssl3CipherSpec *spec); SSLCipherAlgorithm SSLInt_CipherSpecToAlgorithm(const ssl3CipherSpec *spec); const PRUint8 *SSLInt_CipherSpecToIv(const ssl3CipherSpec *spec); void SSLInt_SetTicketLifetime(uint32_t lifetime); -void SSLInt_SetMaxEarlyDataSize(uint32_t size); SECStatus SSLInt_SetSocketMaxEarlyDataSize(PRFileDesc *fd, uint32_t size); void SSLInt_RolloverAntiReplay(void); diff --git a/security/nss/gtests/ssl_gtest/ssl_0rtt_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_0rtt_unittest.cc index 1fd26b2ec190..8847312b800b 100644 --- a/security/nss/gtests/ssl_gtest/ssl_0rtt_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_0rtt_unittest.cc @@ -459,10 +459,13 @@ static void CheckEarlyDataLimit(const std::shared_ptr& agent, } TEST_P(TlsConnectTls13, SendTooMuchEarlyData) { + EnsureTlsSetup(); const char* big_message = "0123456789abcdef"; const size_t short_size = strlen(big_message) - 1; const PRInt32 short_length = static_cast(short_size); - SSLInt_SetMaxEarlyDataSize(static_cast(short_size)); + EXPECT_EQ(SECSuccess, + SSL_SetMaxEarlyDataSize(server_->ssl_fd(), + static_cast(short_size))); SetupForZeroRtt(); client_->Set0RttEnabled(true); @@ -514,8 +517,10 @@ TEST_P(TlsConnectTls13, SendTooMuchEarlyData) { } TEST_P(TlsConnectTls13, ReceiveTooMuchEarlyData) { + EnsureTlsSetup(); + const size_t limit = 5; - SSLInt_SetMaxEarlyDataSize(limit); + EXPECT_EQ(SECSuccess, SSL_SetMaxEarlyDataSize(server_->ssl_fd(), limit)); SetupForZeroRtt(); client_->Set0RttEnabled(true); diff --git a/security/nss/gtests/ssl_gtest/ssl_resumption_unittest.cc b/security/nss/gtests/ssl_gtest/ssl_resumption_unittest.cc index 8c449acababa..d93a190e0b6a 100644 --- a/security/nss/gtests/ssl_gtest/ssl_resumption_unittest.cc +++ b/security/nss/gtests/ssl_gtest/ssl_resumption_unittest.cc @@ -1014,4 +1014,25 @@ TEST_P(TlsConnectTls13ResumptionToken, ConnectResumeGetInfoZeroRtt) { SendReceive(); } +// Resumption on sessions with client authentication only works with internal +// caching. +TEST_P(TlsConnectGenericResumption, ConnectResumeClientAuth) { + ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH); + client_->SetupClientAuth(); + server_->RequestClientAuth(true); + Connect(); + SendReceive(); + EXPECT_FALSE(client_->resumption_callback_called()); + + Reset(); + ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH); + if (use_external_cache()) { + ExpectResumption(RESUME_NONE); + } else { + ExpectResumption(RESUME_TICKET); + } + Connect(); + SendReceive(); +} + } // namespace nss_test diff --git a/security/nss/gtests/ssl_gtest/tls_agent.cc b/security/nss/gtests/ssl_gtest/tls_agent.cc index ded09cb996aa..172fc9195aed 100644 --- a/security/nss/gtests/ssl_gtest/tls_agent.cc +++ b/security/nss/gtests/ssl_gtest/tls_agent.cc @@ -66,6 +66,7 @@ TlsAgent::TlsAgent(const std::string& name, Role role, expected_sent_alert_(kTlsAlertCloseNotify), expected_sent_alert_level_(kTlsAlertWarning), handshake_callback_called_(false), + resumption_callback_called_(false), error_code_(0), send_ctr_(0), recv_ctr_(0), @@ -183,6 +184,10 @@ bool TlsAgent::EnsureTlsSetup(PRFileDesc* modelSocket) { ScopedCERTCertList anchors(CERT_NewCertList()); rv = SSL_SetTrustAnchors(ssl_fd(), anchors.get()); if (rv != SECSuccess) return false; + + rv = SSL_SetMaxEarlyDataSize(ssl_fd(), 1024); + EXPECT_EQ(SECSuccess, rv); + if (rv != SECSuccess) return false; } else { rv = SSL_SetURL(ssl_fd(), "server"); EXPECT_EQ(SECSuccess, rv); @@ -420,6 +425,7 @@ SECStatus ResumptionTokenCallback(PRFileDesc* fd, std::vector new_token(resumptionToken, resumptionToken + len); reinterpret_cast(ctx)->SetResumptionToken(new_token); + reinterpret_cast(ctx)->SetResumptionCallbackCalled(); return SECSuccess; } diff --git a/security/nss/gtests/ssl_gtest/tls_agent.h b/security/nss/gtests/ssl_gtest/tls_agent.h index e578b8b09943..731296a20c8b 100644 --- a/security/nss/gtests/ssl_gtest/tls_agent.h +++ b/security/nss/gtests/ssl_gtest/tls_agent.h @@ -179,6 +179,10 @@ class TlsAgent : public PollTarget { sizeof(SSLResumptionTokenInfo)); ASSERT_EQ(SECSuccess, rv); } + void SetResumptionCallbackCalled() { resumption_callback_called_ = true; } + bool resumption_callback_called() const { + return resumption_callback_called_; + } const std::string& name() const { return name_; } @@ -396,6 +400,7 @@ class TlsAgent : public PollTarget { uint8_t expected_sent_alert_; uint8_t expected_sent_alert_level_; bool handshake_callback_called_; + bool resumption_callback_called_; SSLChannelInfo info_; SSLCipherSuiteInfo csinfo_; SSLVersionRange vrange_; diff --git a/security/nss/gtests/ssl_gtest/tls_connect.cc b/security/nss/gtests/ssl_gtest/tls_connect.cc index c5cfda9ecec5..b1e90d89db3e 100644 --- a/security/nss/gtests/ssl_gtest/tls_connect.cc +++ b/security/nss/gtests/ssl_gtest/tls_connect.cc @@ -197,7 +197,6 @@ void TlsConnectTestBase::SetUp() { SSL_ConfigServerSessionIDCache(1024, 0, 0, g_working_dir_path.c_str()); SSLInt_ClearSelfEncryptKey(); SSLInt_SetTicketLifetime(30); - SSLInt_SetMaxEarlyDataSize(1024); SSL_SetupAntiReplay(1 * PR_USEC_PER_SEC, 1, 3); ClearStats(); Init(); diff --git a/security/nss/gtests/ssl_gtest/tls_connect.h b/security/nss/gtests/ssl_gtest/tls_connect.h index 730ec31ad4e8..b13f158428b9 100644 --- a/security/nss/gtests/ssl_gtest/tls_connect.h +++ b/security/nss/gtests/ssl_gtest/tls_connect.h @@ -225,6 +225,8 @@ class TlsConnectGenericResumption client_->SetResumptionTokenCallback(); } } + + bool use_external_cache() const { return external_cache_; } }; class TlsConnectTls13ResumptionToken diff --git a/security/nss/lib/freebl/Makefile b/security/nss/lib/freebl/Makefile index 0b3daa2756a5..6c8e6a2ead82 100644 --- a/security/nss/lib/freebl/Makefile +++ b/security/nss/lib/freebl/Makefile @@ -527,7 +527,12 @@ ifndef NSS_DISABLE_CHACHAPOLY EXTRA_SRCS += chacha20_vec.c endif else - EXTRA_SRCS += poly1305.c + ifeq ($(CPU_ARCH),aarch64) + EXTRA_SRCS += Hacl_Poly1305_64.c + else + EXTRA_SRCS += poly1305.c + endif + EXTRA_SRCS += chacha20.c VERIFIED_SRCS += Hacl_Chacha20.c endif # x86_64 diff --git a/security/nss/lib/freebl/lowhash_vector.c b/security/nss/lib/freebl/lowhash_vector.c index 7690c98da938..be53bbdc62e3 100644 --- a/security/nss/lib/freebl/lowhash_vector.c +++ b/security/nss/lib/freebl/lowhash_vector.c @@ -102,13 +102,13 @@ freebl_LoadDSO(void) static PRCallOnceType loadFreeBLOnce; -static PRStatus +static void freebl_RunLoaderOnce(void) { /* Don't have NSPR, so can use the real PR_CallOnce, implement a stripped * down version. */ if (loadFreeBLOnce.initialized) { - return loadFreeBLOnce.status; + return; } if (__sync_lock_test_and_set(&loadFreeBLOnce.inProgress, 1) == 0) { loadFreeBLOnce.status = freebl_LoadDSO(); @@ -122,17 +122,21 @@ freebl_RunLoaderOnce(void) sleep(1); /* don't have condition variables, just give up the CPU */ } } +} - return loadFreeBLOnce.status; +static const NSSLOWVector * +freebl_InitVector(void) +{ + if (!vector) { + freebl_RunLoaderOnce(); + } + return vector; } const FREEBLVector * FREEBL_GetVector(void) { - if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) { - return NULL; - } - if (vector) { + if (freebl_InitVector()) { return (vector->p_FREEBL_GetVector)(); } return NULL; @@ -141,25 +145,26 @@ FREEBL_GetVector(void) NSSLOWInitContext * NSSLOW_Init(void) { - if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) - return NULL; - return (vector->p_NSSLOW_Init)(); + if (freebl_InitVector()) { + return (vector->p_NSSLOW_Init)(); + } + return NULL; } void NSSLOW_Shutdown(NSSLOWInitContext *context) { - if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) - return; - (vector->p_NSSLOW_Shutdown)(context); + if (freebl_InitVector()) { + (vector->p_NSSLOW_Shutdown)(context); + } } void NSSLOW_Reset(NSSLOWInitContext *context) { - if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) - return; - (vector->p_NSSLOW_Reset)(context); + if (freebl_InitVector()) { + (vector->p_NSSLOW_Reset)(context); + } } NSSLOWHASHContext * @@ -167,17 +172,18 @@ NSSLOWHASH_NewContext( NSSLOWInitContext *initContext, HASH_HashType hashType) { - if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) - return NULL; - return (vector->p_NSSLOWHASH_NewContext)(initContext, hashType); + if (freebl_InitVector()) { + return (vector->p_NSSLOWHASH_NewContext)(initContext, hashType); + } + return NULL; } void NSSLOWHASH_Begin(NSSLOWHASHContext *context) { - if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) - return; - (vector->p_NSSLOWHASH_Begin)(context); + if (freebl_InitVector()) { + (vector->p_NSSLOWHASH_Begin)(context); + } } void @@ -185,9 +191,9 @@ NSSLOWHASH_Update(NSSLOWHASHContext *context, const unsigned char *buf, unsigned int len) { - if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) - return; - (vector->p_NSSLOWHASH_Update)(context, buf, len); + if (freebl_InitVector()) { + (vector->p_NSSLOWHASH_Update)(context, buf, len); + } } void @@ -195,23 +201,24 @@ NSSLOWHASH_End(NSSLOWHASHContext *context, unsigned char *buf, unsigned int *ret, unsigned int len) { - if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) - return; - (vector->p_NSSLOWHASH_End)(context, buf, ret, len); + if (freebl_InitVector()) { + (vector->p_NSSLOWHASH_End)(context, buf, ret, len); + } } void NSSLOWHASH_Destroy(NSSLOWHASHContext *context) { - if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) - return; - (vector->p_NSSLOWHASH_Destroy)(context); + if (freebl_InitVector()) { + (vector->p_NSSLOWHASH_Destroy)(context); + } } unsigned int NSSLOWHASH_Length(NSSLOWHASHContext *context) { - if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) - return -1; - return (vector->p_NSSLOWHASH_Length)(context); + if (freebl_InitVector()) { + return (vector->p_NSSLOWHASH_Length)(context); + } + return -1; } diff --git a/security/nss/lib/freebl/stubs.c b/security/nss/lib/freebl/stubs.c index 4d41ef975f4f..c42f694d7e15 100644 --- a/security/nss/lib/freebl/stubs.c +++ b/security/nss/lib/freebl/stubs.c @@ -36,6 +36,7 @@ #include #include #include +#include #include /* Android API < 21 doesn't define RTLD_NOLOAD */ @@ -252,7 +253,12 @@ PORT_ZAllocAligned_stub(size_t bytes, size_t alignment, void **mem) } memset(*mem, 0, len); - return (void *)(((uintptr_t)*mem + x) & ~(uintptr_t)x); + + /* We're pretty sure this is non-zero, but let's assure scan-build too. */ + void *ret = (void *)(((uintptr_t)*mem + x) & ~(uintptr_t)x); + assert(ret); + + return ret; } extern void * diff --git a/security/nss/lib/ssl/ssl3con.c b/security/nss/lib/ssl/ssl3con.c index bffafa3d1e08..89fd06dfcadc 100644 --- a/security/nss/lib/ssl/ssl3con.c +++ b/security/nss/lib/ssl/ssl3con.c @@ -4272,6 +4272,7 @@ ssl3_ComputeHandshakeHashes(sslSocket *ss, sizeof(stackBuf), &stateLen); if (stateBuf == NULL) { ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE); + rv = SECFailure; goto tls12_loser; } rv |= PK11_DigestFinal(h, hashes->u.raw, &hashes->len, @@ -4283,7 +4284,6 @@ ssl3_ComputeHandshakeHashes(sslSocket *ss, } hashes->hashAlg = ssl3_GetSuitePrfHash(ss); - rv = SECSuccess; tls12_loser: if (stateBuf) { @@ -4315,6 +4315,7 @@ ssl3_ComputeHandshakeHashes(sslSocket *ss, sizeof md5StackBuf, &md5StateLen); if (md5StateBuf == NULL) { ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); + rv = SECFailure; goto loser; } md5 = ss->ssl3.hs.md5; @@ -4323,6 +4324,7 @@ ssl3_ComputeHandshakeHashes(sslSocket *ss, sizeof shaStackBuf, &shaStateLen); if (shaStateBuf == NULL) { ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); + rv = SECFailure; goto loser; } sha = ss->ssl3.hs.sha; @@ -4418,7 +4420,6 @@ ssl3_ComputeHandshakeHashes(sslSocket *ss, PRINT_BUF(60, (NULL, "SHA outer: result", hashes->u.s.sha, SHA1_LENGTH)); hashes->len = MD5_LENGTH + SHA1_LENGTH; - rv = SECSuccess; loser: if (md5StateBuf) { diff --git a/security/nss/lib/ssl/ssl3exthandle.c b/security/nss/lib/ssl/ssl3exthandle.c index acf5aae6bfd7..e6388945e123 100644 --- a/security/nss/lib/ssl/ssl3exthandle.c +++ b/security/nss/lib/ssl/ssl3exthandle.c @@ -821,7 +821,7 @@ ssl3_EncodeSessionTicket(sslSocket *ss, const NewSessionTicket *ticket, if (rv != SECSuccess) goto loser; - rv = sslBuffer_AppendNumber(&plaintext, ssl_max_early_data_size, 4); + rv = sslBuffer_AppendNumber(&plaintext, ss->opt.maxEarlyDataSize, 4); if (rv != SECSuccess) goto loser; diff --git a/security/nss/lib/ssl/sslexp.h b/security/nss/lib/ssl/sslexp.h index 7ecf2703ee2f..08654f8854cc 100644 --- a/security/nss/lib/ssl/sslexp.h +++ b/security/nss/lib/ssl/sslexp.h @@ -444,6 +444,14 @@ typedef SECStatus(PR_CALLBACK *SSLResumptionTokenCallback)( (PRFileDesc * _fd, const PRUint8 *_token, const unsigned int _len), \ (fd, token, len)) +/* TLS 1.3 allows a server to set a limit on the number of bytes of early data + * that can be received. This allows that limit to be set. This function has no + * effect on a client. */ +#define SSL_SetMaxEarlyDataSize(fd, size) \ + SSL_EXPERIMENTAL_API("SSL_SetMaxEarlyDataSize", \ + (PRFileDesc * _fd, PRUint32 _size), \ + (fd, size)) + /* Deprecated experimental APIs */ #define SSL_UseAltServerHelloType(fd, enable) SSL_DEPRECATED_EXPERIMENTAL_API diff --git a/security/nss/lib/ssl/sslimpl.h b/security/nss/lib/ssl/sslimpl.h index 231873a54e9f..10d0333d9e1e 100644 --- a/security/nss/lib/ssl/sslimpl.h +++ b/security/nss/lib/ssl/sslimpl.h @@ -233,6 +233,7 @@ typedef struct sslOptionsStr { * list of supported protocols. */ SECItem nextProtoNego; + PRUint32 maxEarlyDataSize; unsigned int useSecurity : 1; unsigned int useSocks : 1; unsigned int requestCertificate : 1; @@ -1069,7 +1070,6 @@ extern FILE *ssl_keylog_iob; extern PZLock *ssl_keylog_lock; extern PRUint32 ssl3_sid_timeout; extern PRUint32 ssl_ticket_lifetime; -extern PRUint32 ssl_max_early_data_size; extern const char *const ssl3_cipherName[]; @@ -1701,7 +1701,7 @@ SECStatus SSLExp_GetResumptionTokenInfo(const PRUint8 *tokenData, unsigned int t SECStatus SSLExp_DestroyResumptionTokenInfo(SSLResumptionTokenInfo *token); -#define SSLResumptionTokenVersion 1 +#define SSLResumptionTokenVersion 2 SEC_END_PROTOS diff --git a/security/nss/lib/ssl/sslnonce.c b/security/nss/lib/ssl/sslnonce.c index a2ed94b93c73..f79c23fc72ec 100644 --- a/security/nss/lib/ssl/sslnonce.c +++ b/security/nss/lib/ssl/sslnonce.c @@ -423,7 +423,10 @@ ReadVariableFromBuffer(sslReader *reader, sslReadBuffer *readerBuffer, if (readerBuffer->len) { SECItem tempItem = { siBuffer, (unsigned char *)readerBuffer->buf, readerBuffer->len }; - SECITEM_CopyItem(NULL, dest, &tempItem); + SECStatus rv = SECITEM_CopyItem(NULL, dest, &tempItem); + if (rv != SECSuccess) { + return rv; + } } return SECSuccess; } @@ -521,6 +524,7 @@ ssl_DecodeResumptionToken(sslSessionID *sid, const PRUint8 *encodedToken, return SECFailure; } if (readerBuffer.len) { + PORT_Assert(readerBuffer.buf); sid->peerID = PORT_Strdup((const char *)readerBuffer.buf); } @@ -532,6 +536,7 @@ ssl_DecodeResumptionToken(sslSessionID *sid, const PRUint8 *encodedToken, if (sid->urlSvrName) { PORT_Free((void *)sid->urlSvrName); } + PORT_Assert(readerBuffer.buf); sid->urlSvrName = PORT_Strdup((const char *)readerBuffer.buf); } @@ -605,6 +610,7 @@ ssl_DecodeResumptionToken(sslSessionID *sid, const PRUint8 *encodedToken, return SECFailure; } if (readerBuffer.len) { + PORT_Assert(readerBuffer.buf); PORT_Memcpy(sid->u.ssl3.sessionID, readerBuffer.buf, readerBuffer.len); } @@ -626,6 +632,7 @@ ssl_DecodeResumptionToken(sslSessionID *sid, const PRUint8 *encodedToken, PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } + PORT_Assert(readerBuffer.buf); PORT_Memcpy(sid->u.ssl3.keys.wrapped_master_secret, readerBuffer.buf, readerBuffer.len); @@ -660,27 +667,10 @@ ssl_DecodeResumptionToken(sslSessionID *sid, const PRUint8 *encodedToken, } sid->u.ssl3.masterWrapSeries = (PRUint16)tmpInt; - if (sslRead_ReadNumber(&reader, 8, &tmpInt) != SECSuccess) { - return SECFailure; - } - sid->u.ssl3.clAuthModuleID = (unsigned long)tmpInt; - if (sslRead_ReadNumber(&reader, 8, &tmpInt) != SECSuccess) { - return SECFailure; - } - sid->u.ssl3.clAuthSlotID = (unsigned long)tmpInt; - if (sslRead_ReadNumber(&reader, 2, &tmpInt) != SECSuccess) { - return SECFailure; - } - sid->u.ssl3.clAuthSeries = (PRUint16)tmpInt; - if (sslRead_ReadNumber(&reader, 1, &tmpInt) != SECSuccess) { return SECFailure; } sid->u.ssl3.masterValid = (char)tmpInt; - if (sslRead_ReadNumber(&reader, 1, &tmpInt) != SECSuccess) { - return SECFailure; - } - sid->u.ssl3.clAuthValid = (char)tmpInt; if (ReadVariableFromBuffer(&reader, &readerBuffer, 1, &sid->u.ssl3.srvName) != SECSuccess) { @@ -758,8 +748,8 @@ ssl_EncodeResumptionToken(sslSessionID *sid, sslBuffer *encodedTokenBuf) { PORT_Assert(encodedTokenBuf); PORT_Assert(sid); - if (!sid->u.ssl3.locked.sessionTicket.ticket.len || !encodedTokenBuf || - !sid || !sid->u.ssl3.keys.resumable || !sid->urlSvrName) { + if (!sid || !sid->u.ssl3.locked.sessionTicket.ticket.len || + !encodedTokenBuf || !sid->u.ssl3.keys.resumable || !sid->urlSvrName) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } @@ -1022,32 +1012,11 @@ ssl_EncodeResumptionToken(sslSessionID *sid, sslBuffer *encodedTokenBuf) return SECFailure; } - rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->u.ssl3.clAuthModuleID, 8); - if (rv != SECSuccess) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->u.ssl3.clAuthSlotID, 8); - if (rv != SECSuccess) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->u.ssl3.clAuthSeries, 2); - if (rv != SECSuccess) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->u.ssl3.masterValid, 1); if (rv != SECSuccess) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } - rv = sslBuffer_AppendNumber(encodedTokenBuf, sid->u.ssl3.clAuthValid, 1); - if (rv != SECSuccess) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } rv = sslBuffer_AppendVariable(encodedTokenBuf, sid->u.ssl3.srvName.data, sid->u.ssl3.srvName.len, 1); @@ -1102,6 +1071,11 @@ ssl_CacheExternalToken(sslSocket *ss) return; } + /* Don't export token if the session used client authentication. */ + if (sid->u.ssl3.clAuthValid) { + return; + } + if (!sid->creationTime) { sid->lastAccessTime = sid->creationTime = ssl_TimeUsec(); } @@ -1160,10 +1134,12 @@ ssl_UncacheSessionID(sslSocket *ss) sslSecurityInfo *sec = &ss->sec; PORT_Assert(sec); - if (sec->isServer) { - ssl_ServerUncacheSessionID(sec->ci.sid); - } else if (!ss->resumptionTokenCallback) { - LockAndUncacheSID(sec->ci.sid); + if (sec->ci.sid) { + if (sec->isServer) { + ssl_ServerUncacheSessionID(sec->ci.sid); + } else if (!ss->resumptionTokenCallback) { + LockAndUncacheSID(sec->ci.sid); + } } } diff --git a/security/nss/lib/ssl/sslsock.c b/security/nss/lib/ssl/sslsock.c index fbc0a174255f..e08d5e23263a 100644 --- a/security/nss/lib/ssl/sslsock.c +++ b/security/nss/lib/ssl/sslsock.c @@ -53,34 +53,35 @@ static const sslSocketOps ssl_secure_ops = { /* SSL. */ ** default settings for socket enables */ static sslOptions ssl_defaults = { - { siBuffer, NULL, 0 }, /* nextProtoNego */ - PR_TRUE, /* useSecurity */ - PR_FALSE, /* useSocks */ - PR_FALSE, /* requestCertificate */ - 2, /* requireCertificate */ - PR_FALSE, /* handshakeAsClient */ - PR_FALSE, /* handshakeAsServer */ - PR_FALSE, /* noCache */ - PR_FALSE, /* fdx */ - PR_TRUE, /* detectRollBack */ - PR_FALSE, /* noLocks */ - PR_FALSE, /* enableSessionTickets */ - PR_FALSE, /* enableDeflate */ - 2, /* enableRenegotiation (default: requires extension) */ - PR_FALSE, /* requireSafeNegotiation */ - PR_FALSE, /* enableFalseStart */ - PR_TRUE, /* cbcRandomIV */ - PR_FALSE, /* enableOCSPStapling */ - PR_FALSE, /* enableNPN */ - PR_TRUE, /* enableALPN */ - PR_TRUE, /* reuseServerECDHEKey */ - PR_FALSE, /* enableFallbackSCSV */ - PR_TRUE, /* enableServerDhe */ - PR_FALSE, /* enableExtendedMS */ - PR_FALSE, /* enableSignedCertTimestamps */ - PR_FALSE, /* requireDHENamedGroups */ - PR_FALSE, /* enable0RttData */ - PR_FALSE /* enableTls13CompatMode */ + .nextProtoNego = { siBuffer, NULL, 0 }, + .maxEarlyDataSize = 1 << 16, + .useSecurity = PR_TRUE, + .useSocks = PR_FALSE, + .requestCertificate = PR_FALSE, + .requireCertificate = SSL_REQUIRE_FIRST_HANDSHAKE, + .handshakeAsClient = PR_FALSE, + .handshakeAsServer = PR_FALSE, + .noCache = PR_FALSE, + .fdx = PR_FALSE, + .detectRollBack = PR_TRUE, + .noLocks = PR_FALSE, + .enableSessionTickets = PR_FALSE, + .enableDeflate = PR_FALSE, + .enableRenegotiation = SSL_RENEGOTIATE_REQUIRES_XTN, + .requireSafeNegotiation = PR_FALSE, + .enableFalseStart = PR_FALSE, + .cbcRandomIV = PR_TRUE, + .enableOCSPStapling = PR_FALSE, + .enableNPN = PR_FALSE, + .enableALPN = PR_TRUE, + .reuseServerECDHEKey = PR_TRUE, + .enableFallbackSCSV = PR_FALSE, + .enableServerDhe = PR_TRUE, + .enableExtendedMS = PR_FALSE, + .enableSignedCertTimestamps = PR_FALSE, + .requireDHENamedGroups = PR_FALSE, + .enable0RttData = PR_FALSE, + .enableTls13CompatMode = PR_FALSE }; /* @@ -1252,6 +1253,18 @@ SSL_OptionSetDefault(PRInt32 which, PRIntn val) return SECSuccess; } +SECStatus +SSLExp_SetMaxEarlyDataSize(PRFileDesc *fd, PRUint32 size) +{ + sslSocket *ss = ssl_FindSocket(fd); + if (!ss) { + return SECFailure; /* Error code already set. */ + } + + ss->opt.maxEarlyDataSize = size; + return SECSuccess; +} + /* function tells us if the cipher suite is one that we no longer support. */ static PRBool ssl_IsRemovedCipherSuite(PRInt32 suite) @@ -3932,6 +3945,7 @@ struct { EXP(InstallExtensionHooks), EXP(KeyUpdate), EXP(SendSessionTicket), + EXP(SetMaxEarlyDataSize), EXP(SetupAntiReplay), EXP(SetResumptionTokenCallback), EXP(SetResumptionToken), diff --git a/security/nss/lib/ssl/tls13con.c b/security/nss/lib/ssl/tls13con.c index 42b8d169ac40..c06acc83a995 100644 --- a/security/nss/lib/ssl/tls13con.c +++ b/security/nss/lib/ssl/tls13con.c @@ -4417,8 +4417,6 @@ tls13_SendClientSecondRound(sslSocket *ss) * } NewSessionTicket; */ -PRUint32 ssl_max_early_data_size = (2 << 16); /* Arbitrary limit. */ - static SECStatus tls13_SendNewSessionTicket(sslSocket *ss, const PRUint8 *appToken, unsigned int appTokenLen) @@ -4520,7 +4518,7 @@ tls13_SendNewSessionTicket(sslSocket *ss, const PRUint8 *appToken, if (rv != SECSuccess) goto loser; - rv = ssl3_AppendHandshakeNumber(ss, ssl_max_early_data_size, 4); + rv = ssl3_AppendHandshakeNumber(ss, ss->opt.maxEarlyDataSize, 4); if (rv != SECSuccess) goto loser; } diff --git a/security/nss/tests/interop/interop.sh b/security/nss/tests/interop/interop.sh index fbdb5766643c..97c82e0ca0c2 100755 --- a/security/nss/tests/interop/interop.sh +++ b/security/nss/tests/interop/interop.sh @@ -57,7 +57,12 @@ interop_run() (cd "$INTEROP"; cargo run -- --client "$client" --server "$server" --rootdir "$BORING"/ssl/test/runner/ --test-cases cases.json) 2>interop-${test_name}.errors | tee interop-${test_name}.log - html_msg "${PIPESTATUS[0]}" 0 "Interop" "Run successfully" + RESULT=${PIPESTATUS[0]} + html_msg "${RESULT}" 0 "Interop" "Run successfully" + if [ $RESULT -ne 0 ]; then + cat interop-${test_name}.errors + cat interop-${test_name}.log + fi grep -i 'FAILED\|Assertion failure' interop-${test_name}.errors html_msg $? 1 "Interop" "No failures" } From 9a6985ae0c640adf8d7e9fa06edd614ff5b6963e Mon Sep 17 00:00:00 2001 From: Olli Pettay Date: Mon, 29 Jan 2018 13:49:48 +0200 Subject: [PATCH 6/8] Bug 1433413 - Optimize IsEventTargetChrome, r=masayuki --- dom/events/EventDispatcher.cpp | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/dom/events/EventDispatcher.cpp b/dom/events/EventDispatcher.cpp index f501929c2ba5..4a0b96ea6b39 100644 --- a/dom/events/EventDispatcher.cpp +++ b/dom/events/EventDispatcher.cpp @@ -102,29 +102,23 @@ static bool IsEventTargetChrome(EventTarget* aEventTarget, *aDocument = nullptr; } - if (NS_WARN_IF(!aEventTarget)) { - return false; - } - - nsCOMPtr doc = do_QueryInterface(aEventTarget); - if (!doc) { - nsCOMPtr node = do_QueryInterface(aEventTarget); - if (node) { - doc = node->OwnerDoc(); - } else { - nsCOMPtr window = do_QueryInterface(aEventTarget); - if (!window) { - return false; - } - doc = window->GetExtantDoc(); - } - if (!doc) { + nsIDocument* doc = nullptr; + nsCOMPtr node = do_QueryInterface(aEventTarget); + if (node) { + doc = node->OwnerDoc(); + } else { + nsCOMPtr window = do_QueryInterface(aEventTarget); + if (!window) { return false; } + doc = window->GetExtantDoc(); } + + // nsContentUtils::IsChromeDoc is null-safe. bool isChrome = nsContentUtils::IsChromeDoc(doc); - if (aDocument) { - doc.swap(*aDocument); + if (aDocument && doc) { + nsCOMPtr retVal = doc; + retVal.swap(*aDocument); } return isChrome; } From 0fae93703ad7b6b0fb0ff20c54e3340e49378e54 Mon Sep 17 00:00:00 2001 From: sotaro Date: Mon, 29 Jan 2018 20:55:09 +0900 Subject: [PATCH 7/8] Bug 1413390 - Add PluginGeometryUpdates handling for WebRenderLayerManager r=jrmuizel --- layout/painting/nsDisplayList.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/layout/painting/nsDisplayList.cpp b/layout/painting/nsDisplayList.cpp index d2d7c87ddbfb..8237e3b1dec0 100644 --- a/layout/painting/nsDisplayList.cpp +++ b/layout/painting/nsDisplayList.cpp @@ -2453,6 +2453,18 @@ already_AddRefed nsDisplayList::PaintRoot(nsDisplayListBuilder* aB } } + // Windowed plugins are not supported with WebRender enabled. + // But PluginGeometry needs to be updated to show plugin. + // Windowed plugins are going to be removed by Bug 1296400. + nsRootPresContext* rootPresContext = presContext->GetRootPresContext(); + if (rootPresContext && XRE_IsContentProcess()) { + if (aBuilder->WillComputePluginGeometry()) { + rootPresContext->ComputePluginGeometryUpdates(aBuilder->RootReferenceFrame(), aBuilder, this); + } + // This must be called even if PluginGeometryUpdates were not computed. + rootPresContext->CollectPluginGeometryUpdates(layerManager); + } + WebRenderLayerManager* wrManager = static_cast(layerManager.get()); MaybeSetupTransactionIdAllocator(layerManager, presContext); From b845f285386b4fc3b85a213dd202d848dc12c3cd Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Mon, 29 Jan 2018 13:25:15 +0100 Subject: [PATCH 8/8] Bug 1433625 - Implement console.createInstance().time("foo") correctly, r=smaug --- dom/console/Console.cpp | 47 ++++++++++++++++++++++++++++++++++++++++- dom/console/Console.h | 6 ++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/dom/console/Console.cpp b/dom/console/Console.cpp index 4e60a0b139ab..300a2aeb661f 100644 --- a/dom/console/Console.cpp +++ b/dom/console/Console.cpp @@ -1357,6 +1357,11 @@ Console::MethodInternal(JSContext* aCx, MethodName aMethodName, // function. if (aMethodName == MethodTrace) { MaybeExecuteDumpFunctionForTrace(aCx, stack); + } else if ((aMethodName == MethodTime || + aMethodName == MethodTimeEnd) && + !aData.IsEmpty()) { + MaybeExecuteDumpFunctionForTime(aCx, aMethodName, aMethodString, + monotonicTimer, aData[0]); } else { MaybeExecuteDumpFunction(aCx, aMethodString, aData); } @@ -2569,7 +2574,7 @@ Console::MonotonicTimer(JSContext* aCx, MethodName aMethodName, // people can do nasty timing attacks with it. See similar code in the // worker Performance implementation. const double maxResolutionMs = 0.005; - return nsRFPService::ReduceTimePrecisionAsMSecs( + *aTimeStamp = nsRFPService::ReduceTimePrecisionAsMSecs( floor(duration / maxResolutionMs) * maxResolutionMs); return true; } @@ -2631,6 +2636,46 @@ Console::MaybeExecuteDumpFunction(JSContext* aCx, ExecuteDumpFunction(message); } +void +Console::MaybeExecuteDumpFunctionForTime(JSContext* aCx, + MethodName aMethodName, + const nsAString& aMethodString, + uint64_t aMonotonicTimer, + const JS::Value& aData) +{ + if (!mDumpFunction && !mDumpToStdout) { + return; + } + + nsAutoString message; + message.AssignLiteral("console."); + message.Append(aMethodString); + message.AppendLiteral(": "); + + if (!mPrefix.IsEmpty()) { + message.Append(mPrefix); + message.AppendLiteral(": "); + } + + JS::Rooted v(aCx, aData); + JS::Rooted jsString(aCx, JS_ValueToSource(aCx, v)); + if (!jsString) { + return; + } + + nsAutoJSString string; + if (NS_WARN_IF(!string.init(aCx, jsString))) { + return; + } + + message.Append(string); + message.AppendLiteral(" @ "); + message.AppendInt(aMonotonicTimer); + + message.AppendLiteral("\n"); + ExecuteDumpFunction(message); +} + void Console::MaybeExecuteDumpFunctionForTrace(JSContext* aCx, nsIStackFrame* aStack) { diff --git a/dom/console/Console.h b/dom/console/Console.h index 6bddeecb6879..53cd4552b918 100644 --- a/dom/console/Console.h +++ b/dom/console/Console.h @@ -391,6 +391,12 @@ private: MaybeExecuteDumpFunction(JSContext* aCx, const nsAString& aMethodName, const Sequence& aData); + void + MaybeExecuteDumpFunctionForTime(JSContext* aCx, MethodName aMethodName, + const nsAString& aMethodString, + uint64_t aMonotonicTimer, + const JS::Value& aData); + void MaybeExecuteDumpFunctionForTrace(JSContext* aCx, nsIStackFrame* aStack);