Bug 1748113 - Always load etc/hosts file in parent process, r=necko-reviewers,valentin

Differential Revision: https://phabricator.services.mozilla.com/D135097
This commit is contained in:
Kershaw Chang 2022-01-06 03:48:57 +00:00
parent a74d5debf3
commit 88b259fb02
8 changed files with 92 additions and 46 deletions

View File

@ -28,6 +28,7 @@ child:
async ClearDNSCache(bool aTrrToo);
async SetDetectedTrrURI(nsCString aURI);
async SetDefaultTRRConnectionInfo(HttpConnectionInfoCloneArgs? aConnInfoArgs);
async UpdateEtcHosts(nsCString[] aHosts);
};
} //namespace net

View File

@ -23,15 +23,10 @@
#include "mozilla/Telemetry.h"
#include "mozilla/TelemetryComms.h"
#include "mozilla/Tokenizer.h"
#include "mozilla/net/rust_helper.h"
#include "mozilla/net/TRRServiceChild.h"
// Put DNSLogging.h at the end to avoid LOG being overwritten by other headers.
#include "DNSLogging.h"
#if defined(XP_WIN) && !defined(__MINGW32__)
# include <shlobj_core.h> // for SHGetSpecialFolderPathA
#endif // XP_WIN
static const char kOpenCaptivePortalLoginEvent[] = "captive-portal-login";
static const char kClearPrivateData[] = "clear-private-data";
static const char kPurge[] = "browser:purge-session-history";
@ -432,48 +427,17 @@ void TRRService::AddEtcHosts(const nsTArray<nsCString>& aArray) {
}
void TRRService::ReadEtcHostsFile() {
if (!StaticPrefs::network_trr_exclude_etc_hosts()) {
if (!XRE_IsParentProcess()) {
return;
}
auto readHostsTask = []() {
MOZ_ASSERT(!NS_IsMainThread(), "Must not run on the main thread");
#if defined(XP_WIN) && !defined(__MINGW32__)
// Inspired by libevent/evdns.c
// Windows is a little coy about where it puts its configuration
// files. Sure, they're _usually_ in C:\windows\system32, but
// there's no reason in principle they couldn't be in
// W:\hoboken chicken emergency
nsCString path;
path.SetLength(MAX_PATH + 1);
if (!SHGetSpecialFolderPathA(NULL, path.BeginWriting(), CSIDL_SYSTEM,
false)) {
LOG(("Calling SHGetSpecialFolderPathA failed"));
return;
DoReadEtcHostsFile([](const nsTArray<nsCString>* aArray) -> bool {
RefPtr<TRRService> service(sTRRServicePtr);
if (service && aArray) {
service->AddEtcHosts(*aArray);
}
path.SetLength(strlen(path.get()));
path.Append("\\drivers\\etc\\hosts");
#elif defined(__MINGW32__)
nsAutoCString path("C:\\windows\\system32\\drivers\\etc\\hosts"_ns);
#else
nsAutoCString path("/etc/hosts"_ns);
#endif
LOG(("Reading hosts file at %s", path.get()));
rust_parse_etc_hosts(&path, [](const nsTArray<nsCString>* aArray) -> bool {
RefPtr<TRRService> service(sTRRServicePtr);
if (service && aArray) {
service->AddEtcHosts(*aArray);
}
return !!service;
});
};
Unused << NS_DispatchBackgroundTask(
NS_NewRunnableFunction("Read /etc/hosts file", readHostsTask),
NS_DISPATCH_EVENT_MAY_BLOCK);
return !!service;
});
}
void TRRService::GetURI(nsACString& result) {

View File

@ -21,6 +21,10 @@
// Put DNSLogging.h at the end to avoid LOG being overwritten by other headers.
#include "DNSLogging.h"
#if defined(XP_WIN) && !defined(__MINGW32__)
# include <shlobj_core.h> // for SHGetSpecialFolderPathA
#endif // XP_WIN
namespace mozilla {
namespace net {
@ -339,5 +343,46 @@ void TRRServiceBase::UnregisterProxyChangeListener() {
pps->RemoveProxyConfigCallback(this);
}
void TRRServiceBase::DoReadEtcHostsFile(ParsingCallback aCallback) {
MOZ_ASSERT(XRE_IsParentProcess());
if (!StaticPrefs::network_trr_exclude_etc_hosts()) {
return;
}
auto readHostsTask = [aCallback]() {
MOZ_ASSERT(!NS_IsMainThread(), "Must not run on the main thread");
#if defined(XP_WIN) && !defined(__MINGW32__)
// Inspired by libevent/evdns.c
// Windows is a little coy about where it puts its configuration
// files. Sure, they're _usually_ in C:\windows\system32, but
// there's no reason in principle they couldn't be in
// W:\hoboken chicken emergency
nsCString path;
path.SetLength(MAX_PATH + 1);
if (!SHGetSpecialFolderPathA(NULL, path.BeginWriting(), CSIDL_SYSTEM,
false)) {
LOG(("Calling SHGetSpecialFolderPathA failed"));
return;
}
path.SetLength(strlen(path.get()));
path.Append("\\drivers\\etc\\hosts");
#elif defined(__MINGW32__)
nsAutoCString path("C:\\windows\\system32\\drivers\\etc\\hosts"_ns);
#else
nsAutoCString path("/etc/hosts"_ns);
#endif
LOG(("Reading hosts file at %s", path.get()));
rust_parse_etc_hosts(&path, aCallback);
};
Unused << NS_DispatchBackgroundTask(
NS_NewRunnableFunction("Read /etc/hosts file", readHostsTask),
NS_DISPATCH_EVENT_MAY_BLOCK);
}
} // namespace net
} // namespace mozilla

View File

@ -8,6 +8,7 @@
#include "mozilla/Atomics.h"
#include "mozilla/DataMutex.h"
#include "mozilla/net/rust_helper.h"
#include "nsString.h"
#include "nsIDNSService.h"
#include "nsIProtocolProxyService2.h"
@ -53,7 +54,8 @@ class TRRServiceBase : public nsIProxyConfigChangedCallback {
void OnTRRModeChange();
void OnTRRURIChange();
virtual void ReadEtcHostsFile() {}
void DoReadEtcHostsFile(ParsingCallback aCallback);
virtual void ReadEtcHostsFile() = 0;
// Called to create a connection info that will be used by TRRServiceChannel.
// Note that when this function is called, mDefaultTRRConnectionInfo will be
// set to null to invalidate the connection info.

View File

@ -111,5 +111,11 @@ mozilla::ipc::IPCResult TRRServiceChild::RecvSetDefaultTRRConnectionInfo(
return IPC_OK();
}
mozilla::ipc::IPCResult TRRServiceChild::RecvUpdateEtcHosts(
nsTArray<nsCString>&& aHosts) {
TRRService::Get()->AddEtcHosts(aHosts);
return IPC_OK();
}
} // namespace net
} // namespace mozilla

View File

@ -41,6 +41,7 @@ class TRRServiceChild : public PTRRServiceChild,
mozilla::ipc::IPCResult RecvSetDetectedTrrURI(const nsCString& aURI);
mozilla::ipc::IPCResult RecvSetDefaultTRRConnectionInfo(
Maybe<HttpConnectionInfoCloneArgs>&& aArgs);
mozilla::ipc::IPCResult RecvUpdateEtcHosts(nsTArray<nsCString>&& aHosts);
private:
virtual ~TRRServiceChild();

View File

@ -25,6 +25,8 @@
namespace mozilla {
namespace net {
static Atomic<TRRServiceParent*> sTRRServiceParentPtr;
static const char* gTRRUriCallbackPrefs[] = {
"network.trr.uri", "network.trr.default_provider_uri",
"network.trr.mode", kRolloutURIPref,
@ -68,8 +70,10 @@ void TRRServiceParent::Init() {
gTRRUriCallbackPrefs, this);
prefsChanged(nullptr);
Unused << socketParent->SendPTRRServiceConstructor(
this, captiveIsPassed, parentalControlEnabled, suffixList);
if (socketParent->SendPTRRServiceConstructor(
this, captiveIsPassed, parentalControlEnabled, suffixList)) {
sTRRServiceParentPtr = this;
}
}
NS_IMETHODIMP
@ -168,6 +172,7 @@ void TRRServiceParent::prefsChanged(const char* aName) {
}
void TRRServiceParent::ActorDestroy(ActorDestroyReason why) {
sTRRServiceParentPtr = nullptr;
Preferences::UnregisterPrefixCallbacks(TRRServiceParent::PrefsChanged,
gTRRUriCallbackPrefs, this);
}
@ -208,5 +213,26 @@ mozilla::ipc::IPCResult TRRServiceParent::RecvSetConfirmationState(
return IPC_OK();
}
void TRRServiceParent::ReadEtcHostsFile() {
if (!sTRRServiceParentPtr) {
return;
}
DoReadEtcHostsFile([](const nsTArray<nsCString>* aArray) -> bool {
RefPtr<TRRServiceParent> service(sTRRServiceParentPtr);
if (service && aArray) {
nsTArray<nsCString> hosts(aArray->Clone());
NS_DispatchToMainThread(NS_NewRunnableFunction(
"TRRServiceParent::ReadEtcHostsFile",
[service, hosts = std::move(hosts)]() mutable {
if (service->CanSend()) {
Unused << service->SendUpdateEtcHosts(hosts);
}
}));
}
return !!service;
});
}
} // namespace net
} // namespace mozilla

View File

@ -36,6 +36,7 @@ class TRRServiceParent : public TRRServiceBase,
mozilla::ipc::IPCResult RecvInitTRRConnectionInfo();
mozilla::ipc::IPCResult RecvSetConfirmationState(uint32_t aNewState);
uint32_t GetConfirmationState() { return mConfirmationState; }
virtual void ReadEtcHostsFile() override;
private:
virtual ~TRRServiceParent();