1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 #include "SocketProcessParent.h"
7 #include "SocketProcessLogging.h"
8
9 #include "AltServiceParent.h"
10 #include "CachePushChecker.h"
11 #include "HttpTransactionParent.h"
12 #include "SocketProcessHost.h"
13 #include "mozilla/Components.h"
14 #include "mozilla/dom/MemoryReportRequest.h"
15 #include "mozilla/ipc/FileDescriptorSetParent.h"
16 #include "mozilla/ipc/IPCStreamAlloc.h"
17 #include "mozilla/ipc/PChildToParentStreamParent.h"
18 #include "mozilla/ipc/PParentToChildStreamParent.h"
19 #include "mozilla/net/DNSRequestParent.h"
20 #include "mozilla/net/ProxyConfigLookupParent.h"
21 #include "mozilla/RemoteLazyInputStreamParent.h"
22 #include "mozilla/Telemetry.h"
23 #include "mozilla/TelemetryIPC.h"
24 #include "nsIAppStartup.h"
25 #include "nsIHttpActivityObserver.h"
26 #include "nsIObserverService.h"
27 #include "nsNSSIOLayer.h"
28 #include "PSMIPCCommon.h"
29 #include "secerr.h"
30 #ifdef MOZ_WEBRTC
31 # include "mozilla/dom/ContentProcessManager.h"
32 # include "mozilla/dom/BrowserParent.h"
33 # include "mozilla/net/WebrtcTCPSocketParent.h"
34 #endif
35 #if defined(MOZ_WIDGET_ANDROID)
36 # include "mozilla/java/GeckoProcessManagerWrappers.h"
37 # include "mozilla/java/GeckoProcessTypeWrappers.h"
38 #endif // defined(MOZ_WIDGET_ANDROID)
39
40 namespace mozilla {
41 namespace net {
42
43 static SocketProcessParent* sSocketProcessParent;
44
SocketProcessParent(SocketProcessHost * aHost)45 SocketProcessParent::SocketProcessParent(SocketProcessHost* aHost)
46 : mHost(aHost) {
47 MOZ_ASSERT(NS_IsMainThread());
48 MOZ_ASSERT(mHost);
49
50 MOZ_COUNT_CTOR(SocketProcessParent);
51 sSocketProcessParent = this;
52 }
53
~SocketProcessParent()54 SocketProcessParent::~SocketProcessParent() {
55 MOZ_ASSERT(NS_IsMainThread());
56
57 MOZ_COUNT_DTOR(SocketProcessParent);
58 sSocketProcessParent = nullptr;
59 }
60
61 /* static */
GetSingleton()62 SocketProcessParent* SocketProcessParent::GetSingleton() {
63 MOZ_ASSERT(NS_IsMainThread());
64
65 return sSocketProcessParent;
66 }
67
ActorDestroy(ActorDestroyReason aWhy)68 void SocketProcessParent::ActorDestroy(ActorDestroyReason aWhy) {
69 #if defined(MOZ_WIDGET_ANDROID)
70 nsCOMPtr<nsIEventTarget> launcherThread(ipc::GetIPCLauncher());
71 MOZ_ASSERT(launcherThread);
72
73 auto procType = java::GeckoProcessType::SOCKET();
74 auto selector =
75 java::GeckoProcessManager::Selector::New(procType, OtherPid());
76
77 launcherThread->Dispatch(NS_NewRunnableFunction(
78 "SocketProcessParent::ActorDestroy",
79 [selector = java::GeckoProcessManager::Selector::GlobalRef(selector)]() {
80 java::GeckoProcessManager::ShutdownProcess(selector);
81 }));
82 #endif // defined(MOZ_WIDGET_ANDROID)
83
84 if (aWhy == AbnormalShutdown) {
85 GenerateCrashReport(OtherPid());
86
87 if (PR_GetEnv("MOZ_CRASHREPORTER_SHUTDOWN")) {
88 printf_stderr("Shutting down due to socket process crash.\n");
89 nsCOMPtr<nsIAppStartup> appService =
90 do_GetService("@mozilla.org/toolkit/app-startup;1");
91 if (appService) {
92 bool userAllowedQuit = true;
93 appService->Quit(nsIAppStartup::eForceQuit, 1, &userAllowedQuit);
94 }
95 }
96 }
97
98 if (mHost) {
99 mHost->OnChannelClosed();
100 }
101 }
102
SendRequestMemoryReport(const uint32_t & aGeneration,const bool & aAnonymize,const bool & aMinimizeMemoryUsage,const Maybe<ipc::FileDescriptor> & aDMDFile)103 bool SocketProcessParent::SendRequestMemoryReport(
104 const uint32_t& aGeneration, const bool& aAnonymize,
105 const bool& aMinimizeMemoryUsage,
106 const Maybe<ipc::FileDescriptor>& aDMDFile) {
107 mMemoryReportRequest = MakeUnique<dom::MemoryReportRequestHost>(aGeneration);
108
109 PSocketProcessParent::SendRequestMemoryReport(
110 aGeneration, aAnonymize, aMinimizeMemoryUsage, aDMDFile,
111 [&](const uint32_t& aGeneration2) {
112 MOZ_ASSERT(gIOService);
113 if (!gIOService->SocketProcess()) {
114 return;
115 }
116 SocketProcessParent* actor = gIOService->SocketProcess()->GetActor();
117 if (!actor) {
118 return;
119 }
120 if (actor->mMemoryReportRequest) {
121 actor->mMemoryReportRequest->Finish(aGeneration2);
122 actor->mMemoryReportRequest = nullptr;
123 }
124 },
125 [&](mozilla::ipc::ResponseRejectReason) {
126 MOZ_ASSERT(gIOService);
127 if (!gIOService->SocketProcess()) {
128 return;
129 }
130 SocketProcessParent* actor = gIOService->SocketProcess()->GetActor();
131 if (!actor) {
132 return;
133 }
134 actor->mMemoryReportRequest = nullptr;
135 });
136
137 return true;
138 }
139
RecvAddMemoryReport(const MemoryReport & aReport)140 mozilla::ipc::IPCResult SocketProcessParent::RecvAddMemoryReport(
141 const MemoryReport& aReport) {
142 if (mMemoryReportRequest) {
143 mMemoryReportRequest->RecvReport(aReport);
144 }
145 return IPC_OK();
146 }
147
RecvAccumulateChildHistograms(nsTArray<HistogramAccumulation> && aAccumulations)148 mozilla::ipc::IPCResult SocketProcessParent::RecvAccumulateChildHistograms(
149 nsTArray<HistogramAccumulation>&& aAccumulations) {
150 TelemetryIPC::AccumulateChildHistograms(Telemetry::ProcessID::Socket,
151 aAccumulations);
152 return IPC_OK();
153 }
154
RecvAccumulateChildKeyedHistograms(nsTArray<KeyedHistogramAccumulation> && aAccumulations)155 mozilla::ipc::IPCResult SocketProcessParent::RecvAccumulateChildKeyedHistograms(
156 nsTArray<KeyedHistogramAccumulation>&& aAccumulations) {
157 TelemetryIPC::AccumulateChildKeyedHistograms(Telemetry::ProcessID::Socket,
158 aAccumulations);
159 return IPC_OK();
160 }
161
RecvUpdateChildScalars(nsTArray<ScalarAction> && aScalarActions)162 mozilla::ipc::IPCResult SocketProcessParent::RecvUpdateChildScalars(
163 nsTArray<ScalarAction>&& aScalarActions) {
164 TelemetryIPC::UpdateChildScalars(Telemetry::ProcessID::Socket,
165 aScalarActions);
166 return IPC_OK();
167 }
168
RecvUpdateChildKeyedScalars(nsTArray<KeyedScalarAction> && aScalarActions)169 mozilla::ipc::IPCResult SocketProcessParent::RecvUpdateChildKeyedScalars(
170 nsTArray<KeyedScalarAction>&& aScalarActions) {
171 TelemetryIPC::UpdateChildKeyedScalars(Telemetry::ProcessID::Socket,
172 aScalarActions);
173 return IPC_OK();
174 }
175
RecvRecordChildEvents(nsTArray<mozilla::Telemetry::ChildEventData> && aEvents)176 mozilla::ipc::IPCResult SocketProcessParent::RecvRecordChildEvents(
177 nsTArray<mozilla::Telemetry::ChildEventData>&& aEvents) {
178 TelemetryIPC::RecordChildEvents(Telemetry::ProcessID::Socket, aEvents);
179 return IPC_OK();
180 }
181
RecvRecordDiscardedData(const mozilla::Telemetry::DiscardedData & aDiscardedData)182 mozilla::ipc::IPCResult SocketProcessParent::RecvRecordDiscardedData(
183 const mozilla::Telemetry::DiscardedData& aDiscardedData) {
184 TelemetryIPC::RecordDiscardedData(Telemetry::ProcessID::Socket,
185 aDiscardedData);
186 return IPC_OK();
187 }
188
AllocPWebrtcTCPSocketParent(const Maybe<TabId> & aTabId)189 PWebrtcTCPSocketParent* SocketProcessParent::AllocPWebrtcTCPSocketParent(
190 const Maybe<TabId>& aTabId) {
191 #ifdef MOZ_WEBRTC
192 WebrtcTCPSocketParent* parent = new WebrtcTCPSocketParent(aTabId);
193 parent->AddRef();
194 return parent;
195 #else
196 return nullptr;
197 #endif
198 }
199
DeallocPWebrtcTCPSocketParent(PWebrtcTCPSocketParent * aActor)200 bool SocketProcessParent::DeallocPWebrtcTCPSocketParent(
201 PWebrtcTCPSocketParent* aActor) {
202 #ifdef MOZ_WEBRTC
203 WebrtcTCPSocketParent* parent = static_cast<WebrtcTCPSocketParent*>(aActor);
204 parent->Release();
205 #endif
206 return true;
207 }
208
AllocPDNSRequestParent(const nsCString & aHost,const nsCString & aTrrServer,const uint16_t & aType,const OriginAttributes & aOriginAttributes,const uint32_t & aFlags)209 already_AddRefed<PDNSRequestParent> SocketProcessParent::AllocPDNSRequestParent(
210 const nsCString& aHost, const nsCString& aTrrServer, const uint16_t& aType,
211 const OriginAttributes& aOriginAttributes, const uint32_t& aFlags) {
212 RefPtr<DNSRequestHandler> handler = new DNSRequestHandler();
213 RefPtr<DNSRequestParent> actor = new DNSRequestParent(handler);
214 return actor.forget();
215 }
216
RecvPDNSRequestConstructor(PDNSRequestParent * aActor,const nsCString & aHost,const nsCString & aTrrServer,const uint16_t & aType,const OriginAttributes & aOriginAttributes,const uint32_t & aFlags)217 mozilla::ipc::IPCResult SocketProcessParent::RecvPDNSRequestConstructor(
218 PDNSRequestParent* aActor, const nsCString& aHost,
219 const nsCString& aTrrServer, const uint16_t& aType,
220 const OriginAttributes& aOriginAttributes, const uint32_t& aFlags) {
221 RefPtr<DNSRequestParent> actor = static_cast<DNSRequestParent*>(aActor);
222 RefPtr<DNSRequestHandler> handler =
223 actor->GetDNSRequest()->AsDNSRequestHandler();
224 handler->DoAsyncResolve(aHost, aTrrServer, aType, aOriginAttributes, aFlags);
225 return IPC_OK();
226 }
227
228 mozilla::ipc::PFileDescriptorSetParent*
AllocPFileDescriptorSetParent(const FileDescriptor & aFD)229 SocketProcessParent::AllocPFileDescriptorSetParent(const FileDescriptor& aFD) {
230 return new mozilla::ipc::FileDescriptorSetParent(aFD);
231 }
232
DeallocPFileDescriptorSetParent(PFileDescriptorSetParent * aActor)233 bool SocketProcessParent::DeallocPFileDescriptorSetParent(
234 PFileDescriptorSetParent* aActor) {
235 delete static_cast<mozilla::ipc::FileDescriptorSetParent*>(aActor);
236 return true;
237 }
238
239 mozilla::ipc::PChildToParentStreamParent*
AllocPChildToParentStreamParent()240 SocketProcessParent::AllocPChildToParentStreamParent() {
241 return mozilla::ipc::AllocPChildToParentStreamParent();
242 }
243
DeallocPChildToParentStreamParent(PChildToParentStreamParent * aActor)244 bool SocketProcessParent::DeallocPChildToParentStreamParent(
245 PChildToParentStreamParent* aActor) {
246 delete aActor;
247 return true;
248 }
249
250 mozilla::ipc::PParentToChildStreamParent*
AllocPParentToChildStreamParent()251 SocketProcessParent::AllocPParentToChildStreamParent() {
252 MOZ_CRASH("PParentToChildStreamChild actors should be manually constructed!");
253 }
254
DeallocPParentToChildStreamParent(PParentToChildStreamParent * aActor)255 bool SocketProcessParent::DeallocPParentToChildStreamParent(
256 PParentToChildStreamParent* aActor) {
257 delete aActor;
258 return true;
259 }
260
261 mozilla::ipc::PParentToChildStreamParent*
SendPParentToChildStreamConstructor(PParentToChildStreamParent * aActor)262 SocketProcessParent::SendPParentToChildStreamConstructor(
263 PParentToChildStreamParent* aActor) {
264 MOZ_ASSERT(NS_IsMainThread());
265 return PSocketProcessParent::SendPParentToChildStreamConstructor(aActor);
266 }
267
268 mozilla::ipc::PFileDescriptorSetParent*
SendPFileDescriptorSetConstructor(const FileDescriptor & aFD)269 SocketProcessParent::SendPFileDescriptorSetConstructor(
270 const FileDescriptor& aFD) {
271 MOZ_ASSERT(NS_IsMainThread());
272 return PSocketProcessParent::SendPFileDescriptorSetConstructor(aFD);
273 }
274
RecvObserveHttpActivity(const HttpActivityArgs & aArgs,const uint32_t & aActivityType,const uint32_t & aActivitySubtype,const PRTime & aTimestamp,const uint64_t & aExtraSizeData,const nsCString & aExtraStringData)275 mozilla::ipc::IPCResult SocketProcessParent::RecvObserveHttpActivity(
276 const HttpActivityArgs& aArgs, const uint32_t& aActivityType,
277 const uint32_t& aActivitySubtype, const PRTime& aTimestamp,
278 const uint64_t& aExtraSizeData, const nsCString& aExtraStringData) {
279 nsCOMPtr<nsIHttpActivityDistributor> activityDistributor =
280 components::HttpActivityDistributor::Service();
281 MOZ_ASSERT(activityDistributor);
282
283 Unused << activityDistributor->ObserveActivityWithArgs(
284 aArgs, aActivityType, aActivitySubtype, aTimestamp, aExtraSizeData,
285 aExtraStringData);
286 return IPC_OK();
287 }
288
RecvInitBackground(Endpoint<PBackgroundParent> && aEndpoint)289 mozilla::ipc::IPCResult SocketProcessParent::RecvInitBackground(
290 Endpoint<PBackgroundParent>&& aEndpoint) {
291 LOG(("SocketProcessParent::RecvInitBackground\n"));
292 if (!ipc::BackgroundParent::Alloc(nullptr, std::move(aEndpoint))) {
293 return IPC_FAIL(this, "BackgroundParent::Alloc failed");
294 }
295
296 return IPC_OK();
297 }
298
299 already_AddRefed<PAltServiceParent>
AllocPAltServiceParent()300 SocketProcessParent::AllocPAltServiceParent() {
301 RefPtr<AltServiceParent> actor = new AltServiceParent();
302 return actor.forget();
303 }
304
RecvGetTLSClientCert(const nsCString & aHostName,const OriginAttributes & aOriginAttributes,const int32_t & aPort,const uint32_t & aProviderFlags,const uint32_t & aProviderTlsFlags,const ByteArray & aServerCert,Maybe<ByteArray> && aClientCert,nsTArray<ByteArray> && aCollectedCANames,bool * aSucceeded,ByteArray * aOutCert,ByteArray * aOutKey,nsTArray<ByteArray> * aBuiltChain)305 mozilla::ipc::IPCResult SocketProcessParent::RecvGetTLSClientCert(
306 const nsCString& aHostName, const OriginAttributes& aOriginAttributes,
307 const int32_t& aPort, const uint32_t& aProviderFlags,
308 const uint32_t& aProviderTlsFlags, const ByteArray& aServerCert,
309 Maybe<ByteArray>&& aClientCert, nsTArray<ByteArray>&& aCollectedCANames,
310 bool* aSucceeded, ByteArray* aOutCert, ByteArray* aOutKey,
311 nsTArray<ByteArray>* aBuiltChain) {
312 *aSucceeded = false;
313
314 SECItem serverCertItem = {
315 siBuffer, const_cast<uint8_t*>(aServerCert.data().Elements()),
316 static_cast<unsigned int>(aServerCert.data().Length())};
317 UniqueCERTCertificate serverCert(CERT_NewTempCertificate(
318 CERT_GetDefaultCertDB(), &serverCertItem, nullptr, false, true));
319 if (!serverCert) {
320 return IPC_OK();
321 }
322
323 RefPtr<nsIX509Cert> clientCert;
324 if (aClientCert) {
325 clientCert = nsNSSCertificate::ConstructFromDER(
326 BitwiseCast<char*, uint8_t*>(aClientCert->data().Elements()),
327 aClientCert->data().Length());
328 if (!clientCert) {
329 return IPC_OK();
330 }
331 }
332
333 ClientAuthInfo info(aHostName, aOriginAttributes, aPort, aProviderFlags,
334 aProviderTlsFlags, clientCert);
335 nsTArray<nsTArray<uint8_t>> collectedCANames;
336 for (auto& name : aCollectedCANames) {
337 collectedCANames.AppendElement(std::move(name.data()));
338 }
339
340 UniqueCERTCertificate cert;
341 UniqueSECKEYPrivateKey key;
342 UniqueCERTCertList builtChain;
343 SECStatus status =
344 DoGetClientAuthData(std::move(info), serverCert,
345 std::move(collectedCANames), cert, key, builtChain);
346 if (status != SECSuccess) {
347 return IPC_OK();
348 }
349
350 SerializeClientCertAndKey(cert, key, *aOutCert, *aOutKey);
351
352 if (builtChain) {
353 for (CERTCertListNode* n = CERT_LIST_HEAD(builtChain);
354 !CERT_LIST_END(n, builtChain); n = CERT_LIST_NEXT(n)) {
355 ByteArray array;
356 array.data().AppendElements(n->cert->derCert.data, n->cert->derCert.len);
357 aBuiltChain->AppendElement(std::move(array));
358 }
359 }
360
361 *aSucceeded = true;
362 return IPC_OK();
363 }
364
365 already_AddRefed<PProxyConfigLookupParent>
AllocPProxyConfigLookupParent(nsIURI * aURI,const uint32_t & aProxyResolveFlags)366 SocketProcessParent::AllocPProxyConfigLookupParent(
367 nsIURI* aURI, const uint32_t& aProxyResolveFlags) {
368 RefPtr<ProxyConfigLookupParent> actor =
369 new ProxyConfigLookupParent(aURI, aProxyResolveFlags);
370 return actor.forget();
371 }
372
RecvPProxyConfigLookupConstructor(PProxyConfigLookupParent * aActor,nsIURI * aURI,const uint32_t & aProxyResolveFlags)373 mozilla::ipc::IPCResult SocketProcessParent::RecvPProxyConfigLookupConstructor(
374 PProxyConfigLookupParent* aActor, nsIURI* aURI,
375 const uint32_t& aProxyResolveFlags) {
376 static_cast<ProxyConfigLookupParent*>(aActor)->DoProxyLookup();
377 return IPC_OK();
378 }
379
RecvCachePushCheck(nsIURI * aPushedURL,OriginAttributes && aOriginAttributes,nsCString && aRequestString,CachePushCheckResolver && aResolver)380 mozilla::ipc::IPCResult SocketProcessParent::RecvCachePushCheck(
381 nsIURI* aPushedURL, OriginAttributes&& aOriginAttributes,
382 nsCString&& aRequestString, CachePushCheckResolver&& aResolver) {
383 RefPtr<CachePushChecker> checker = new CachePushChecker(
384 aPushedURL, aOriginAttributes, aRequestString, aResolver);
385 if (NS_FAILED(checker->DoCheck())) {
386 aResolver(false);
387 }
388 return IPC_OK();
389 }
390
391 // To ensure that IPDL is finished before SocketParent gets deleted.
392 class DeferredDeleteSocketProcessParent : public Runnable {
393 public:
DeferredDeleteSocketProcessParent(UniquePtr<SocketProcessParent> && aParent)394 explicit DeferredDeleteSocketProcessParent(
395 UniquePtr<SocketProcessParent>&& aParent)
396 : Runnable("net::DeferredDeleteSocketProcessParent"),
397 mParent(std::move(aParent)) {}
398
Run()399 NS_IMETHODIMP Run() override { return NS_OK; }
400
401 private:
402 UniquePtr<SocketProcessParent> mParent;
403 };
404
405 /* static */
Destroy(UniquePtr<SocketProcessParent> && aParent)406 void SocketProcessParent::Destroy(UniquePtr<SocketProcessParent>&& aParent) {
407 NS_DispatchToMainThread(
408 new DeferredDeleteSocketProcessParent(std::move(aParent)));
409 }
410
411 already_AddRefed<PRemoteLazyInputStreamParent>
AllocPRemoteLazyInputStreamParent(const nsID & aID,const uint64_t & aSize)412 SocketProcessParent::AllocPRemoteLazyInputStreamParent(const nsID& aID,
413 const uint64_t& aSize) {
414 RefPtr<RemoteLazyInputStreamParent> actor =
415 RemoteLazyInputStreamParent::Create(aID, aSize, this);
416 return actor.forget();
417 }
418
419 mozilla::ipc::IPCResult
RecvPRemoteLazyInputStreamConstructor(PRemoteLazyInputStreamParent * aActor,const nsID & aID,const uint64_t & aSize)420 SocketProcessParent::RecvPRemoteLazyInputStreamConstructor(
421 PRemoteLazyInputStreamParent* aActor, const nsID& aID,
422 const uint64_t& aSize) {
423 if (!static_cast<RemoteLazyInputStreamParent*>(aActor)->HasValidStream()) {
424 return IPC_FAIL_NO_REASON(this);
425 }
426
427 return IPC_OK();
428 }
429
RecvODoHServiceActivated(const bool & aActivated)430 mozilla::ipc::IPCResult SocketProcessParent::RecvODoHServiceActivated(
431 const bool& aActivated) {
432 nsCOMPtr<nsIObserverService> observerService =
433 mozilla::services::GetObserverService();
434
435 if (observerService) {
436 observerService->NotifyObservers(nullptr, "odoh-service-activated",
437 aActivated ? u"true" : u"false");
438 }
439 return IPC_OK();
440 }
441
442 } // namespace net
443 } // namespace mozilla
444