author | Tom Ritter <tom@mozilla.com> |
Tue, 18 Sep 2018 13:05:26 -0500 | |
changeset 443186 | 920270da576f92d10e511d1f51eaf183ceb6483f |
parent 443185 | f1c0fa980fd1ce976b3628fe8ea445e6f337a168 |
child 443187 | b00e84c0233b17a1daf0feccf660580aa5fe2d30 |
push id | 34943 |
push user | csabou@mozilla.com |
push date | Fri, 26 Oct 2018 21:57:01 +0000 |
treeherder | mozilla-central@3dc7cdbb2b5f [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | baku, froydnj |
bugs | 1432429 |
milestone | 65.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -1192,16 +1192,18 @@ pref("services.sync.prefs.sync.privacy.c pref("services.sync.prefs.sync.privacy.clearOnShutdown.cookies", true); pref("services.sync.prefs.sync.privacy.clearOnShutdown.downloads", true); pref("services.sync.prefs.sync.privacy.clearOnShutdown.formdata", true); pref("services.sync.prefs.sync.privacy.clearOnShutdown.history", true); pref("services.sync.prefs.sync.privacy.clearOnShutdown.offlineApps", true); pref("services.sync.prefs.sync.privacy.clearOnShutdown.sessions", true); pref("services.sync.prefs.sync.privacy.clearOnShutdown.siteSettings", true); pref("services.sync.prefs.sync.privacy.donottrackheader.enabled", true); +pref("services.sync.prefs.sync.privacy.fuzzyfox.enabled", true); +pref("services.sync.prefs.sync.privacy.fuzzyfox.clockgrainus", true); pref("services.sync.prefs.sync.privacy.sanitize.sanitizeOnShutdown", true); pref("services.sync.prefs.sync.privacy.trackingprotection.enabled", true); pref("services.sync.prefs.sync.privacy.trackingprotection.pbmode.enabled", true); pref("services.sync.prefs.sync.privacy.resistFingerprinting", true); pref("services.sync.prefs.sync.privacy.reduceTimerPrecision", true); pref("services.sync.prefs.sync.privacy.resistFingerprinting.reduceTimerPrecision.microseconds", true); pref("services.sync.prefs.sync.privacy.resistFingerprinting.reduceTimerPrecision.jitter", true); pref("services.sync.prefs.sync.security.OCSP.enabled", true);
--- a/layout/build/nsLayoutStatics.cpp +++ b/layout/build/nsLayoutStatics.cpp @@ -97,16 +97,17 @@ #include "mozilla/dom/CustomElementRegistry.h" #include "mozilla/EventDispatcher.h" #include "mozilla/IMEStateManager.h" #include "mozilla/dom/HTMLVideoElement.h" #include "TouchManager.h" #include "DecoderDoctorLogger.h" #include "MediaDecoder.h" #include "mozilla/ClearSiteData.h" +#include "mozilla/Fuzzyfox.h" #include "mozilla/ServoBindings.h" #include "mozilla/StaticPresData.h" #include "mozilla/dom/WebIDLGlobalNameHash.h" #include "mozilla/dom/ipc/IPCBlobInputStreamStorage.h" #include "mozilla/dom/U2FTokenManager.h" #include "mozilla/dom/PointerEventHandler.h" #include "mozilla/dom/BlobURLProtocolHandler.h" #include "nsThreadManager.h" @@ -279,16 +280,18 @@ nsLayoutStatics::Initialize() if (XRE_IsParentProcess()) { // On content process we initialize DOMPrefs when PContentChild is fully // initialized. mozilla::dom::DOMPrefs::Initialize(); } nsThreadManager::InitializeShutdownObserver(); + mozilla::Fuzzyfox::Start(); + ClearSiteData::Initialize(); return NS_OK; } void nsLayoutStatics::Shutdown() {
--- a/mozglue/misc/TimeStamp_windows.cpp +++ b/mozglue/misc/TimeStamp_windows.cpp @@ -58,36 +58,30 @@ static const uint32_t kFailureThreshold // If we are not able to get the value of GTC time increment, use this value // which is the most usual increment. static const DWORD kDefaultTimeIncrement = 156001; // ---------------------------------------------------------------------------- // Global variables, not changing at runtime // ---------------------------------------------------------------------------- -/** - * The [mt] unit: - * - * Many values are kept in ticks of the Performance Coutner x 1000, - * further just referred as [mt], meaning milli-ticks. - * - * This is needed to preserve maximum precision of the performance frequency - * representation. GetTickCount64 values in milliseconds are multiplied with - * frequency per second. Therefor we need to multiply QPC value by 1000 to - * have the same units to allow simple arithmentic with both QPC and GTC. - */ - -#define ms2mt(x) ((x) * sFrequencyPerSec) -#define mt2ms(x) ((x) / sFrequencyPerSec) -#define mt2ms_f(x) (double(x) / sFrequencyPerSec) - // Result of QueryPerformanceFrequency // We use default of 1 for the case we can't use QueryPerformanceCounter // to make mt/ms conversions work despite that. -static LONGLONG sFrequencyPerSec = 1; +static uint64_t sFrequencyPerSec = 1; + +namespace mozilla { + +MFBT_API uint64_t +GetQueryPerformanceFrequencyPerSec() +{ + return sFrequencyPerSec; +} + +} // How much we are tolerant to GTC occasional loose of resoltion. // This number says how many multiples of the minimal GTC resolution // detected on the system are acceptable. This number is empirical. static const LONGLONG kGTCTickLeapTolerance = 4; // Base tolerance (more: "inability of detection" range) threshold is calculated // dynamically, and kept in sGTCResolutionThreshold.
--- a/mozglue/misc/TimeStamp_windows.h +++ b/mozglue/misc/TimeStamp_windows.h @@ -6,16 +6,34 @@ #ifndef mozilla_TimeStamp_windows_h #define mozilla_TimeStamp_windows_h #include "mozilla/Types.h" namespace mozilla { +/** + * The [mt] unit: + * + * Many values are kept in ticks of the Performance Counter x 1000, + * further just referred as [mt], meaning milli-ticks. + * + * This is needed to preserve maximum precision of the performance frequency + * representation. GetTickCount64 values in milliseconds are multiplied with + * frequency per second. Therefore we need to multiply QPC value by 1000 to + * have the same units to allow simple arithmentic with both QPC and GTC. + */ +#define ms2mt(x) ((x) * mozilla::GetQueryPerformanceFrequencyPerSec()) +#define mt2ms(x) ((x) / mozilla::GetQueryPerformanceFrequencyPerSec()) +#define mt2ms_f(x) (double(x) / mozilla::GetQueryPerformanceFrequencyPerSec()) + +MFBT_API uint64_t +GetQueryPerformanceFrequencyPerSec(); + class TimeStamp; class TimeStampValue { friend struct IPC::ParamTraits<mozilla::TimeStampValue>; friend class TimeStamp; // Both QPC and GTC are kept in [mt] units.
new file mode 100644 --- /dev/null +++ b/toolkit/components/fuzzyfox/Fuzzyfox.cpp @@ -0,0 +1,382 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 "Fuzzyfox.h" +#include "mozilla/Logging.h" +#include "mozilla/Preferences.h" +#include "mozilla/Services.h" +#include "mozilla/SystemGroup.h" +#include "mozilla/TimeStamp.h" +#include "nsComponentManagerUtils.h" +#include "nsIPrefBranch.h" +#include "nsIPrefService.h" +#include "nsServiceManagerUtils.h" +#include "prrng.h" +#include "prtime.h" + +// For usleep/Sleep & QueryPerformanceFrequency +#ifdef XP_WIN +#include <windows.h> +#else +#include <unistd.h> +#endif + +using namespace mozilla; + +static LazyLogModule sFuzzyfoxLog("Fuzzyfox"); + +#define US_TO_NS(x) ((x)*1000) +#define NS_TO_US(x) ((x)/1000) + +#ifdef LOG +#undef LOG +#endif + +#define LOG(level, args) MOZ_LOG(sFuzzyfoxLog, mozilla::LogLevel::level, args) + +#define FUZZYFOX_ENABLED_PREF "privacy.fuzzyfox.enabled" +#define FUZZYFOX_ENABLED_PREF_DEFAULT false +#define FUZZYFOX_CLOCKGRAIN_PREF "privacy.fuzzyfox.clockgrainus" +#define FUZZYFOX_CLOCKGRAIN_PREF_DEFAULT 100 + +Atomic<uint32_t, Relaxed> Fuzzyfox::sFuzzyfoxClockGrain; + +NS_IMPL_ISUPPORTS_INHERITED(Fuzzyfox, Runnable, nsIObserver) + +/* static */ void +Fuzzyfox::Start() +{ + MOZ_ASSERT(NS_IsMainThread()); + + RefPtr<Fuzzyfox> r = new Fuzzyfox(); + SystemGroup::Dispatch(TaskCategory::Other, r.forget()); +} + +Fuzzyfox::Fuzzyfox() + : Runnable("Fuzzyfox") + , mSanityCheck(false) + , mStartTime(0) + , mDuration(PickDuration()) + , mTickType(eUptick) +{ + MOZ_ASSERT(NS_IsMainThread()); + + // [[ I originally ran this after observing profile-after-change, but + // it turned out that this contructor was getting called _after_ that + // event had already fired. ]] + Preferences::AddAtomicUintVarCache(&sFuzzyfoxClockGrain, + FUZZYFOX_CLOCKGRAIN_PREF, + FUZZYFOX_CLOCKGRAIN_PREF_DEFAULT); + + bool fuzzyfoxEnabled = + Preferences::GetBool(FUZZYFOX_ENABLED_PREF, FUZZYFOX_ENABLED_PREF_DEFAULT); + + LOG(Info, ("PT(%p) Created Fuzzyfox, FuzzyFox is now %s \n", + this, (fuzzyfoxEnabled ? "enabled" : "disabled"))); + + TimeStamp::SetFuzzyfoxEnabled(fuzzyfoxEnabled); + + // Should I see if these fail? And do what? + nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID); + prefs->AddObserver(FUZZYFOX_ENABLED_PREF, this, false); + prefs->AddObserver(FUZZYFOX_CLOCKGRAIN_PREF, this, false); +} + +Fuzzyfox::~Fuzzyfox() = default; + +/* + * Fuzzyfox::Run is the core of FuzzyFox. Every so often we pop into this method, and pick + * a new point in the future to hold time constant until. If we have not reached the _previous_ + * point in time we had picked, we sleep until we do so. + * Then we round the current time downwards to a configurable grain value, fix it in place so + * time does not advance, and let execution continue. + */ +NS_IMETHODIMP +Fuzzyfox::Observe(nsISupports* aObject, const char* aTopic, + const char16_t* aMessage) +{ + if (!strcmp(NS_PREFBRANCH_PREFCHANGE_TOPIC_ID, aTopic)) { + NS_ConvertUTF16toUTF8 pref(aMessage); + + if (pref.EqualsLiteral(FUZZYFOX_ENABLED_PREF)) { + bool fuzzyfoxEnabled = + Preferences::GetBool(FUZZYFOX_ENABLED_PREF, FUZZYFOX_ENABLED_PREF_DEFAULT); + + LOG(Info, ("PT(%p) Observed a pref change, FuzzyFox is now %s \n", + this, (fuzzyfoxEnabled ? "enabled" : "disabled"))); + + + TimeStamp::SetFuzzyfoxEnabled(fuzzyfoxEnabled); + + + if (TimeStamp::GetFuzzyfoxEnabled()) { + // Queue a runnable + nsCOMPtr<nsIRunnable> r = this; + SystemGroup::Dispatch(TaskCategory::Other, r.forget()); + } else { + mStartTime = 0; + mTickType = eUptick; + mSanityCheck = false; + } + } + } + return NS_OK; +} + +#define DISPATCH_AND_RETURN() \ + nsCOMPtr<nsIRunnable> r = this; \ + SystemGroup::Dispatch(TaskCategory::Other, r.forget()); \ + return NS_OK + +NS_IMETHODIMP +Fuzzyfox::Run() +{ + MOZ_ASSERT(NS_IsMainThread()); + if (!TimeStamp::GetFuzzyfoxEnabled()) { + LOG(Info, ("[FuzzyfoxEvent] PT(%p) Fuzzyfox is shut down, doing nothing \n", this)); + return NS_OK; + } + + if (mStartTime == 0) { + // This is the first time we are running afer enabling FuzzyFox. We need + // to prevent time from going backwards, so for the first run we round the time up + // to the next grain. + mStartTime = CeilToGrain(ActualTime()); + MOZ_ASSERT(mStartTime != 0); + TimeStamp newTimeStamp = CeilToGrain(TimeStamp::NowUnfuzzed()); + Fuzzyfox::UpdateClocks(mStartTime, newTimeStamp); + + mSanityCheck = true; + LOG(Info, ("[FuzzyfoxEvent] PT(%p) Going to start Fuzzyfox, queuing up the job \n", + this)); + + DISPATCH_AND_RETURN(); + } + + // We need to check how long its been since we ran + uint64_t endTime = ActualTime(); + + uint64_t remaining = 0; + + // Pick the amount to sleep + if (endTime < mStartTime) { + // This can only happen if we just enabled FuzzyFox, rounded up, and then re-ran the + // runnable before we advanced to the next grain. + // If that happens, then repeat the current time. + // We use mSanityCheck just to be sure (and will eventually remove it.) + MOZ_ASSERT(mSanityCheck); + LOG(Debug, ("[FuzzyfoxEvent] PT(%p) endTime < mStartTime mStartTime %" PRIu64 " endTime %" PRIu64 " \n", + this, mStartTime, endTime)); + + mSanityCheck = true; + DISPATCH_AND_RETURN(); + } + + uint64_t actualRunDuration = endTime - mStartTime; + if (actualRunDuration > mDuration) { + // We ran over our budget! + uint64_t over = actualRunDuration - mDuration; + LOG(Verbose, ("[FuzzyfoxEvent] PT(%p) Overran budget of %" PRIu32 " by %" PRIu64 " \n", + this, mDuration, over)); + + uint64_t nextDuration = PickDuration(); + while (over > nextDuration) { + over -= nextDuration; + nextDuration = PickDuration(); + mTickType = mTickType == eUptick ? eDowntick : eUptick; + } + + remaining = nextDuration - over; + } else { + // Didn't go over budget + remaining = mDuration - actualRunDuration; + LOG(Verbose, ("[FuzzyfoxEvent] PT(%p) Finishing budget of %" PRIu32 " with %" PRIu64 " \n", + this, mDuration, remaining)); + } + mSanityCheck = false; + + // Sleep for now +#ifdef XP_WIN + Sleep(remaining); +#else + usleep(remaining); +#endif + + /* + * Update clocks (and fire pending events etc) + * + * Note: Anytime we round the current time to the grain, and then round the 'real' + * time to the grain, we are introducing the risk that we split the grain. That is, + * the time advances enough after the first rounding that the second rounding causes + * us to move to a different grain. + * + * In theory, such an occurance breaks the security of FuzzyFox, and if an + * attacker can influence the event to occur reliably, and then measure against it + * they can attack FuzzyFox. But such an attack is so difficult that it will + * never be acheived until you read this comment in a future Academic Publication + * that demonstrates it. And at that point the paper would surely never be accepted + * into any _respectable_ journal unless the authors had also presented a solution + * for the issue that was usable and incorporated into Firefox! + */ + uint64_t newTime = FloorToGrain(ActualTime()); + TimeStamp newTimeStamp = FloorToGrain(TimeStamp::NowUnfuzzed()); + UpdateClocks(newTime, newTimeStamp); + + // Reset values + mTickType = mTickType == eUptick ? eDowntick : eUptick; + mStartTime = ActualTime(); + mDuration = PickDuration(); + + DISPATCH_AND_RETURN(); +} + +/* + * ActualTime returns the unfuzzed/unrounded time in microseconds since the epoch + */ +uint64_t +Fuzzyfox::ActualTime() +{ + return PR_Now(); +} + +/* + * Calculate a duration we will wait until we allow time to advance again + */ +uint64_t +Fuzzyfox::PickDuration() +{ + // TODO: Bug 1484298 - use a real RNG + long int rval = rand(); + + // Avoid divide by zero errors and overflow errors + uint32_t duration = sFuzzyfoxClockGrain <= 0 ? 1 : sFuzzyfoxClockGrain; + duration = duration >= (UINT32_MAX / 2) ? (UINT32_MAX / 2) : duration; + + // We want uniform distribution from 1->duration*2 + // so that the mean is duration + return 1 + (rval % (duration * 2)); +} + +/* + * Update the TimeStamp's class value for the current (constant) time and dispatch + * the new (constant) timestamp so observers can register to receive it to update + * their own time code. + */ +void +Fuzzyfox::UpdateClocks(uint64_t aNewTime, TimeStamp aNewTimeStamp) +{ + // newTime is the new canonical time for this scope! + #ifndef XP_WIN + LOG(Verbose, ("[Time] New time is %" PRIu64 " (compare to %" PRIu64 ") and timestamp is %" PRIu64 " (compare to %" PRIu64 ")\n", + aNewTime, ActualTime(), aNewTimeStamp.mValue.mTimeStamp, TimeStamp::NowUnfuzzed().mValue.mTimeStamp)); + #else + LOG(Verbose, ("[Time] New time is %" PRIu64 " (compare to %" PRIu64 ") \n", aNewTime, ActualTime())); + #endif + + // Fire notifications + if (MOZ_UNLIKELY(!mObs)) { + mObs = services::GetObserverService(); + if (NS_WARN_IF(!mObs)) { + return; + } + } + + // Event firings on occur on downticks and have no data + if (mTickType == eDowntick) { + mObs->NotifyObservers(nullptr, FUZZYFOX_FIREOUTBOUND_OBSERVER_TOPIC, nullptr); + } + + if (!mTimeUpdateWrapper) { + mTimeUpdateWrapper = do_CreateInstance(NS_SUPPORTS_PRINT64_CONTRACTID); + if (NS_WARN_IF(!mTimeUpdateWrapper)) { + return; + } + } + + mTimeUpdateWrapper->SetData(aNewTime); + + // Clocks get the new official (frozen) time. This happens on all ticks + mObs->NotifyObservers(mTimeUpdateWrapper, FUZZYFOX_UPDATECLOCK_OBSERVER_TOPIC, nullptr); + + // Update the timestamp's canonicaltime + TimeStamp::UpdateFuzzyTimeStamp(aNewTimeStamp); +} + +uint64_t +Fuzzyfox::GetClockGrain() +{ + return sFuzzyfoxClockGrain; +} + + +/* + * FloorToGrain accepts a timestamp in microsecond precision + * and returns it in microseconds, rounded down to the nearest + * ClockGrain value. + */ +uint64_t +Fuzzyfox::FloorToGrain(uint64_t aValue) +{ + return aValue - (aValue % GetClockGrain()); +} + + +/* + * FloorToGrain accepts a timestamp and returns it, rounded down + * to the nearest ClockGrain value. + */ +TimeStamp +Fuzzyfox::FloorToGrain(TimeStamp aValue) +{ +#ifdef XP_WIN + // grain is in us + uint64_t grain = GetClockGrain(); + // GTC and QPS are stored in |mt| and need to be converted to + uint64_t GTC = mt2ms(aValue.mValue.mGTC) * 1000; + uint64_t QPC = mt2ms(aValue.mValue.mQPC) * 1000; + + return TimeStamp(TimeStampValue( + ms2mt((GTC - (GTC % grain)) / 1000), + ms2mt((QPC - (QPC % grain)) / 1000), + aValue.mValue.mHasQPC, true)); +#else + return TimeStamp(TimeStampValue(true, US_TO_NS(FloorToGrain(NS_TO_US(aValue.mValue.mTimeStamp))))); +#endif +} + +/* + * CeilToGrain accepts a timestamp in microsecond precision + * and returns it in microseconds, rounded up to the nearest + * ClockGrain value. + */ +uint64_t +Fuzzyfox::CeilToGrain(uint64_t aValue) +{ + return (aValue / GetClockGrain()) * GetClockGrain(); +} + +/* + * CeilToGrain accepts a timestamp and returns it, rounded up + * to the nearest ClockGrain value. + */ +TimeStamp +Fuzzyfox::CeilToGrain(TimeStamp aValue) +{ +#ifdef XP_WIN + // grain is in us + uint64_t grain = GetClockGrain(); + // GTC and QPS are stored in |mt| and need to be converted + uint64_t GTC = mt2ms(aValue.mValue.mGTC) * 1000; + uint64_t QPC = mt2ms(aValue.mValue.mQPC) * 1000; + + return TimeStamp(TimeStampValue( + ms2mt(((GTC / grain) * grain) / 1000), + ms2mt(((QPC / grain) * grain) / 1000), + aValue.mValue.mHasQPC, true)); +#else + return TimeStamp(TimeStampValue(true, US_TO_NS(CeilToGrain(NS_TO_US(aValue.mValue.mTimeStamp))))); +#endif +} \ No newline at end of file
new file mode 100644 --- /dev/null +++ b/toolkit/components/fuzzyfox/Fuzzyfox.h @@ -0,0 +1,137 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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_Fuzzyfox_h +#define mozilla_Fuzzyfox_h + +#include "nsIObserver.h" +#include "nsIObserverService.h" +#include "nsISupportsPrimitives.h" +#include "nsThreadUtils.h" +#include "mozilla/TimeStamp.h" + + +/* + * This topic publishes the new canonical time according to Fuzzyfox, + * in microseconds since the epoch. If code needs to know the current time, + * it should listen for this topic and keep track of the 'current' time, + * so as to respect Fuzzyfox and be in sync with the rest of the browser's + * timekeeping. + */ +#define FUZZYFOX_UPDATECLOCK_OBSERVER_TOPIC "fuzzyfox-update-clocks" + +/* + * For Fuzzyfox's security guarentees to hold, the browser must not execute + * actions while it should be paused. We currently only pause the main thread, + * so actions that occur on other threads should be queued until the browser + * unpaused (and moreso than unpauses: until it reaches a downtick.) + * This topic indicates when any queued outbound events should be delivered. + * TODO: Bug 1484300 and 1484299 would apply this to other communication channels + */ +#define FUZZYFOX_FIREOUTBOUND_OBSERVER_TOPIC "fuzzyfox-fire-outbound" + +namespace mozilla { + + +/* + * Fuzzyfox is an implementation of the Fermata concept presented in + * Trusted Browsers for Uncertain Times. + * + * Web Browsers expose explicit (performance.now()) and implicit + * (WebVTT, Video Frames) timers that, when combined with algorithmic + * improvements such as edge thresholding, produce extremely high + * resolution clocks. + * + * High Resolution clocks can be used to time network accesses, browser + * cache reads, web page rendering, access to the CPU cache, and other + * operations - and the time these operations take to perform can yield + * detailed information about user information we want to keep private. + * + * Fuzzyfox limits the information disclosure by limiting an attacker's + * ability to create a high resolution clock. It does this by introducing + * a concept called 'fuzzy time' that degrades all clocks (explicit and + * implicit). This is done through a combination of holding time constant + * during program execution and pausing program execution. + * + * @InProceedings{KS16, + * author = {David Kohlbrenner and Hovav Shacham}, + * title = {Trusted Browsers for Uncertain Times}, + * booktitle = {Proceedings of USENIX Security 2016}, + * pages = {463-80}, + * year = 2016, + * editor = {Thorsten Holz and Stefan Savage}, + * month = aug, + * organization = {USENIX} + * } + * https://www.usenix.org/system/files/conference/usenixsecurity16/sec16_paper_kohlbrenner.pdf + * + * Fuzzyfox is an adaptation of + * W.-M. Hu, “Reducing timing channels with fuzzy time,” in + * Proceedings of IEEE Security and Privacy (“Oakland”) + * 1991, T. F. Lunt and J. McLean, Eds. IEEE Computer + * Society, May 1991, pp. 8–20. + */ +class Fuzzyfox final : public Runnable, public nsIObserver +{ +public: + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_NSIOBSERVER + + static void + Start(); + + NS_IMETHOD + Run() override; + +private: + Fuzzyfox(); + ~Fuzzyfox(); + + uint64_t + ActualTime(); + + uint64_t + PickDuration(); + + void + UpdateClocks(uint64_t aNewTime, TimeStamp aNewTimeStamp); + + uint64_t + GetClockGrain(); + + uint64_t + FloorToGrain(uint64_t aValue); + + TimeStamp + FloorToGrain(TimeStamp aValue); + + uint64_t + CeilToGrain(uint64_t aValue); + + TimeStamp + CeilToGrain(TimeStamp aValue); + + bool mSanityCheck; + uint64_t mStartTime; + uint32_t mDuration; + + enum Tick { + eUptick, + eDowntick, + }; + + Tick mTickType; + + nsCOMPtr<nsIObserverService> mObs = nullptr; + nsCOMPtr<nsISupportsPRInt64> mTimeUpdateWrapper = nullptr; + + static Atomic<bool, Relaxed> sFuzzyfoxEnabledPrefMapped; + static Atomic<uint32_t, Relaxed> sFuzzyfoxClockGrain; +}; + +} // mozilla namespace + +#endif /* mozilla_Fuzzyfox_h */
new file mode 100644 --- /dev/null +++ b/toolkit/components/fuzzyfox/moz.build @@ -0,0 +1,15 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +SOURCES += [ + 'Fuzzyfox.cpp', +] + +EXPORTS.mozilla += [ + 'Fuzzyfox.h' +] + +FINAL_LIBRARY = 'xul'
--- a/toolkit/components/moz.build +++ b/toolkit/components/moz.build @@ -31,16 +31,17 @@ DIRS += [ 'crashes', 'crashmonitor', 'downloads', 'enterprisepolicies', 'extensions', 'filewatcher', 'finalizationwitness', 'find', + 'fuzzyfox', 'jsoncpp/src/lib_json', 'lz4', 'mediasniffer', 'microformats', 'mozintl', 'mozprotocol', 'osfile', 'parentalcontrols',