tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 9f7cc5351f2eccfe7f15c8157b4a834dce785c9d
parent 9df584253d6c16afc69609848fb4ca227d9357d3
Author: Nika Layzell <nika@thelayzells.com>
Date:   Tue, 16 Dec 2025 04:53:46 +0000

Bug 1927599 - Part 2: Parent process cannot have child task_t on iOS, r=ipc-reviewers,profiler-reviewers,mstange,jld

Transferring a task_t over XPC during child process startup appears to cause a
connection failure. It seems likely that transferring a task in this way is a
sandbox violation on-device.

This mostly consists of changing ifdefs associated with the task_t object to be
macOS-specific instead. iOS simulator builds will stop working after this
change until the IPC backend is changed.

Differential Revision: https://phabricator.services.mozilla.com/D227102

Diffstat:
Mdom/base/ChromeUtils.cpp | 8++++----
Mipc/glue/GeckoChildProcessHost.cpp | 33+++++++++++----------------------
Mipc/glue/GeckoChildProcessHost.h | 4++--
Mtoolkit/components/processtools/ProcInfo.h | 6+++---
Mtoolkit/components/processtools/ProcInfo.mm | 2++
Mtoolkit/xre/IOSBootstrap.mm | 3+--
Mtools/profiler/core/platform.cpp | 2+-
7 files changed, 24 insertions(+), 34 deletions(-)

diff --git a/dom/base/ChromeUtils.cpp b/dom/base/ChromeUtils.cpp @@ -1861,10 +1861,10 @@ already_AddRefed<Promise> ChromeUtils::RequestProcInfo(GlobalObject& aGlobal, // DOM windows. /* aUtilityInfo = */ std::move(utilityActors), /* aChild = */ 0 // Without a ContentProcess, no ChildId. -#ifdef XP_DARWIN +#ifdef XP_MACOSX , /* aChildTask = */ aGeckoProcess->GetChildTask() -#endif // XP_DARWIN +#endif // XP_MACOSX ); }); @@ -1965,10 +1965,10 @@ already_AddRefed<Promise> ChromeUtils::RequestProcInfo(GlobalObject& aGlobal, /* aWindowInfo = */ std::move(windows), /* aUtilityInfo = */ nsTArray<UtilityInfo>(), /* aChild = */ contentParent->ChildID() -#ifdef XP_DARWIN +#ifdef XP_MACOSX , /* aChildTask = */ contentParent->Process()->GetChildTask() -#endif // XP_DARWIN +#endif // XP_MACOSX ); } diff --git a/ipc/glue/GeckoChildProcessHost.cpp b/ipc/glue/GeckoChildProcessHost.cpp @@ -131,7 +131,7 @@ namespace ipc { struct LaunchResults { base::ProcessHandle mHandle = 0; -#ifdef XP_DARWIN +#ifdef XP_MACOSX task_t mChildTask = MACH_PORT_NULL; #endif #ifdef XP_IOS @@ -388,7 +388,7 @@ GeckoChildProcessHost::GeckoChildProcessHost(GeckoProcessType aProcessType, #endif mHandleLock("mozilla.ipc.GeckoChildProcessHost.mHandleLock"), mChildProcessHandle(0), -#if defined(XP_DARWIN) +#if defined(XP_MACOSX) mChildTask(MACH_PORT_NULL), #endif #if defined(MOZ_SANDBOX) && defined(XP_MACOSX) @@ -425,7 +425,7 @@ GeckoChildProcessHost::~GeckoChildProcessHost() { { mozilla::AutoWriteLock hLock(mHandleLock); -#if defined(XP_DARWIN) +#if defined(XP_MACOSX) if (mChildTask != MACH_PORT_NULL) { mach_port_deallocate(mach_task_self(), mChildTask); } @@ -462,7 +462,7 @@ base::ProcessId GeckoChildProcessHost::GetChildProcessId() { return base::GetProcId(mChildProcessHandle); } -#ifdef XP_DARWIN +#ifdef XP_MACOSX task_t GeckoChildProcessHost::GetChildTask() { mozilla::AutoReadLock handleLock(mHandleLock); return mChildTask; @@ -776,7 +776,7 @@ bool GeckoChildProcessHost::AsyncLaunch( // "safe" invalid value to use in places like this. aResults.mHandle = 0; -#ifdef XP_DARWIN +#ifdef XP_MACOSX this->mChildTask = aResults.mChildTask; #endif #ifdef XP_IOS @@ -789,7 +789,7 @@ bool GeckoChildProcessHost::AsyncLaunch( if (mNodeChannel) { mNodeChannel->SetOtherPid( base::GetProcId(this->mChildProcessHandle)); -#ifdef XP_DARWIN +#ifdef XP_MACOSX mNodeChannel->SetMachTaskPort(this->mChildTask); #endif } @@ -1511,27 +1511,16 @@ RefPtr<ProcessLaunchPromise> IosProcessLauncher::DoLaunch() { return; } - // FIXME: We have to trust the child to tell us its pid & mach task. + // NOTE: We have to trust the child to tell us its pid. The child is + // blocked by sandbox from sending its mach task. // WebKit uses `xpc_connection_get_pid` to get the pid, however this // is marked as unavailable on iOS. // - // Given how the process is started, however, validating this - // information it sends us this early during startup may be - // unnecessary. - self->mResults.mChildTask = - xpc_dictionary_copy_mach_send(reply, "task"); + // The process hasn't had a chance to load any untrusted content at + // this point, so we should be able to trust it. pid_t pid = static_cast<pid_t>(xpc_dictionary_get_int64(reply, "pid")); - CHROMIUM_LOG(INFO) << "ExtensionKit process started, task: " - << self->mResults.mChildTask << ", pid: " << pid; - - pid_t taskPid; - kern_return_t kr = pid_for_task(self->mResults.mChildTask, &taskPid); - if (kr != KERN_SUCCESS || pid != taskPid) { - CHROMIUM_LOG(ERROR) << "Could not validate child task matches pid"; - promise->Reject(LaunchError("pid_for_task mismatch"), __func__); - return; - } + CHROMIUM_LOG(INFO) << "ExtensionKit process started, pid: " << pid; self->mResults.mHandle = pid; promise->Resolve(std::move(self->mResults), __func__); diff --git a/ipc/glue/GeckoChildProcessHost.h b/ipc/glue/GeckoChildProcessHost.h @@ -164,7 +164,7 @@ class GeckoChildProcessHost : public SupportsWeakPtr, GeckoProcessType GetProcessType() { return mProcessType; } -#ifdef XP_DARWIN +#ifdef XP_MACOSX task_t GetChildTask(); #endif @@ -266,7 +266,7 @@ class GeckoChildProcessHost : public SupportsWeakPtr, mozilla::RWLock mHandleLock; ProcessHandle mChildProcessHandle MOZ_GUARDED_BY(mHandleLock); -#if defined(XP_DARWIN) +#if defined(XP_MACOSX) task_t mChildTask MOZ_GUARDED_BY(mHandleLock); #endif #if defined(MOZ_WIDGET_UIKIT) diff --git a/toolkit/components/processtools/ProcInfo.h b/toolkit/components/processtools/ProcInfo.h @@ -181,7 +181,7 @@ struct ProcInfoRequest { ProcInfoRequest(base::ProcessId aPid, ProcType aProcessType, const nsACString& aOrigin, nsTArray<WindowInfo>&& aWindowInfo, nsTArray<UtilityInfo>&& aUtilityInfo, uint32_t aChildId = 0 -#ifdef XP_DARWIN +#ifdef XP_MACOSX , mach_port_t aChildTask = 0 #endif // XP_DARWIN @@ -192,7 +192,7 @@ struct ProcInfoRequest { windowInfo(std::move(aWindowInfo)), utilityInfo(std::move(aUtilityInfo)), childId(aChildId) -#ifdef XP_DARWIN +#ifdef XP_MACOSX , childTask(aChildTask) #endif // XP_DARWIN @@ -205,7 +205,7 @@ struct ProcInfoRequest { const nsTArray<UtilityInfo> utilityInfo; // If the process is a child, its child id, otherwise `0`. const int32_t childId; -#ifdef XP_DARWIN +#ifdef XP_MACOSX const mach_port_t childTask; #endif // XP_DARWIN }; diff --git a/toolkit/components/processtools/ProcInfo.mm b/toolkit/components/processtools/ProcInfo.mm @@ -100,6 +100,7 @@ ProcInfoPromise::ResolveOrRejectValue GetProcInfoSync( info.windows = std::move(request.windowInfo); info.utilityActors = std::move(request.utilityInfo); +#ifdef XP_MACOSX mach_port_t selectedTask; // If we did not get a task from a child process, we use mach_task_self() if (request.childTask == MACH_PORT_NULL) { @@ -191,6 +192,7 @@ ProcInfoPromise::ResolveOrRejectValue GetProcInfoSync( thread->name.AssignASCII(threadInfoData.pth_name); thread->tid = identifierInfo.thread_id; } +#endif if (!gathered.put(request.pid, std::move(info))) { result.SetReject(NS_ERROR_OUT_OF_MEMORY); diff --git a/toolkit/xre/IOSBootstrap.mm b/toolkit/xre/IOSBootstrap.mm @@ -136,10 +136,9 @@ void HandleBootstrapMessage(xpc_object_t aEvent) { close(fd); } - // Immediately send a reply with our pid and mach task port. + // Immediately send a reply with our pid auto reply = mozilla::AdoptDarwinObject(xpc_dictionary_create_reply(aEvent)); xpc_dictionary_set_int64(reply.get(), "pid", getpid()); - xpc_dictionary_set_mach_send(reply.get(), "task", mach_task_self()); xpc_connection_send_message(xpc_dictionary_get_remote_connection(aEvent), reply.get()); diff --git a/tools/profiler/core/platform.cpp b/tools/profiler/core/platform.cpp @@ -5350,7 +5350,7 @@ void SamplerThread::SpyOnUnregisteredThreads() { /* aWindowInfo = */ nsTArray<WindowInfo>{}, /* aUtilityInfo = */ nsTArray<UtilityInfo>{}, /* aChild = */ 0 -#ifdef XP_DARWIN +#ifdef XP_MACOSX , /* aChildTask = */ MACH_PORT_NULL #endif // XP_DARWIN